2009-10-03 2 views
4

J'utilise EJB3 sur Glassfish à l'aide du gestionnaire de persistance TopLink par défaut. Au sein d'un bean session, lorsque le gestionnaire de persistance intercepte une exception de base de données, il marque la transaction à annuler et lance une exception EJBException, qui enveloppe à son tour une exception RollbackException. Maintenant, je m'attendais à être en mesure d'obtenir l'exception jdbc originale à cause de l'exception de l'une de ces exceptions, mais ce n'est pas le cas.EJB3 Obtention d'erreurs JDBC d'origine

Il est important que je récupère l'exception d'origine, car j'ai besoin de rapporter aux utilisateurs quel est le problème, et pour ce faire, j'ai besoin d'analyser les codes d'erreur SQL.

Est-ce que quelqu'un sait s'il est possible d'obtenir cette information de Toplink? Ou si Hibernate le rend possible?

Merci,

Répondre

1

La seule façon que j'ai trouvé pour faire ce que je veux, est de forcer le gestionnaire à écrire sur la base de données en utilisant manager.flush(), puis d'attraper l'exception PersistenceException qui se produit. Je peux alors enregistrer l'erreur de base de données comme je veux, et lancer une exception EJBException pour forcer la restauration. Laissant le conteneur pour faire le flush semble perdre irrémédiablement tous les messages utiles avec TopLink.

+1

J'ai le même problème, pouvez-vous modifier votre réponse avec un échantillon de code? –

1

Bonne question, Ant

Je sais que vous voulez lancer une exception de base de données, mais quand il se produit l'application, dans la plupart du temps, ne parvient pas à rétablir son état initial ou il ne sait pas comment s'en remettre. Il doit donc être traité comme une exception d'exécution. Quelques problèmes dans la base de données des exceptions comprennent

    échec de la connexion de base de données
  • requête est mal
  • tableau
  • ou d'une colonne n'existe pas

Ci-dessus vous voyez l'application est pas être en mesure de rétablir l'état initial . Si vous pensez qu'il est possible de restaurer son état initial , vous devez utiliser une exception d'application. Le client recevra la même exception d'application générée par votre méthode métier. Si vous voulez être en mesure d'obtenir l'exception exacte lancée par votre méthode d'entreprise, vous avez deux choix:

  • Utilisez un motif de délégué commercial pour accéder à votre EJB

Comme vous le savez, exception d'exécution est enveloppées par un EDBException, de sorte que vous shold utiliser quelque chose comme

supposons que vous avez cette session bean sans état

@Stateless 
public class BeanImpl implements Bean { 

    public void doSomething() { 

     try { 
      // some code 
     } catch(SomeException e) { 
      throw new EJBException(e); 
     } 

    }   

} 

donc y OU envelopper votre grain de session par l'intermédiaire d'un délégué commercial

public class BeamBusinessDelegate implements Bean { 

    // your stateless session bean goes here 
    private Bean bean; 

    public BeamImpl() { 
     InitialContext i = new InitialContext(); 

     bean = (Bean) i.lookup(<GLOBAL_JNDI_ADDRESS_OR_RELATIVE_ENVIRONMENT_NAMING_CONTEXT_ADDRESS>); 
    } 

    public void doSomething() { 
     try { 
      bean.doSomething() 
     } catch(EJBException e) { 
      throw e.getCause(); 
     } 
    } 
} 

Ou vous pouvez étend EDBException selon vos besoins

public class DatabaseException extends EJBException { 

} 

Donc, dans votre méthode d'affaires

@Stateless 
public class BeanImpl implements Bean { 

    public void doSomething() { 

     try { 
      // some code 
     } catch(SomeException e) { 
      throw new DatabaseException(); 
     } 

    }   

} 

Cordialement,

+0

Salut - merci pour la réponse. Vos exemples démontrent à peu près exactement ce que nous faisons déjà. Je pense que vous avez mal compris mon problème. Le problème est que Toplink, gestionnaire de persistance par défaut de Glassfishes, n'inclut pas la cause d'origine dans le champ 'cause' de l'exception EJBException. Donc ma question est vraiment, y at-il un moyen d'obtenir Toplink pour inclure la cause correctement, ou Hibernate fait-il mieux? –

+0

Oh - et il semble aussi qu'il n'était pas clair que ce n'est pas mon code qui lève l'exception - nous utilisons Entity Beans pour conserver les données, et c'est le gestionnaire de persistance qui lance l'exception EJBException qui enveloppe une exception RolledbackException pas avoir sa cause définie. –

+0

Ant, JPA est une abstraction de niveau supérieur au-dessus de JDBC. Je pense que vous ne pouvez pas accéder à la couche JBDC sous-jacente. Après avoir vu PersistenceException - http://www.oracle.com/technology/products/ias/toplink/jpa/resources/javadoc/javax/persistence/PersistenceException.html - exception racine de l'API Java Persisntece, il ne vous fournit pas un moyen dans lequel vous pouvez accéder à la couche JDBC sous-jacente, donc je pense que ce n'est pas possible. –

3

J'ai eu le même problème. J'ai fini par utiliser la méthode d'intercepteur AroundInvoke, de cette façon vous pouvez attraper n'importe quelle exception du côté du serveur, et extraire toutes les informations que vous voulez et les recouvrir pour lancer votre propre exception, et configurer EjbContext pour annuler la transaction.

Je peux vous donner un exemple si vous ne vous présentez pas correctement.

+1

Je n'avais jamais rencontré d'intercepteurs auparavant, mais j'ai juste fait quelques lectures autour d'eux, et ça ressemble au genre de chose que je veux. Cependant, il semble que je puisse définir des Intercepteurs pour les méthodes commerciales et pour les événements de cycle de vie, mais aucun d'entre eux ne semble être tout à fait ce que je veux, puisque les méthodes que je veux intercepter sont dans l'EntityManager. Quelques autres pointeurs seraient reçus avec reconnaissance! –