AS/400 or iSeries™ is a midrange business server system from IBM®. RPG and COBOL were the popular languages for the original AS/400 applications development, and now, IBM Toolbox for Java (JTOpen) is the set of Java application program interfaces (APIs) exposed by IBM to open up the legacy world of iSeries. To encourage open systems and cross-platform development, JTOpen is distributed for free and is open source. JTOpen contains APIs to execute programs, commands, access data queues/data areas, and so forth on iSeries using Java programs. This article provides a new dimension to expose Legacy AS/400 elements to the open world.
If a company uses RPG programs for order processing, it's generally because the company wants to integrate the RPG programs with suppliers around the world. For example, an order is sent as postal mail and is manually typed into the AS/400 system using a console program. When the CIO wants to do this, he or she is given a choice of developing a Web site, which all suppliers can access but cannot integrate with disparate, existing systems -- one has JSP web site, another ASP.Net, and another uses a custom C++ program. Another possible solution is to expose it as a web service. This solves the client program problem because SOAP/XML are industry standards. The console program and suppliers can call the RPG program with minimal extra code change at the supplier client resulting in no charge to the company. This method of exposing legacy AS/400 programs is reliable since it uses JTOpen with IBM support and is easier for Java developers due to awareness of open standards like web services.
You can also expose data queues and data areas as web services. Data queue read/write operations can be specified by a SOAP message, which in turn can be materialized on an iSeries machine using data queue APIs provided by JTOpen. A more simple web service would be to execute commands (or a batch of commands) on iSeries using a web service command.
Integration of AXIS with Tomcat
Let?s now look at how to invoke an iSeries COBOL program through Tomcat and AXIS (Apache eXtensible Interaction System). Tomcat is a container that provides an environment for Java code to run in the web server.
Tomcat is developed in an open, participatory environment and released under the Apache software license. Tomcat is a collaboration of the best-of-breed developers from around the world.
AXIS is essentially a SOAP engine; it's more like a framework for constructing SOAP processors such as clients, servers, and gateways. AXIS includes a server that plugs into a servlet container, such as Tomcat. It has an extensive support for the Web Services Description Language (WSDL) and has an emitter tool for generating Java classes from WSDL, and vice versa.
You need to at least have Tomcat 4.1.x with its full distribution. If not, download the Xecers 2.5.x parser and include the JARs. You'll also need the Java Activation Framework (JAF-1.0.x), Java Software Development Kit (SDK) 1.4. x, and AXIS 1.1. With an assumption of C:/ as your root directory, you need to copy C:\axis-1_1\webapps\axis to C:\jakarta-tomcat-4.1.30\webapps.
Make sure you include all the jt400 JARs of IBM iSeries and Access for Windows® for the implementation class to use it. When you're done, set up the CLASSPATH for the above mentioned directory structure of Tomcat. You can set the CLASSPATH similar to the examples below, or it can be set in your own way.
set AXIS_HOME= C:\jakarta-tomcat-4.1.30\webapps\axis\WEB-INF |
set AXIS_LIB=%AXIS_HOME%\lib\ |
set AXISCLASSPATH=%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery.jar; |
Getting started creating a web service
When you complete the steps above, you'll be ready to create a web service, which invokes the COBOL program in the iSeries server.
Web services are technologies that allow applications to communicate with each other in a language and platform-independent manner. It?s just a software interface that describes a collection of operations that you can access over a network through standardized XML messaging. Web services provide the freedom of change and evolution over time, as long as it has an appropriate interface. The versatility of XML makes web services different from other component technologies in that it allows the separation of syntax from semantics. It also allows Web services to be processed and understood by each service and the environment it exists in. Here objects can be defined as services, communicating with other services in an XML-defined grammar whereby each service then translates and analyzes the message according to its local implementation and environment.
The main objective of using a Web service is that it provides existing or legacy software applications with service interfaces without changing the original applications, allowing them to fully operate in the service environment.
Figure 1 below describes the scenario of invoking the COBOL program in an iSeries server using a Web service where there is no change in the existing application (COBOL program), nor is there any change in the Java program which invokes the application. Through the Web service, you're just providing an interface through which the applications can communicate with each other.
We?re using the tools mentioned above for creating such a scenario, but they should be compatible with other Web services development tools as well. Tomcat is used as a Web server for deploying the service, and AXIS (a popular Web service development kit) is used for developing the service.
Figure 1. Layout of invoking a COBOL program in iSeries using a Web service
As a simple scenario, you can take a Java program with user name as"test" and password as " test400" that invokes the COBOL program in the IFS path: /QSYS.LIB/PNPLIB.LIB/RKCB6STCPW.PGMin. To invoke the COBOL program in an iSeries server, the Java program takes two strings as input parameters that need to be passed as AS400Text objects. After swapping the two given strings, the results are extracted using getOuptData () method. To know more about iSeries data conversions, visit the iSeries Information Center.
Creating the intended Web service
Listing 1 illustrates the Java code to invoke the iSeries program.
Listing 1. Simple Java code to invoke the iSeries program (InvokeCB6STSwap1.java)
import com.ibm.as400.access.*;
public class InvokeCB6STSwap1{
public String[] dowebserviceswap(String i1, String i2){
String[] swap_string= new String[]{"",""};
ProgramCall pgm =null;
try{
// declare and instantiate parameterlist
ProgramParameter[] paramlist = new ProgramParameter[2];
// creating an AS400 Text object
AS400Text txt = new AS400Text(10);
paramlist[0] = new ProgramParameter(txt.toBytes(i1),10);
paramlist[1] = new ProgramParameter(txt.toBytes(i2),10);
System.out.println("In/p1:"+ i1+ " "+ paramlist[0].getInputData());
System.out.println("In/p2:"+ i2+ " "+ paramlist[1].getInputData());
String programName = "/QSYS.LIB/PNPLIB.LIB/RKCB6STCPW.PGM";
// Create an AS400 object.
AS400 conn = new AS400("testmachine","test","test400");
// Create a program call object.
pgm = new ProgramCall(conn);
// Constructor to through which program name
and parameterlist is passed.
pgm.setProgram(programName, paramlist);
if (pgm.run() != true) {
System.out.println("Messages");
AS400Message[] messageList = pgm.getMessageList();
StringBuffer strBuff = new StringBuffer ();
for (int i = 0; i < messageList.length; i++)
{strBuff.append(messageList[i].getText());}
System.out.println("printing Error: " +strBuff.toString());
}else {
String o1 = (String) txt.toObject(paramlist[0].getOutputData());
String o2 = (String) txt.toObject(paramlist[1].getOutputData());
System.out.println("O/p1:"+ o1);
System.out.println("O/p2:"+ o2);
swap_string = new String[]{o1,o2};
AS400Message[] messageList = pgm.getMessageList();
StringBuffer strBuff = new StringBuffer ();
for (int i = 0; i < messageList.length; i++){
strBuff.append(messageList[i].getText());}
System.out.println("printing strBuff: " +strBuff.toString());
}
System.out.println(" After run \n");
} catch (Exception e){
System.out.println("Program " + pgm.getProgram() + " issued an exception!");
e.printStackTrace();
}
return swap_string;
}
} |
Defining the deployment descriptor
To convert the above Java program into a Web service using custom deployment, you need to define a deployment descriptor. A deployment descriptor tells you about the service name, service provider, parameter name, and its value where the parameter name specifies the class name and the methods that need to be exposed as a Web service interface for users to access the service. Listing 2 illustrates the code for the deployment descriptor.
Listing 2. deployment descriptor (deploy.wsdd)
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java= |
When you?re finished, use the command below to deploy the service in the server. You also need to set the appropriate CLASSPATH as mentioned above.
>java org.apache.axis.client.AdminClient deployswap.wsdd |
If you're successful in deploying the service, the following message appears in the command prompt.
Processing file deployswap.wsdd |
<Admin>Done processing</Admin> |
Then you can view the list of services deployed in the AXIS server and the WSDL document generated by the server, which describes the service. The client then invokes the service only by finding description given in the WSDL document in the simple scenario. Figure 2 shows the List of services deployed in AXIS and Figure 3 shows the WSDL document generated by the server.
Figure 2: List of Services deployed in AXIS
Figure 3. WSDL document generated by the server
Build a client to invoke the service
When you can view the WSDL document of the intended service, the server side is over and you're now ready to build a client to invoke the service. There are two ways to build a client: one is to do it as an ordinary console client and the other as a servlet client. Listing 3 illustrates the code for the console client.
Listing 3. Console client code to invoke the service
import java.net.URL;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import javax.xml.rpc.ParameterMode;
public class ClientCB6STSwap{
public static void main(String args[])throws Exception{
//tells us about the target service
String endpoint="http://localhost:8080/axis/services/InvokeCB6STSwap1";
String returnval[];
String i1= new String("Rajesh");
String i2= new String("Logic2");
System.out.println("Input given");
System.out.println(i1);
System.out.println(i2);
Service service = new Service();
//Creates a service object to call the service
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new URL(endpoint));
call.setOperationName("dowebserviceswap");//Passing the method name
call.addParameter("op1",XMLType.XSD_STRING,ParameterMode.IN); |
Once you compile the code, you need to deploy it in the server to access the service. To deploy the service, copy the class file into C:\jakarta-tomcat-4.1.30\webapps\axis\WEB-INF\classes. You're now ready to access the service, as shown in Figure 4 below.
Figure 4: When invoked through the console client
Now, you?re ready to build a servlet client for invoking the Web service. Listing 4 illustrates the servlet code for receiving the input and Listing 5 illustrates the servlet code for invoking the service.
Listing 4. Servlet client for receiving the input (ClientCB6STServlet1.java)
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class ClientCB6STServlet1 extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws IOException,ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<Html>");
out.println("<Head>");
out.println("<Title> SWAP WebService");
out.println("</Title >");
out.println("</Head>");
out.println("<Body background=
\"C:/Documents and Settings/Administrator/Desktop/gray_fabric.gif\">");
out.println("<H1 align=\"center\" > SWAP WEBSERVICE");
out.println("<Form name=\"client1\" method=
\"get\" action=\"http://localhost:8080/servlet/ClientCB6STServlet\">");
out.println("<BR>");
out.println("<i>");
out.println("The Strings Before Swapping");
out.println("</i>");
out.println("</BR>");
out.println("<Br>");
out.println("<i>");
out.println("First String:");
out.println("</i>");
out.println("<Input type= text name=\"str1\" >");
out.println("</Br>");
out.println("<Br>");
out.println("<i>");
out.println("Second String:");
out.println("</i>");
out.println("<Input type=text name=\"str2\">");
out.println("</Br>");
out.println("<Br>");
out.println("<Input type=submit value=\"Submit\" >");
out.println("</Br >");
out.println("</Form >");
out.println("</H1>");
out.println("</Body>");
out.println("</Html>");
}
} |
Listing 5. Servlet client for invoking the service
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import javax.xml.rpc.ParameterMode;
public class ClientCB6STServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws IOException,ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String[] result= new String[]{};
String first_str= request.getParameter("str1"); //Receiving the parameter1
String second_str = request.getParameter("str2");//Receiving the parameter2
try{
result=doWebServiceCall(first_str,second_str);
//calling the method to invoke the WS
}catch(Exception exp){}
out.println("<Html>");
out.println("<Head>");
out.println("<Title> SWAP WebService");
out.println("</Title>");
out.println("</Head>");
out.println("<Body background=
\"C:/Documents and Settings/Administrator/Desktop/gray_fabric.gif\">");
out.println("<H1 align=\"center\"> SWAP WEBSERVICE");
out.println("<Form name=\"client2\" method=\"get\" ");
out.println("<BR>");
out.println("<i>");
out.println("The Strings After Swapping");
out.println("</i>");
out.println("</BR>");
out.println("<Br>");
out.println("<i>");
out.println("First String:");
out.println("</i>");
out.println("<Input type=text value=" +result[0]+ ">");
out.println("</Br>");
out.println("<Br>");
out.println("<i>");
out.println("Second String:");
out.println("</i>");
out.println("<Input type=text value=" +result[1]+ ">");
out.println("</Br>");
out.println("</Form>");
out.println("</H1>");
out.println("</Body>");
out.println("</Html>");
}
public String[] doWebServiceCall(String i1, String i2) throws Exception{
String[] ret_value;Service service = new Service();
//Creating a service object
Call call =(Call)service.createCall();
//making a call through the service object
call.setTargetEndpointAddress
("http://localhost:8080/axis/services/InvokeCB6STSwap1");
call.setOperationName("dowebserviceswap");
//invoking the exposed method.
call.addParameter("op1",XMLType.XSD_STRING,ParameterMode.IN);
call.addParameter("op2",XMLType.XSD_STRING,ParameterMode.IN);
//invoking the service and capturing the return value
call.setReturnType(XMLType.XSD_QNAME,String[].class);
ret_value=(String[])call.invoke(new Object[] {i1, i2});
return ret_value;
}
}
|
Since you're going to deploy the servlet in a different directory of the servlet container, you need to take certain steps when coming to the servlet client.
- You need to add all the JARs found in the AXIS to the default directory of the servlet container. The default directory of the servlet container is C:\jakarta-tomcat-4.1.30\webapps\ROOT\WEB-INF\lib. If you cannot find the default directory, create one using the same name.
- Similarly, you need to add the Client Access JARs to the above directory.
- Place all the class files of the servlet in C:\jakarta-tomcat-4.1.30\webapps\ROOT\WEB-INF\classes. If you cannot find the class directory, just create one using the same name.
When all steps are complete, you can now test the Web service with a servlet client. If you followed all the steps correctly, then you should be able to access the service, as shown in Figure 5 and Figure 6 below.
Figure 5. Servlet client for receiving the input
Figure 6. Servlet client after invoking the service
In terms of reusability, the method described in this article can be used across:
- All AS/400 applications
- All programs (PGMS)
- All databases (using JDBC classes of JTOpen)
- All AS/400 objects (PGMs, data queues, data areas, with/without PCML
- Across various Web service client languages due to SOAP/XML
It also provides both external and internal security:
- External -- application specific username and password, which will be a part of client application
- Internal -- using AS/400 authentication
Invoking an iSeries program through a Web service isn't a very difficult task. In fact, you only need to take care of the initial setup for creating such an application. The scenario we illustrate in this article uses very simple data types, but you can use the same scenario for complex data types, providing good data binding techniques. It's also compatible with other Web services tools. AXIS is one of the popular tools in the industry for creating a Web service, but other tools are also available. To learn more about the tools used, Web services, and Client Access, visit the links provided in the Resources section of the article.
| Description | Name | Size | Download method |
|---|---|---|---|
| Download the files used in this article | ws-sharenet.zip | 14KB | HTTP |
Information about download methods
- Visit the Apache Web site for more information about AXIS.
- Check out the IBM iSeries Information Center for up-to-date, techical information on iSeries.
- Download IBM WebSphere® Business Integration Adapters -- Adapter for iSeries User Guide for detailed information regarding installation, configuration, and business object development for the IBM WebSphere Business Integration Adaptor for iSeries.
- New to Web services? Browse the New to Web services main page to get a head start.
- Visit Ammai.com find resources to help you learn and use Web services technologies.
- Browse for books on these and other technical topics.
- Get involved in the developerWorks community by participating in
developerWorks blogs.
- Want more? The developerWorks SOA and Web services zone hosts hundreds of informative articles and introductory, intermediate, and advanced tutorials on how to develop Web services applications.
Amutha Hariramakrishnan is a project trainee at IBM Software Labs, Bangalore, India. She is currently working in the Adapters Dedicated Development Center. She holds a MS degree in Computer Applications from PSG College of Technology. Her areas of interest include Web services and autonomic computing. You can contact Amutha at amuthah@in.ibm.com.
Rajesh Kalyanaraman works as a Software Engineer at IBM Software Labs, Bangalore, India. He is currently working in the business integration domain on Java technologies. He has good experience in both legacy and open systems. He has written a book on voice user interfaces and has penned many articles. His interests include autonomic computing, business integration, and intelligent interfaces. You can contact Rajesh at rajeshka@in.ibm.com.




