I recently learned that I can easily make any session bean method Asynchronous by simply adding the @Asynchronous
annotation.
E.g.
@Asynch
Even though the solution I found was tested only on Java EE 7/GlassFish 4.1, I think that it should work for GlassFish 3.x too.
There's a JIRA entry on java.net where the different settings are listed. As Oracle is going to pull the plug on that site, I'll quote the relevant post here (formatting added):
The configuration is in domain.xml, for example,
<ejb-container> <property name="thread-core-pool-size" value="10"></property> <property name="thread-max-pool-size" value="100"></property> <property name="thread-queue-capacity" value="20"></property> <property name="thread-keep-alive-seconds" value="600"</property> <property name="allow-core-thread-timeout" value="false"></property> <property name="prestart-all-core-threads" value="false"></property> </ejb-container>
All of the above properties are optional. Their default values:
thread-core-pool-size: 16 thread-max-pool-size: 32 thread-queue-capacity: Integer.MAX_VALUE thread-keep-alive-seconds: 60 allow-core-thread-timeout: false prestart-all-core-threads: false
Via that thread, I also found a blog post that explains how the core and max pool size work. Quote of the important point:
In the past SUN declared correctly: "That is exactly how it is supposed to behave. First the threads grow to coreSize, then the queue is used, then if the queue fills up then the number of threads expands from coreSize to maxSize. Hence if you use an unbounded queue the last part never happens. This is all described in the documentation. If you want an unbounded queue but more threads then increase the core size. Otherwise consider whether a bounded queue is more suitable to your needs."
I think timeout could be achieved by invoking Future.cancel(boolean) from a method annotated @Timeout. Requires keeping a reference to the Future returned by the async method, Singleton-ejb can be used for this.
@Stateless
public class AsyncEjb {
@Resource
private SessionContext sessionContext;
@Asynchronous
public Future<String> asyncMethod() {
...
//Check if canceled by timer
if(sessionContext.wasCancelCalled()) {
...
}
...
}
}
@Singleton
public class SingletonEjb {
@EJB
AsyncEjb asyncEjb;
Future<String> theFuture;
public void asyncMethod() {
theFuture = asyncEjb.asyncMethod();
//Create programatic timer
long duration = 6000;
Timer timer =
timerService.createSingleActionTimer(duration, new TimerConfig());
}
//Method invoked when timer runs out
@Timeout
public void timeout(Timer timer) {
theFuture.cancel(true);
}
}
Edit (new below):
In glassfish you may configure the ejb-pool by seting below attributes in the admin console
see Tuning the EJB Pool