3 votes

Rollback transaction à l'intérieur du managed bean

Je voudrais annuler une transaction non pas dans un EJB mais dans un bean géré par JSF. Dans l'EJB, nous pouvons utiliser SessionContext.setRollBackOnly() mais que puis-je utiliser dans le managed bean ?

@Stateless
@Local(AccountLocal.class)
public class AccountBean implements AccountLocal {

   public void test1() throws CustomException(){
      ...
   } 

   public void test2() throws CustomException(){
      ...
      throw new CustomException();
   }   

   public void test3() throws CustomException(){
      ...
   }

   public void all() throws CustomException(){
       test1();
       test2();
       test3();
   } 

}

Dans mon haricot géré :

@SessionScoped
public class LoginBean implements Serializable{

   public void test(){

      try{
         accountBean.test1();
         accountBean.test2();
         accountBean.test3();
      }catch(CustomException e){
         // WHAT HERE TO ROLLBACK TRANSACTION ?
      }      
    }    
}

EDIT : Comment puis-je m'assurer que si l'un des test1 , test2 o test3 les autres vont aussi reculer ?

J'ai testé ce code et accountBean.test1(); est validé même si accountBean.test2(); roule en arrière.

La solution ne serait-elle pas d'imbriquer ces 3 méthodes dans une seule méthode EJB ?

 @SessionScoped
public class LoginBean implements Serializable{

   public void test(){

      try{
         accountBean.all();
      }catch(CustomException e){
        ...
      }      
    }    
}

5voto

BalusC Points 498232

Les transactions sont automatiquement annulées par le conteneur EJB si une exception non vérifiée est levée (notez que l'exception JPA PersistenceException en est un). Votre CustomException semble être une exception vérifiée. Si vous le modifiez pour étendre RuntimeException comme suit

public class CustomException extends RuntimeException {
    // ...
}

ou la création d'un nouveau n'est pas une option, alors vous devez définir l'adresse de l'utilisateur. @ApplicationException sur la classe avec l'annotation rollback défini comme suit true .

Par exemple

@ApplicationException(rollback=true)
public class CustomException extends Exception {
    // ...
}

Veuillez noter que le problème concret n'a rien à voir avec JSF. La couche service et la gestion des transactions sont complètement en dehors de la responsabilité du JSF. C'est plutôt la responsabilité d'EJB. JSF devrait simplement agir en tant que "vue" dans cette perspective.

Voir aussi :

1voto

Mike Braun Points 2729

Je me fais l'avocat du diable ici, car le conseil de BalusC selon lequel vous ne devriez pas laisser vos haricots de sauvegarde agir comme des services est absolument vrai.

Mais, à titre purement technique, il est possible de démarrer une transaction JTA dans un backing bean, puis de contrôler le démarrage et le commit ou le rollback de manière programmatique.

Vous pouvez le faire en injectant un UserTransaction via @Resource. Avant d'appeler vos méthodes EJB, appelez start sur cette instance, et après le dernier appel, faites un commit ou un rollback.

Encore une fois, il s'agit d'une réponse purement théorique . En pratique, ne faites pas cela et laissez le backing bean appeler une méthode EJB qui appelle d'autres EJB beans si nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X