As bkail states the pooling semantics of @Stateless beans are vendor-specific. That said in EJB 3.1 we added the @AccessTimeout annotation which can be used on the bean class or methods of a @Stateless, @Stateful or @Singleton bean.
@AccessTimeout
In a general sense this annotation portably specifies up to how long a caller will wait if a wait condition occurs with concurrent access. Specific to each bean type, wait conditions will occur when:
@Singleton - an @Lock(WRITE) method is being invoked and container-managed concurrency is being used. All methods are @Lock(WRITE) by default.
@Stateful - any method of the instance is being invoked and a second invocation occurs. OR the @Stateful bean is in a transaction and the caller is invoking it from outside that transaction.
@Stateless - no instances are available in the pool. As noted, however, pooling sematics, if any, are not covered by the spec. If the vendor's pooling semantics do involve a wait condition, the @AccessTimeout should apply.
Usage
The @AccessTimeout is simply a convenience wrapper around the long and TimeUnit tuples commonly used in the java.util.concurrent API.
import java.util.concurrent.TimeUnit;
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface AccessTimeout {
long value();
TimeUnit unit() default TimeUnit.MILLISECONDS;
}
When explicitly set on a bean class or method, it has three possible meanings:
@AccessTimeout(-1) - Never timeout, wait as long as it takes. Potentially forever.
@AccessTimeout(0) - Never wait. Immediately throw ConcurrentAccessException if a wait condition would have occurred.
@AccessTimout(30, TimeUnit.SECONDS) - Wait up to 30 seconds if a wait condition occurs. After that, throw ConcurrentAccessTimeoutExcpetion
No standard default
Note that the value attribute has no default. This was intentional and intended to communicate that if @AccessTimeout is not explicitly used, the behavior you get is vendor-specific.
Some vendors will wait for a preconfigured time and throw javax.ejb.ConcurrentAccessException, some vendors will throw it immediately. When we were defining this annotation it became clear that all of us vendors were doing things a bit differently and enforcing a default would cause problems for existing apps.
On a similar note, prior to EJB 3.0 there was no default transaction attribute and it was different for every vendor. Thank goodness EJB 3.0 was different enough that we could finally say, "For EJB 3.0 beans the default is REQUIRED."