RPG で Java のメソッドを使用する

今までも「RPG で C ランタイム関数を使用する」などで RPG で多言語で作成したモジュールを使用するやり方を見てきましたが、今回は Java のクラスやメソッドを使いたい場合にどうやるか、を見てみたいと思います。

と言っても、たまたま「Prototyping and Calling Java Methods from RPG」という記事を見て、そのとおりやってみましたってだけなんですけどね。。


サンプル・プログラム

↓がプログラム例です。

数字の文字列を数字に変換し、add メソッドを使って足し算をして、画面に表示をする、といったシンプルなプログラムです。

     H DFTACTGRP(*NO)

     D newString       PR              O   ExtProc(*JAVA:
     D                                             'java.lang.String':
     D                                             *CONSTRUCTOR)
     D                                     Class(*JAVA:'java.lang.String')
     D  bytes                        30A   Const Varying

     D String2BigD     PR              O   ExtProc(*JAVA:
     D                                         'java.math.BigDecimal':
     D                                         *CONSTRUCTOR)
     D                                     Class(*JAVA:'java.math.BigDecimal')
     D  String                         O   Class(*JAVA:'java.lang.String')
     D                                     Const

     D BigD2String     PR              O   ExtProc(*JAVA:
     D                                             'java.math.BigDecimal':
     D                                             'toString')
     D                                     Class(*JAVA:'java.lang.String')

     D getBytes        PR            30A   ExtProc(*JAVA:
     D                                             'java.lang.String':
     D                                             'getBytes')
     D                                     Varying

     D string1         S               O   Class(*JAVA:'java.lang.String')
     D string2         S               O   Class(*JAVA:'java.lang.String')

     D add             PR              O   ExtProc(*JAVA:
     D                                         'java.math.BigDecimal':
     D                                         'add')
     D                                     Class(*JAVA:'java.math.BigDecimal')
     D  BigD                           O   Class(*JAVA:'java.math.BigDecimal')
     D                                     Const

     D BigD1           S               O   Class(*JAVA:'java.math.BigDecimal')
     D BigD2           S               O   Class(*JAVA:'java.math.BigDecimal')

     D Sum             S               O   Class(*JAVA:'java.math.BigDecimal')
     D StringSum       S               O   Class(*JAVA:'java.lang.String')
     D DisplaySum      S             30A   Varying

      /Free

          String1 = newString('2.3') ;
          String2 = newString('3.7') ;

          BigD1 = String2BigD(string1) ;
          BigD2 = String2BigD(string2) ;

          Sum = add(BigD1:BigD2) ;
          StringSum = BigD2String(Sum) ;
          DisplaySum = getBytes(StringSum) ;

          dsply DisplaySum ;

          *inLR = *on ;
          return ;

      /End-Free

メソッドをプロトタイプとして定義

使用したいメソッドをプロトタイプとして定義します。(プロトタイプについては「パラメータの受け取り (ILE RPG)」を見てみてください)

ExtProc で、最初の引数にメソッドの所属するクラス名、次の引数に関数/サブプロシージャとして使用したいメソッドを指定してプロトタイプ定義を行います。

マニュアルに載っている例ですが、たとえば

static String  Integer.toString(int)

というメソッドは

D tostring        PR              O   EXTPROC(*JAVA: 
D                                      'java.lang.Integer': 
D                                      'toString') 
D                                     CLASS(*JAVA:'java.lang.String')
D                                     STATIC 
D    num                        10I 0 VALUE 

と定義します。

ExtProc キーワードにすぐ続く Class キーワードで定義されているクラスが、このプロトタイプで定義されているサブプロシージャ(関数)の戻り値となるクラスです。
ですから、プロトタイプの戻り値はたいていの場合は O タイプですね。後述しますが、"オブジェクト"の O です。Class キーワードを使用して実際のクラスを指定します。

通常のプロトタイプ定義と同様ですが、続けてサブプロシージャで取る引数の定義を行っています。

D    num                        10I 0 VALUE 

データタイプの互換性については↓を参照してください。(出典はマニュアル

Java Data Type ILE RPG Data Type RPG Definitions
boolean indicator N
byte 1 integer 3I 0
character 1A
byte[] character length > 1 (See 3.) nA
array of character length=1 (See 4.) 1A DIM(x)
date D
time T
timestamp Z
short 2-byte integer 5I 0
char UCS-2 length=1 1C
char[] UCS-2 length>1 (See 3.) nC
array of UCS-2 length=1 (See 4.) 1C DIM(x)
int 4-byte integer 10I 0
long 8-byte integer 20I 0
float 4-byte float 4F
double 8-byte float 8F
any object object O CLASS(x)
any array array of equivalent type (See 4.) DIM(x)
注:
1. Java byte タイプが文字(1A) との間で変換される時は、ASCII 変換が行なわれます。
Java byte タイプが整数(3I) データ・タイプとの間で変換される場合は、ASCII 変換は行なわれません。

2. Java でいかなるタイプを持つ配列の場合も、RPG で同等タイプの配列を定義することができますが、文字で長さが1 より大きいか、またはUCS-2 で長さが1
より大きいデータ・タイプの配列は使用できないことに注意してください。

3. UCS-2 で長さが1 より大きいデータ・タイプおよび文字で長さが1 より大きいデータ・タイプの場合、VARYING キーワードを使用することができます。Java
byte[] およびchar[] は固定長で宣言することはできないため、一般的にVARYING キーワードの使用をお勧めします。

4. Java 配列は固定長で宣言できないため、RPG の配列データ・タイプでは配列パラメーターとして一般にOPTIONS(*VARSIZE) をコーディングする必要があり
ます。

ゾーン、パック、2 進、および符号なしのデータ・タイプはJava では使用できません。
ゾーン、パック、2 進、または符号なしのフィールドをパラメーターとして渡した場合、コンパイラーは適切な変換を行ないます。ただしその結果として、切り
捨てが行なわれるかまたは精度が失われる(あるいはその両方) 可能性があります。

メソッドを呼び出す際、コンパイラーが配列をパラメーターとして受け入れるのは、そのパラメーターがDIM キーワードを使用してプロトタイプされている場合
のみです。
↓のデータタイプの場合は値渡ししかできないので VALUE キーワードが必要になります。
boolean 
byte 
int 
short 
long 
float 
double 

マニュアルの例をいくつか見てみましょう。

static Integer Integer.getInteger(String, Integer)

は↓のように、

D getint          PR              O   EXTPROC(*JAVA:
D                                      'java.lang.Integer':
D                                      'getInteger')
D                                     CLASS(*JAVA:'java.lang.Integer')
D                                     STATIC
D   string                        O   CLASS(*JAVA:'java.lang.String') CONST
D   num                           O   CLASS(*JAVA:'java.lang.Integer') CONST
short shortValue()

は↓のように、

D shortval        PR             5I 0 EXTPROC(*JAVA:
D                                      'java.lang.Integer':
D                                      'shortValue'
boolean equals(Object)

は↓のように、

D equals          PR              N   EXTPROC(*JAVA:
D                                      'java.lang.Integer':
D                                      'equals')
D  obj                            O   CLASS(*JAVA:'java.lang.Object')

定義されます。

今回のサンプルの中の例をいくつか見てみましょう。

     D BigD2String     PR              O   ExtProc(*JAVA:
     D                                             'java.math.BigDecimal':
     D                                             'toString')
     D                                     Class(*JAVA:'java.lang.String')

java.math.BigDecimal の toString メソッドの定義を見てみると↓のようになっています。

String toString()

他の例を見てみましょう。

     D add             PR              O   ExtProc(*JAVA:
     D                                         'java.math.BigDecimal':
     D                                         'add')
     D                                     Class(*JAVA:'java.math.BigDecimal')
     D  BigD                           O   Class(*JAVA:'java.math.BigDecimal')
     D                                     Const

java.math.BigDecimal の add メソッドの定義を見てみると↓のようになっています。

BigDecimal add(BigDecimal val) 

どちらも対応しているのがわかりますね。

コンストラクタ

コンストラクタの定義については、メソッド名に *CONSTRUCTOR と指定することで行えます。

java.lang.String クラスでバイト列を引数に取るコンストラクタは

String(byte[] bytes) 

↓のように、

     D newString       PR              O   ExtProc(*JAVA:
     D                                             'java.lang.String':
     D                                             *CONSTRUCTOR)
     D                                     Class(*JAVA:'java.lang.String')
     D  bytes                        30A   Const Varying

java.math.BigDecimal クラスで String オブジェクトを引数に取るコンストラクタは

BigDecimal(String val) 

↓のように

     D String2BigD     PR              O   ExtProc(*JAVA:
     D                                         'java.math.BigDecimal':
     D                                         *CONSTRUCTOR)
     D                                     Class(*JAVA:'java.math.BigDecimal')
     D  String                         O   Class(*JAVA:'java.lang.String')
     D                                     Const

定義されます。

考慮点

プロトタイプと定義したメソッドに、自オブジェクトへの参照を含む場合はいくつかの考慮点があります。

マニュアルに載っている例をいくつか挙げます。

BigDecimal add(BigDecimal val) 

などのように自オブジェクトに対しての参照が必要なものには、プロトタイプ定義では↓のように引数はそのまま一つですが、

D add             PR              O    EXTPROC(*JAVA:
D                                       'java.math.BigDecimal':
D                                       'add')
D                                      CLASS(*JAVA:'java.math.BigDecimal')
D   bd1                           O    CLASS(*JAVA:'java.math.BigDecimal') 
D                                      CONST

実際に RPG 内でプロシージャを使用する際は、その引数の前に一つ自オブジェクトを表す引数を追加する必要があります。

C                   EVAL      sum = add(bdnum1:bdnum2)

また、

str.getBytes()

のように使用されるものも、クラスのメソッド定義としては引数を取らないので↓のようなプロトタイプ定義になりますが、

D getBytes        PR            10A   EXTPROC(*JAVA:
D                                       'java.lang.String':
D                                       'getBytes') VARYING

↓のように String オブジェクトの自インスタンスへの参照を引数として取るようにします。

C                   EVAL      fld = getBytes(str)

ただし、static メソッドだった場合は、

D getBytes        PR            10A   EXTPROC(*JAVA:
D                                       'java.lang.String':
D                                       'getBytes') VARYING
D                                     STATIC

↓のようにそのまま使用できます。

C                   EVAL      fld = getBytes()

戻りクラスを"オブジェクト"データタイプで指定

説明が前後したような形になっていますが、引数や戻り値、プログラムの中の定数や変数に使用される Java のクラスの定義の仕方を見てみましょう。

データタイプを "O" と定義し、Class(*JAVA: というキーワードに続けて ' で囲んだクラス名を指定します。

     D string1         S               O   Class(*JAVA:'java.lang.String')

     D BigD1           S               O   Class(*JAVA:'java.math.BigDecimal')

ちなみに、このデータタイプ "O" というのは、V5R1 から使用できるようになった"オブジェクト"というデータタイプです。

実行結果

コンパイルと実行結果をみてみましょう。

通常の CRTBNDRPG/CRTRPGMOD コマンドでコンパイルできます。

実行すると JVM が自動的に起動されるのがわかりますね。

その他

QIBM_RPG_JAVA_PROPERTIES

QIBM_RPG_JAVA_PROPERTIES という環境変数を使用すると、RPG ユーザーは、JVM を開始するために使用される Java のプロパティーを明示的に設定することができます。

以下マニュアルからの転載です。

この環境変数は、なんらかのRPG プログラムがジョブ内でJava メソッドを呼び出す前に設定する必要があります。
この環境変数には、オプション・ストリングのどこにも使用されない何らかの文字によって区切られ、終了される、Java オプションが含まれます。通常は、 この文字としてセミコロンを使用することをお勧めします。

例:
1. 1 つのオプションのみを指定する場合: システムのデフォルトJDK が1.3 であり、RPG プログラムでJDK 1.4 を使用する場合には、環境変数 QIBM_RPG_JAVA_PROPERTIES を ’-Djava.version=1.4;’ に設定します。1 つのオプションのみを使用する場合であっても、終了文字は必要ですので注意してください。この例では、セミコロンを使用しています。
2. 複数のオプションを指定する場合: os400.stdout オプションもデフォルト値以外の値に設定したい場合には、環境変数を次の値に設定することができます。’-Djava.version=1.4!-Dos400.stdout=file:mystdout.txt!’ この例では、区切り文字および終了文字として感嘆符を使用しています。

QIBM_RPG_JAVA_EXCP_TRACE

こちらもマニュアルからの転載です。

QIBM_RPG_JAVA_EXCP_TRACE を使用すると、RPG ユーザーは、Java メソッドへのRPG 呼び出しが例外で終了した場合に、例外トレースを利用することができます。
この環境変数は、いつでも設定、変更、または除去することができます。
この環境変数に値’Y’ が含まれる場合には、RPG からのJava メソッドの呼び出し時にJava 例外が派生したり、呼び出されたJava メソッドが呼び出し元に対して例外をthrow したりした場合に、その例外に関するJava トレースが出力されます。デフォルトでは、画面に出力されるようになっているため、
読み取れない可能性があります。ファイルに出力させるためには、Java オプションos400.stderr を設定してください。(これは、新しいジョブで実行する必要があることがあり、QIBM_RPG_JAVA_PROPERTIES 環境変数を ’-Dos400.stderr=file:stderr.txt;’ に設定することによって実行できます。)

[Top Pageに戻る]

Ads by TOK2