Reputation: 972
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.
Upvotes: 1
Views: 4519
Reputation: 3192
In addition to @Ladicek answer, I believe you want to use runSubscriptionOn
and not emitOn
. See https://smallrye.io/smallrye-mutiny/latest/guides/emit-on-vs-run-subscription-on/ as reference.
Upvotes: 4
Reputation: 972
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.
Upvotes: 1
Reputation: 6577
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.
Upvotes: 5