This is the first of a series of tips on the topic of roundtripping. This tip introduces the notion of roundtripping and begins to hint at some problems with the existing JAX-RPC mapping rules. Once you understand what roundtripping is good for, subsequent tips will go into greater detail with issues.
Roundtripping is the process of mapping from one representation to another and back again. In the normal course of events, you would like to end up with what you started. For instance, take a number from the Arabic numeral system, such as 9. Map this number to the Roman numeral system. You end up with IX. Now map that back to the Arabic numeral system and you end up with, no surprise, 9.
But why is this no surprise? It is no surprise because the mapping from Arabic to Roman numerals, and back again, is what is mathematically known as one-to-one and onto. In short, for each Arabic numeral, there is one, and only one, Roman numeral which maps to it. The same is true for the mapping of Arabic to Roman numerals.
Or is it? What about the Arabic numeral 0? There is no mapping of Arabic 0 to a Roman numeral. So while it seems that there are no surprises, there really are.
Before I proceed, let me answer a question you might be asking: why do we care about roundtripping? I'll tell you. A typical Web services scenario is to take an existing application and expose it as a Web service. To do this in the Java world, first you generate a WSDL file from existing Java code (Java-to-WSDL). Then, from this WSDL file, you generate the Web services files (Java helper classes, deployment descriptors, etc.) for this service (WSDL-to-Java). Bundle all this stuff into an EAR file and you've got yourself a Web service of the original application. You started with a Java file, mapped it to WSDL, then mapped the WSDL back again to a Java file.
The above paragraph discusses the server side. Note that you do the WSDL-to-Java step on the client side as well, but that's not particularly interesting from a roundtrip point-of-view. You don't have Java code to start with on the client, so you didn't do the Java-to-WSDL step. It doesn't really matter if the client-side Java code is completely different from the server-side Java code. All that matters is that the messages which the client sends are acceptable to the server, and vice versa. So these roundtripping issues really only concern themselves with the server.
Note that so far I've discussed Java-to-WSDL-to-Java roundtripping. You could also consider WSDL-to-Java-to-WSDL roundtripping (which actually has many more problems). But you will seldom run across a use case for roundtripping beginning with WSDL. So I will stick with Java-to-WSDL-to-Java which, as shown in the previous paragraph, is a very common use case.
The Arabic numeral zero cannot map to the Roman numeral system. There are also things in Java language which do not map to WSDL, like objects which have behavior; for instance: InputStream, OutputStream, Class, Thread, etc. Keep in mind that Web services sends data across the wire, not Java objects -- after all, the receiver of a SOAP message might not be Java-based, and might not even be object-oriented.
The set of Java objects that cannot map to WSDL obviously cannot roundtrip back to Java types; so by their nature, there are no roundtrip issues with them. So I will not discuss them in this tip.
There is a large set of Java types which behave like the Arabic numeral nine, types which do map to WSDL. But even this set of Java-to-WSDL-mappable data types is not fully roundtrippable.
Most Java types in the Java-to-WSDL-mappable set map back to Java types just fine. For instance, Java code's int maps to the XML type xsd:int, and this maps back to Java code's int. Since most things roundtrip just fine, it is easy to fall into the trap of assuming that all things roundtrip just fine. But there is one problem type: java.util.Date.
Java code's java.util.Date maps to XML schema's xsd:datetime. But then xsd:datetime maps back to Java code as java.util.Calendar. Why couldn't JAX-RPC map Date to xsd:date and then back to Date? And Calendar to datetime and back to Calendar? That would have cleared up this roundtrip issue, but there are two very good reasons this could not be done.
- Maintaining roundtrippability was not a goal of JAX-RPC.
-
java.util.Datehas more info than can be contained within anxsd:datetype (time, for instance), so JAX-RPC uses an XML schema type that can hold all of the info:xsd:datetime.
The easiest way around the issue of Date not roundtripping is simply to avoid it. Use java.util.Calendar instead because it does roundtrip. Besides, many of the Date methods have been deprecated in favor of Calendar methods, so you probably want a Calendar object anyway.
Perhaps you cannot change the original API. Another alternative is to write wrapper code around the APIs that use Date. The wrapper code would be the Web service, and it would delegate all invocations to the real implementation. They are fairly simple to write. For example, given the original, unchangeable interface in Listing 1, you could write for it the wrapper in Listing 2.
Listing 1. Legacy API
package com.ibm.developerWorks.roundtrip;
public class Legacy {
public void setDate(java.util.Date date) {...};
} |
Listing 2. Web service wrapper around the original legacy application
package com.ibm.developerWorks.roundtrip;
public class Wrapper {
private Legacy legacy = new Legacy();
public void setDate(java.util.Calendar calendar) {
legacy.setDate(calendar.getTime());
}
} |
Modify the mapping metadata file
Web services for J2EE (commonly referred to as JSR-109) defines a mapping metadata file which allows you to 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.
There are other roundtrip issues besides java.util.Date which I will cover in more detail in subsequent tips. Stay tuned for further roundtripping tips which will go into more details.
A typical Web services scenario is to take an existing application and expose it as a Web service. To do so, you will have to round trip from Java types to WSDL and back to Java types. In this roundtripping, the original constructs are not necessarily preserved. This tip showed that, if the original Java API contained java.util.Date, then the roundtrip resulting API will not match the original.
There are a number of ways to work around roundtrip issues: you could avoid them altogether; you could write Web service wrappers around the original implementation, or you could modify the mapping metadata file (though this tip did not go into details on the mapping metadata file).
- Read the Web Services Description Language (WSDL) 1.1, the specification of WSDL.
- 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 service engine performance and API design. Richard has also worked on the development of CORBA tooling and chip validation software.
Comments (Undergoing maintenance)





