I'm working on a project powered by Payara Micro and it is configured by a domain.xml file.
I'm facing an issue with the @Asynchronous
annotation.
While the Oracle documentation explains this:
Clients calling asynchronous methods, however, immediately have control returned to them by the enterprise bean container.
My @Asynchronous
annotated method does not return immediately.
@Path("foo")
public class FooResource {
@GET
public String get() {
System.out.println("Request started");
this.doSomething();
System.out.println("Request ended");
return "Hello world! ";
}
@Asynchronous
public void doSomething() {
try {
System.out.println("Long task started");
Thread.sleep(2000);
System.out.println("Long task ended");
} catch (InterruptedException e) {
System.out.println("Long task failed");
}
}
}
In my mind it should result in:
Request started
Long task started
Request ended
Long task ended
but it results in:
Request started
Long task started
Long task ended
Request ended
I published on Github a simple Gradle project to reproduce the behavior here.
CodePudding user response:
Your method invocation will be truly asynchronous if you actually invoke the method of an EJB. The call in your sample is a local method call, completely bypassing the container and its annotation processing.
A proper EJB invocation would require an actual EJB:
@Stateless
class MyEJB {
@Asynchronous
public void doSomething() {
try {
System.out.println("Long task started");
Thread.sleep(2000);
System.out.println("Long task ended");
} catch (InterruptedException e) {
System.out.println("Long task failed");
}
}
}
... and the method invocation in your resource class:
class MyResource {
@Inject MyEJB myEJB;
@Path("foo")
public class FooResource {
@GET
public String get() {
System.out.println("Request started");
myEJB.doSomething(); // <-- This is the important change!
System.out.println("Request ended");
return "Hello world! ";
}
}