Précédent   Forum des professionnels en informatique > Java > Général Java > Persistance > JPA
JPA Forum d'entraide sur l'API de persistance JPA (Java Persistence API)
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 05/01/2012, 17h14   #1
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 77
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 77
Points : 39
Points : 39
Par défaut Rollback d'une transaction dans @PostPersist

Bonjour,

Je souhaite annuler (rollback) une transaction dans la callback @PostPersist d'une entité. Mon but est de vérifier des paramètres et, si ils ne sont pas bon, d'annuler la transaction pour que l'objet en question ne soit pas enregistré.

J'ai lu sur un site l'information suivante :
Citation:
If a callback method throws an exception within an active transaction, the transaction is marked for rollback and no more callback methods are invoked for that operation.
Cependant lorsque je lance une exception dans ma méthode j'obtiens l'erreur suivante:
Code :
1
2
3
4
5
6
7
8
9
10
....
Caused by: javax.transaction.RollbackException: Transaction marked for rollback.
	at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:473)
	at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:852)
	at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5114)
	... 37 more
Caused by: java.lang.ClassCastException: java.lang.Exception cannot be cast to java.lang.Error
	at org.eclipse.persistence.internal.jpa.metadata.listeners.EntityListener.invokeMethod(EntityListener.java:257)
	at org.eclipse.persistence.internal.jpa.metadata.listeners.EntityClassListener.invokeMethod(EntityClassListener.java:75)
	at org.eclipse.persistence.internal.jpa.metadata.listeners.EntityListener.postInsert(EntityListener.java:344)
La transaction est bien annulée mais par l'exception :
Code :
Caused by: java.lang.ClassCastException: java.lang.Exception cannot be cast to java.lang.Error
et pas par mon exception à moi.

Pour l'instant mon code se limite à :
Code :
1
2
3
4
@PostPersist
private void test() throws Exception {
    throw new Exception("test");
}
Comment faut-il faire pour annuler proprement une transaction dans une callback?
piemur2000 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2012, 18h02   #2
Membre éprouvé
 
Homme Philippe BASTIANI
Architecte technique
Inscription : juin 2005
Messages : 257
Détails du profil
Informations personnelles :
Nom : Homme Philippe BASTIANI
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Architecte technique
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : juin 2005
Messages : 257
Points : 487
Points : 487
Bizarre ton ClassCastException!!!

Pour info c'est une RuntimeException et plus précisément un PersistenceException que l'implémentation JPA lance...

Normalement la transaction ne doit pas être terminée donc tu devrais pouvoir retrouver la transaction en cours et faire un rollback...

A tester avec l'EntityManager utilisé dans ta transaction:
Code :
1
2
3
4
5
6
EntityManager em = getEntityManagerUsedInTransaction();
EntityTransaction et = em.getTransaction();
if (et.isActive() ) {
    // tes tests puis si nécessaire
    et.rollback()
}
Meilleurs vœux,
Philippe
Philippe Bastiani est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2012, 11h11   #3
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 77
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 77
Points : 39
Points : 39
Ça à l'air pas mal en effet mais je fais comment pour récupérer l'entity manager dans mon entité?

Je suis dans un projet Java EE sous NetBeans et j'utilise l'annotation @PersistenceContext dans mes SessionBean. Mais dans l'entité je ne peux pas utiliser l'annotation @PersistenceContext.
piemur2000 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2012, 16h53   #4
Membre éprouvé
 
Homme Philippe BASTIANI
Architecte technique
Inscription : juin 2005
Messages : 257
Détails du profil
Informations personnelles :
Nom : Homme Philippe BASTIANI
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Architecte technique
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : juin 2005
Messages : 257
Points : 487
Points : 487
Via jndi lookup... Ou plus simplement avec un listener...

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Entity 
@EntityListeners({TonListener.class})
MonEntite {...}
 
public class TonListener{ 
public EntityRefresher() {}
 
private static EntityManager em = null;
 
public static void setEntityManager(EntityManager entityManager) 
{ 
em = entityManager; 
}
 
@PostPersist 
public void tonTraitement(Object entity) {
// ton traitement
}
}
 
Dans ta classe de service:
TonListener.setEntityManager(em);
Mais, après réflexion, pour des raisons de portabilité, je me demande si c'est une bonne idée (c.f. le JSR317):

3.5 Entity Listeners and Callback Methods (JSR 317: JavaTM Persistence API, Version 2.0):

The following rules apply to lifecycle callbacks:
• Lifecycle callback methods may throw unchecked/runtime exceptions. A runtime exception thrown by a callback method that executes within a transaction causes that transaction to be marked for rollback.
• Lifecycle callbacks can invoke JNDI, JDBC, JMS, and enterprise beans.
In general, the lifecycle method of a portable application should not invoke EntityManager or Query operations, access other entity instances, or modify relationships within the same persistence context.[43] A lifecycle callback method may modify the non-relationship state of the entity on which it is invoked.

Je n'ai pas trouvé d'explication sur le problème de cast initial ! Mais tu noteras qu'il ne faut pas lancer de checked exceptions dans les callbacks ! Seules les RuntimeExceptions sont possibles...

Citation:
Envoyé par piemur2000 Voir le message
Je souhaite annuler (rollback) une transaction dans la callback @PostPersist d'une entité. Mon but est de vérifier des paramètres et, si ils ne sont pas bon, d'annuler la transaction pour que l'objet en question ne soit pas enregistré.
Dans tous les cas annuler une transaction ici n'est pas une bonne idée (les entités sont déjà en base)... tu devrais donc agir en amont !
Philippe Bastiani est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h12.


 
 
 
 
Partenaires

Hébergement Web