VIII. Create a utility Java class to process the iBatis

advertisement
RPG API Web Service Tutorial
By Don Denoncourt
CAS Severn, Inc.
ddenoncourt@cassevern.com
I.
II.
III.
IV.
Create the SQL Stored Procedure over the RPG API.
Create the Web service host and client Web projects in WDSc.
Create the Account JavaBean to hold values returned from the RPG API.
Download the IBM Toolbox for Java [jt400.jar] from the iSeries to your
WDSc projects
V.
Download the iBatis jar files to your WDSc projects
VI.
Create the iBatis configuration XML specify the JDBC connection data and
xml specific to the WebService
VII. Create the iBatis XML to associate the SQL Stored Procedure with the Java
Accounts “data structure” JavaBean
VIII. Create a utility Java class to process the iBatis configuration XML
IX.
Create the GetAccount JavaBean that wraps a call to the RPG API and
builds an array of Account objects.
X.
Create a JUnit test and test the utility.
XI.
Create the Search Accounts Web Service.
XII. Consume the Search Accounts Web Service
XIII. Testing the Client Web Applications Web Service Proxy classes with a JSP
I. Create the SQL Stored Procedure over the RPG API.
1. Upload or key the GETACCTS RPG that is in the appendix of this article and
compile it to [yourlib]
2. From a 5350 command line, key STRSQL and press Enter
3. In the SQL editor, key CREATE PROCEDURE and press F4
4. Key the following and press Enter
 Procedure: GETACCTS
 Library: [yourlib]
 RESULT SETS: 1
 Language: RPGLE
 PARAMETER STYLE: 1
5. In the second panel, key the following and press Enter:
 Program: getaccts
 Library: [yourlib]
6. In the subfile panel, key the following three entries and press Enter:
Usage
Parameter Type Length
Scale
IN
kount
DEC 5
0
OUT
error
CHAR 1
OUT
errorMsg CHAR 50
7. The SQL Stored Procedure should then be created. Look over the SQL syntax for
a moment. In a production environment I would suggest copying and pasting that
statement to comment lines in the RPG (which is in the appendix at the end of the
tutorial.)
II. Create the Web service host and client Web projects in WDSc.
1. To start WDSc, in the lower left-hand corner of Windows, click Start|All
Programs|IBM Rational|IBM WebSphere Development Studio
Client for iSeries V6.0|IBM WebSphere Development
Studio Client for iSeries. If you are prompted for workspace, accept
the default value and click OK.
2. From WDSc’s main application menu, select File|New|Project…
3. In the New Project/Select a wizard panel, select Dynamic Web Project
4. In the New Dynamic Web Project panel.
 Click the Show Advanced button
 Key a name of WebServiceHost (note that the Context Root will
automatically be changed to be the same as the project name.)
 Change the Servlet version to 2.3
 Change the Target server to WebSphere Application Server
v5.1 Express (the WAS 5.1 Test Environment in on
two “Optional Software” CDs in your WDSc 6.0
installation CD set.)
 Click Finish
 If you are prompted with “Confirm Perspective Switch” Click Yes
5. Run the wizard again and create a project called WebServiceClient
 Be sure to specify Servlet version 2.3 and Target server of WebSphere
v5.1 Express
Note that this lab is using WebSphere v5.1 Express only to circumvent problems
with WebSphere 6.0 when multiple WDSc projects from multiple labs add and
remove and otherwise confuse WebSphere 6.0 to the point that it is unusable
without administration.
III. Create the Account JavaBean to hold values returned from the RPG API.
1. In Project Explorer (see Figure 1 below,)select the WebServiceHost project, open
the Java Resources/JavaSource folder, right-click on that folder, and select
New|Class.
2. In the New Java Class panel, key the case-sensitive Package of
com.denoncourt
3. Key the case-sensitive Name of Account
4. Click Finish.
5. WDSc will open the newly created Account.java file in the Java editor.
6. Between the class’s curly braces, add
private String number = null;
private String name = null;
private String balance = null;
public Account() {}
7. File|Save to force a compile.
8. To generate the required getter and setter functions in the JavaBean you will use a
WDSc wizard. In Project Explorer, expand WebServiceHost/Java
Resources/JavaSource/com.denoncourt/Account.java/Account; select the
balance, name, and number nodes (see Figure 2); then right-click and select
Source|Generate Getters and Setters.
9. In the Generate Getters and Setters panel, accept the defaults to generate getter
and setters for all three fields, and click OK.
10. File|Save and the Account.java class is now ready to hold information returned
from the RPG API.
Figure 1: WDSc’s Project Explorer view
Figure 2: The Account class’s balance, name, and number private attributes in the Project
Explorer view.
IV. Download the IBM Toolbox for Java [jt400.jar] from the iSeries to your WDSc
projects
1. Open a DOS window, click Start, click Run…, and key CMD
2. Write down of the directory name as you will later need to traverse to that
directory from Windows Explorer.
3. FTP to the iSeries, change the IFS directory, and download the toolbox in binary
mode with the following steps:
 C:\Documents and Settings\username>ftp [host name
or ip of your iSeries]
 ftp> cd /qibm/proddata/http/public/jt400/lib
 ftp> bin
 ftp> get jt400.jar
 ftp> quit
 C:\Documents and Settings\username>exit
4. Now you need to copy the jt400 jar file to the WebService projects in WDSc
 Open Windows Explorer, by right mousing on the Windows Start button
and selecting Explore
 Traverse to the directory noted in step 2)
 Find jt400.jar, select it, right mouse and select Copy
5. In WDSc’s Project Explorer, traverse to Dynamic Web Projects,
WebServiceHost, WebContent, WEB-INF, lib
6. Right mouse on lib and select paste
V. Download the iBatis jar files to your WDSc projects
Downloads are available from http://ibatis.apache.org/javadownloads.html
1. Open a DOS window, click Start, click Run…, and key CMD
2. Write down of the directory name as you will need to traverse to that directory
from Windows Explorer.
3. In Windows Explorer (right mouse on the Windows Start button and select
Explore,) traverse to the download directory and extract the iBatis download.
4. Under the extracted directory called iBatis/lib you will see three downloaded
iBatis jar files. Copy these to the WebService projects in WDSc
 Select the three iBatis jar files in Windows Explorer, right mouse, and
select Copy
5. In WDSc’s Project Explorer, traverse to Dynamic Web Projects,
WebServiceHost, WebContent, WEB-INF, lib
 Right mouse on lib and select paste
VI. Create the iBatis configuration XML specify the JDBC connection data and xml
specific to the WebService
1. In WDSc’s Project Explorer, traverse to Dynamic Web Projects,
WebServiceHost, Java Resources, JavaSource, com.denoncourt
2. Right mouse on com.denoncourt and select New|Other…
3. Click Show All Wizards
4. Expand the XML folder, select XML, and click Next
5. Click the Create XML file from scratch and click Next
6. Key a case-sensitive File name of sqlMapConfig.xml and click Finish
7. When the xml opens in WDSc’s editor replace its contents with:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC
"-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property name="JDBC.Driver"
value="com.ibm.as400.access.AS400JDBCDriver"/>
<property name="JDBC.ConnectionURL"
value="jdbc:as400://YourISeriesIP/yourlib"/>
<property name="JDBC.Username" value="yourusername"/>
<property name="JDBC.Password" value="yourpassword"/>
</dataSource>
</transactionManager>
<sqlMap resource="com/denoncourt/Account.xml"/>
</sqlMapConfig>
Replace YourISeriesIP, yourusername, and yourpassword
8.
9. File|Save or Control-S to save the file.
VII. Create the iBatis XML to associate the SQL Stored Procedure with the Java
Accounts “data structure” JavaBean
1. In WDSc’s Project Explorer, traverse to Dynamic Web Projects,
WebServiceHost, Java Resources, JavaSource, com.denoncourt
2. Right mouse on com.denoncourt and select New|Other…
3. Click Show All Wizards
4. Expand the XML folder, select XML
 If you are prompted with a “Confirm Enablement” dialog, click OK
 Click Next
5. Click the Create XML file from scratch and click Next
6. Key a case-sensitive File name of Account.xml and click Finish
7. When the xml opens in WDSc’s editor replace its contents with the following:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="Account">
<parameterMap id="entryPList" class="java.util.Map" >
<parameter property="count" jdbcType="NUMERIC"
javaType="java.math.BigDecimal" mode="IN"/>
<parameter property="errorCode" jdbcType="CHAR"
javaType="java.lang.String"
mode="OUT"/>
<parameter property="errorDesc" jdbcType="CHAR"
javaType="java.lang.String"
mode="OUT"/>
</parameterMap>
<resultMap id="resultMap" class="com.denoncourt.Account">
<result property="number" column="AccountNo"/>
<result property="name"
column="AccountName"/>
<result property="balance" column="Balance"/>
</resultMap>
<procedure id="getAccounts" parameterMap="entryPList"
resultMap="resultMap">
call yourlib.getaccts(?,?,?)
</procedure>
</sqlMap>
8. Change the call statement to specify the library procedure name you specified
when you created the stored procedure.
9. Save the file
VIII. Create a utility Java class to process the iBatis configuration XML
1. In Project Explorer, select the WebServiceHost project, expand the Java
Resources/JavaSource folder, select JavaSource, right-click and select New|Class.
2. In the New Java Class panel, key a case-sensitive Package of
com.denoncourt, key a case-sensitive name of SqlConfig and click Finish.
3. WDSc will open the newly created SqlConfig.java file in the Java editor.
4. Replace the contents of the file with the following:
package com.denoncourt;
import java.io.Reader;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
public class SqlConfig {
private static final SqlMapClient sqlMap;
static {
try {
String resource =
"com/denoncourt/sqlMapConfig.xml";
Reader reader =
Resources.getResourceAsReader(resource);
sqlMap =
SqlMapClientBuilder.buildSqlMapClient(reader);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(
"Error initializing SqlConfig class. Cause: "
+ e);
}
}
public static SqlMapClient getSqlMapInstance() {
return sqlMap;
}
}
5. Save the file
IX. Create the GetAccount JavaBean that wraps a call to the RPG API and builds an
array of Account objects.
1. In Project Explorer, select the WebServiceHost project, open the Java
Resources/JavaSource folder, then right-click and select New|Class.
2. In the New Java Class panel, key a case-sensitive Package of
com.denoncourt
3. Key a case-sensitive Name of GetAccounts
4. Click Finish.
5. WDSc will open the newly created GetAccounts.java file in the Java editor.
6. Replace the file contents with:
package com.denoncourt;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import com.ibatis.sqlmap.client.SqlMapClient;
public class GetAccounts {
private static SqlMapClient sqlMap =
SqlConfig.getSqlMapInstance();
public Account[] search(final int count)
throws IllegalArgumentException, SQLException
{
HashMap entryPList = new HashMap();
entryPList.put("count", new BigDecimal(count));
entryPList.put("errorCode", null);
entryPList.put("errorDesc", null);
List list = sqlMap.queryForList(
"getAccounts",
entryPList);
String errorCode =
(String)entryPList.get("errorCode");
if (errorCode.charAt(0) == '1') {
String message =
(String)entryPList.get("errorDesc");
throw new
IllegalArgumentException(message.trim());
}
return (Account[])list.toArray(new Account[0]);
}
}
7. Save the file.
X. Create a JUnit test and test the utility.
This step is used to be sure the Java code works before generating a WebService and
having it fail within a more complex environment.
Select the GetAccounts.java file in the Project Explorer view
Right mouse and select New|Other
In the Select a wizard panel, select Java|Junit|JUnit Test Case and click Next
When you get the popup ‘The JUnit library “junit.jar” is not in the build path. Do
you want to add it?’ Click Yes.
5. In the New JUnit Test Case panel, accept the defaults and click Finish
6. Replace the generated GetAccountsTest source with:
1.
2.
3.
4.
package com.denoncourt;
import java.sql.SQLException;
import com.denoncourt.Account;
import junit.framework.TestCase;
public class GetAccountsTest extends TestCase {
public void testSearch() {
GetAccounts rpg = new GetAccounts();
Account[] accounts = null;
try {
accounts = rpg.search(5);
} catch (SQLException e) {
fail(e.toString());
}
assertEquals(5, accounts.length);
for (int i = 0; i < accounts.length; i++) {
assertEquals(Integer.toString(i+1),
accounts[i].getNumber());
assertEquals("Denoncourt",
accounts[i].getName().trim());
assertEquals(Integer.toString(i+1)+".00",
accounts[i].getBalance());
}
try {
accounts = rpg.search(105);
} catch (IllegalArgumentException iae) {
assertEquals("Invalid Count", iae.getMessage());
} catch (SQLException e) {
fail(e.toString());
}
}
}
7. File|Save
8. To run the test, in the Project Explorer view, select GetAccountsTest, right-mouse
and select Run|JUnit Test.
9. Click on the JUnit tab in the lower portion of WDSc, you should see a long green
bar to identify success.
XI. Create the Search Accounts Web Service.
1. In Project Explorer, in the WebServiceHost project,.select GetAcounts.java
2. Right-click and select Web Services|Create Web Service.
3. In Web services dialog, leave the Web service type as JavaBean Web service,
select Generate a Proxy, and uncheck Start Web service in Web Project.
4. Click Finish.
 The wizard will create a set of Web service classes and deploy the services to the
WebServiceHost Web application.
 The wizard will also generate a WebSphere profile as shown in Figure 3.
5. In the Servers view, select the generated “WebSphere Express v5.1 Test
Environment,” right-mouse and select Publish.
6. When the “Publishing successful” dialog is displayed, click OK.
Figure 3: The Servers view lists WebSphere profiles available for deployment and test of
Web services.
XII. Consume the Search Accounts Web Service
The web service will be used by a different project – to simulate a web application on a
different machine in a different network.
1. In Project Explorer, traverse to the WebServiceHost project’s
WebContent/wsdl/com/denoncourt folder, select GetAccounts.wsdl
directory, right-click and select Web Services|Generate Client
2. In the Web Service panel, leave Client proxy type at the default of Java
proxy, check the ”Overwrite files without warning,” and
”Create Folders when necessary” checkboxes and click Next
3. In the Web Service Selection Page panel, accept the default WSDL and click Next
4. In the Client Environment Configuration panel, change the Client project
dropdown to specify WebServiceClient, and click Finish



The client java proxy code will be generated in WebServiceClient/Java
Resources/JavaSource/.
Those classes were completely generated with information in the WSDL. The
classes do not have the ability to call the stored procedure on the iSeries.
All the classes know how to do is to communicate, via the low-level SOAP
protocol, to a Web Service called GetAccounts and build Account JavaBean
objects from the response
XIII. Testing the Client Web Applications Web Service Proxy classes with a JSP
There are only three classes, of the ten proxy classes generated, in the WebServiceClient
project that you need to be aware of.
 The first is the Account class, which is simply a JavaBean that holds the
account information returned by the Web service.
 The second is the GetAccountsServiceLocator, which is used to find and get a
handle to the get accounts web service out in the Web world.
 The third is the GetAccounts class which proxies the GetAccounts Web
service provided by the WebServiceClient web application.
These three classes can easily be used in a client application to request account
information. For example:
Account[] accts =
new GetAccountsServiceLocator().getGetAccounts().search(5);
To see how you might use the Web Service proxies in a JSP:
1. In Project Explorer, open the WebServiceClient project, select the WebContent
folder, then right-click and select New|JSP File
2. In the New JSP file panel, key a File Name of TestGetAccounts.jsp and
click Finish.
3. In the JSP editor, click the Source tab and replace the contents of
TestGetAccounts.jsp with:
<%@ page import="com.denoncourt.*" %>
<HTML>
<BODY>
<%
int kount = 0;
try {
if (request.getParameter("count") != null) {
kount = java.lang.Integer.parseInt(request.getParameter("count"));
Account[] accts = new GetAccountsServiceLocator().
getGetAccounts().search(kount);
%>
<table >
<tr><th>Num</th><th>Name</th><th>Balance</th></tr>
<% for (int i = 0; i < accts.length; i ++) { %>
<tr>
<td> <%= accts[i].getNumber() %> </td>
<td> <%= accts[i].getName() %> </td>
<td> <%= accts[i].getBalance() %> </td>
</tr>
<% } /* close for loop */ %>
</table>
<% } /* if count in HTTP request */
} catch (Exception e) {
out.println(e.toString());
}
%>
<form action="TestGetAccounts.jsp" method="POST">
Enter a count: 
<input type="text" name="count" value="<%=kount%>"/>
<input type="submit" value="submit"/>
</form>
</BODY>
</HTML>
4. Save the JSP then, in the Project Explorer view, select TestGetAccounts.jsp,
right-mouse, and select Run|Run on Server…
5. In the Server selection panel, click the “Choose and existing server” radio button
and select “WebSphere Express V5.1 Test Environment” and click Finish.
 The JSP will open in WDSc’s integrated Web browser.
6. Test the JSP page a couple of times with numbers 1–100.
7. Try it again with a number larger than 100. The JSP responds with the message
“java.lang.IllegalArgumentException: Invalid Count.”
8. Just to show you that your Web Service is available to any client tool, change the
URL in WDSc’s web browser to
http://localhost:7080/WebServiceHost/wsdl/com/denoncourt/GetAccounts.wsdl
 With the WSDL itself available on the Web, any developer with network access
and an IDE, such as WDSc, can generate client code to consume the Web service.
Sharing the Wealth with Web Services
Web services are a great mechanism for sharing business processes among various client
applications. For example, to share the Web services with .Net and ColdFusion
applications, I simply send the Web service’s WSDL XML to the .Net and ColdFusion
developers, who then use their favorite IDE to generate the low-level TCP/IP code
required to communicate with my Java- and RPG-based Web services. Conversely, you
can use WDSc to create the low-level TCP/IP code required to consume Web services
provided by various business partners. It doesn’t matter what language those Web
services are implemented with because all you need is the WSDL XML file. That’s the
beauty of Web services — sharing business processes across the Internet without the
need to know their implementation.
Appendix:
The GETACCTS ILE RPG program:
D RESULTSET
D ACCOUNTNO
D AccountName
D Balance
DCount
DS
OCCURS(100)
1
8
79
S
7
78
89
0
2
LIKE(CountIn)
DError
S
LIKE(ErrorIn)
DErrorMsg
S
LIKE(ErrorMsgIn)
DIndex
S
5 0
C
*ENTRY
PLIST
C
Count
PARM
CountIn
C
PARM
Error
ErrorIn
C
PARM
ErrorMsg
ErrorMsgIn
/FREE
IF Count > 100 or Count < 1;
eval Error = '1';
eval ErrorMsg = 'Invalid Count';
eval Count = 0;
else;
for Index = 1 to Count;
%occur(ResultSet) = Index;
eval AccountNo = Index;
eval AccountName = 'Denoncourt';
eval Balance = Index;
ENDFOR;
eval Error = '0';
eval ErrorMsg = '';
ENDIF;
/END-FREE
C/exec sql
C+ SET RESULT SETS ARRAY :ResultSet
C+ FOR :Count ROWS
C/end-exec
C
RETURN
5 0
1
50
Tip: the code in TestGetAccounts.jsp can easily be changed to handle dynamic IP
addresses:
Account[] accts = new GetAccountsServiceLocator().
getGetAccounts(
new URL("http://127.0.0.1:7080/Host/services/GetAccounts")
).search(3);
Where the URL string could be a variable.
Download