Skip to main content

This documentation is for an older version of this product. See the latest version of this content.Opens in a new tab

Java からの ObjectScript メソッドおよび関数の呼び出し

この章では、ObjectScript クラス・メソッドとユーザ定義関数を Java アプリケーションから直接呼び出すことを可能にするクラス IRIS のメソッドを説明します。詳細および例は、以下のセクションを参照してください。

クラス・メソッドの呼び出し

クラス IRIS の以下のメソッドは、ObjectScript クラス・メソッドを呼び出し、メソッド名により指定されるタイプの値を返します : classMethodBoolean()classMethodBytes()classMethodDouble()classMethodIRISList()classMethodLong()classMethodObject()classMethodString()、および classMethodVoid()classMethodStatusCode() を使用して、ObjectScript %StatusOpens in a new tab を返すクラス・メソッドからエラー・メッセージを取得します (“%Status エラー・コードの取得” を参照)。

これらのメソッドはすべて、className および methodNameString 引数に加え、0 個以上のメソッド引数を取ります。これは、IntegerShortStringLongDoubleFloatbyte[]BooleanTimeDateTimestampIRISList、または IRISObjectのいずれかの型にできます。接続が双方向の場合 (“Java 逆プロキシ・オブジェクトの使用法” を参照)、任意の Java オブジェクトを引数として使用できます。Native SDK がこれらのデータ型を処理する方法の詳細は、“クラス IRIS のサポートされているデータ型” を参照してください。

すべての引数の数よりも少ない数の引数を渡すか、末尾の引数に対して null を渡すことで、引数リストで末尾の引数を省略できます。非 null 引数が null 引数の右側に渡されると、例外がスローされます。

ObjectScript クラス・メソッドの呼び出し

この例のコードでは、サポートされている各データ型のクラス・メソッドを ObjectScript テスト・クラス User.NativeTest から呼び出します (この例の直後に表示されています)。変数 irisjv はクラス IRIS の以前に定義されたインスタンスで、現在サーバに接続されていると想定します。

  String className = "User.NativeTest";
  String comment = "";

  comment = "cmBoolean() tests whether two numbers are equal (true=1,false=0): ";
  boolean boolVal = irisjv.classMethodBoolean(className,"cmBoolean",7,7);
  System.out.println(comment+boolVal);

  comment = "cmBytes creates byte array [72,105,33]. String value of array: ";
  byte[] byteVal = irisjv.classMethodBytes(className,"cmBytes",72,105,33);
  System.out.println(comment+(new String(byteVal)));

  comment = "cmString() concatenates \"Hello\" + arg: ";
  String stringVal = irisjv.classMethodString(className,"cmString","World");
  System.out.println(comment+stringVal);

  comment = "cmLong() returns the sum of two numbers: ";
  Long longVal = irisjv.classMethodLong(className,"cmLong",7,8);
  System.out.println(comment+longVal);

  comment = "cmDouble() multiplies a number by 1.5: ";
  Double doubleVal = irisjv.classMethodDouble(className,"cmDouble",10);
  System.out.println(comment+doubleVal);

  comment = "cmProcedure assigns a value to global node ^cmGlobal: ";
  irisjv.classMethodVoid(className,"cmVoid",67);
  // Read global array ^cmGlobal and then delete it
  System.out.println(comment+irisjv.getInteger("^cmGlobal"));
  irisjv.kill("cmGlobal");

  comment = "cmList() returns a $LIST containing two values: ";
  IRISList listVal = irisjv.classMethodList(className,"cmList","The answer is ",42);
  System.out.println(comment+listVal.get(1)+listVal.get(2));
ObjectScript クラス User.NativeTest

前の例を実行するには、この ObjectScript クラスがコンパイルされ、サーバで使用可能である必要があります。

Class User.NativeTest Extends %Persistent
{
ClassMethod cmBoolean(cm1 As %Integer, cm2 As %Integer) As %Boolean
{
    Quit (cm1=cm2)
}
ClassMethod cmBytes(cm1 As %Integer, cm2 As %Integer, cm3 As %Integer) As %Binary
{
    Quit $CHAR(cm1,cm2,cm3)
}
ClassMethod cmString(cm1 As %String) As %String
{
    Quit "Hello "_cm1
}
ClassMethod cmLong(cm1 As %Integer, cm2 As %Integer) As %Integer
{
    Quit cm1+cm2
}
ClassMethod cmDouble(cm1 As %Double) As %Double
{
    Quit cm1 * 1.5
}
ClassMethod cmVoid(cm1 As %Integer)
{
    Set ^cmGlobal=cm1
    Quit ^cmGlobal
}
ClassMethod cmList(cm1 As %String, cm2 As %Integer)
{
    Set list = $LISTBUILD(cm1,cm2)
    Quit list
}
}

ターミナルからこれらのメソッドを呼び出すことで、それらをテストできます。例を以下に示します。

USER>write ##class(User.NativeTest).cmString("World")
Hello World

関数の呼び出し

関数の呼び出しは、メソッド呼び出しと似ていますが、引数の順序が異なります。関数ラベルを最初に指定し、その後に関数が含まれるルーチン名を続けます。これは ObjectScript で使用される順序に対応しており、関数呼び出しは以下の形式になります。

  set result = $$myFunctionLabel^myRoutineName([arguments])

関数がサポートされている理由は古いコード・ベースに必要であるためで ("ObjectScript の使用法" の “呼び出し可能なユーザ定義コードモジュール” を参照)、可能であれば新しいコードでは常にメソッド呼び出しを使用するようにしてください。ObjectScript では、既存のルーチンのメソッド・ラッパを作成するための特別なキーワードも提供されているため、効率性が損なわれることはありません ("サーバ側プログラミングの入門ガイド" の “呼び出しメソッド” を参照)。

このセクションの Native SDK メソッドは、ユーザ定義の ObjectScript 関数またはプロシージャを呼び出して、メソッド名で示されるタイプの値を返します : functionBoolean()functionBytes()functionDouble()functionIRISList()functionObject()functionLong()functionString()、または procedure() (戻り値なし)。

これらは、functionLabel および routineNameString 引数に加え、0 個以上の関数の引数を取ります。これは、IntegerShortStringLongDoubleFloatbyte[]BooleanTimeDateTimestampIRISList、または IRISObjectのいずれかの型にできます。接続が双方向の場合 (“Java 逆プロキシ・オブジェクトの使用法” を参照)、任意の Java オブジェクトを引数として使用できます。Native SDK がこれらのデータ型を処理する方法の詳細は、“クラス IRIS のサポートされているデータ型” を参照してください。

すべての引数の数よりも少ない数の引数を渡すか、末尾の引数に対して null を渡すことで、引数リストで末尾の引数を省略できます。非 null 引数が null 引数の右側に渡されると、例外がスローされます。

Note:
組み込みのシステム関数はサポートされません

これらのメソッドは、ユーザ定義ルーチンで関数を呼び出すように設計されています。ObjectScript システム関数 ($ 文字で開始。"ObjectScript リファレンス" の “ObjectScript 関数” を参照) を Java コードから直接呼び出すことはできません。ただし、システム関数を呼び出してその結果を返す ObjectScript ラッパ関数を記述することで、間接的にシステム関数を呼び出すことができます。例えば、fnList() 関数 (このセクションの最後にある "ObjectScript Routine NativeRoutine.mac" を参照) は $LISTBUILD を呼び出します。

Native SDK による ObjectScript ルーチンの関数の呼び出し

この例のコードでは、サポートされている各データ型の関数を ObjectScript ルーチン NativeRoutine から呼び出します (この例の直後に表示されているファイル NativeRoutine.mac)。irisjv はクラス IRIS の既存のインスタンスで、現在サーバに接続されていると想定します。

  String routineName = "NativeRoutine";
  String comment = "";

  comment = "fnBoolean() tests whether two numbers are equal (true=1,false=0): ";
  boolean boolVal = irisjv.functionBool("fnBoolean",routineName,7,7);
  System.out.println(comment+boolVal);

  comment = "fnBytes creates byte array [72,105,33]. String value of the array: ";
  byte[] byteVal = new String(irisjv.functionBytes("fnBytes",routineName,72,105,33));
  System.out.println(comment+(new String(byteVal)));

  comment = "fnString() concatenates \"Hello\" + arg: ";
  String stringVal = irisjv.functionString("fnString",routineName,"World");
  System.out.println(comment+stringVal);

  comment = "fnLong() returns the sum of two numbers: ";
  Long longVal = irisjv.functionInt("fnLong",routineName,7,8);
  System.out.println(comment+longVal);

  comment = "fnDouble() multiplies a number by 1.5: ";
  Double doubleVal = irisjv.functionDouble("fnDouble",routineName,5);
  System.out.println(comment+doubleVal);

  comment = "fnProcedure assigns a value to global array ^fnGlobal: ";
  irisjv.procedure("fnProcedure",routineName,88);
  // Read global array ^fnGlobal and then delete it
  System.out.println(comment+irisjv.getInteger("^fnGlobal")+"\n\n");
  irisjv.kill("fnGlobal");

  comment = "fnList() returns a $LIST containing two values: ";
  IRISList listVal = irisjv.functionList("fnList",routineName,"The answer is ",42);
  System.out.println(comment+listVal.get(1)+listVal.get(2));
ObjectScript ルーチン NativeRoutine.mac

前の例を実行するには、この ObjectScript ルーチンがコンパイルされ、サーバで使用可能である必要があります。

fnBoolean(fn1,fn2) public {
   quit (fn1=fn2)
}
fnBytes(fn1,fn2,fn3) public {
    quit $CHAR(fn1,fn2,fn3)
}
fnString(fn1) public {
    quit "Hello "_fn1
}
fnLong(fn1,fn2) public {
    quit fn1+fn2
}
fnDouble(fn1) public {
    quit fn1 * 1.5
}
fnProcedure(fn1) public {
    set ^fnGlobal=fn1
    quit
}
fnList(fn1,fn2) public {
    set list = $LISTBUILD(fn1,fn2)
    quit list
}

ターミナルからこれらの関数を呼び出すことで、それらをテストできます。例を以下に示します。

USER>write $$fnString^NativeRoutine("World")
Hello World

クラス・ライブラリ・メソッドの呼び出し

InterSystems クラス・ライブラリのほとんどのクラスでは、メソッドが %StatusOpens in a new tab 値のみを返す呼び出し規則を使用します。実際の結果は、参照によって渡される引数で返されます。このセクションでは、参照渡しを実行し、%StatusOpens in a new tab 値を読み取る方法について説明します。

参照渡し引数の使用

Native SDK は、メソッドと関数の両方で参照渡しをサポートします。参照によって引数を渡すには、以下のように引数の値をクラス jdbc.IRISReference のインスタンスに割り当て、そのインスタンスを引数として渡します。

  IRISReference valueRef = new IRISReference(""); // set inital value to null string
  irisjv.classMethodString("%SomeClass","SomeMethod",valueRef);
  String myString = valueRef.value;  // get the method result

以下にその実際の例を示します。

参照渡し引数の使用

この例は、%SYS.DatabaseQuery.GetDatabaseFreeSpace()Opens in a new tab を呼び出して、iristemp データベースで利用可能な空き容量の量 (MB 単位) を取得します。

  IRISReference freeMB = new IRISReference(0); // set inital value to 0
  String dir = "C:/InterSystems/IRIS/mgr/iristemp"; // directory to be tested
  Object status = null;

  try {
    System.out.print("\n\nCalling %SYS.DatabaseQuery.GetDatabaseFreeSpace()... ");
    status = irisjv.classMethodObject("%SYS.DatabaseQuery","GetDatabaseFreeSpace",dir,freeMB);
    System.out.println("\nFree space in " + dir + " = " + freeMB.value + "MB");
  }
  catch (RuntimeException e) {
    System.out.print("Call to class method GetDatabaseFreeSpace() returned error:");
    System.out.println(e.getMessage());
  }

出力 :

Calling %SYS.DatabaseQuery.GetDatabaseFreeSpace()...
Free space in C:/InterSystems/IRIS/mgr/iristemp = 8.9MB

%Status エラー・コードの取得

クラス・メソッドが戻り値の型として ObjectScript %StatusOpens in a new tab を持つ場合、classMethodStatusCode() を使用してエラー・メッセージを取得できます。クラス・メソッドの呼び出しが失敗した場合、結果として生成される RuntimeException エラーには、%StatusOpens in a new tab エラー・コードとメッセージが含まれます。

以下の例では、ValidatePassword() メソッドは %StatusOpens in a new tab オブジェクトを返します。パスワードが無効である場合 (例えばパスワードが短すぎる場合)、例外がスローされ、%StatusOpens in a new tab メッセージにより失敗した理由が説明されます。変数 irisjv はクラス IRIS の以前に定義されたインスタンスで、現在サーバに接続されていると想定します。

classMethodStatusCode() を使用した ObjectScript %Status 値の取得

この例では、無効なパスワードを %SYSTEM.Security.ValidatePassword()Opens in a new tab に渡し、エラー・メッセージを取得します。

  String className = "%SYSTEM.Security";
  String methodName = "ValidatePassword";
  String pwd = ""; // an invalid password
  try {
// This call will throw a RuntimeException containing the %Status error message:
    irisjv.classMethodStatusCode(className,methodName,pwd);
// This call would fail silently or throw a generic error message:
    Object status = irisjv.classMethodObject(className,methodName,pwd);
    System.out.println("\nPassword validated!");

  } catch (RuntimeException e) {
    System.out.println("Call to "+methodName+"(\""+pwd+"\") returned error:");
    System.out.println(e.getMessage());
  }

この例では、意図的に、参照渡し引数を使用しないメソッドを呼び出していることに注意してください。

より複雑な例を試すには、前の例 ("参照渡し引数の使用") でステータス・コードの取得を試してみることができます。無効なディレクトリを渡すことで強制的に例外を発生させます。

Note:
インスタンス・メソッドを呼び出す際の IRISObject.invokeStatusCode() の使用

classMethodStatusCode() メソッドは、クラス・メソッドの呼び出しに使用されます。プロキシ・オブジェクトのインスタンス・メソッドを呼び出す際 (“Java 逆プロキシ・オブジェクトの使用法” を参照)、IRISObject.invokeStatusCode() メソッドをまったく同じ方法で使用できます。

FeedbackOpens in a new tab