EJB Singleton et javax. ejb. Concurrent Access Timeout Exception: JBAS014373

Il existe un mécanisme de lock sur les EJB permettant de verrouiller celui-ci. Cela permet de définir, quand le Bean est accessible pour traiter une requête.
Expert technique JEEMis à jour le 28 Janv 2014

Il peut être très utile dutiliser un Bean de type Singleton pour réaliser par exemple une tâche AsynchroneSe dit d'un traitement ou d'un événement qui est traité dans une temporalité différente de l'appelant. denvoi de mail.

Par contre il convient de comprendre un peu comment fonctionne le Singleton pour éviter ce genre derreur : 

Lerreur même si elle est très explicite (ConcurrentAccessTimeoutException) se doit être un peu expliquée pour comprendre pourquoi ce problème se produit et comment le résoudre.

Lock sur les Bean

Il existe un mécanisme de lock sur les EJB permettant de verrouiller celui-ci. Cela permet de définir, quand le Bean est accessible pour traiter une requête. 

Ce mécanisme est quelque peu différent selon le type de Bean employé : 

StatefulUn process est dit "stateful" (avec état) lorsqu'il peut être réutilisé sans limite. : Aucune requête concurrente ne pourra être effectuée sur un bean Stateful. La requête suivant devra donc être sérialisée par le conteneur dEJB pour être exécutée après libération du lock sur lEJB Stateful.

StatelessUn process est dit stateless (sans état) lorsqu'il est indépendant. Chaque transaction est effectuée comme si c'était la première fois. : Il y a toujours un pool de bean Stateless prêt à être utilisés, le lock va permettre de définir si un nouvel élément du pool doit être utilisé. Si toutes les instances du pool sont utilisées et quaucune autre instance ne peut être créee, alors le conteneur dEJB sérialisera la requête.

Singleton : Le cas qui nous interèsse dans cet article! à chaque fois quune méthode de ce Singleton est invoquée. Les requêtes seront donc systématiquement sérialisée par le conteneur dEJB si une méthode de ce Singleton est déjà en cours dinvocation. 

Cette sérialisation est transparente, si vos requêtes asynchrones sont traitées rapidement. Mais vous pouvez être confronté à un Timeout, si la requête précédente nest pas terminée alors quun certain temps sest écoulé depuis la sérialization. Par exemple, un envoi de mail, prend un certain temps, de même quune écriture pour un traitement de fichier conséquent, 

Il existe une annotation permettant de redéfinir la durée de ce timeout : @AccessTimeout

@Singleton
@AccessTimeout(-1)
public class MailSender 

Dans cet exemple, nous définissons un timeout à -1, cest à dire aucun timeout, la requête sera donc sérialisée, jusquà ce quelle soit traitée.

Cette valeur de -1 peut paraître attrayante, mais il est possible que votre conteneur dEJB, nautorise pas la valeur -1. Cest par exemple le cas de JBoss7, qui reprend la valeur par défaut (5000 ms) si on lui donne -1 comme valeur.

Il convient alors de donner une valeur réelle et finie au timeout, nous allons voir ci-dessous comment préocéder.

On peut également définir les valeurs suivantes : 

@AccessTimeout(0) signifiera quune réquête ne pourra pas être sérialisée. Elle devra donc être exécutée tout de suite si le Singleton est libre, sinon elle sera perdue

@AccessTimeout(value=30, unit = TimeUnit.SECONDS) signifiera que la requête sera sérialisée pendant 30 secondes.

Attention tout de même à lutilisation de ce AccessTimeout qui est à paramétrer selon lutilisation et la durée du traitement qui sera effectué par votre singleton ou votre bean.