Search code examples
quarkusresteasymutinyquarkus-reactive

Is there a difference between Uni<List<T>> vs Multi<T> in Quarkus Resteasy reactive?


When implementing a reactive endpoint, is there any difference between returning Uni<List<T>> vs Multi<T> ?

@Path("/fruits")
public class FruitResource {

    @GET
    @Path("uni")
    public Uni<List<Fruit>> getUni() {
        return Fruit.listAll();
    }

    @GET
    @Path("multi")
    public Multi<Fruit> getMulti() {
        return Fruit.streamAll();
    }
}

I find it easier to use a Multi because I can simply transform each each element to a DTO using onItem().transform(fruit -> ...)
With an Uni, I would get a List in the transform method which is less convenient.

In all Quarkus guides, I see they are using a Uni<List>>, is there any good reason for using this rather than a Multi ?


Solution

  • In this particular use case, there isn't much difference in using one or the other. Except that the default response header from the rest API will change (it's subtle, but some clients might behave differently based on what you are doing):

    For Uni:

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    content-length: 75
    

    For Multi:

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    transfer-encoding: chunked
    

    This is because a Multi is supposed to be used when one generates a stream of potentially endless events (like geod said in the other answer).

    If you are using Panache with Hibernate Reactive, streaming the results from a query on the database is not supported. So, the current implementation of Fruit.streamAll just converts the Uni<List<Fruit>> into a Multi<Fruit>.

    You can see the code on GitHub:

            Uni<List<T>> results = list();
            return (Multi<T>) results.toMulti().flatMap(list -> {
                return Multi.createFrom().iterable(list);
            });