IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java EE Discussion :

Restauration du Timer avant deploiement d'un EJB [EJB Timer]


Sujet :

Java EE

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 34
    Points
    34
    Par défaut Restauration du Timer avant deploiement d'un EJB
    Bonjour à tous,

    Je déclare un Timer dans une méthode et j'attend l'exécution du Timer dans une autre méthode annoté @Timeout. Tout fonctionne sauf la restauration de mon Timer lors d'un reboot de mon AS.

    Le problème est que lorsque le Stateless est redéployé, le Timer est expiré et il est donc automatiquement déclenché or le Stateless inject un EJB qui à ce moment n'a pas encore été déployé. J'ai donc une erreur et mon Timer n'est pas restauré...

    Quelqu'un aurait-il une solution ?

    Voici ma classe qui créer et gère le Timer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    @Stateless
    @WebService(name = "MyWebService_001", serviceName = "MyWebService_001")
    public class MyWebService {
    	private static final Logger logger = Logger
    			.getLogger(MyWebService.class);
     
    	@EJB
    	private MyManagerRemote myManagerRemote;
     
    	@Resource
    	private TimerService timerService;
     
     
    	@Timeout
    	@WebMethod(exclude = true)
    	public void processTimer(Timer timer) {
    		if(logger.isTraceEnabled())
    			logger.trace("Blabla");
     
    	}
     
    	public Boolean processSync(
    			@WebParam(name = "externalId") Long externalId,
    			@WebParam(name = "control") ControlDTO controlDTO) {
    		try {
    			myManagerRemote.processSync(externalId, controlDTO);
     
    			if(logger.isTraceEnabled())
    				logger.trace("Création du timer");
    			timerService.createTimer(30000, null);
     
     
    			return Boolean.TRUE;
    		} catch (Exception e) {
    			logger.error("Erreur", e);
    			return Boolean.FALSE;
    		}
    	}
    Voici ici mon erreur plutot clair :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    2012-01-26 16:32:16,627 INFO  [org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-21-thread-1) Timer: [id=0dbdfc03-fb0e-4326-a7cc-b9e46768fb37 timedObjectId=jboss.j2ee:ear=bss.deployment.banking.ear-0.0.1-SNAPSHOT.ear,jar=bss.module.banking.service.impl-0.0.1-SNAPSHOT.jar,name=MyWebService,service=EJB3 auto-timer?:false persistent?:true timerService=org.jboss.ejb3.timerservice.mk2.TimerServiceImpl@37fb87e4 initialExpiration=2012-01-26 16:31:39.663 intervalDuration(in milli sec)=0 nextExpiration=null timerState=IN_TIMEOUT will be retried
    2012-01-26 16:32:16,627 INFO  [org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-21-thread-1) Retrying timeout for timer: [id=0dbdfc03-fb0e-4326-a7cc-b9e46768fb37 timedObjectId=jboss.j2ee:ear=bss.deployment.banking.ear-0.0.1-SNAPSHOT.ear,jar=bss.module.banking.service.impl-0.0.1-SNAPSHOT.jar,name=MyWebService,service=EJB3 auto-timer?:false persistent?:true timerService=org.jboss.ejb3.timerservice.mk2.TimerServiceImpl@37fb87e4 initialExpiration=2012-01-26 16:31:39.663 intervalDuration(in milli sec)=0 nextExpiration=null timerState=IN_TIMEOUT
    2012-01-26 16:32:16,632 ERROR [org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-21-thread-1) Error during retyring timeout for timer: [id=0dbdfc03-fb0e-4326-a7cc-b9e46768fb37 timedObjectId=jboss.j2ee:ear=bss.deployment.banking.ear-0.0.1-SNAPSHOT.ear,jar=bss.module.banking.service.impl-0.0.1-SNAPSHOT.jar,name=MyWebService,service=EJB3 auto-timer?:false persistent?:true timerService=org.jboss.ejb3.timerservice.mk2.TimerServiceImpl@37fb87e4 initialExpiration=2012-01-26 16:31:39.663 intervalDuration(in milli sec)=0 nextExpiration=null timerState=RETRY_TIMEOUT: javax.ejb.EJBException: org.jboss.injection.manager.spi.InjectionException: javax.naming.NamingException: Could not dereference object [Root exception is javax.naming.NamingException: Could not dereference object [Root exception is javax.naming.NameNotFoundException: MyManager not bound]]

  2. #2
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    Bonjour,
    Est-ce qu'on ne peut pas mettre un delay sur le timer pour qu'il ne démarre pas trop vite ?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 34
    Points
    34
    Par défaut
    Bonjour et merci de ta réponse,

    J'ai bien essayé de regarder de ce coté mais je n'ai rien trouvé, je continue mes recherches...

  4. #4
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    et avec un timer persistant ?

  5. #5
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut Autre idée : changer d'architecture
    Peut-être que les MDB correspondraient à ton besoin : tu envoies un message qui sera timestampé et pourra être interprété seulement après un délai fixé d'expiration "interne" contrôlé par le récepteur.
    Si le MOM garantit que le message ne se perde pas (mode persistant), c'est bon.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 34
    Points
    34
    Par défaut
    Justement le timer est déjà persisté puisqu'une tentative de restauration est faite lorsque je redéploie mon module.

    Les MDB sont une solution mais je vais devoir redévelopper un TimerService-like alors que le service existe déjà.

    J'essaie de modifier la valeur du mbean :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
       <mbean code="org.jboss.ejb.txtimer.FixedDelayRetryPolicy" name="jboss.ejb:service=EJBTimerService,retryPolicy=fixedDelay">
         <attribute name="Delay">100</attribute>
       </mbean>
    à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
       <mbean code="org.jboss.ejb.txtimer.FixedDelayRetryPolicy" name="jboss.ejb:service=EJBTimerService,retryPolicy=fixedDelay">
         <attribute name="Delay">5000</attribute>
       </mbean>

    Mais le retry de restauration du timer se fait sans délai.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    2012-01-27 10:21:05,847 INFO  [org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-17-thread-1) Timer: [id=f102692f-dd5f-472e-8ac1-0f48daae2aab timedObjectId=jboss.j2ee:ear=bss.deploym ...... BLA BLA BLA .... intervalDuration(in milli sec)=0 nextExpiration=null timerState=IN_TIMEOUT will be retried
    2012-01-27 10:21:05,847 INFO  [org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-17-thread-1) Retrying timeout for timer: [id=f102692f-dd5f-472e-8ac1-0f48daae2aab timedObjectId=jboss.j2ee:ear=bss.deployment.banking.ear-0.0.1-SNAPSHOT.ear,jar=bss.module.banking.service.impl-0.0.1-SNAPSHOT.jar,name=MyWebService,service=EJB3 auto-timer?:false persistent?:true timerService=org.jboss.ejb3.timerservice.mk2.TimerServiceImpl@569421aa initialExpiration=2012-01-27 10:20:45.391 intervalDuration(in milli sec)=0 nextExpiration=null timerState=IN_TIMEOUT
    J'imagine que quelque chose m'échappe mais je ne vois pas encore quoi.

    En tout cas merci de tes réponses.

  7. #7
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    OK... je commence (lentement) à piger...
    Est-ce que le timeout est si important, au fond ? Il y a peut-être un signal externe, sur la ressource purgée, qui pourrait déclencher la méthode ?


    @EJB
    private MyManagerRemote myManagerRemote;
    => le timer ne devrait-il pas invoquer une méthode de cet EJB-ci ? Au lieu d'une méthode "locale" stateless ? Elle ne pourrait être invoquée qu'après instanciation, je suppose.

  8. #8
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    Peut-être que tu peux réclamer l'EJB "remote" auprès du contexte dans la méthode, aussi. Comme ça tu ne dépends pas de l'injection.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 34
    Points
    34
    Par défaut
    En fait lorsque processSync fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    			timerService.createTimer(30000, null);
    La méthode se déclare un timer qui à la fin de son délai exécute la méthode annotée @Timeout se trouvant dans le même bean.

    Donc lorsque je redéploie mon EAR, le timer est arrivé à son terme, disons 1min avant, donc la restauration déclenche le traitement du timer(= appel à la méthode annotée @Timeout) tout de suite, dès l'installation de mon Stateless MyWebService.

    Le problème est que ce Stateless inject un myManagerRemote, qui se trouve dans le même EAR mais qui est "installé" après MyWebService et donc l'injection me renvoie une erreur du type MyManagerRemote not bound car dès l'appel à une méthode dans MyWebService, l'injection est effectuée.

    Est-ce plus clair ?

    Une solution serait de pouvoir définir l'ordre d'installation des beans de mon EAR.

  10. #10
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    En fait lorsque processSync fait :
    timerService.createTimer(30000, null);
    La méthode se déclare un timer qui à la fin de son délai exécute la méthode annotée @Timeout se trouvant dans le même bean.
    Nous sommes bien d'accord.
    Mais ne serait-ce pas à l'EJB "remote" d'indiquer à l'EJB Stateless qu'il en a terminé ?.. Avec un p'tit message persistant, par exemple...

    Une solution serait de pouvoir définir l'ordre d'installation des beans de mon EAR.
    C'est possible sur des beans @Singleton. Peut-être que l'EJB "remote" mériterait d'être un singleton.
    Je crois que la meilleure façon de déclencher ou d'attendre le déploiement de cet EJB est encore de le demander explicitement en début de méthode : tu es sûr de ne pas passer devant ;-)

  11. #11
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    En fait, je pense au scenario suivant :

    On effectue un traitement (purge) et on envoie un message dans une queue persistante pour signaler qu'on a terminé.
    Là, il y a un redémarrage (mais ça n'est pas systématique, si j'ai bien compris).
    Un EJB @Startup écoute la queue et trouve une demande de reprise ; il récupère les ressources nécessaires et exécute le post-traitement en faisant appel à un EJB Stateless.
    L'EJB Stateless, qui est soit déjà à l'écoute, soit a été mis à l'écoute au démarrage, reçoit sa petite demande après avoir été initialisé.

    NB : il existe des paramètres spécifiques aux différentes implémentations du fournisseur qui permettent de retarder la livraison des messages (time to delivery).

    Je comprends que le truc bizarre, c'est de ne pas avoir l'injection, même avec un timeout plus long... Le truc, c'est que comme c'est un EJB "stateless", justement, j'imagine que le conteneur ne s'embarrasse pas de son état. Les EJB injectés font partie de l'état ! Et si tu passais en "stateful" ?

  12. #12
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut Au temps pour moi...
    Pas de timer sur un stateful !
    ET pas d'injection par constructeur non plus !

    Je ne vois que le pulling auprès du contexte.
    Mais c'est quand même bizarre, cette histoire... Le conteneur est bien sensé instancier l'EJB, injecter les dépendances PUIS passer le bean au service timer. Que produit un log dans @PostConstruct des différents beans ?

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 34
    Points
    34
    Par défaut
    J'ai trouvé une solution, pas la plus élégante mais cela fonctionne bien :

    Soit annoté la classe de:
    @Depends(value = "jboss.j2ee:ear=bss.deployment.mymodule.ear-0.0.1-SNAPSHOT.ear,jar=bss.module.mymodule.service.impl-0.0.1-SNAPSHOT.jar,name=MyManager,service=EJB3")

    Soit l'équivalent dans le jboss.xml : la base <depends>

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Servlet][EJB3] deploiement d'un EJB
    Par AlxAlpha dans le forum Services Web
    Réponses: 0
    Dernier message: 25/02/2011, 22h24
  2. Construction d'un contexte au deploiement d'un ejb
    Par Heimdal dans le forum Java EE
    Réponses: 0
    Dernier message: 24/06/2009, 15h21
  3. Réponses: 5
    Dernier message: 21/02/2008, 17h47
  4. Exception au deploiement d'EJB
    Par ChristianVial dans le forum Wildfly/JBoss
    Réponses: 4
    Dernier message: 29/09/2006, 18h07
  5. [Jonas] prb de deploiement EJB
    Par Alec6 dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 13/12/2004, 12h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo