@EJB @Singleton et ConcurrencyManagement
Rédigé par gorki Aucun commentaireLe problème :
Un EJB singleton qui sert de cache remonte une erreur avec JBoss 7.1.1 :
EJB Invocation failed on component XXXX for method public java.lang.Object: javax.ejb.EJBTransactionRolledbackException: JBAS014373: EJB 3.1 PFD2 4.8.5.5.1 concurrent access timeout on org.jboss.invocation.InterceptorContext$Invocation@398e7b17 - could not obtain lock within 5000MILLISECONDS
Solution :
Tout est déjà écrit bien sur, encore aurait-il fallu le lire :)
Par défaut les EJB @Singleton sont
-
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
- protégés par un @Lock(LockType.WRITE)
donc les méthodes sont synchronisés par le container. On peut
- soit passer la méthode ou la classe en LockType.READ,
- soit passer en Bean-managed (@ConcurrencyManagement(ConcurrencyManagementType.BEAN)). Là c'est vous qui gérer le tout.
Pour reproduire systématiquement, il suffit de mettre un sleep de 6s dans la méthode problématique.
Note:
- Si le pool des ejb n'est pas assez grand on a un permit timeout et non un concurrent ascess timeout.
- Le timeout sous JBoss est configuré dans cette section très intéressante :
<subsystem xmlns="urn:jboss:domain:ejb3:1.2"> <session-bean> <stateless> <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/> </stateless> <stateful default-access-timeout="5000" cache-ref="simple"/> <singleton default-access-timeout="5000"/> </session-bean> <pools> <bean-instance-pools> <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/> <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/> </bean-instance-pools> </pools> <caches> <cache name="simple" aliases="NoPassivationCache"/> <cache name="passivating" passivation-store-ref="file" aliases="SimpleStatefulCache"/> </caches> <passivation-stores> <file-passivation-store name="file"/> </passivation-stores> <async thread-pool-name="default"/> <timer-service thread-pool-name="default"> <data-store path="timer-service-data" relative-to="jboss.server.data.dir"/> </timer-service> <remote connector-ref="remoting-connector" thread-pool-name="default"/> <thread-pools> <thread-pool name="default"> <max-threads count="10"/> <keepalive-time time="100" unit="milliseconds"/> </thread-pool> </thread-pools> </subsystem>