简体   繁体   中英

How to publish static collection with vertx and quarkus

I'm building an application with Quarkus and it's vert.x extension. Now I want to build a REST endpoint which should stream all saved addresses. To test this whiout a reactive data source I wan't to create a ArrayList with example addresses and stream them so I can check if my test works. But I don't find how I can stream a collection.

My actual code:

    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;
      }
    }

And this is my test:

    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());
      }
    }

Edit 1: I tried the following:


    @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");
      }

And this works. So the problem must have something to do with the address objects.

You can use something like

  @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));
  }

Where yourToString is a method that will create the proper string representation (json perhaps).

I could fix it, I missed a dependency:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>

And had to convert my objects to json manually and so on change the return type to 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);
      }
    }

Also my test was wrong, this is how it looks like now:

    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());
      }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM