Calling Java Methods from ILE RPG
This section describes how to call Java™ methods from ILE RPG programs.
If the method is not a static method, then it is called an "instance method" and an object instance must be coded as an extra first parameter in order to call the method. For example, if an instance method is prototyped with one parameter, you must call it with two parameters, the first being the instance parameter.
- Java methods can be called using existing operation codes CALLP (when no return value is expected) and EVAL (when a return value is expected). When your RPG procedure attempts to make call to a Java method, RPG will check to see if the Java Virtual Machine (JVM) has been started. If not, RPG will start the JVM for you. It is also possible to start JVM yourself using the JNI function described in Creating the Java Virtual Machine (JVM)
- If you are using your own classes (or any classes outside the
normal java.xxx classes), be sure to have your CLASSPATH environment
variable setup before you call any Java methods.
When RPG starts up the JVM for you, it will add the classes in your
CLASSPATH environment variable to the standard classpath, so when
you use your own classes, Java will
be able to find them. Set the CLASSPATH environment variable interactively
like this:
The directories must be separated by colons.===>ADDENVVAR ENVVAR(CLASSPATH) VALUE('/myclasses/:/xyzJava/classes/')
- Normally, Java does its own garbage collection, detecting when an object is no longer needed. When you create objects by calling Java constructors from your non-native RPG procedure, Java has no way of knowing that the object can be destroyed, so it never destroys them. You can enable garbage collection for several objects at once by calling the JNI functions described in Telling Java to free several objects at once. If you know you are not going to need an object any more, you should tell this to Java by calling the JNI function described in Telling Java you are finished with a temporary object.
See Additional RPG Coding for Using Java for more information about the various JNI functions.
Example 1
In this example, the goal is to add two BigDecimal values together. In order to do this, two BigDecimal objects must be instantiated by calling the constructor for the BigDecimal class, fields must be declared to store the BigDecimal objects, and the add() method in the BigDecimal class must be called.
* Prototype the BigDecimal constructor that accepts a String
* parameter. It returns a new BigDecimal object.
* Since the string parameter is not changed by the constructor, we will
* code the CONST keyword. This will make it more convenient
* to call the constructor.
*
D bdcreate1 PR O EXTPROC(*JAVA:
D 'java.math.BigDecimal':
D *CONSTRUCTOR)
D str O CLASS(*JAVA:'java.lang.String')
D CONST
*
* Prototype the BigDecimal constructor that accepts a double
* parameter. 8F maps to the Java double data type and so must
* be passed by VALUE. It returns a BigDecimal object.
*
D bdcreate2 PR O EXTPROC(*JAVA:
D 'java.math.BigDecimal':
D *CONSTRUCTOR)
D double 8F VALUE
* Define fields to store the BigDecimal objects.
*
D bdnum1 S O CLASS(*JAVA:'java.math.BigDecimal')
D bdnum2 S O CLASS(*JAVA:'java.math.BigDecimal')
*
* Since one of the constructors we are using requires a String object,
* we will also need to construct one of those. Prototype the String
* constructor that accepts a byte array as a parameter. It returns
* a String object.
*
D makestring PR O EXTPROC(*JAVA:
D 'java.lang.String':
D *CONSTRUCTOR)
D bytes 30A CONST VARYING
*
* Define a field to store the String object.
*
D string S O CLASS(*JAVA:'java.lang.String')
*
* Prototype the BigDecimal add method. It accepts a BigDecimal object
* as a parameter, and returns a BigDecimal object (the sum of the parameter
* and of the BigDecimal object used to make the call).
*
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
*
* Define a field to store the sum. *
D sum S O CLASS(*JAVA:'java.math.BigDecimal')
D
D double S 8F INZ(1.1)
D fld1 S 10A
* Define a prototype to retrieve the String version of the BigDecimal
D getBdString PR O CLASS(*JAVA:'java.lang.String')
D EXTPROC(*JAVA:
D 'java.math.BigDecimal':
D 'toString')
* Define a prototype to retrieve the value of a String
D getBytes PR 65535A VARYING
D EXTPROC(*JAVA:
D 'java.lang.String':
D 'getBytes')
* Define a variable to hold the value of a BigDecimal object
D bdVal S 63P 5
Here is the code that does the call.
* Call the constructor for the String class, to create a String
* object from fld1. Since we are calling the constructor, we
* do not need to pass a String object as the first parameter.
*
C EVAL string =
C makestring('123456789012345678901234567890')
*
* Call the BigDecimal constructor that accepts a String
* parameter, using the String object we just instantiated.
*
C EVAL bdnum1 = bdcreate1(string)
*
* Call the BigDecimal constructor that accepts a double
* as a parameter.
*
C EVAL bdnum2 = bdcreate2(double)
*
* Add the two BigDecimal objects together by calling the
* add method. The prototype indicates that add accepts
* one parameter, but since add is not a static method, we
* must also pass a BigDecimal object in order to make the
* call, and it must be passed as the first parameter.
* bdnum1 is the object we are using to make the
* call, and bdnum2 is the parameter.
*
C EVAL sum = add(bdnum1:bdnum2)
* sum now contains a BigDecimal object with the value
* bdnum1 + bdnum2.
C EVAL bdVal =
C %DECH(getBytes(getBdString(sum)) : 63 : 5)
* val now contains a value of the sum.
* If the value of the sum is larger than the variable "val" can
* hold, an overflow exception would occur.
Example 2
This example shows how to perform a TRIM in Java by using the trim() method as an alternative to the ILE RPG %TRIM built-in function. The trim() method in the String class is not a static method, so a String object is needed in order to call it.
* Define a field to store the String object we wish to trim
*
D str S O CLASS(*JAVA:'java.lang.String')
D makestring PR O EXTPROC(*JAVA:
D 'java.lang.String':
D *CONSTRUCTOR)
D CLASS(*JAVA:'java.lang.String')
D parm 65535A CONST VARYING
*
* Prototype the String method getBytes which converts a String to a byte
* array. We can then store this byte array in an alpha field.
*
D getBytes PR 65535A EXTPROC(*JAVA:
D 'java.lang.String':
D 'getBytes') VARYING
*
* Prototype the String method trim. It doesn't take any parameters,
* but since it is not a static method, must be called using a String
* object.
*
D trimstring PR O CLASS(*JAVA:'java.lang.String')
D EXTPROC(*JAVA:
D 'java.lang.String':
D 'trim')
D fld S 10A INZ(' hello ') VARYING
The call is coded as follows:
* Call the String constructor
*
C EVAL str = makestring(fld)
*
* Trim the string by calling the String trim() method.
* We will reuse the str field to store the result.
*
C EVAL str = trimstring(str)
*
* Convert the string back to a byte array and store it
* in fld.
*
C EVAL fld = getBytes(str)
C EVAL fld = getBytes()
If the method does not return a value, use the CALLP operation code.