Exception handling statements

You can add statements that handle exceptions in actions.

IRL provides mechanisms for reporting and handling exceptions. When an error occurs, the rule throws an exception. This means that the normal flow of the rule is interrupted, and the rule engine attempts to find an exception handler, that is, a block of code that handles a particular type of error. The exception handler generally does the necessary actions to recover from the error.

Exception setup

Before you can catch an exception, code somewhere must throw one. Any Java™ code can throw an exception.

A throw expression is any kind of expression whose type is assignable to the Java Throwable type or subclass. A throw expression can be specified either in the API or in a rule. When an exception is thrown it can be caught by the API or a rule—with a try-catch-finally statement or by any Java code—which causes the IRL code to run.

Note:

A thrown exception is an IlrUserRuntimeException subtype of IlrRunTimeException which encapsulates the exception thrown by the throw statement.

  • IlrSystemRuntimeException is thrown when Decision Server detects an error at runtime. This kind of exception cannot be recovered; it is used only for debugging purposes.

  • IlrUserRuntimeException, on the other hand, could be used to reset the context and relaunch the rules.

The try-catch-finally statements

The try-catch-finally statements are:

  • The try statement identifies a block of statements within which an exception might be thrown.

  • The catch statement must be associated with a try statement and identifies a block of statements that can handle a particular type of exception. The statements are run if an exception of a particular type occurs within the try block. There can be as many statements following a try statement as needed. Each statement handles any and all exceptions that are instances of the class listed in parentheses, of any of its subclasses, or of a class that implements the interface listed in parentheses.

  • The finally statement must be associated with a try statement and identifies a block of statements that is run regardless of whether or not an error occurs within the try block. The finally statement is generally used to clean up after the code in the try statement. If an exception occurs in the try block and there is an associated catch block to handle the exception, control transfers first to the catch block and then to the finally block.

Here is the general form of these statements:

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

IRL allows general exception handlers that handle multiple types of exceptions. However, more specialized exception handlers can determine what type of exception occurred and assist in the recovery of these errors. Handlers that are too general can make code more error prone by catching and handling exceptions that were not anticipated and for which the handler was not intended.

The following try statements demonstrate how to create an exception and throw it.

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) ; 
   }
}

The try-catch statements use a method call from a Java class to throw an exception when the variable passed into method1 is not equal to 1. Here is method1:

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") ; 
   } 
}

Exceptions thrown by any rule or Java code within the scope of the rule engine is caught by the try-catch statements for that specific exception.

The following CatchCustomer rule provides an example of a try-catch statement block capable of catching exceptions thrown by the ILOG Rule language and/or Java code. The rule uses two classes, Customer and Item, and two subclasses of the Java Exception class, TooHighExpense and 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?");
    }
  }
}

In the example, a customer is given a budget. The customer is not allowed to buy items that exceed the allocated budget. If the customer attempts to buy items that exceed the budget, a TooHighExpense exception is thrown. In addition, to buy items the customer must be a member. If a nonmember attempts to buy an item, an IsNotMember exception is thrown.

The two Java classes IsNotMember and TooHighExpense used in the CatchCustomer rule are shown here:

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;
};