2

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 ?

Olivier Boissé
  • 15,834
  • 6
  • 38
  • 56

2 Answers2

3

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);
        });
Davide D'Alto
  • 7,421
  • 2
  • 16
  • 30
  • thanks for referencing the source code. The method name `streamAll` is a bit confusing, we could think we are streaming the DB when calling the method whereas it's not the case – Olivier Boissé Nov 15 '22 at 09:33
  • Yeah, that's why we don't return Multi in the Hibernate Reactive API. Panache is different because it's more of an experimental API that can be reused with different libraries. Also, when the db and the Vert.x client support it, we might implement the method the way it supposed to be. But one still need to know or check what's happening underneath to see if it fits the required use case. – Davide D'Alto Nov 15 '22 at 10:14
  • 1
    Maybe we could improve the javadoc, and explain that the default behaviour is to convert the method that returns a uni. – Davide D'Alto Nov 15 '22 at 10:15
1

Multi<T> means that the stream is potentially endless and that dictates results in the data being streamed from the REST layer to the client.

Uni<List<T>> on the other hand means that there is a list of finite data that will be available and the REST layer treats it the same as it would with List<T>

geoand
  • 60,071
  • 24
  • 172
  • 190