RPG Native Methods

To define an RPG native method, you code the prototype the same way as you would code the prototype for an ordinary Java™ method. Then, you write the RPG subprocedure normally. You must code the EXPORT keyword on the Procedure-Begin Specification for the native method.

You must have your native methods in a service program in your library list. In your Java class that is calling your native methods, you must have a static statement like this:
       static
       {
            System.loadLibrary ("MYSRVPGM");
       }       
This will enable Java to find your native methods. Aside from adding *JAVA and the class to the EXTPROC keyword for the prototype of a native method, you write your native method like any subprocedure. Figure 1 is an example of a Java class that calls a native method.
CAUTION:
If you are using environment variables to control how the JVM is started, you must be sure that the environment variables exist in the job before any RPG programs call Java methods. If you use ADDENVVAR LEVEL(*SYS), the environment variable will be added at the system level, and by default, every job will start with that environment variable set. If you do this, be sure that the classpath includes all the directories containing the Java classes that may be needed by any application on the system.
Figure 1. Java Class Calling a Native Method
       class MyClass
       {

          static
          {
            System.loadLibrary ("MYSRVPGM");
          }

         native boolean checkCust (byte custName[]);

          void anotherMethod ()
          {
             boolean found;
             // call the native method
             found = checkCust (str.getBytes());
           }
        }      

Figure 2 is a prototype of an RPG native method.

Figure 2. RPG Native Method Prototype
D checkCust       PR              N   EXTPROC(*JAVA
D                                           : 'MyClass'
D                                           : 'checkCust')
D   custName                   100A   VARYING CONST 

The native method itself is coded just like any subprocedure. Figure 3 is an example of a native method coded in RPG.

Figure 3. Native Method Coded in RPG
P checkCust       B                   EXPORT
D checkCust       PI              N
D   custName                   100A   VARYING CONST
 /free   chain custName  rec;
   return %found;
 /end-free
P checkCust       E      
Java calls your service program from the default activation group. If your service program is created with activation group *CALLER, it will run in the default activation group. This can sometimes cause problems:
  • If you are debugging your native methods, and you want to make a change to the code, you will have to sign off and sign back on again before Java will see the new version.
  • If you are calling other procedures in the service program from other RPG code that is not running in the default activation group, then you will not be able to share any global variables between the "ordinary procedures" and the native methods. This scenario can arise if a procedure in your RPG service program sets up some global variables, and then calls a Java class which then calls a native method in that service program. Those native methods will not see the same data that the first procedure set up.

If you create any Java objects in your native methods, by default they will be destroyed by Java when the native method returns. If you want the object to be available after the native method returns (for example, if you want to use it from another native method later), then you must tell Java that you want to make a global reference, by calling the JNI wrapper procedure getNewGlobalRef . When you are finished with the global reference, you will call JNI wrapper procedure freeGlobalRef, so Java can reclaim the object. See Telling Java you want an object to be permanent and Telling Java you are finished with a permanent object for more information about these wrapper procedures.

If your RPG native method ends abnormally with an unhandled exception, the RPG compiler will throw an exception to Java. The exception is of class java.lang.Exception, and has the form RPG nnnnn, where nnnnn is the RPG status code.
              try
              {
                 nativeMethod ();
              }
              catch (Exception exc)
              {
                 …
              }