Implementing High Performance Web Services Using JAX-WS 2.0

   
By Bharath Mundlapudi, August 2006  

Articles Index

Service-oriented architecture (SOA) allows businesses to enable legacy systems and new software products as a service to a wider audience by way of the Internet. Web services technology is the cornerstone of SOA implementation, which involves complex business transactions between various business entities. XML processing, the core component of web services technology, involves SOAP processing, XML binding, and XML parsing. Understanding various traits of the Web Services Description Language (WSDL) is important for gaining better performance and scalability of web services.

This article shows how to implement high performance web services using the Java API for XML Web Services (JAX-WS) 2.0 and provides feature and performance comparisons with the Java API for XML-Based RPC (JAX-RPC) 1.1. The performance data in this article will help you design highly performant web services.

Web Services Stack Overview

Sun's initial implementation of web services was called JAX-RPC 1.1 ( JSR 101). This was a standards-based implementation, but the binding and parsing layers underneath it were proprietary. Additionally, JAX-RPC 1.1 does not completely cover schema specification.

Sun's newer version of the web services stack, JAX-WS 2.0 ( JSR 224), is completely standards based. Even the binding layer, the Java Architecture for XML Binding (JAXB, JSR 222), and the parsing layer, the Streaming API for XML (StAX, JSR 173) are standards based and also support schema specification 100 percent.

Figure 1: Web Services Stack
 

Figure 1 represents the JAX-RPC and JAX-WS implementations. The advantages with JAX-WS are ease of development and high performance. As the performance of JAXB and StAX improves, so does the performance of the JAX-WS stack. For this reason, the JAX-WS stack is referred to as an integrated stack.

Web Services Performance

Understanding web services performance is important because it allows the developer to design and implement efficient enterprise web services for performance and scalability. You can measure the performance of the web services stack in two ways, depending on your deployment model: end-to-end performance and endpoint performance.

End-to-End Performance

If a web service deployment involves the client and server stack, then measurements in the performance tests should include both of these components. This requires a thick client, which exercises the client side of the web services stack. Figure 2 illustrates end-to-end performance, in which a client driver uses a thick web services stack to send and receive SOAP requests.

Figure 2: In end-to-end performance, the client driver uses a thick web services stack to send and receive SOAP requests.
 

Endpoint performance

In this case, the only concern is the endpoint, that is, the server-side performance. For these measurements, you can use a thin client with an HTTP driver to stress the endpoint. Figure 3 illustrates endpoint performance, in which a client uses a thin HTTP driver to send and receive SOAP requests.

Figure 3: In endpoint performance, a client uses a thin HTTP driver to send and receive SOAP requests.
 

This article focuses on performance data for end-to-end performance, with only occasional references to endpoint performance.

The WSTest Benchmark

This article uses the WSTest benchmark to measure JAX-RPC and JAX-WS performance. WSTest is a client-server microbenchmark developed at Sun Microsystems to measure the performance of the Java technology web services stack. WSTest is designed to mimic real-world web service processing. Typically, any web service application needs a container to run. WSTest can be deployed either on GlassFish or Tomcat. This benchmark is highly configurable to meet the needs of the real-world simulation such as number of clients, addition of test cases, percentage mix of web services processing (for example, the percentage of time you would like a particular use case to be executed), and so on. This is very similar to an application server that deploys web services and concurrently processes a number of SOAP requests from users. WSTest reports the number of transactions per second and the average response time.

Performance Measurements

This section discusses primitive performance, primitive array performance, payload performance, and binding performance in web services.

Primitive Performance

Primitives such as int, short, long, float, and so on form the basic building blocks for implementing efficient web services. Any complex business structure eventually comes down to constituent individual primitives. This section compares the performance of various primitives, to provide you some information for choosing one over the other.

Consider the WSDL sample shown in WSDL Sample 1.

WSDL Sample 1

<xsd:element type="xsd:int" name="echoInt" />
<xsd:element type="xsd:int" name="echoIntResponse" />
...
<message name="echoIntSoapIn">
    <part name="params" element="types:echoInt" />
</message>
<message name="echoIntSoapOut">
    <part name="result" element="types:echoIntResponse" />
</message>
 

WSDL Sample 1 shows the integer primitive echoing back and forth between client and server. Code Sample 1 shows the corresponding web service implementation code.

Code Sample 1

public int echoInt(int params)
{
      return params;
}
 

Similarly, changing the different primitives in the WSDL produces the corresponding service implementation code. Table 1 compares the Java technology primitives generated for JAX-RPC 1.1 and JAX-WS 2.0 for the corresponding XSD primitive types defined in the WSDL.

Table 1: Comparison of Primitives Generated in JAX-RPC 1.1 and JAX-WS 2.0 for the Corresponding XSD Types
 
 
XSD Type
JAX-RPC 1.1
JAX-WS 2.0
xsd:boolean
boolean
boolean
xsd:short
short
short
xsd:int
int
int
xsd:long
long
long
xsd:integer
BigInteger
BigInteger
xsd:float
float
float
xsd:double
double
double
xsd:decimal
BigDecimal
BigDecimal
xsd:date
Java.util.calendar
Javax.xml.datatype.XMLGregorianCalendar
xsd:time
Java.util.calendar
Javax.xml.datatype.XMLGregorianCalendar
xsd:datetime
Java.util.calendar
Javax.xml.datatype.XMLGregorianCalendar
 

The graph in Figure 4 shows the performance of XSD primitives. The x-axis indicates the XSD primitives such as boolean, short, and so on. The y-axis indicates the throughput, the number of transactions per second.

Figure 4: XSD Primitive Performance
 

Note that there is not much performance difference when choosing from boolean, short, int, long, integer; from float, double, decimal; or from date, time, datetime. But the scale/precision set -- such as the number of decimal points required for float, double, and decimal -- can affect the serialization, deserialization, and payload costs, all of which have a direct impact on performance. Also, it is best to use the xsd:decimal/BigDecimal type to avoid rounding off decimal values for all monetary calculations.

The graph in Figure 4 implies that all the primitives will give the same performance when the binding layer is not stressed.

Primitive Array Performance

As you may have noted in the example of primitives performance, you are not stressing the binding layer. If you send only the primitives back and forth, then the performance of primitives is masked by the performance of the container, such as doing the connection handling, scheduling the tasks, and so on. This section shows how primitive arrays perform when the binding layer is stressed. This is a way of moving the magnifying lens from the container layer to the binding layer.

Consider WSDL Sample 2.

WSDL Sample 2

<xsd:complexType name="intArray">
    <xsd:sequence>
       <xsd:element minOccurs="0" maxOccurs="unbounded" ref="types:echoInt"/>
    </xsd:sequence>
</xsd:complexType>

<xsd:element type="types:intArray" name="echoIntArray" />
<xsd:element type="types:intArray" name="echoIntArrayResponse" />

...

<message name="echoIntArraySoapIn">
    <part name="params" element="types:echoIntArray" />
</message>
<message name="echoIntArraySoapOut">
    <part name="result" element="types:echoIntArrayResponse" />
</message>
 

The WSDL code in WSDL Sample 2 shows an example for sending and receiving the array of integer primitives. Code Sample 2 shows the corresponding web service implementation code for JAX-RPC 1.1.

Code Sample 2

public int[] echoInt(int[] params)
{
      return params;
}
 

Code Sample 3 shows the corresponding web service implementation code for JAX-WS 2.0.

Code Sample 3

public void echoIntArray(Holder<List<Integer>> echoInt)
{

}
 

Table 2 shows the distinction between JAX-RPC 1.1 and JAX-WS 2.0 at the service endpoint for various Java technology primitive arrays generated for the corresponding XSD primitives with minOccurs and maxOccurs attributes.

Table 2: Comparison of Primitive Arrays Generated in JAX-RPC 1.1 and JAX-WS 2.0 for the Corresponding XSD Types
 
 
XSD Type
JAX-RPC 1.1
JAX-WS 2.0
xsd:boolean
Boolean[]
List<Boolean>
xsd:short
Short[]
List<Short>
xsd:int
Int[]
List<Integer>
xsd:long
Long[]
List<Long>
xsd:integer
BigInteger[]
List<BigInteger>
xsd:float
Float[]
List<Float>
xsd:double
Double[]
List<Double>
xsd:decimal
BigDecimal[]
List<BigDecimal>
xsd:date
Java.util.calendar[]
List<Javax.xml.datatype.XMLGregorianCalendar>
xsd:time
Java.util.calendar[]
List<Javax.xml.datatype.XMLGregorianCalendar>
xsd:datetime
Java.util.calendar[]
List<Javax.xml.datatype.XMLGregorianCalendar>
 

Note that JAX-RPC 1.1 generates indexed arrays, whereas JAX-WS 2.0 generates list interfaces.

The graph in Figure 5 shows the performance of XSD primitive arrays. The x-axis indicates XSD primitive arrays such as array (size=100) of boolean, short, and so on. The y-axis indicates the throughput, that is, the number of transactions per second.

Figure 5: Primitive Array Performance
 

As you can see, once you start stressing the binding layer, the performance of primitives varies. Also note that JAX-WS 2.0 performs better in all cases and shows great improvement -- nearly double in some cases -- in date, time, and datetime. The locking issue in JAX-RPC 1.1 for datetime has now been addressed in JAX-WS 2.0. Figure 5 showcases the performance improvements in JAX-WS 2.0.

Payload Performance

Web services performance is proportional to the amount of payload sent: The more payload you send, the more processing is required for the serialization and deserialization, as well as for binding and parsing. This has a considerable effect on performance.

Consider a hypothetical case in which you have to send and receive items with the item structure shown in Code Sample 4. For example, in a supply-chain management system, you would request line items for a particular order or to process a batch of items.

Code Sample 4

# Item{
id,
description,
price,
inventory,
# location {
id,
description,
address,
},
creationdate
} ;
 

The graph in Figure 6 shows the performance of JAX-WS relative to JAX-RPC in percentage as the payload size -- that is, the number of items -- varies. The x-axis represents the number of items sent and received, and the y-axis represents the percentage of JAX-WS throughput compared to that of JAX-RPC. In this use case, a transaction is defined as the sending and receiving of an array of items.

Figure 6: Payload Performance
 

The graph in Figure 6 indicates that, at payloads over 100 items, JAX-WS throughput almost doubles the performance of JAX-RPC, whereas at payloads lower than 100 items, JAX-WS and JAX-RPC give similar results. In general, JAX-WS performance is better than that of JAX-RPC at larger payloads.

Binding Performance

There are multiple ways to handle XML documents in Java web services. This section compares the performance of document-handling JAXB and Document Object Model (DOM) binding for an XML document, specifically an industry-standard 100 kilobyte Universal Business Language (UBL) invoice.

JAXB Binding

JAXB binding provides a way to convert from Java technology objects to XML and from XML to Java technology objects. The syntax for JAXB binding is shown in WSDL Sample 3, in which an element named echoJAXB in the schema section of the WSDL code refers to a type named InvoiceType. This approach is also referred to as schema binding because the artifacts generated are dependent on the schema.

WSDL Sample 3

<xsd:element name="InvoiceType">
    ...
</xsd:element>
<xsd:element name="echoJAXB" type="types:InvoiceType" />
 

When the WSDL sample in Code Sample 5 is compiled using wscompile, it generates the InvoiceType Java technology object at the service endpoint.

Code Sample 5

public void echoSX(Holder<InvoiceType> invoice) {

}
 

JAXB binding provides several advantages: ease of development, hidden code complexity, lack of boilerplate code, and better performance than nonschema binding. All the developer needs to do is to access the generated JAXB Java class methods for accessing XML content.

One disadvantage with JAXB binding is that the generated Java classes are coupled to the schema defined in the WSDL, which makes the JAXB binding approach harder for writing generic code.

DOM Binding

DOM binding provides a way to convert from a DOM tree to XML and from XML to a DOM tree. The syntax for DOM binding is shown in Code Sample 6, in which an element named echoDOM in the schema section of WSDL has an xsd:any type, which allows the application to send any arbitrary XML data. The attribute processContents="skip" on the xsd:any type means that the XML content is not validated. This approach is also referred to as nonschema binding because the artifacts generated are not dependent on the schema.

WSDL Sample 4

<xsd:element name="echoDOM">
   <xsd:complexType>
      <xsd:sequence>
         <xsd:any processContents="skip" />
      </xsd:sequence>
   </xsd:complexType>
</xsd:element>
 

When compiled using wscompile, the code in WSDL Sample 4 generates the DOM Element at the service endpoint, as Code Sample 6 shows.

Code Sample 6

public EchoNSXResponse echoNSX(EchoNSX invoice) {
    Element e = (Element)invoice.getAny();
    EchoNSXResponse res = new EchoNSXResponse();
    res.setAny(e);
    return res;
}
 

The advantage of DOM binding is that it allows the developer to write more generic and extendable programs. The disadvantages of DOM binding are that it requires the developer to write more complex code depending on the schema and requires the developer to write more boilerplate code for navigating the DOM tree, which results in reduced performance. Note that in Code Sample 6, only the infrastructural performance is measured; that is, no user code or business logic is involved.

In this use case, a transaction is the sending and receiving of a 100 kilobyte UBL invoice XML document. For the graph in Figure 7, the x-axis represents the binding type, and the y-axis represents the throughput. Note: Figure 7 shows the graph for endpoint performance, meaning that it measures only the server-side web services stack.

Figure 7: Binding Performace
 

The graph in Figure 7 illustrates that JAXB binding performs significantly better than does DOM binding. Also, note that the performance of JAX-WS is much better than that of JAX-RPC. In addition, the performance of JAX-WS is even more visible in the case of DOM binding.

Summary

To conclude,

  • Choose the primitives depending on the requirements -- such as the number of digits, precision, and so on -- because primitives can affect the performance based on their usage.
  • An increase in payload size will reduce the throughput and have considerable effect on performance.
  • JAXB binding or schema binding provides better performance than does DOM or nonschema binding.
  • JAX-WS 2.0 gives better binding performance than does JAX-RPC 1.1.
  • For large payload sizes, the performance of JAX-WS 2.0 is about twice that of JAX-RPC 1.1.
For More Information
Acknowledgments

I would like to thank Sameer Tyagi, Santiago Pericas-Geertsen, and Geneviève Duboscq for their valuable feedback and comments on this article.

About the Author

Bharath Mundlapudi is a staff engineer in the Java Performance Engineering Group, Java SE, at Sun Microsystems and focuses mainly on XML and web services performance. He currently leads benchmark development for web services, and he measures and improves the performance and scalability of the web services stack in GlassFish on Symmetric Multiprocessing (SMP) and Chip Multithreading (CMT) systems.

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.