Exceptions d'application

Les exceptions d'application alertent le client de problèmes spécifiques à l'application ou ayant trait à la logique métier ; ils ne rapportent pas les exceptions relevant du système. Cette rubrique décrit brièvement comment les exceptions d'application sont définies et donne des exemples de l'annotation @ApplicationException et de l'élément qui lui correspond dans le descripteur de déploiement, application-exception.

Définition d'une exception d'application

Le fournisseur d'Enterprise JavaBeans (EJB) définit les exceptions de son application en même temps que sa logique métier. Les exceptions d'application ne servent pas à rapporter les erreurs de niveau système (les exceptions système sont là pour ça). Elles sont au contraire utilisées par les méthodes métier pour signaler au client toute activité entreprise au niveau de l'application et qui est susceptible de provoquer une erreur ; par exemple, des valeurs d'argument non valides sont passées à une méthode métier. Dans la plupart des cas, le client peut retrouver un état de traitement normal après avoir été confronté à une exception de l'application.

Vous pouvez définir une exception d'application dans la clause throws d'une méthode. La méthode que vous utilisez pour définir l'exception d'application peut être celle d'une interface métier, d'une vue sans interface, d'une interface home, d'une interface de composant, d'une interface d'écouteur de message ou du point d'extrémité de service Web du bean enterprise (EJB). Au moment de définir l'exception, n'oubliez pas qu'une exception d'application peut être :

  • Une sous-classe, directe ou indirecte, de java.lang.Exception, classe mère qui produit une exception contrôlée.
  • Une sous-classe de java.lang.RuntimeException, classe qui produit une exception non contrôlée.
Avertissement : Vous ne pouvez pas définir une exception d'application comme sous-classe de java.rmi.RemoteException, car cette dernière, ainsi que ses sous-classes, sont réservées aux problèmes qui relèvent du système.

Les exceptions d'application standard suivantes, ainsi que leurs sous-classes, sont utilisées pour rapporter les erreurs au client :

  • javax.ejb.CreateException
  • javax.ejb.RemoveException
  • javax.ejb.FinderException

Les exceptions d'application citées plus haut sont définies respectivement dans les méthodes de création (create), de suppression (remove) et de localisation (findXXX) de l'interface EJBHome, de l'interface EJBLocalHome ou des deux. Ces interfaces proviennent de composants relativement anciens puisque leur écriture remonte à la spécification du client EJB 2.1.

Dans la spécification EJB 3.0, l'annotation @ApplicationException n'avait qu'un seul paramètre optionnel d'annulation (rollback). L'élément application-exception correspondant n'avait qu'un seul sous-élément optionnel, rollback, qui pouvait être mis à true ou false. Ce paramètre et le sous-élément correspondant étaient utilisés pour préciser si la transaction était marquée pour annulation. Leur valeur par défaut était false. L'héritage d'une exception d'application ne pouvait pas être spécifié et il n'y avait donc pas moyen de lui donner une valeur par défaut explicite. Dans notre produit WebSphere, l'implémentation de la spécification EJB 3.0 ne fournissait pas de mécanisme d'héritage d'une exception d'application, mis à part si l'exception était définie dans la clause throws d'une méthode métier d'un bean. Par opposition, la spécification EJB 3.1 introduit le paramètre optionnel inherited dans l'annotation @ApplicationException et le sous-élément optionnel inherited dans l'élément correspondant du descripteur de déploiement, application-exception. Par défaut, le fait de marquer une exception comme exception d'application désigne également comme exceptions d'application toutes les sous-classes de cette exception (autrement dit, inherited=true). Vous pouvez invalider ce comportement d'héritage en mettant à false le paramètre inherited de l'annotation @ApplicationException. De même, dans le descripteur de déploiement, vous pouvez invalider le comportement d'héritage en mettant à false le sous-élément inherited de l'élément application-exception. Pour plus d'informations sur les exceptions d'application, reportez-vous à la section 14.1.1 de la spécification EJB 3.1.

Exemple : Héritage entre exceptions d'application - Utilisation d'annotations

import javax.ejb.ApplicationException;

@ApplicationException(inherited=true, rollback=true)
public class RTExceptionA extends RuntimeException{

   //RTExceptionA
   
}
public class RTExceptionB extends RTExceptionA{

   //RTExceptionB

}
import javax.ejb.ApplicationException;

@ApplicationException(inherited=false, rollback=false)
public class RTExceptionC extends RTExceptionB{

   //RTExceptionC

}
public class RTExceptionD extends RTExceptionC{

   //RTExceptionD 
   
}

L'exemple précédent produit les résultats suivants :

  • RTExceptionA est une exception d'application avec annulation de la transaction.
  • RTExceptionB est une exception d'application avec annulation de la transaction.
  • RTExceptionC est une exception d'application sans annulation de la transaction.
  • RTExceptionD n'est pas une exception d'application.

Exemple : Héritage entre exceptions d'application - Utilisation de XML

public class RTExceptionA extends RuntimeException{

   //RTExceptionA
   
}
public class RTExceptionB extends RTExceptionA{

   //RTExceptionB

}
public class RTExceptionC extends RTExceptionB{

   //RTExceptionC

}
public class RTExceptionD extends RTExceptionC{

   //RTExceptionD 
   
}
<!-- Example ejb-jar.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_ID" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
    metadata-complete="true" version="3.1">
    <assembly-descriptor>
        <application-exception>
            <exception-class>myXML.example.package.RTExceptionA</exception-class>
            <rollback>true</rollback>
            <inherited>true</inherited>
        </application-exception>
        <application-exception>
            <exception-class>myXML.example.package.RTExceptionC</exception-class>
            <rollback>false</rollback>
            <inherited>false</inherited>
        </application-exception>
    </assembly-descriptor>
</ejb-jar> 

Comme dans la version annotée, l'exemple précédent produit les résultats suivants :

  • RTExceptionA est une exception d'application avec annulation de la transaction.
  • RTExceptionB est une exception d'application avec annulation de la transaction.
  • RTExceptionC est une exception d'application sans annulation de la transaction.
  • RTExceptionD n'est pas une exception d'application.
A faire : Vous pouvez utiliser les sous-éléments rollback et inherited de l'élément application-exception pour redéfinir explicitement les attributs rollback et inherited dont les valeurs ont été spécifiées, explicitement ou non, par l'annotation @ApplicationException.

Lorsque vous spécifiez une exception dans la clause throws d'une méthode métier d'un bean, l'exception contrôlée résultante est une exception d'application. Toutes les sous-classes de cette exception d'application sont également des exceptions d'application. Aucune option n'est prévue pour invalider ce comportement d'héritage des exceptions d'application contrôlées. Vous pouvez utiliser l'élément inherited pour déterminer la valeur de l'élément rollback des sous-classes de l'exception d'application contrôlée. Si l'élément inherited de l'exception mère est réglé à true et que son élément rollback est lui aussi à true, alors les sous-classes de cette exception d'application contrôlée héritent de la valeur rollback=true.

Reproduire le comportement d'héritage des exceptions d'application propre à EJB 3.0 :

Si vous avez une application EJB 3.0 et que vous souhaitez y préserver le comportement propre à cette version de la spécification (à savoir que les sous-classes d'une exception d'application ne sont pas elles-mêmes des exceptions d'application), les solutions suivantes s'offrent à vous :
  • Vous pouvez modifier l'annotation @ApplicationException de l'exception en y ajoutant l'attribut inherited avec la valeur false.
  • Vous pouvez ajouter un descripteur de déploiement version 3.1 et, dans l'élément application-exception de l'exception concernée, régler explicitement à false le sous-élément inherited. Si vous avez déjà un descripteur de déploiement version 3.0, vous devez le faire migrer vers un descripteur et un schéma XSD version 3.1 et attribuer explicitement la valeur false au sous-élément inherited.

Reproduire le comportement d'héritage des exceptions d'application propre à EJB 3.0 à l'aide d'annotations

Supposons que vous aviez jusqu'à présent le code suivant :

import javax.ejb.ApplicationException;

@ApplicationException()
public class EJB30_RTException extends RuntimeException{

   //EJB30_RTException, in EJB 3.0 subclasses were not application exceptions 
   
}

Vous devez modifier l'annotation @ApplicationException afin d'y inclure la paire attribut-valeur inherited=false :

import javax.ejb.ApplicationException;

@ApplicationException(inherited=false)
public class EJB30_RTException extends RuntimeException{

   //EJB30_RTException,  now you must explicitly set inherited to false to disable inheritance
   
}

Exemple : Reproduire le comportement d'héritage des exceptions d'application propre à EJB 3.0 à l'aide de XML

Supposons que vous aviez jusqu'à présent le code suivant :

<!-- Example ejb-jar.xml -->

<?xml version="1.0" encoding="UTF-8"?>
  <ejb-jar id="ejb-jar_ID" xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
      metadata-complete="true" version="3.0">
    <assembly-descriptor>
        <application-exception>
            <exception-class>myXML.example.package.EJB30_RTException</exception-class>
        </application-exception>
    </assembly-descriptor>
</ejb-jar> 

Vous devez modifier votre code afin d'y inclure l'élément inherited réglé sur false et le faire migrer vers un descripteur de déploiement et un schéma XSD version 3.1 :

<!-- Example ejb-jar.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_ID" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
    metadata-complete="true" version="3.1">
    <assembly-descriptor>
        <application-exception>
            <exception-class>myXML.example.package.EJB30_RTException</exception-class>
            <rollback>false</rollback>
            <inherited>false</inherited>
        </application-exception>
    </assembly-descriptor>
</ejb-jar> 

Icône indiquant le type de rubrique Rubrique de concept



Icône d'horodatage Dernière mise à jour: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=cejb_app_exception
Nom du fichier : cejb_app_exception.html