例外処理ステートメント

アクションに例外を処理するステートメントを追加することができます。

IRL には、例外を報告および処理するための機能があります。 エラーが生じると、ルールは例外を発します。 これによって、ルールの標準フローが中断され、ルール・エンジンは例外ハンドラー、すなわち、特定の種類のエラーを処理するコードのブロックを見つけようとします。 通常、例外ハンドラーは、エラーから回復するために必要なアクションを実行します。

例外のセットアップ

例外をキャッチするには、どこかのコードが例外をスローする必要があります。 任意の Java™ コードが例外をスローできます。

throw 式は、タイプが Java Throwable タイプまたはサブクラスに割り当て可能な任意の種類の式です。 throw 式は、API と ルールのいずれでも指定できます。 例外がスローされた場合、 try-catch-finally ステートメントまたは任意の Java コードを使用して、API またはルールによって例外をキャッチすることができます。これにより、IRL コードが実行されます。

注:

スローされる例外は、throw ステートメントによってスローされた例外をカプセル化した IlrRunTimeExceptionIlrUserRuntimeException サブタイプです。

  • Decision Server が実行時にエラーを検出すると、 IlrSystemRuntimeException がスローされます。 この種類の例外は回復できません。したがって、デバッグのためだけに使用されます。

  • 一方、IlrUserRuntimeException を使用すると、コンテキストをリセットしたり、ルールを再起動したりすることができます。

try-catch-finally ステートメント

try-catch-finally ステートメントは、次のように構成されます。

  • try ステートメントは、例外がスローされる可能性があるステートメント・ブロックを識別します。

  • catch ステートメントは、try ステートメントと関連付ける必要があり、特定タイプの 例外を処理できるステートメント・ブロックを識別します。 このステートメントは、try ブロック内で特定のタイプの例外が発生した場合に実行されます。 try ステートメントのあとには、必要なだけステートメントを 続けることができます。 各ステートメントは、括弧内に記述されたクラス、そのサブクラス、または括弧内に記述されたインターフェースを実装するクラスのインスタンスである例外のいずれか、またはすべてを処理します。

  • finally ステートメントは、 try ステートメントと関連付ける必要があり、 try ブロック内でエラーが発生するかどうかに関係なく実行されるステートメントのブロックを識別します。 一般に、finally ステートメントは、try ステートメントの コード実行後、クリーンアップのために使用されます。 try ブロック内で例外が発生し、例外を処理するための関連 catch ブロックが ある場合、制御はまず catch ブロックに移り、その後 finally ブロックに移ります。

次に示すのは、これらのステートメントの一般的な形式です。

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

IRL では、一般例外ハンドラーで、複数の種類の例外を処理することができます。 しかし、より専門化された例外ハンドラーは、発生した例外のタイプを特定することができ、エラーの回復に役立ちます。 ハンドラーが一般的すぎると、予期されずハンドラーが意図されていなかった例外をキャッチおよび処理することで、コードがエラーになりやすい傾向にあります。

以下の try ステートメントは、例外を作成し、それをスローする方法を示しています。

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

try-catch ステートメントは、Java クラスからのメソッド呼び出しを使用して、 method1 に渡された変数が 1と等しくない場合に例外をスローします。 以下にメソッド 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") ; 
   } 
}

ルール・エンジンのスコープ内のルールまたは Java コードによってスローされた例外は、その特定の例外の try-catch ステートメントによってキャッチされます。

以下の CatchCustomer ルールは、ILOG ルール言語または Java コード (あるいはその両方) によってスローされた例外をキャッチできる try-catch ステートメント・ブロックの例を示しています。 この規則は、 CustomerItemの 2 つのクラスと、Java Exception クラスの 2 つのサブクラス、 TooHighExpenseIsNotMemberを使用します。

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

この例では、顧客に予算が与えられます。 顧客は、割り当てられた予算を超える品物を購入できません。 顧客が予算を超える品物を買おうとすると、TooHighExpense 例外が発生します。 さらに、品物を購入するには、顧客がメンバーでなければなりません。 非メンバーが品物を買おうとすると、IsNotMember 例外が発生します。

CatchCustomer 規則で使用される 2 つの Java クラス IsNotMember および TooHighExpense を以下に示します。

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