This is the second of three tips on roundtripping and data integrity. This tip addresses the importance of following Java coding conventions. For an introduction to the concept behind roundtripping please read the previous tip as listed in the Resources section.
The Java APIs for XML-Based Remote Procedure Call (JAX-RPC) protocol (see Resources) is Java-centric, not WSDL-centric. It contains a fairly elaborate set of rules for mapping WSDL names to Java-friendly names which follow the Java coding conventions. This is good because JAX-RPC users will be Java programmers. In fact, they may not even care that your Web service is a Web service. They probably do not know or care about WSDL and XML, and all the quirks that they bring to the table. All they may care about is that they can write Java code to call your service and expect the JAX-RPC APIs for your service to look familiar; in other words, to follow Java coding conventions.
However, the drawback to this approach is that your original Java service must follow Java coding conventions to begin with in order to avoid roundtripping issues. If you start with a Java application which does not follow Java coding conventions, your code will not roundtrip because the resulting code will follow the Java coding conventions.
Let's start with a simple example. The use case in which roundtripping issues arise is when you expose an existing application as a Web service. Assume that an existing application implements the interface and bean in Listings 1 and 2. You will notice that there are a lot of violations of the Java coding conventions. (Besides showcasing Java coding convention problems, this example also presents java.util.Date, which we showed, in the first roundtrip tip, to not be roundtripable.)
Listing 1. Population application interface
package com.ibm.developerWorks.roundtrip;
public interface population {
public life GetALife();
} |
Listing 2. Life bean
package com.ibm.developerWorks.roundtrip;
public class life {
public java.util.Date birthday;
public java.util.Date deathday;
} |
To expose this application as a Web service, the first thing you do is run the population interface through your favorite JAX-RPC Java-to-WSDL tool. If you tell that tool to generate a RPC/literal binding, you should end up with a WSDL file similar to the one in Listing 3.
Listing 3. Population application's WSDL
<?xml version="1.0" encoding="UTF-8"?>
<definitions
targetNamespace="http://roundtrip.developerWorks.ibm.com"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:impl="http://roundtrip.developerWorks.ibm.com"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<schema
targetNamespace="http://roundtrip.developerWorks.ibm.com"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<complexType name="life">
<sequence>
<element name="deathday" nillable="true" type="xsd:dateTime"/>
<element name="birthday" nillable="true" type="xsd:dateTime"/>
</sequence>
</complexType>
</schema>
</types>
<message name="GetALifeRequest"/>
<message name="GetALifeResponse">
<part name="GetALifeReturn" type="impl:life"/>
</message>
<portType name="population">
<operation name="GetALife">
<input message="impl:GetALifeRequest" name="GetALifeRequest"/>
<output message="impl:GetALifeResponse" name="GetALifeResponse"/>
</operation>
</portType>
<binding name="populationSoapBinding" type="impl:population">
...
</binding>
<service name="populationService">
...
</service>
</definitions>
|
Once you have the WSDL file, you will have to generate artifacts. The application's Web services EAR file will require these artifacts. These generated artifacts are deployment descriptors and helper classes. You generate them using your favorite WSDL-to-Java tool, completing the round trip from Java language to WSDL and back to Java language. These generated artifacts will obey Java coding conventions.
If roundtripping were perfect, you could simply bundle your original application code into an EAR file with the generated artifacts and you would have yourself a merry little Web service. But roundtripping isn't perfect. The generated artifacts assume that the application code follows Java coding conventions. In other words, they assume the application is made up of Population and Life classes, but your original classes are population and life. See listings 4 and 5 to see what the artifacts generated from the WSDL in listing 3 assume the Population and Life classes look like. Please note the inconsistencies highlighted below between the original Java code and the expected Java code.
Listing 4. Population service endpoint interface generated from the WSDL
package com.ibm.developerWorks.roundtrip;
public interface Population extends java.rmi.Remote {
public Life getALife() throws java.rmi.RemoteException;
} |
Listing 5. Life bean generated from the WSDL
package com.ibm.developerWorks.roundtrip;
public class Life implements java.io.Serializable {
public java.util.Calendar getBirthday() {...} |
Try building an EAR file with your original code and the generated artifacts. At best, you will get a build-time or install-time error. At worst, the EAR file will build and install successfully, but you will get some obscure runtime error that will take you days to debug. So, you can see why it is important to understand the inconsistencies between your original code and what the generated artifacts assume your code looks like.
Table 1 summarizes all of the inconsistencies which have arisen because the original Java code did not follow the Java coding conventions.
Table 1. Java constructs which do not round trip
| Problem | Java-to-WSDL-to-Java | From the example |
|---|---|---|
Date becomes Calendar | java.util.Datexsd:datetimejava.util.Calendar | Life's "birthday" and "deathday" properties |
| Case changes in bean name | class bean { | Class name life vs Life |
| Case change in interface name and method names | interface y { | Interface name population vs Populationand method name GetALife vs getALife |
| Public instance variable vs accessors | class Bean { | Life's "birthday" and "deathday" properties |
How to avoid coding convention roundtrip issues
Since roundtripping isn't perfect, extra work is required in addition to using the original code in your Web service EAR file.
The easiest way around these issues is simply to avoid them. Always follow the Java coding conventions.
Perhaps you cannot change the original code. Another alternative is to write wrappers around the original application. The wrapper code would be the Web service, and it would delegate all invocations to the real implementation. Listing 6 shows a wrapper for this example. The EAR file which is packaged with this tip implements this wrapper. (Note that for this wrapper we generated Life and Population into a different package than the original life and population classes. We developed this example on Windows which isn't particularly friendly to file names that differ only in case.)
Listing 6. Web service wrapper around the original population application
package com.ibm.developerWorks.roundtrip;
import java.rmi.RemoteException;
import java.util.Calendar;
import com.ibm.developerWorks.roundtrip.generated.Life;
import com.ibm.developerWorks.roundtrip.generated.Population;
public class WrapperImpl implements Population {
private population p = new populationImpl();
public Life getALife() throws RemoteException {
life l = p.GetALife();
Life L = new Life();
Calendar birthday = Calendar.getInstance();
birthday.setTime(l.birthday);
Calendar deathday = Calendar.getInstance();
deathday.setTime(l.deathday);
L.setBirthday(birthday);
L.setDeathday(deathday);
return L;
}
} |
Modify the mapping metadata file
Web services for J2EE (commonly referred to as JSR-109 -- see Resources) defines a mapping metadata file which lets you bypass some of the JAX-RPC mapping rules. Stay tuned for a future tip which will give some hints about modifying this mapping metadata file to get around roundtripping issues.
When roundtripping a Web service, it is important to follow Java coding conventions. Failure to do so will compromise roundtripping.
There are a number of ways to work around these roundtrip issues:
- you could avoid them altogether by simply following the conventions
- you could write Web services wrappers around the original implementation
- you could modify the mapping metadata file (this tip does not go into details on the mapping metadata file).
- Read the first tip in this series, "Roundtrip issues, an introduction" (developerWorks, March 2004).
- Read the specification Web Services Description Language (WSDL) 1.1.
- Get the IBM WebSphere Application Server Technology for Developers, version 6.0, an early release of WebSphere Application Server supporting the latest J2EE, version 1.4.
- Java API for XML-Based RPC (JAX-RPC) Downloads & Specifications provides links to the JAX-RPC 1.1 specification itself, as well as javadocs, class files, and Sun's JAX-RPC reference implementation.
- Download the Web Services for J2EE (JSR-109) specification.
Russell Butek is one of the developers of the IBM® WebSphere® Web services engine. He is also an IBM representative on the JAX-RPC Java Specification Request (JSR) expert group. He was involved in the implementation of Apache's AXIS SOAP engine, driving AXIS 1.0 to comply with JAX-RPC 1.0. Previously, he was a developer of the IBM CORBA ORB and an IBM representative on a number of OMG task forces: the portable interceptor task force (of which he was chair), the core task force, and the interoperability task force.
Richard Scheuerle is one of the developers of the IBM® WebSphere® Web services engine. He was involved in the implementation of Apache's AXIS SOAP engine. Richard has 10 years of development experience with compiler/language design. Currently he is concentrating on the Web services engine performance and API design. Richard has also worked on the development of CORBA tooling and chip validation software.





