10 Web services performance tuning tips

This tutorial focuses on design guidelines and techniques to improve the performance of your Web services. Enjoy it!

Web Service Performance Tip 1: Use coarse grained Web Services

One of the biggest mistakes that many developers make when approaching web services is defining operations and messages  that are too fine-grained. By doing so, developers usually define more than they really need. You need to ensure that your web service is coarse-grained and that the messages being defined are business oriented and not programmer’s oriented.

The reason why top-down Web services are the pure web services is really this: you define at first the business and then the programming interface.
Don’t define a web service operation for every Java method you want to expose. Rather, you should define an operation for each action you need to expose.

public void checkInventory(long itemId) {
 InventoryDAO.checkInventory(itemId);
}
public void checkAccount(long itemId) {
 CustomerDAO.checkAccount(clientId);
}
public void saveOrder(long itemId, long clientId) {
 OrderDAO.persisteOrder(itemId,clientId);
}

and this is the coarse grained web service we expose:

@WebMethod
public void makeOrder(long itemId, long clientId) {
 InventoryDAO.checkInventory(itemId);
 CustomerDAO.checkAccount(clientId);
 OrderDAO.persisteOrder(itemId,clientId);
}

For the sake of simplicity we don’t have added any transaction commit/rollback however what we want to stress is that the first kind of web service is a bad design practice at first and then also will yield poor performance because of 3 round trips to the server carrying SOAP packets.

Web Service Performance tip 2: Use primitive types, String or simple POJO as parameters and return type

Web services have been defined from the grounds up to be interoperable components. That is you can return both primitive types and Objects. How do a C# client is able to retrieve a Java type returned by a Web Service or viceversa ? that’s possible because the Objects moving from/to the Webservices are flattened into XML.

As you can imagine the size of the Object which is the parameter or the return type has a huge impact on the performance. Be careful with Objects which contain large Collections as fields- they are usually responsible of web services bad performance. If you have collections or fields which are not useful in your response mark them as transient fields:

@XmlRootElement
public class Customer   {
 
    private String password;
    private List<String> phoneNumbers;
 
    @XmlTransient
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    @XmlElement(name = "phone-number")
    public List<String> getPhoneNumbers() {
        return phoneNumbers;
    }
 
    public void setPhoneNumbers(List<String> phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }
 
     
}

Web Service Performance tip 3: Evaluate carefully how much data your need to return

Consider returning only subsets of data if the Database queries are fast but the graph of Object is fairly complex. Example:

@PersistenceContext(unitName = "persistenceUnit")
private EntityManager em;
 
@WebMethod
public List  readTaskListByPage(@WebParam(name = "start") 
 int start,
 @WebParam(name = "stop")  
 int stop) {

 Query dbQuery = em.createQuery(query);    

 List   listObjects = dbQuery.setFirstResult(start)
 .setMaxResults(stop-start).getResultList();

 return listObjects;        

}

Check this tutorial to learn how to paginate your Entity objects: How to paginate your Entity data

On the other hand if your bottleneck is the Database Connectivity reduce the trips to the Service and try to return as much data as possible.

Web Service Performance Tip 4: Inspect your SOAP packet

This tip is the logic continuation of the previous one: if you are dealing with complex Object types always check what is actually moving around the network. There are many ways to sniff a SOAP packet, from a tcp-proxy software which analyze the packets between two destinations.

The following tutorial covers all tips and hints to debug SOAP Web Services: How to debug Web Service request and response

Web Service Performance Tip 5: Cache on the Client when possible

If your client application requests the same information repeatedly from the server, you’ll eventually realize the server’s performance, and consequently your application’s response time, is not fast enough.
Depending on the frequency of the messaging and the type of data, it could be necessary to cache data on the client.

This approach however needs to address one important issue: how do we know that the data we are requesting is consistent ? the technical solution to this is inverting the order of elements: when the Data in our RDBMS has become inconsistent a Notification needs to be issued so that the Client cache is refreshed.

When using a middleware such as WildFly / JBoss EAP, it will act as a client towards the Database. Check if using a second level cache is an option for your use case: Using Hibernate second level cache with JBoss AS and WildFly

Web Service Performance Tip 6: Evaluate using async messaging model

In some scenarios, responses to Web service requests are not provided immediately, but rather sometime after the initial request transactions complete. This might be due to the fact that the transport is slow and/or unreliable, or the processing is complex and/or long-running. In this situation you should consider an asynchronous messaging model.

JAX-WS supports two models for asynchronous request-response messaging: polling and callback. Polling enables client code to repeatedly check a response object to determine whether a response has been received. Alternatively, the callback approach defines a handler that processes the response asynchronously when it is available.

Consider using asynchronous Web methods is particularly useful if you perform I/O-bound operations such as:

  • Accessing streams
  • File I/O operations
  • Calling another Web service

Finally, check this tutorial to learn more about using Async Web Services: JAX-WS asynchronous Web Services made simple

Web Service Performance Tip 7: Use JAX-WS Web Services

The Webservices based on JAX-WS perform much better then JAX-RPC earlier Web services.
This is due to the fact that JAX-WS use JAXB for data type marshalling/unmarshalling which has a significant performance advantage over DOM based parsers.

For a detailed comparison benchmark check here:
http://java.sun.com/developer/technicalArticles/WebServices/high_performance/

Web Service Performance Tip 8: Are you using the right type of Web Service?

Unlike SOAP Web Services, RESTful web services are stateless client-server architecture in which the web services are viewed as resources and can be identified by their URLs.
REST as a protocol does not define any form of message envelope, while SOAP does have this standard. So at first you don’t have the overhead of headers and additional layers of SOAP elements on the XML payload. That’s not a big thing, even if for limited-profile devices such as PDAs and mobile phones it can make a difference.

However the real performance difference does not rely on wire speed but with cachability. REST suggests using the web’s semantics instead of trying to tunnel over it via XML, so RESTful web services are generally designed to correctly use cache headers, so they work well with the web’s standard infrastructure like caching proxies and even local browser caches.

RESTFUL web services are not a silver bullet, they are adviced in these kind of scenarios:

REST web services are a good choices when your web services are completely stateless. Since there is no formal way to describe the web services interface, it’s required that the service producer and service consumer have a mutual understanding of the context and content being passed along.

On the other hand a SOAP-based design may be appropriate when a formal contract must be established to describe the interface that the web service offers. The Web Services Description Language (WSDL) describes the details such as messages, operations, bindings, and location of the web service. Another scenario where it’s mandatory to use SOAP based web services is an architecture that needs to handle asynchronous processing and invocation.

Web Service Performance tip 9: cache JBossWS Service and Port

When using JBossWS, retrieving the Service and Port of a Web Service is a costly operation.

Consider, however that they are not thread-safe so access to them needs to be synchronized. The simplest way to do this is to add synchronized blocks around proxy invocations:

synchronized(clientProxy) {
  clientProxy.invokeOperation();
}

Web Service Performance Tip 10: Use Literal Message Encoding for Parameter Formatting

The encoded formatting of the parameters in messages creates larger messages than literal message encoding (literal message encoding is the default). In general, you should use literal format unless you are forced to switch to SOAP encoding for interoperability with a Web services platform that does not support the literal format. Here’s an example of an RPC/encoded SOAP message for helloWorld

<soap:envelope>
  <soap:body>
     <helloWorld>
       <a xsi:type="xsd:string">George</a>
       <b xsi:type="xsd:string">Michael</b>
     </helloWorld>
   </soap:body>
</soap:envelope> 

Here the operation name appears in the message, so the receiver has an easy time dispatching this message to the implementation of the operation.The type encoding info (such as xsi:type=”xsd:int”) is usually just overhead which degrades throughput performance. And this is the equivalent Document/literal wrapped SOAP message :

<soap:envelope>

  <soap:body>

    <helloWorld> <a>George</a> <b>Michael</b></helloWorld>

  </soap:body>

</soap:envelope>

How to monitor Webservices SOAP messages ?

This tutorial is now outdated. Please check the most recent version of it here: How to debug Web Services

Sometimes it’s useful for debugging features to inspect the SOAP messages which are returned by JBoss Web Service Stack. As a matter of fact when you issue a Web service request the kind of data you return is marshalled into XML using an XML marshaller.

All you have to do is adding this System Property to your Jboss EAP / WildFly servers and restart:

<system-properties>
        <property name="org.apache.cxf.logging.enabled" value="true"/>
</system-properties>

Invoking JBoss Web Services with Flex

Flex® is a free, open source framework for building highly interactive, expressive web applications that deploy consistently on all major browsers, desktops, and operating systems. It provides a modern, standards-based language and programming model that supports common design patterns. In this tutorial we’ll explore how to connect to JBoss webservices using a Flex Interface.

 

As we said Flex uses a declarative XML-based language (MXML) to describe UI layout and behaviors. In addition, to create the client login, it can use ActionScript 3, a which is a powerful object-oriented programming language.

One of the benefits of Flex is its reach – the Adobe Flash Player, upon which Flex applications run, is already installed on most every computers.

In order to run our example we’ll use Adobe Flex® Builder 3 software which is  a highly productive, Eclipse based development environment. You can try the evaluation version and then decide if you want to buy the license.

http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3email

 

Why developing in Flex when you have JSF ?

 

Both Flex and Java Server Faces are new technologies which still are still in evolution.

Flex strongest points include an easy to learn language, a good IDE if using commercial Flex-Builder tool, visual editing tools that look like it will be shown on the server, and extreme flexibility for giving a new look to existing legacy applications.

On the other hand JSF strengths are the excellent tools available in the market, the community size (developer base) and knowledge, lots of component libraries and AJAX support, a mature language, and an improved web framework for those who have been working in Java for some years and want to move to something better and easier than Struts.

It’s difficult to evaluate which is the best choice, however as most of you certainly know, it’s not always a matter of which framework is better in a real-life Project: it depends on the skills of your developers, on your company partnerships, sometimes even on personal tastes. So it’s good to know a bit of both world, then you’ll evaluate what’s better for you.

 

Coding the Server Side

Ok, we’ll cover first the server side which is a simple JAX-WS web service. 
This Web Service expose a method sayHello which returns a Person object created from the parameters (name and surname) passed.  

package sample;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.WebParam;

@WebService(name = "HelloWorld", targetNamespace = "http://webservice_consumer/helloworld")
public class HelloWorldWS
{
   @WebMethod
   public Person sayHello(String name,String surname)
   {

      String greeting = "Hello " + name + " -  " + surname;
      
      System.out.println(greeting);
      Person p = new Person();
      p.setName(name);
      p.setSurname(surname);
      
      return p;
      
   }

}

The class Person is a bare-bones Java Bean.

public class Person {

 private String name;
 private String surname;

 public String getName() {
    return name;
 }
 public void setName(String name) {
    this.name = name;
 }
 public String getSurname() {
    return surname;
 }
 public void setSurname(String surname) {
    this.surname = surname;
 }

}

Last piece of the webservice is the web.xml file which contains a standard mapping for the WebService:

<?xml version="1.0" encoding="UTF-8"?>


<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">  
  <servlet> 
    <servlet-name>HelloWorldWS</servlet-name>  
    <servlet-class>sample.HelloWorldWS</servlet-class>  
  </servlet>  
  
  <servlet-mapping> 
    <servlet-name>HelloWorldWS</servlet-name>  
    <url-pattern>/HelloWorldWS</url-pattern> 
  </servlet-mapping>   
  
</web-app>

 

Ok, compile and package your webservice in a file named webservice_consumer.war

Building the Flex Tier

Ok now the Flex side: As we said Flex uses a declarative language (MXML) which has already many built-in functions. For our purpose we’ll use the <mx:WebService> tag. It requires mainly to know the WSDL address of the Web Service.

<mx:WebService id="webService" wsdl="http://localhost:8080/webservice_consumer/HelloWorldWS?wsdl" >
     <mx:operation name="sayHello" resultFormat="object" result="display(event);">        
     
     <mx:request xmlns="" > 
 
        <arg0>Peter</arg0> 
        <arg1>Pan</arg1> 
 
      </mx:request> 

   </mx:operation> 
   
</mx:WebService>  

Inside the operation tag notice the following attributes: 

                resultFormat=”object”
                result=”display(event);”
                fault=”displayfault(event);”

               
the first one instructs the compiler that the return type of the Web Service is a complex object. Then, with result, it instructs the compiler to invoke the “display” method when the operation is completed. In case of failure the “displayfault” method is triggered.

How do we code this methods ? simply using Action Script. ActionScript is a powerful object-oriented programming language executed by the ActionScript Virtual Machine (AVM) built into the Flash Player. For this sample we’ll use just need to evaluate the result of the Web Service and populate a text field with its value.        

Then the <mx:request> tag is used to pass the actual parameters, name and surname. By the way ? how do you map your Flex parameters to Java parameters ? simply have a look at the WSDL of your Webservice. The two String parameters (name and surname) have beed defined as arg0 and arg1

<xs:complexType name=”sayHello”>
 <xs:sequence>
   <xs:element minOccurs=”0″ name=”arg0″ type=”xs:string” />
   <xs:element minOccurs=”0″ name=”arg1″ type=”xs:string” />
  </xs:sequence>
</xs:complexType>

So you simply pass them as:

 

    <arg0>   
         <name>Peter</name>
    </arg0>  
    <arg1>     
         <surname>Pan</surname>     
    </arg1> 

This is the full flex.mxml file.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white" viewSourceURL="srcview/index.html">

    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.events.FaultEvent;
            import mx.utils.ObjectUtil;

            private var startTime:int;
            private var endTime:int;

            private function button_click():void {
                
                webService.sayHello.send();
                startTime = getTimer();
                lbl.text = "Wait.......";
            }

            private function display(evt:ResultEvent):void {
                textField.text = ObjectUtil.toString(evt.result.name);
                textField.text += ObjectUtil.toString(evt.result.surname);
                calcTime();
            }

            private function displayfault(evt:FaultEvent):void {
                Alert.show(evt.type);
                calcTime();
                lbl.text = "ERROR:::::";
            }

            private function calcTime():void {
                endTime = getTimer();
                lbl.text = "total time: " + (endTime - startTime) + "ms";
            }
        ]]>
    </mx:Script>

    <mx:WebService id="webService"
          wsdl="http://localhost:8080/webservice_consumer/HelloWorldWS?wsdl"
          useProxy="false">
                           
        <mx:operation name="sayHello"
                resultFormat="object"
                result="display(event);"
                fault="displayfault(event);">
            <mx:request xmlns="" >
                 <arg0>Peter</arg0>
                 <arg1>Pan</arg1>
            </mx:request>
        </mx:operation>
                                             
    </mx:WebService>
    <mx:Label text="Web Service output"/>
    <mx:TextInput id="textField"
            editable="false" />
    <mx:Spacer width="100%" />

    <mx:ApplicationControlBar dock="true">
        <mx:Button id="button"
                label="call web service"
                click="button_click();" />
        <mx:Label id="lbl" />
    </mx:ApplicationControlBar>

</mx:Application> 

 

Running the sample

In order to run the sample create a new Flex Project from the Menu:

You don’t need to specify any Application Server, since you are using native Flex API for accessing Web Services. Now create a new MXML application from the main menu; paste the code in it.
 

To run the code, right-click on the source code and “Run As Flex Application”

If everything was completed successfully you should see the outoput from your Flex GUI

Special Thanks:
A special thank to Costantino Saponara who has helped me to get on working with the Flex environment. Thank you !