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

Glassfish et Payara Java Discussion :

Transactions : pas de rollback après une exception levée


Sujet :

Glassfish et Payara Java

  1. #1
    Membre averti
    Avatar de if_zen
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2004
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 275
    Points : 316
    Points
    316
    Par défaut Transactions : pas de rollback après une exception levée
    Bonjour à tous,

    En considérant l'algorithme suivant :

    EjbA.creerPersonne(Personne p) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    - Paramétrer p
    - Appeler EjbB.creerEntreprise(p.getEntreprise())
    - Sauvegarder p
    - XXX
    - Retourner p
    EjbB.creerEntreprise(Entreprise e) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    - Paramétrer e
    - Sauvegarder e
    - retourner e
    Je suis sur Glassfish 301.

    J'ai cru comprendre, grosso modo, que les transactions étaient gérées "automatiquement" à l'appel des méthodes EJB (j'utilise l'EntityManager au fait pour mes connexions à la base de données). Je n'utilise pas de TransactionAttribute sur ma méthode ou ma classe, donc il semblerait que l'attribut utilisé par défaut soit REQUIRED.

    En supposant que je lève une exception à la ligne que j'ai notée XXX ci-dessus, j'ai pas mal de problèmes qui apparaissent :

    - L'objet Entreprise créé est persisté en base, donc pas de rollback sur sa création.
    - Pareil pour l'objet Personne
    - Mes deux objets utilisent une table séquence pour leur ID (@GeneratedValue(strategy = GenerationType.TABLE) : L'objet est inséré mais l'ID n'est pas mis à jour dans ma table séquence. Cela signifie que je dois faire un update à la main pour rattraper le tir, sinon j'ai un duplicate exception. Il semblerait que le Rollback soit donc fait sur les tables séquences, mais pas sur les entités.

    Est-ce que quelqu'un pourrait m'expliquer ce qui ne va pas ? Je dois écrire quoi pour que mes transactions soient correctement gérées, et surtout que mes tables "séquence" restent bien synchronisées avec les objets qu'elles gèrent ?

    En vous remerciant par avance.

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Ci-joint un extrait de la doc oracle sur les transactions avec les EJB.
    There are two ways to roll back a container-managed transaction. First, if a system exception is thrown, the container will automatically roll back the transaction. Second, by invoking the setRollbackOnly method of the EJBContext interface, the bean method instructs the container to roll back the transaction. If the bean throws an application exception, the rollback is not automatic, but may be initiated by a call to setRollbackOnly. For a description of system and application exceptions, see Handling Exceptions.

  3. #3
    Membre averti
    Avatar de if_zen
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2004
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 275
    Points : 316
    Points
    316
    Par défaut
    Merci fr1mann pour cette réponse, je vais étudier le fonctionnement de cette méthode, parce que je ne vois pas trop comment l'utiliser :
    - en début de méthode mes objets ne seraient pas persistés
    - avant de lever l'exception, les objets sont déjà persistés

    Ou alors j'utilise em.flush() trop tôt...
    En fait mon "Sauvegarder" correspond à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    em.persist(t);
    em.flush();
    em étant mon EntityManager.

    Edit :
    En fait il semble qu'il ne soit pas prévu de Rollback du tout pour les exceptions "faites maison" (http://java.sun.com/j2ee/tutorial/1_...MP6.html#63681), mais dans ce cas, il reste le problème de la synchronisation de ma table sequence avec mes tables entités.

    Et puis c'est pas normal que mon objet "Entreprise" soit créé en base à la ligne XXX ; il ne peut plus y avoir de rollback du coup

  4. #4
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Si ce n'est pas une exception système, il n'y a pas de rollback automatique, tu seras donc obligé d'utiliser la méthode setRollbackOnly de ton EJB.

    Sinon, tu transformes ton exception.

    Le flush exécute les insctructions SQL, normal que tu vois tes données en base.
    Tu peux le virer pour qu'il ait lieu au commit de la transaction de ton EJB.

  5. #5
    Membre averti
    Avatar de if_zen
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2004
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 275
    Points : 316
    Points
    316
    Par défaut
    Re,

    Merci pour ces précisions, je suis en train d'adapter mon traitement pour ne plus appeler les flush ; par contre, un souci vient s'ajouter du coup. Lorsque j'accède à une collection d'un objet nouvellement créé, je n'ai pas une liste vide, comme c'était le cas lorsque je faisais un flush, mais null. Du coup, je trouve cela pas très pratique à gérer ; est-ce que je passe à côté de quelque chose ou est-ce normal ? A la rigueur je pourrais faire un merge() après le persist(), mais j'ai peur que ça alourdisse les traitements au final.

    Merci pour les précision et désolé pour la petite déviation du sujet principal, c'est un deuxième effet kiss cool...

  6. #6
    Membre averti
    Avatar de if_zen
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2004
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 275
    Points : 316
    Points
    316
    Par défaut
    Rebonsoir,

    Bon alors mis à part le dernier problème que j'ai soulevé (j'ai fait un merge() sur mon nouvel objet pour pouvoir accéder à sa collection et y ajouter un nouvel élément), j'ai réussi à me dépatouiller !

    Il fallait déjà que je supprime les appels aux flush() évidemment, après tout est rentré dans l'ordre en fait ! L'exception que je levais étant une IllegalArgumentException (donc une RuntimeException), je n'ai pas eu à avoir à faire de rollback manuel.

    Un truc qui me chagrine quand même pas mal, c'est que le flush() enregistre bien les objets Entity mais il ne met pas à jour la séquence lorsque son ID repose sur une telle table. Je ne trouve pas cela logique et ça sent le bug, faudrait que je vérifie si ça le fait toujours sur la version 3.1.

  7. #7
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Ce que tu peux faire, c'est initialiser une nouvelle collection dans ton entity, pour éviter d'avoir un null.

    Pour ta séquence, je ne sais pas. J'utilise plutôt le type GenerationType.SEQUENCE et là, on a rien à faire, mais il n'est peut-être pas compatible avec ta base de données.

  8. #8
    Membre averti
    Avatar de if_zen
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juin 2004
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 275
    Points : 316
    Points
    316
    Par défaut
    Bonjour fr1man,

    Merci beaucoup pour ton aide, je passe en résolu :-) Effectivement le schéma de ma base de données ne me permet pas de changer de stratégie.

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

Discussions similaires

  1. Corriger le traitement aprés une Exception
    Par gatua dans le forum C++
    Réponses: 13
    Dernier message: 24/01/2008, 18h58
  2. Comment continuer un pgr apres une exception ?
    Par stan314 dans le forum Général Python
    Réponses: 1
    Dernier message: 30/09/2007, 18h03
  3. Réponses: 1
    Dernier message: 11/10/2006, 16h24
  4. Réponses: 6
    Dernier message: 28/08/2006, 17h02
  5. Expliciter une exception levée par un objet OLE
    Par Bleuarff dans le forum Windows
    Réponses: 3
    Dernier message: 12/05/2005, 16h10

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