In the first article, you learned that the demo application implements a buyer-seller scenario. It consists of a number of roles, which are all designed as web services, with service interfaces defined in WSDL. Only the Customer role is not implemented as a web service, because it serves as the client for your application. Figure 1 shows this structure.
Figure 1. Roles and operations

(Figure 1 is Copyright © XMethods and has been used with permission).
The application that I will describe in this article implements the roles Supplier, Warehouse, and Bank as web services running on WebSphere. The business logic of these services is represented by JavaBeans. The Customer role is implemented as a set of Java Server Pages (JSPs). Both the service implementations and the JSPs are bundled into one Web module. Besides the Java and JSP code, this Web module also contains a number of configuration files as well as the WSDL service definitions for all services. Finally, this Web module is packaged into a J2EE Enterprise Archive (EAR) file. You can install this EAR file on any J2EE compliant application server. Before continuing, you should download the complete EAR file, including source code from the demo home page.
Figure 1 also shows that some of the services act as clients to other services. For example, the Supplier service uses the Warehouse service to ensure that an order can be fulfilled. Each service implementation uses a mapping file to identify where the services it uses can be found. This mechanism was described in the previous article. (See Resources.)
Before you start importing and running the actual code, let me walk you through a little bit of theory. This will help you to understand the content of the application package.
The web services in this application have been implemented following the JAX-RPC specification. This means that each <portType> element that is defined in the WSDL document is mapped to a Java interface. For example, the Supplier web service is mapped to an interface called net.xmethods.www.ISupplierSoap. The interface name is taken from the <portType> name ('ISupplierSoap' in this case), and the package name from the namespace of the <portType> element in WSDL. However, the specification does not mandate how the namespace to package name mapping is done. Listing 1 shows the ISupplierSoap interface, which was generated from the WSDL service definition using the Apache Axis WSDL2Java tool.
Listing 1. ISupplierSoap interface
package net.xmethods.www;
public interface ISupplierSoap extends java.rmi.Remote {
public java.lang.String sendPO(net.xmethods.www.PO po)
throws java.rmi.RemoteException;
public void shipConfirm(java.lang.String customerID, java.lang.String poNumber)
throws java.rmi.RemoteException;
public java.lang.String
getPOStatus(java.lang.String customerID, java.lang.String poNumber)
throws java.rmi.RemoteException;
public net.xmethods.www.Invoice
getInvoice(java.lang.String customerID, java.lang.String poNumber)
throws java.rmi.RemoteException;
public net.xmethods.www.Catalog getCatalog() throws java.rmi.RemoteException;
}
|
Note that the JAX-RPC specification also states that each method in the interface must throw java.rmi.RemoteException.
The Apache Axis WSDL2Java tool also generates a number of additional classes:
- The net.xmethods.www.ISupplierSoapImpl class contains the actual implementation of the service. It implements the service interface class.
- The net.xmethods.www.ISupplierSoapStub class also implements the service interface, but acts as a proxy to the actual service. It is used by a client.
- The net.xmethods.www.SupplierService class represents the <service> element in the WSDL document (it is also called the 'generated service interface'). It contains a number of methods that make it easier for a client to obtain a client side stub to the service. Its methods make it possible to define the actual endpoint location of the service at runtime.
- The net.xmethods.www.SupplierServiceLocator class implements the generated service interface above.
You will find these classes for all of the services in our application.
Running the application in WebSphere Studio Application Developer
In the following sections, I will show you how you can install the application in WebSphere Studio Application Developer (Application Developer). You can run and debug it in the WebSphere Test Environment within the tool, or on a stand alone application server, which I will describe towards the end of the article.
To import the application into Application Developer, open the tool in the J2EE perspective (Figure 2). Then select the File -> Import option.
Figure 2. Application Developer Import

Click on the 'Next' button. In the next dialog, specify the location where you downloaded the EAR file with the application. Enter 'WSIDEAR' as the Enterprise Application project name, as shown in Figure 3.
Figure 3. EAR Import

Now click on 'Finish', which will start the import process. After completion, you will see that a new Enterprise Application, named wsidEAR, has been created, which contains one Web module called wsid.war. The Web module is represented by a Web project called 'wsid' (see Figure 4).
Figure 4. wsid.war

Before you can have a closer look at the new Web project, you have to make one change to its build path properties, in order to remove one compile problem. You have to add an XML parser library to the classpath; you will use the Apache Xerces library here, which is already included with WebSphere. To make this change, open a 'web' perspective in Application Developer and select the 'wsid' Web project. Click on the right mouse button and select 'Properties' from the pop-up menu. Then click on the 'Java Build Path' entry on the left and select the Libraries tab. Your window should now look like Figure 5.
Figure 5. Java Build Path
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
Now click on the 'Add External JARs' button and add the xerces.jar file from the \plugins\org.apache.xerces directory in your WebSphere Studio install directory. After you have added the jar file, click on OK in the project properties window. This will resolve the compile problem.
There are some configuration options that let you control how the application is run, and I will explore these in a minute, but first let's simply run the application as is. To do so, open the Web perspective in Application Developer, right click the 'wsid' Web project and select 'Run on Server' from the pop-up menu as shown in Figure 6.
Figure 6. Run on Server

This will publish the new application to the WebSphere Test Environment. After that, the server is started and the application is activated. Your Web module is defined with a base context root definition of '/wsid', which means it can be accessed as http://localhost:8080/wsid/. The tool will start a browser window and load this URL (causing the welcome.jsp page to be loaded, because that is the default starting page for this Web module). The result is shown in Figure 7.
Figure 7. WebSphere Test Environment
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
Don't worry if you see several exception messages in the Console window -- this will be explained shortly. The application itself should work as you have seen it on the IBM developerWorks server described in the first article, so I won't cover it in detail here again. The only difference is that you are running the services locally on your machine instead of on the IBM server!
In order to make a service implementation available on the application server, you must make this service known to the Axis runtime. Without going into too much detail, this process involves storing information about a service, its interface, its ID, and its implementation class in a file that the Axis runtime uses to resolve incoming requests to the right target.
There are two ways of 'deploying' a service into Axis. One is to use a JSP-base administration application that lets you specify all of the required values through a user interface. The second approach is to do the same thing programmatically, using a class that Axis provides called org.apache.axis.client.AdminClient. You will use this second option in your application and deploy the services on the fly whenever the application is first used.
The first page that is loaded as part of the application is the welcome.jsp page, and thus the code for deployment of the supported services is placed in this file. All of the required values are passed to the Axis runtime in the form of a file with the extension .wsdd. In other words, there is one such file for each service. Listing 2 contains an example which shows the deployment file for the Bank service.
Listing 2. Bank service deployment file
<deployment
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<!-- Services from bankService WSDL service -->
<service name="bank" provider="java:RPC" style="document">
<parameter name="wsdlTargetNamespace" value="http://www.xmethods.net/ws-demo/"/>
<parameter name="wsdlServiceElement" value="bankService"/>
<parameter name="wsdlServicePort" value="bank"/>
<parameter name="className" value="net.xmethods.www.IBankSoapImpl"/>
<parameter name="wsdlPortType" value="IBankSoap"/>
<operation name="charge" qname="operNS:chargeRequest"
xmlns:operNS="http://www.xmethods.net/ws-demo/" returnQName="retNS:chargeResponse"
xmlns:retNS="http://www.xmethods.net/ws-demo/"
returnType="rtns:>chargeResponse"
xmlns:rtns="http://www.xmethods.net/ws-demo/" >
<parameter qname="pns:chargeRequest"
xmlns:pns="http://www.xmethods.net/ws-demo/" type="tns:>chargeRequest"
xmlns:tns="http://www.xmethods.net/ws-demo/"/>
</operation>
<parameter name="allowedMethods" value="charge"/>
<typeMapping
xmlns:ns="http://www.xmethods.net/ws-demo/"
qname="ns:>chargeResponse"
type="java:net.xmethods.www.ChargeResponse"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""
/>
<typeMapping
xmlns:ns="http://www.xmethods.net/ws-demo/"
qname="ns:>chargeRequest"
type="java:net.xmethods.www.ChargeRequest"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""
/>
</service>
</deployment>
|
Deploying this information through the org.apache.axis.clientAdminClient class is fairly straightforward; Listing 3 shows the code extracted from the welcome.jsp file.
Listing 3. Code from welcome.jsp
// auto deploy the web services
if (!init) {
// deploy
AdminClient ac = new AdminClient();
String[] wsdds = {"warehouse.wsdd", "bank.wsdd", "supplier.wsdd", "logger.wsdd"};
String[] args = new String[3];
for (int i=0; i<wsdds.length; i++) {
args[0] = "-l";
args[1] = net.xmethods.www.Data.local + "services/AdminService";
args[2] = getServletContext().getRealPath(wsdds[i]);
try {
ac.process(args);
} catch (Exception e) {
e.printStackTrace();
}
}
init = true;
}
|
The Admin service is itself deployed as a web service. It is preinstalled into the Axis runtime. After running this code, the services can be accessed locally on your application server.
The application is set up so that it can be run with or without access to the Internet. By default, (that is, after you installed the EAR file without change), it runs without requiring any remote resources. However, since this is an interoperability demonstration, you want to be able to test multiple remote web services with it.
At startup time, the application loads information about available services and their endpoints from a configuration file called ROLES.php. Typically, this configuration file is located on a server at the XMethods web site, namely at http://www.xmethods.net/wsid/online/app/ROLES.php. However, to allow you to make changes to your local configuration (you don't have write access to the file at XMethods), the code will check if a local copy of this file exists, and if it does, it will use this local file. The application looks for this file in the '/app' directory of the Web module, and if you installed the EAR file for this application, you can find it there, with only the local service configured. This is why you can run the application without connectivity to the Internet.
Once you rename this file and restart the Web application (you have to restart the application, reloading the welcome.jsp is not sufficient), and you are connected to the Internet, you will use the configuration file from the XMethods server. You will note this change when you run the application in that you will have more combinations of suppliers and customers available in the drop-down list on the first page of the application. You are then using the endpoints as defined in the remote configuration file. The only exception is the 'local' supplier and customer roles, which are always using the local application server. In the 'local' case, you will still access the supplier through its web services interface, even though the customer application and the service run on the same server in this case.
You can manipulate the mapping of warehouses and banks to certain suppliers and customers too. These mappings are read from files called xml\CREDITMAPS.xml and xml\WAREHOUSEMAPS.xml. If you rename the local copies of these files and restart the Web application, you will use the remote copies of the files at the XMethods web site. Feel free to make changes to the content of these files and see what, if any, impact this has on the application.
Finally, the content of the local product catalog is taken from a file called xml\CATALOG.xml. Normally you won't change the content of this file, the local copy mainly exists to allow you to run the application without being connected to the Internet.
Debugging and tracing the application
If you want to step through certain areas of the code, you can do so by setting breakpoints and reloading the application. Make sure that you have started the server in debug mode. Obviously, you can only debug services that you run locally.
The application will also write logs of certain events to a log file, which you can use for tracing purposes. Logging is also done via a web service, namely the Logger service. This service is different from the others in that only one real implementation of this service exists on the XMethods server. Its URL is http://www.xmethods.net/wsid/online/log. You will not find a configuration option for this endpoint in the ROLES.php file as it is hardcoded in the application. You can view the log file at the XMethods site under http://www.xmethods.net/wsid/online/log.cgi.
If you run your application locally, without a connection to the Internet, you cannot access this service, and thus cannot trace what is going on. To allow tracing when running without a connection, the application contains a simple log service that will print log requests to the screen (the implementation class for this is net.xmethods.www.ILoggerImpl). This log service is deployed to the server together with the other services, as part of the code that exists in the welcome.jsp file. However, some log requests are already sent by the application before the local log service is deployed. This leads to the exception messages that you might have noticed when you ran the application for the first time.
Whether the local or the remote log service is used depends on a flag that is set in the net.xmethods.www.Data class called 'useLocalLogger'. If set to true, the local logger service is accessed, and if you change it to false, it will go to the XMethods logger service.
Another method of tracing what data are exchanged between the services is the 'tcpmon' tool that comes with Apache Axis. This tool allows you to trace data packages that are exchanged over HTTP. You use it by directing your service requests to the address and port under which the tool was started, and then forward the requests to the actual endpoint from there. The local ROLES.php file comes in handy at this point, because it lets us change the port under which the local service is available.
To start the tcpmon tool from within Application Developer, find the class org.apache.axis.utils.tcpmon in the axis.jar file (which is stored in our application in the \WEB-INF\lib directory). Select the class and use the 'Run' icon to start this class as a Java Application, as shown in Figure 8.
Figure 8. tcpmon from Application Developer

Once the tool has started, specify a new port to receive requests (for example, 12345) and forward them to the actual service endpoint, namely 'localhost' as the hostname and 8080 for the port (this is where the WebSphere Test Environment runs), as shown in Figure 9.
Figure 9. tcpmon from Application Developer
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
Click on the Add button to add this new listener. Now change the endpoint address of the ROLES.php file to use the same port you have used in the tcpmon tool, 12345 in our case. The updated file now looks like Listing 4.
Listing 4. ROLES.php
<roles updatecode="20021027083911"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ROLES.xsd">
<role participant="ibm">
<type>customer</type>
<id>ibm-customer</id>
</role>
<role participant="ibm">
<type>supplier</type>
<id>ibm-supplier</id>
<endpoint>http://localhost:12345/wsid/services/supplier</endpoint>
</role>
<role participant="ibm">
<type>bank</type>
<id>ibm-bank</id>
<endpoint>http://localhost:8080/wsid/services/bank</endpoint>
</role>
<role participant="ibm">
<type>warehouse</type>
<id>ibm-warehouse</id>
<endpoint>http://localhost:8080/wsid/services/warehouse</endpoint>
</role>
</roles>
|
Now start the application in the test environment, and you will notice that all requests to the Supplier service are now routed through the tcpmon tool, as shown in Figure 10.
Figure 10. Requests routed through tcpmon
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
This way, you can examine the actual SOAP messages that are sent to and from the service. Note that in this example, you only monitor the Supplier service. The tcpmon tool lets you set up additional listeners, and by configuring these in the ROLES.php file, you can separately monitor all of the services in the application.
Installing the application in WebSphere Application Server Version 4
So far, I have shown you how you can install, run, and debug the application in the WebSphere Test Environment of WebSphere Studio Application Developer. If you want to install and run it in a separately installed application server, you need to make one change to the code. This is due to the fact that you need to define under which URL the locally deployed services can be accessed. The original EAR file contains code that assumes that it will be installed under port 8080, which is what the test environment uses by default. If you run your WebSphere Application Server with a plugin and a web server on port 80, which is the most common case, then you need to change the static 'local' variable in the net.xmethods.www.Data class to http://localhost:80/wsid. Once you have made that change, you can export the application as an EAR file from WebSphere Studio Application Developer and directly install it into your WebSphere Application Server.
The application has also been successfully tested and run in both Application Developer version 5 and WebSphere Application Server version 5, so if you happen to run those newer versions of the product, feel free to install and run it there.
Sam Ruby developed the original IBM implementation of this application for the Web Services One conference in Boston. Richard Bonneau from IONA, David Rees from Amberpoint and Hoa Nguyen from webMethods own their respective companies' implementation and were very helpful in testing the application. Finally, Tony Hong from XMethods was the initiator of this activity and hosts the demonstration's homepage at http://www.xmethods.net/wsid/online.
- Read the first part of this article, Web services interoperability, Part 1. (developerWorks, January 2003)
- See the Web Services Interoperability demo and download the code.
- See the WSID XMethods Homepage.
- Learn more about Web Services Interoperability.
- See the Apache Axis package, which was used to implement this demo.
- Read an introduction to JAX-RPC, including the specification itself.
- Find the first in a series of articles on developerWorks about JAX-RPC. (developerWorks, November 2002)
André Tost works as a Solution Architect in the WebSphere Business Development group, where he helps IBM's Strategic Alliance partners integrate their applications with WebSphere. His special focus is on Web services technology throughout the WebSphere product family. Before his current assignment, he spent ten years in various development and architecture roles in IBM software development, most recently for the WebSphere Business Components product. Originally from Germany, he now lives and works in Rochester, Minnesota. In his spare time, he likes to spend time with his family and play and watch soccer whenever possible.




