如何使用 vertx 和 quarkus 发布静态集合
How to publish static collection with vertx and quarkus
我正在使用 Quarkus 构建一个应用程序,它是 vert.x 扩展。现在我想构建一个 REST 端点,它应该流式传输所有保存的地址。为了在没有反应性数据源的情况下测试这个,我不想创建一个带有示例地址的 ArrayList 并流式传输它们,这样我就可以检查我的测试是否有效。但是我找不到如何流式传输集合。
我的实际代码:
import io.vertx.reactivex.core.Vertx;
import org.reactivestreams.Publisher;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Collection;
@Path("/addresses")
public class AddressResource {
private Collection<Address> adresses;
@Inject private Vertx vertx;
public AddressResource() {
super();
adresses = new ArrayList<>();
}
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<Address> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
// What to do here?
return null;
}
}
这是我的测试:
import io.quarkus.test.junit.QuarkusTest;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import javax.json.bind.JsonbBuilder;
import java.util.ArrayList;
import java.util.List;
import static io.restassured.RestAssured.given;
@QuarkusTest
public class DBServiceTest {
@Test
void testGetAddresses() throws InterruptedException {
given()
.when()
.get("/addresses")
.then()
.statusCode(200)
.body(Matchers.containsInAnyOrder(readTestAdresses().toArray()));
}
private List<Address> readTestAdresses() {
return JsonbBuilder.create()
.fromJson(
this.getClass().getResourceAsStream("test-addresses.json"),
new ArrayList<Address>() {}.getClass().getGenericSuperclass());
}
}
编辑 1:
我尝试了以下方法:
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
adresses.add(address);
return Flowable.just("Test 1","Test 2","Test 3");
}
这行得通。所以问题一定与地址对象有关。
您可以使用
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
return Flowable.just(address, address, address,....).map(a -> yourToString(a));
}
其中 yourToString
是一种将创建正确字符串表示的方法(可能是 json)。
我可以修复它,我错过了一个依赖项:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>
并且必须手动将我的对象转换为 json 等等,将 return 类型更改为 Publisher<String>
:
import io.reactivex.Flowable;
import io.vertx.core.json.Json;
import org.reactivestreams.Publisher;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Collection;
@Path("/addresses")
@Consumes(MediaType.APPLICATION_JSON)
public class AddressResource {
private Collection<Address> addresses;
public AddressResource() {
super();
addresses = new ArrayList<>();
}
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
addresses.add(address);
return Flowable.fromIterable(addresses).map(Json::encode);
}
}
我的测试也是错误的,现在是这样的:
import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import javax.json.bind.JsonbBuilder;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.sse.SseEventSource;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import static org.assertj.core.api.Assertions.assertThat;
@QuarkusTest
public class DBServiceTest {
@TestHTTPResource("/addresses")
private URL enpointUrl;
@Test
@DisplayName("Get all addresses")
void testGetAddresses() {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(String.valueOf(enpointUrl));
try (SseEventSource source = SseEventSource.target(target).build()) {
CompletableFuture<Collection<Address>> futureAddresses = new CompletableFuture<>();
Set<Address> foundAddresses = new HashSet<>();
source.register(
event -> {
if (!foundAddresses.add(
event.readData(Address.class, MediaType.APPLICATION_JSON_TYPE))) {
futureAddresses.complete(foundAddresses);
}
},
Assertions::fail);
source.open();
Collection<Address> addresses = futureAddresses.join();
assertThat(addresses).containsExactlyInAnyOrderElementsOf(readTestAdresses());
}
}
private List<Address> readTestAdresses() {
return JsonbBuilder.create()
.fromJson(
this.getClass().getResourceAsStream("test-addresses.json"),
new ArrayList<Address>() {}.getClass().getGenericSuperclass());
}
}
我正在使用 Quarkus 构建一个应用程序,它是 vert.x 扩展。现在我想构建一个 REST 端点,它应该流式传输所有保存的地址。为了在没有反应性数据源的情况下测试这个,我不想创建一个带有示例地址的 ArrayList 并流式传输它们,这样我就可以检查我的测试是否有效。但是我找不到如何流式传输集合。
我的实际代码:
import io.vertx.reactivex.core.Vertx;
import org.reactivestreams.Publisher;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Collection;
@Path("/addresses")
public class AddressResource {
private Collection<Address> adresses;
@Inject private Vertx vertx;
public AddressResource() {
super();
adresses = new ArrayList<>();
}
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<Address> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
// What to do here?
return null;
}
}
这是我的测试:
import io.quarkus.test.junit.QuarkusTest;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import javax.json.bind.JsonbBuilder;
import java.util.ArrayList;
import java.util.List;
import static io.restassured.RestAssured.given;
@QuarkusTest
public class DBServiceTest {
@Test
void testGetAddresses() throws InterruptedException {
given()
.when()
.get("/addresses")
.then()
.statusCode(200)
.body(Matchers.containsInAnyOrder(readTestAdresses().toArray()));
}
private List<Address> readTestAdresses() {
return JsonbBuilder.create()
.fromJson(
this.getClass().getResourceAsStream("test-addresses.json"),
new ArrayList<Address>() {}.getClass().getGenericSuperclass());
}
}
编辑 1: 我尝试了以下方法:
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
adresses.add(address);
return Flowable.just("Test 1","Test 2","Test 3");
}
这行得通。所以问题一定与地址对象有关。
您可以使用
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
return Flowable.just(address, address, address,....).map(a -> yourToString(a));
}
其中 yourToString
是一种将创建正确字符串表示的方法(可能是 json)。
我可以修复它,我错过了一个依赖项:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>
并且必须手动将我的对象转换为 json 等等,将 return 类型更改为 Publisher<String>
:
import io.reactivex.Flowable;
import io.vertx.core.json.Json;
import org.reactivestreams.Publisher;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Collection;
@Path("/addresses")
@Consumes(MediaType.APPLICATION_JSON)
public class AddressResource {
private Collection<Address> addresses;
public AddressResource() {
super();
addresses = new ArrayList<>();
}
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
addresses.add(address);
return Flowable.fromIterable(addresses).map(Json::encode);
}
}
我的测试也是错误的,现在是这样的:
import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import javax.json.bind.JsonbBuilder;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.sse.SseEventSource;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import static org.assertj.core.api.Assertions.assertThat;
@QuarkusTest
public class DBServiceTest {
@TestHTTPResource("/addresses")
private URL enpointUrl;
@Test
@DisplayName("Get all addresses")
void testGetAddresses() {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(String.valueOf(enpointUrl));
try (SseEventSource source = SseEventSource.target(target).build()) {
CompletableFuture<Collection<Address>> futureAddresses = new CompletableFuture<>();
Set<Address> foundAddresses = new HashSet<>();
source.register(
event -> {
if (!foundAddresses.add(
event.readData(Address.class, MediaType.APPLICATION_JSON_TYPE))) {
futureAddresses.complete(foundAddresses);
}
},
Assertions::fail);
source.open();
Collection<Address> addresses = futureAddresses.join();
assertThat(addresses).containsExactlyInAnyOrderElementsOf(readTestAdresses());
}
}
private List<Address> readTestAdresses() {
return JsonbBuilder.create()
.fromJson(
this.getClass().getResourceAsStream("test-addresses.json"),
new ArrayList<Address>() {}.getClass().getGenericSuperclass());
}
}