If you have been using JAX-RPC for developing web services, you may have noticed how XML gets into churned into typed objects. Implementations may differ in the exact details, but the Java SOAP toolkits I know go through some hoops to get request/response data from memory to the wire and vice versa. Some of these hoops cause data duplication, which you may want to avoid for performance reasons.
To drive my testing, I used the following schema types for a web services request.
<xs:element name="GetAddressRequest"> <xs:complexType> <xs:sequence> <xs:element name="firstName" type="xs:string"/> <xs:element name="lastName" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element>
I used Apache Axis for testing. Axis’ WSDL2Java tool generated the following classes from the above schema types. For brevity, I removed some of the generated code from these classes.
public class GetAddressRequest implements java.io.Serializable
{
private java.lang.String firstName;
private java.lang.String lastName;
public GetAddressRequest() {
}
public GetAddressRequest(java.lang.String firstName, java.lang.String lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
// setters and getters for each of the private fields.
}
This code seems useful. Particularly, the setters and getters
make it easy for client/service implementations to create and process
messages without worrying about XML, and make web services programming type safe (within the constraints of JAX-RPC type mapping rules, of course). But there in lies a trouble.
Although JAX-RPC clients and service implementations program to these typed classes, these objects are not directly used for (de) serializing (from) to XML on the wire.
JAX-RPC includes handlers for processing inbound and outbound messages. These handlers use SAAJ for processing messages. For those not familiar with SAAJ, SAAJ is a DOM-like API for processing multipart SOAP messages. Here is the typical flow.
|--------------| |---------------| SOAP Message --> | SAAJ Objects | --> JAX-RPC Handlers --> | JAX-RPC Beans | --> Service Impl |--------------| |---------------|
The JAX-RPC runtime first converts the SOAP message received from the sender into DOM (SAAJ) to let any inbound handlers process the request. The runtime then converts this DOM into a set of beans generated from the WSDL. The process repeats on the outbound message as well. The runtime converts the beans returned from the service implementation into DOM (SAAJ) to let any outbound handlers process the response.
The point is that, although the runtime exposes WSDL-generated types to service implementations, it still creates DOM (SAAJ) for each request and response message in memory. This is not just a question of memory usage, it is also a question of cycles spent converting DOM into typed objects and vice versa. You cannot avoid this duplication with JAX-RPC. I’m not an expert on JAX-RPC, and so cannot say why JAX-RPC designers made this choice. If performance is a real-concern, I would stay away from using JAX-RPC. I would rather stick with SAAJ, although it is not the friendliest APIs around.