Sauter au contenu

Gestion des erreurs avec “BPEL Error Hospital”

20 juillet 2009

Oracle BPEL Error Hospital est un framework qui est apparu avec Oracle SOA Suite 10.1.3.3. Il permet de gérer l’ensemble des erreurs techniques qui ont lieu lors de l’exécution des flux BPEL.

Lorsque vous utilisez BPEL Error Hospital, vous ne gérez plus les erreurs au niveau flux à l’aide de branches catch ou catchAll, mais vous les externalisez dans un composant spécifique sur le serveur. Vous pouvez ainsi définir la même gestion des erreurs pour l’ensemble des flux d’un domaine ou pour un ensemble de flux définis dans une liste. Vous disposerez alors de traitements globaux de gestion des erreurs.

La première application consiste sans doute à récupérer les erreurs intervenant lors de l’appel des services web tiers ou plus généralement une erreur détectée dans une activité  Invoke. BPEL Error Hospital va alors pouvoir initialiser un traitement spécifié dans un fichier sur le serveur et, lui même déclencher un large spectre de réponse : interaction humaine via la Console BPEL, relance du flux, exécution d’un code Java, etc.

Comment paramètrer Oracle BPEL Error Hospital ?

Note:
Lorsque vous utilisez BPEL Error Hospital pour gérer les erreurs BPEL, les branches catch et catchAll du flux ne sont plus déclenchées. Il est néanmoins possible de déclencher les directives de gestion des erreurs du flux en relançant les exceptions depuis le framework grace à un  “rethrow”.

Mettre en place ce type de gestion des erreurs est très simple. Il faut :

  • Modifier le fichier fault-binding.xml sur le serveur pour déclarer la configuration de “BPEL Error Hospital” qui doit être utilisée
  • Créer un fichier qui contient le détail des actions à exécuter en fonction des exceptions capturées

Etape 1: Modifier le fichier fault-binding.xml

Le fichier fault-binding.xml est situé dans le répertoire bpel/domains/default/config, il se base sur le schéma /bpel/system/xmllib/fault-policy-binding.xsd.

Modifiez ce fichier pour spécifier le fichier de traitement des erreurs qui doit être utilisé. On peut spécifier plusieurs fichiers en fonction du flux, du partnerLink, ou du portType déclenchant l’erreur.

<faultPolicyBindings version="2.0.1"
   xmlns="http://schemas.oracle.com/bpel/faultpolicy"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <!-- On définit la politique applicable à l'ensemble des processus -->
   <process faultPolicy="DefaultPolicy"/>

   <!-- On peut cibler plus finement en gérant les erreurs apparaissant
        sur des partnerLink précis. Dans ce cas, on appliquera
        la politique DBPolicy  -->
   <partnerLink faultPolicy="DBPolicy">
      <portType
         xmlns:db="http://xmlns.oracle.com/pcbpel/adapter/db/insert/">
         db:insert_plt</portType>
   </partnerLink>
</faultPolicyBindings>

Dans ce cas, la politique de traitement des erreurs sera par défaut pour l’ensemble des flux celle définie dans le fichier DefaultPolicy.xml.

En revanche, une politique de traitement des erreurs particulière sera mise en place en ce qui concerne les insertions en base de données. En effet toutes les erreurs apparaissant lors d’une insertion en base de données via le DBAdapter et dont le portType est “db:insert_plt” seront gérées dans le fichier DBPolicy.xml

Etape 2: Créer le fichier de paramètrage de la gestion des erreurs

Il faut ensuite créer un fichier .xml dans le répertoire  bpel/domains/default/config/fault-policies. Dans ce fichier, dans notre cas DefaultPolicy.xml, spécifiez l’identifiant (id) de la faultPolicy ainsi que les traitements qui doivent être déclenchés pour chaque type d’erreur. Ces traitements seront exécutés si les erreurs correspondantes sont déclenchées dans les flux, partnerLink, ou portType. Voici un exemple d’un tel fichier qui met en place les actions suivantes :

  • ora-retry permet de rejouer le flux ;
  • ora-rethrow-fault permet de déclencher la gestion des erreurs du décrit dans les balises “catch” ou “catchAll ” du flux;
  • ora-replay-scope permet de rejouer un “scope” du flux en particulier ;
  • ora-human-intervention permet de mettre le flux en attente. Pour continuer l’exécution du flux, une personne devra le relancer via l’onglet « Activités » de la BPEL Console par exemple;
  • ora-terminate permet d’arrêter et d’abandonner le flux exécuté.
<faultPolicy version="2.0.1" id="DefaultPolicy"
   xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns="http://schemas.oracle.com/bpel/faultpolicy"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Conditions>
   <!-- remoteFault : Faute apparaissant lorsque le service appelé ne répond pas -->
   <faultName
      xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
      name="bpelx:remoteFault">
      <condition>
      <!-- On exécutera l’activité ora-retry pour
       toutes les erreurs remoteFault dont le code est 123-->
         <test>$fault.code/code="123"</test>
         <action ref="ora-retry"/>
      </condition>
   </faultName>
   <!-- bindingFault : Faute apparaissant si le endpoint n'existe
        pas ou ne peut être accédé -->
   <faultName
      xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
      name="bpelx:bindingFault">
      <condition>
         <action ref="ora-rethrow-fault"/>
      </condition>
   </faultName>
   <faultname
      xmlns:flt="http://www.easyteam.fr/AnomalieMiseEnAttente"
      name="flt:anomalieMiseEnAttente">
      <condition>
         <action ref="ora-human-intervention"/>
      </condition>
   </faultname>
</Conditions>
<Actions>
   <!-- Cette action va permettre de rejouer l'appel 8 fois avec des
        intervalles de 2, 4, 8, 16, 32, 64, 128, 256 secondes. -->
   <Action id="ora-retry">
      <retry>
         <retryCount>8</retryCount>
         <retryInterval>2</retryInterval>
         <exponentialBackoff/>
         <!-- En cas de succès du retry, la méthode handleRetrySuccess
              de la classe spécifiée dans la balise action envoi-mail sera appelée-->
         <retrySuccessAction ref="envoi-mail"/>
      </retry>
   </Action>
   <!-- Cette action va permettre de rejouer le scope sur lequel on s'est arrêté-->
   <Action id="ora-replay-scope">
      <replayScope/>
   </Action>
   <!-- L'erreur sera relancée dans le flux et pourra éventuellement être attrapée
        par les branches catch si elles sont présentes-->
   <Action id="ora-rethrow-fault">
      <rethrowFault/>
   </Action>
   <!-- Le flux sera mis "en attente" dans la BPEL Console, une intervention humaine
        sera nécessaire pour poursuivre le traitement-->
   <Action id="ora-human-intervention">
      <humanIntervention/>
   </Action>
   <!-- Le flux sera avorté et le traitement stoppé -->
   <Action id="ora-terminate">
      <abort/>
   </Action>
</Actions>
</faultPolicy>

Etape 3: Aller plus loin et appeler une classe Java

Vous pouvez aussi faire appel à une classe Java depuis le fichier de paramètrage de BPEL Error Hospital. Pour cela, définissez une action personalisée comme ci-dessous l’action envoi-mail:

<faultPolicy>
  ...
  <faultName
     xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
     name="bpelx:remoteFault">
     <condition>
        <action ref="envoi-mail"/>
     </condition>
  </faultName>
  ...
</faultPolicy>

Pour les erreurs du type remoteFault, on va exécuter l’action envoi-mail. Il suffit alors de lier cette action à une classe Java. On précise alors le nom de la classe à appeler dans la balise Action:

<faultPolicy>
  ...
  <Actions>
    <Action id="envoi-mail">
       <javaAction
          className="com.easyteam.EnvoiMail"
          propertySet="proprietes-envoi-mail"/>
    </Action>
  </Actions>
  ...
</faultPolicy>

Ci-dessous, un exemple de définition de propriétés pour la classe d’envoi d’email, ces lignes sont à rajouter en dessous de la balise Actions. Ces propriétés sont en fait éléments qui pourront être récupérés dans la méthode appelée. Il peut s’agir de paramètres techniques tels que le serveur SMTP ou encore d’éléments fonctionnels qui permettront de formater le contenu du mail envoyé.

<faultPolicy>
  ...
  <Actions>
  ...
  </Actions>
  <Properties>
     <propertySet name="proprietes-envoi-mail">
        <property name="from">
           hospital@easyteam.fr
        </property>
        <property name="to">
           hospital_receivers@easyteam.fr
        </property>
        <property name="subject">
           Erreur lors d’un appel de WS tiers
        </property>
        <property name="env">Easyteam.Fabrication</property>
        <property name="host">EasyteamSMTP</property>
        <property name="port">25</property>
     </propertySet>
  </Properties>
</faultPolicy>

Pour terminer, il reste à mettre en place votre classe Java implémentant l’interface IFaultRecoveryJavaClass dont voici le squelette :

package com.easyteam;

import com.collaxa.cube.engine.ext.wmp.faultpolicy.FaultRecoveryContext;
import com.oracle.bpel.client.BPELFault;
import com.oracle.bpel.client.config.faultpolicy.IFaultRecoveryContext;
import com.oracle.bpel.client.config.faultpolicy.IFaultRecoveryJavaClass;

import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class EnvoiMail implements IFaultRecoveryJavaClass {

private String from;
private String to;
private String subject;
private String env;
private String host;
private String port;

private Properties myProperties;

public EnvoiMail() {

private void envoiMailAlerte(IFaultRecoveryContext myFaultRecoveryContext, boolean successOrError) {
try {
...
} catch (Exception a_Exception) {
System.out.println("Exception levée lors de l'envoi d'email");
}
}

/**
* Lorsque l'attribut retrySuccessAction pointant sur cette classe est présent dans le bloc d'action Retry
* alors cette méthode est appelée par défaut par Hospital.
*/
public void handleRetrySuccess(IFaultRecoveryContext myFaultRecoveryContext) {
envoiMailAlerte(myFaultRecoveryContext, true);
}

/**
* Il s'agit de la méthode appelée par défaut par Hospital lorsque cette classe est sélectionnée dans
* l'attribut className de la balise javaAction
*/
public String handleBPELFault(IFaultRecoveryContext myFaultRecoveryContext) {
envoiMailAlerte(myFaultRecoveryContext, false);
return "Mail envoyé";
}
}

Cette classe doit être placée dans le répertoire  /bpel/system/classes.

N’oubliez pas de redémarrer le serveur à chaque changement de vos classes Java ou des fichiers .xml définissant vos politiques de traitement des erreurs.


Conclusion

Ainsi, comme on l’a vu, l’utilisation de ce framework va grandement simplifier les choses puisqu’il permet de centraliser la gestion des erreurs au sein d’un même référentiel.
La maintenance sera donc plus aisée et les évolutions de gestion des erreurs ne seront plus lourdes puisqu’il suffira de modifier un simple fichier .xml et éventuellement vos classes Java.
Par ailleurs, bien que la gestion des erreurs soit dorénavant unique (plus de catch dans chaque flux), la granularité demeure fine puisqu’il est possible de descendre au niveau du portType pour spécifier un traitement particulier.
Enfin, la possibilité d’appeler des classes Java ouvre de nombreuses possibilités puisqu’il est alors possible d’utiliser les API de BPEL mises à disposition par Oracle et ainsi interagir avec les flux comme bon nous semble.

Si vous voulez en savoir plus, lisez les articles suivants:

DefaultPolicy.xml
Un commentaire laisser un →
  1. Eric Elzinga lien permanent
    20 juillet 2009 07:19

    Part 2 of “Oracle BPEL 10.1.3.3 Fault Policy Management” can be found here, http://eelzinga.wordpress.com/2009/02/14/oracle-bpel-fault-policy-framework-handling-custom-business-faults/ , “Oracle BPEL Fault Policy Framework handling custom business faults”

Répondre

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Gravatar
Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Twitter picture

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Connexion à %s

Suivre

Get every new post delivered to your Inbox.

Joignez-vous à 36 followers