Getting javax.ejb.ConcurrentAccessTimeoutException WFLYEJB0241 on Singleton EJB in JBoss EAP 8 / 7 / 6
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 8.x
- 7.x
- 6.x
- Java Enterprise
- EJB 3.1 onwards
Issue
- Our @Singleton EJB is logging this exception in EAP 7:
ERROR [org.jboss.as.ejb3.invocation] (ServerService Thread Pool -- 208) WFLYEJB0034: Jakarta Enterprise Beans Invocation failed on component MySingletonEJBImpl for method public abstract void com.redhat.examples.MySingletonEJB.invoke(java.lang.String): javax.ejb.ConcurrentAccessTimeoutException: WFLYEJB0241: Enterprise Beans 3.1 PFD2 4.8.5.5.1 concurrent access timeout on MySingletonEJBImpl - could not obtain lock within 5000MILLISECONDS
at org.jboss.as.ejb3.component.singleton.ContainerManagedConcurrencyInterceptor.processInvocation(ContainerManagedConcurrencyInterceptor.java:102) [wildfly-ejb3-7.4.0.GA-redhat-00005.jar:7.4.0.GA-redhat-00005]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
...
- Getting exception like below.
javax.ejb.ConcurrentAccessTimeoutException: JBAS014373: EJB 3.1 PFD2 4.8.5.5.1 concurrent access timeout on org.jboss.invocation.InterceptorContext$Invocation@7d5446 - could not obtain lock within 5000MILLISECONDS
org.jboss.as.ejb3.concurrency.ContainerManagedConcurrencyInterceptor.processInvocation(ContainerManagedConcurrencyInterceptor.java:100) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
...
- Having the error above even if the class is annotated with @Lock(READ)
@Singleton
@javax.ejb.Lock(javax.ejb.LockType.READ)
public class MySingletonBean {
public void aReadMethod() {...}
@javax.ejb.Lock(javax.ejb.LockType.WRITE)
public void aWriteMethod() {...}
}
Resolution
After confirming there was not a root cause, ie one of the Singleton methods calling another resource just happened to take longer due to an issue in the resources it invokes, then there are several options to change the concurrency timeout:
-
If there is no need to prevent from concurrent access the fix would be to change the
@Singletonto@Statelessto your ejb. Here a lot of clients are able to call it and it is ok to have multiple instances. -
The access timeout for a method or the Singleton class to specify a value instead of using the default timeout (which is defined in the EAP profile configuration). For example:
@AccessTimeout(unit = TimeUnit.MILLISECONDS, value=5000)
- Alternatively, one could use some concurrency settings on the @Singleton methods Content from docs.oracle.com is not included.Managing Concurrent Access in a Singleton Session Bean to allow ones which are safe to be called concurrently to be called without blocking. And also you can look for the method from where you are getting exception that takes to long and speed it up, such as don't have the
singletondo long processes, use anMDB, asynchronous invocation or something to offload some work if a response is not needed.
Note that methods with @Lock(WRITE) will lock the Singleton for concurrent invocations even if the class is annotated with @Lock(READ).
It is not recommended to use synchronized within a Singleton with ConcurrencyManagement CONTAINER, if you need fine grained management you should change to BEAN and synchronize it in the code.
The timeout can be controlled by annotation AccessTimeout, a value >0 will be the time in milliseconds; =0 will prevent from any concurrent access and =-1 will block until the Bean is free to process the invocation.
- The default Singleton timeout can be changed in the EAP profile configuration, in the ejb3 subsystem:
[standalone@embedded /] /subsystem=ejb3:write-attribute(name=default-singleton-bean-access-timeout,value=10000)
<subsystem xmlns="urn:jboss:domain:ejb3:10.0">
<session-bean>
...
<singleton default-access-timeout="10000"/>
</session-bean>
Related
- How to enable and view ejb invocation & pool statistics in JBoss EAP 8 / 7 / 6
- Content from jakarta.ee is not included.jakarta.ejb.AccessTimeout / Content from jakarta.ee is not included.javax.ejb.AccessTimeout
- Content from jakarta.ee is not included.jakarta.ejb.Lock / Content from jakarta.ee is not included.javax.ejb.Lock
- Content from jakarta.ee is not included.jakarta.ejb.AccessTimeout / Content from jakarta.ee is not included.javax.ejb.AccessTimeout
- Content from docs.oracle.com is not included.Managing Concurrent Access in a Singleton Session Bean
Root Cause
For Singletons with ConcurrencyManagement CONTAINER the server will take care of the invocations. The default timeout is 5000ms. If an invocation is blocked for that time the container will throw a ConcurrentAccessTimeoutException to the client.
The default is configured in the ejb3 subsystem:
<subsystem xmlns="urn:jboss:domain:ejb3:9.0">
<session-bean>
...
<singleton default-access-timeout="5000"/>
</session-bean>
...
It can be configured in using the CLI command below, the value is in milliseconds
[standalone@embedded /] /subsystem=ejb3/:write-attribute(name=default-singleton-bean-access-timeout,value=
Diagnostic Steps
Check the Singleton methods to see if the invocation time of its methods could take longer than the timeout allowed and the number of concurrent invocations that might occur to see if the timeout should be increased of if there is another root cause such as a resource called from one of the methods that had an issue that resulted in the method taking longer.
If the Singleton EJB methods could take an extended time to process and / or there can be a large number of clients attempting to invoke methods concurrently, enabling EJB Statistics and running a load test will show the concurrent invocations, average time to process, etc.
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.