Posts Tagged ‘WSDL’

Contract-driven web services with JAX-WS

Monday, July 28th, 2008

Attentive readers will notice that I have previously advocated both contract-first web services and JAX-WS. Although these might seem like contradictory concepts at first glance, I believe I can make a case for the use of these two approaches together. Although many “Hello World” web service examples with JAX-WS simply use the @WebService annotation, a much more sophisticated web service can be developed by digging in to the optional attributes of the javax.jws.WebService annotation. One in particular that jumps out:

-wsdlLocation: allows the specification of a URL of an existing WSDL file. This file can be stored on the web or referenced with a local URL. The WSDL and an external JAX-WS XML bindings file can be used to specify the service operations and the Java type mapping respectively.

Maybe you are not interested in creating your own WSDL or XML bindings file, and you instead want to use Java as your language to express your service contract. Although you lose some power in this arrangement (mainly in the area of XSD data constraints), this may be a more natural approach for most Java developers.

One important consideration in maintaining the contract of a web service is versioning capabilities. If you need to provide backwards-compatibility when you make service operation signature or semantic changes, consider the use of version-based namespaces. Again, the @WebService annotation provides for this with another optional attribute, targetNamespace. It is good practice to embed a version number in both the service endpoint URL and the service namespace to protect against future changes that break backward compatibility.

Having a mechanism for versioning is only half the battle. Having a minimally invasive way to continue to separate your web service endpoint from refactoring and change in your Java code is the key. The approach that I rely on is to inject business services into my service endpoint class rather than directly annotating business services with the JAX-WS annotations. These classes can be a simple 1-to-1 delegate at first, but can adopt more complex mapping and adapting behavior over time if needed for backward compatibility. This allows business services (Java) and web services (JAX-WS/SOAP) to have different refactoring and backward compatibility restrictions (if desired).

The most simple example:

@WebService
public class HelloWorldWebService {
private HelloWorldService service;

public void setHelloWorldService(HelloWorldService service) {
this.service = service; //service delegate injection point
}

@WebMethod
public String helloWorld() {
return service.helloWorld();
}
}

It is tempting to take the easy way out and simply annotate a concrete service class with web service functionality. My preferred breakdown is to have a business service interface, a business service implementation, and a concrete web service endpoint class with annotations. This makes your business services completely unaware of remoting considerations, which is good insulation against future adoptions/un-adoptions of technologies. If the REST advocates have their way and take over the world, you can always rip out your JAX-WS service endpoint class and replace it with the remoting strategy du jour.

You can create a contract-driven SOAP web service with varying degrees of rigor easily with JAX-WS. Understanding your constraints and how closely you want to adhere to contract-driven approaches should allow you to find a happy place where you can leverage the JAX-WS toolset and still build robust and stable web services.

Software development methodologies can easily be adopted with religious zeal, but it is important to remember that our ultimate goal is to build software that delivers on business needs!