Instructions de traitement des exceptions

Vous pouvez ajouter des instructions qui traitent les exceptions dans les actions.

IRL prévoit des mécanismes pour rapporter et traiter les exceptions. Lorsqu'une erreur se produit, la règle émet une exception. Cela signifie que le flot normal de la règle est interrompu et que le moteur de règles tente de trouver un gestionnaire d'exceptions, c'est-à-dire un bloc de code chargé de traiter un type particulier d'erreur. Le gestionnaire d'exceptions exécute généralement les actions nécessaires pour récupérer de l'erreur.

Mécanisme de traitement des exceptions

Pour qu'une exception soit interceptée (catch), il faut qu'un code quelque part en émette une (throw). Tout code Java™ peut émettre une exception.

Une expression throw est tout type d'expression dont le type peut être affecté au type ou à la sous-classe Java Throwable . Une expression throw peut être spécifiée soit dans l'API, soit dans une règle. Lorsqu'une exception est émise, elle peut être interceptée par l'API ou une règle-avec une instruction try-catch-finally ou par un code Java-ce qui entraîne l'exécution du code IRL.

Remarque :

Une exception émise est un sous-type IlrUserRuntimeException de IlrRunTimeException qui encapsule l'exception émise par l'instruction throw.

  • IlrSystemRuntimeException est émis lorsque Decision Server détecte une erreur lors de l'exécution. Il n'est pas possible de récupérer de ce genre d'exception, qui ne sert qu'au débogage.

  • IlrUserRuntimeException, en revanche, peut servir à réinitialiser le contexte et à relancer les règles.

Les instructions try-catch-finally

Les instructions try-catch-finally sont :

  • L'instruction try identifie un bloc d'instructions au sein duquel une exception est susceptible d'être émise.

  • L'instruction catch, qui doit être associée à une instruction try, identifie un bloc d'instructions capable de traiter un type particulier d'exception. Les instructions sont exécutées si une exception d'un type particulier se produit dans le bloc try. Il peut y avoir autant d'instructions que nécessaire à la suite d'une instruction try. Chacune traite toutes les exceptions qui sont des instances de la classe listée entre parenthèses ou de l'une de ses sous-classes, ou encore des instances d'une classe qui implémente l'interface listée entre parenthèses.

  • L'instruction finally doit être associée à une instruction try et identifie un bloc d'instructions qui est exécuté, qu'une erreur se produise ou non dans le bloc try. L'instruction finally effectue généralement un nettoyage après le code dans l'instruction try. Si une exception est détectée dans le bloc try et qu'il existe un bloc catch associé pour traiter cette exception, le contrôle est d'abord transféré au bloc catch, puis au bloc finally.

Voici la forme générale de ces instructions :

try {
    statements
} 
catch (ExceptionType1 name) {
    statements
} 
catch (ExceptionType2 name) {
    statements
} 
...
finally {
    statements
}

IRL prévoit l'utilisation de gestionnaires généraux, capables de traiter plusieurs types d'exceptions. Des gestionnaires plus spécialisés peuvent cependant déterminer précisément quel type d'exception a été émis et aider à récupérer des erreurs. Un gestionnaire d'exceptions trop général peut rendre le code plus sujet aux erreurs en interceptant et en traitant des exceptions qui n'étaient pas prévues et auxquelles le gestionnaire n'était pas destiné.

Les instructions try suivantes montrent comment créer une exception et l'émettre.

then {
   try {
      method1(1) ; 
      System.out.println("Call method1(1) was OK") ; 
   }
   catch ( Exception e ) { 
   System.out.println("Catch from method1(1) call") ; 
   }
   try {
      method1(2) ;
      System.out.println("Call method1(2) was OK") ;
   }
   catch ( Exception e ) { 
      System.out.println("Catch from method1(2) call") ; 
      System.out.println("Exception details :-") ;
      System.out.println("Message: " + e) ; 
   }
}

Les instructions try-catch utilisent un appel de méthode d'une classe Java pour émettre une exception lorsque la variable transmise à method1 n'est pas égale à 1. Voici la méthode 1 :

public static void method1(i) throws Exception{
   if (i == 1) { 
      System.out.println("method1 - Things are fine \n") ; 
   }
   else {        
      System.out.println("method1 - Somethings wrong! \n") ;
      throw new Exception("method1 - Its an exception! \n") ; 
   } 
}

Les exceptions émises par une règle ou un code Java dans la portée du moteur de règles sont interceptées par les instructions try-catch pour cette exception spécifique.

La règle CatchCustomer suivante fournit un exemple de bloc d'instructions try-catch capable d'attraper les exceptions lancées par le langage de règles ILOG® et/ou le code Java. La règle utilise deux classes, Customer et Item, et deux sous-classes de la classe Java Exception , TooHighExpense et IsNotMember.

rule CatchCustomer
{
  when {
   ?c: Customer();
   ?item: Item();
  }
  then {
    try {  
      System.out.println("Customer " + ?c.getName() + " wants to buy "
                         + " item " + ?item.getLabel() + " for a price of " +
                         ?item.getPrice() + "$");
      IsMember(?c);
      ?c.buy(?item);
    }
    catch (TooHighExpense ex) {
      System.out.println("M/Mrs/Mz " + ?c.getName() + " you have already
                         bought:");
      int j = 0;
      for(j = 0; j<?c.getItems().size(); j++) {
        java.util.Enumeration ?i = ?c.getItem(j);
        System.out.println("   Item: " + ?i.getLabel() + " costs " +
                           ?i.getPrice() + "$");
      }
      System.out.println("You have at your disposal " + ?c.getBudget() + "$");
      System.out.println("The current purchase is not allowed");
    }
    catch (IsNotMember ex) {
      System.out.println("M/Mrs/Mz " + ?c.getName() + 
                         ", you are not a member; would you like to
                          subscribe?");
    }
  }
}

Dans cet exemple, un budget est alloué à un client. Celui-ci n'est pas autorisé à acheter des articles dont le montant dépasserait le budget alloué. S'il tente d'acheter des articles pour un montant dépassant le budget, une exception TooHighExpense est émise. En outre, pour pouvoir acheter des articles, le client doit être un membre. S'il n'est pas membre et tente d'acheter un article, une exception IsNotMember est émise.

Les deux classes Java IsNotMember et TooHighExpense utilisées dans la règle CatchCustomer sont présentées ici:

public class IsNotMember extends Exception
{
    public IsNotMember(String name){
      super();
      this.customer = name;
    }
    public void printStackTrace(PrintWriter s){ 
      s.println("An IsNotMember exception has been caused by customer "
                + customer + ". We are sorry but you can not make a purchase "
                + "without being a member.");
      super.printStackTrace(s);
      }
    String customer;
};


public class TooHighExpense extends Exception
{
    public TooHighExpense(String name, int expense, int limit, int price){
      super();
      this.expense = expense;
      this.limit = limit;
      this.price = price;
      this.customer = name;
    }
    public void printStackTrace(PrintWriter s){ 
      s.println("A TooHighExpense exception has been caused by customer "
                + customer + ". For this customer, the current expense is " + expense + 
                " and the authorized budget is " + limit +
                ". The purchase of the item whose price is " + price
                + " is not allowed.");
      super.printStackTrace(s);
      }
    private int price;
    private int limit;
    private int expense;
    String customer;
};