简体   繁体   中英

How does Uni<T> works in Quarkus

I am trying to understand the behavior of Uni in Quarkus framework, after checking out their official tutorial getting started with async guide . In the service method I have made the following changes

package org.acme.getting.started.async;

import javax.enterprise.context.ApplicationScoped;

import io.smallrye.mutiny.Uni;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@ApplicationScoped
public class GreetingService {

    ExecutorService executor = Executors.newFixedThreadPool(10, r -> {
        return new Thread(r, "CUSTOM_TASK_EXECUTION_THREAD");
    });


    public Uni<String> greeting(String name) {
        System.out.println("greeting Executing on Thread "+Thread.currentThread().getName());
        return Uni.createFrom().item(ioSimulation(name))
                .emitOn(executor);//Infrastructure.getDefaultExecutor()
    }

    public String ioSimulation(String param){
        System.out.println("ioSimulation Executing on Thread "+Thread.currentThread().getName());
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello "+param;

    }

}

Then I have tested the /greeting/{name} resource, the execution was not async at all, in fact it executed all related methods within the same thread and in synchronous manner.

then what would be the difference between

@GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public Uni<String> greeting(@PathParam String name) {
    }

and

@GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam String name) {
    }

and how is it asynchronous? please help me to understand it.

The problem is in Uni.createFrom().item(ioSimulation(name)) . You synchronously call ioSimulation before the Uni is created.

You should at least use the Supplier variant: Uni.createFrom().item(() -> ioSimulation(name)) . That should help.

In addition to @Ladicek answer, I believe you want to use runSubscriptionOn and not emitOn . See https://smallrye.io/smallrye-mutiny/guides/emit-subscription as reference.

both the answers above are correct. I made some changes in service class and ioSimulation(String param) method was offloaded to the custom thread pool. The final solution is given below

public class GreetingService {

    ThreadFactory threadFactory = new NameableThreadFactory("CUSTOM_TASK_EXECUTION_THREAD");
    ExecutorService executor = Executors.newFixedThreadPool(10, threadFactory);

    public Uni<String> greeting(String name) {
        System.out.println("greeting Executing on Thread "+Thread.currentThread().getName());
        return Uni.createFrom().item(()->ioSimulation(name))
                .runSubscriptionOn(executor);//Infrastructure.getDefaultExecutor()
    }


    public String ioSimulation(String param){
        System.out.println("ioSimulation Executing on Thread "+Thread.currentThread().getName());
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello "+param;

    }
}

-- update --

emitOn(Executor executor) will also works asynchronously if you pass supplier in item method but the approach is slightly different, I have figured that while experimenting with Uni , this is my repo, incase if anyone is interested.

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