Pages

Monday, April 8, 2013

Calling AS/400 RPG Programs from Java

Effective SOA solutions take advantage of all the services available across the systems, which include the legacy systems in your organization. There are several ways you can integrate the existing services running on your legacy systems. This series of posts is about using the AS/400 services directly in your Java applications. I will be covering how to call RPG programs, AS/400 Commands and AS/400 DataQueues in your Java applications.

Fortunately IBM has provided a very nice easy to use library for communicating with the AS/400 server from Java. The IBM Toolbox for Java is a library of Java classes that give Java programs easy access to IBM iSeries data and resources. JT Open is the open source version of Toolbox for Java. You can go to JT Open link to download the full set of java libraries and some more details of how that can be used to easily communicate with the AS/400 server. There are several ways you can access the services on AS/400 server, most common are as follows.

All of these different methods of accessing the AS/400 services and have their own pros and cons. JT Open is a very powerful library and provides very easy to use APIs to communicate with the AS/400 services. These posts are about exploiting the JT Open libraries to use the AS/400 services. I am splitting these different approaches to separate posts. Click on the topic above to see the relevant post for that topic.

  • Calling AS/400 RPG Programme.

In this post, I am going to demonstrate how to execute the RPG programs from Java. First thing we need are the details of an RPG program that we will be calling from our Java client. For the purpose of this exercise we created a test RPG program in our AS/400 system that takes two parameters, one for input and one for output. The program takes the input parameter as the first name and tries to find the users with that name in the system and returns the last name of the user if it exists and ERROR if it fails to find the user. Here are the details of the program:


Program Name: RAZPGM.PGM 
Library Name: RAZA.LIB 
PGM Location: QSYS.LIB 

We have two options at our disposal here to call this same program from our Java application. One approach is to call this program directly using the ProgramCall class and the other option is to generate an XML document that contains all the information needed by AS/400 to call the program and pass it on to the AS/400. The first approach is easier and gives you more control whereas the XML approach is a lot more flexible. Both of these approaches are very easy to use. I did not create a performance benchmark for this exercise; however, my little tests did not show any significant difference in performance.

Using ProgramCall Class
One way of calling a RPG program from Java is to use the ProgramCall class in JT Open library that will seamlessly integrate the RPG program into your java application. Calling a program is fairly trivial, all you need to do is to create an AS/400 instance and pass it to the ProgramCall constructer and then call the program with list of parameters. Let's see how the ProgramCall class is used to call this RPG program.

package as400;

import java.util.Date;

import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400Message;
import com.ibm.as400.access.ProgramCall;
import com.ibm.as400.access.ProgramParameter;


/**
 * Test program to test the RPG call from Java.
 */
public class AS400Test {

 public static void main(String[] args) {  
  
  String server="yourserver.company.com";
  String user = "AS400USER";
  String pass = "AS400PWRD";

  String input = "RAZA";
  String fullProgramName = "/QSYS.LIB/RAZA.LIB/RAZPGM.PGM";

  AS400 as400 = null;
  
  try  {
   
   // Create an AS400 object  
   as400 = new AS400(server, user, pass);  

   // Create a parameter list
   // The list must have both input and output parameters
   ProgramParameter[] parmList = new ProgramParameter[2];  

   // Convert the Strings to IBM format
   byte[] inData = input.getBytes("IBM285");

   // Create the input parameter  
   parmList[0] = new ProgramParameter(inData);

   // Create the output parameter
   parmList[1] = new ProgramParameter(5);

   // Create a program object  
   // specifying the name of the  
   // program and the parameter list.  
   ProgramCall pgm = new ProgramCall(as400);  
   pgm.setProgram(fullProgramName, parmList);  

   // Run the program.  
   if (!pgm.run()) {  
    // If the AS/400 cannot run the  
    // program, look at the message list  
    // to find out why it didn't run.  
    AS400Message[] messageList = pgm.getMessageList();
    for (AS400Message message : messageList) {
     System.out.println(message.getID() + " - " + message.getText());
    }

   } else {  
    // Else the program ran. Process the  
    // second parameter, which contains  
    // the returned data.
    byte[] data = parmList[1].getOutputData();  
    String lastName = new String(data, "IBM285").trim();

    System.out.println("Output is " +  lastName);  
   }  

  } catch (Exception e) {  
   e.printStackTrace();  
  }finally{
   try{
    // Make sure to disconnect   
    as400.disconnectAllServices();  
   }catch(Exception e){}
  }  
  
  System.exit(0);  
 }  
}

And here is the out put of this program when you run it.


Output is ABIDI

Notice the parmList array of parameters. Each member of this array is an instance of ProgramParameter. Notice the difference between the first and second ProgramParameter() constructors. The first one takes an array of byte and the second one takes an integer. When you pass a byte array, that indicates this as an input parameter where the byte array contains the data that you want to pass on as a parameter to the RPG program. When just an integer is specified, it tells the program that this is an output parameter of the specified size.

Using PCML document
Another way is to create an XML document using the Program Call Markup Language (PCML) format that IBM has provided. This is essentially a simple XML document that you can pass on to the AS/400 system and the AS/400 will extract the program information and parameters from the XML document and will execute the program for you. Now let's see how the PCML works. Here is a sample PCML file that is using the same RPG program.


<pcml version="1.0">

  <!-- Program RAZPGM and its parameter list -->
  <program name="razpgm" path="/QSYS.LIB/RAZA.LIB/RAZPGM.PGM">
    <data name="firstName"    type="char"    length="4"    usage="input"    init="RAZA"/>
    <data name="lastName"     type="char"    length="5"    usage="output" />
  </program>

</pcml>

And here is the Java program that is using this PCML file to call the RPG program.


package as400;

import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400Message;
import com.ibm.as400.data.ProgramCallDocument;



/**
 * Test program to test the RPG call from Java using PCML.
 */
public class AS400XMLTest {

 public static void main(String[] argv){
  
  String server="yourserver.company.com";
  String user = "AS400USER";
  String pass = "AS400PWRD";
  
  AS400 as400 = null;

  try {
   
   // Create an AS400 object  
   as400 = new AS400(server, user, pass);
   
   // Construct ProgramCallDocument
   // First parameter is system to connect to
   // Second parameter is pcml resource name. In this example, 
   // PCML source file "qsyrusri.pcml" must be found in the classpath.
   ProgramCallDocument pcml = new ProgramCallDocument(as400, "qsyrusri.pcml");

   // Request to call the API
   // If return code is false, we received messages from the server
   if(!pcml.callProgram("razpgm")) {
    
    // If the AS/400 cannot run the  
    // program, look at the message list  
    // to find out why it didn't run.  
    AS400Message[] msgs = pcml.getMessageList("razpgm");
    
    for (AS400Message message : msgs) {
     System.out.println(message.getID() + " - " + message.getText());
    }
    
   }else{
    
    // Return code was true, call to RAZPGM succeeded
    // Write the results to standard output
    Object value = pcml.getValue("razpgm.lastName");
    System.out.println("Output is " +  value);  
   }
   
  }catch (Exception e){
   e.printStackTrace();
  }finally{
   try{
    // Make sure to disconnect   
    as400.disconnectAllServices();  
   }catch(Exception e){}
  }

  System.exit(0);
 }
}

Note here that in the java program we are not passing any parameters. The parameter value is provided in the XML document. Also note that the program name and the parameter names are referenced using the name of the program in the tag of the XML document. Rest of the XML document is pretty self-explanatory.

And here is the output when this program is executed.


Output is ABIDI

These are the very basics of how to use the IBM Toolbox for Java to communicate with programs in AS/400. For more details and advanced topics you can consult the IBM programmers guide. To view or download the PDF version of this document, select IBM® Toolbox for Java™ (about 3100 KB).

No comments:

Post a Comment