Wednesday, December 20, 2006

JAX-WS, WSDL and Tools

I've mentioned that I'm looking at Celtix's Open-Source ESB. One thing you notice right off the bat is the incorporation of the new JAX-WS standard. Annotations in particular make it much easier to expose an existing java service as a web service or create a new one as a web service.

Here is an example -

Interface Definition

package pgn.objects.wsdl.full.devservices.customerrequest.ver1;

import javax.jws.WebParam.Mode;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding;
import javax.jws.WebMethod;
import javax.jws.WebResult;

/**
* This class was generated by the CXF 2.0-M1-IONA
* Wed Dec 13 15:45:39 EST 2006
* Generated source version: 2.0-M1-IONA
*
*/

@WebService(wsdlLocation = "file:/C:/IONA/samples/service_creation/customerinfo/wsdl/
customerrequestver1.wsdl", targetNamespace = "urn:pgn:objects:wsdl:full:devservices:customerrequest:ver1", name = "customerrequestPT")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE, use = SOAPBinding.Use.LITERAL, style = SOAPBinding.Style.DOCUMENT)

public interface CustomerrequestPT {

@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@WebResult(targetNamespace = "urn:pgn:objects:xmlschema:messagetypes:devservices:
customerrequest:ver1", partName = "CreateCustomerResponse", name = "CreateCustomerResponse")
@WebMethod(operationName = "getCustomerRequest")
public pgn.objects.xmlschema.messagetypes.devservices.
customerrequest.ver1.
CustomerResponseType getCustomerRequest(
@WebParam(targetNamespace = "urn:pgn:objects:xmlschema:messagetypes:devservices:
customerrequest:ver1", partName = "CreateCustomerRequest", name = "CreateCustomerRequest")
pgn.objects.xmlschema.messagetypes.devservices.customerrequest.ver1.
CustomerRequestType createCustomerRequest
);
}

The annotations defined the communication style and structure that match what is in the WSDL.


An excerpt of the implementation of the Interface
package pgn.objects.wsdl.full.devservices.customerrequest.ver1;

import pgn.objects.wsdl.full.devservices.customerrequest.ver1.
CustomerrequestPT;
import pgn.objects.xmlschema.messagetypes.devservices.
customerinfo.ver1.*;
import pgn.objects.xmlschema.messagetypes.devservices.
customerrequest.ver1.*;
import java.util.*;
import java.io.*;


@javax.jws.WebService(serviceName ="CustomerRequest", portName = "customerrequestPort", endpointInterface ="pgn.objects.wsdl.full.devservices.customerrequest.ver1.CustomerrequestPT", targetNamespace ="urn:pgn:objects:wsdl:full:devservices:customerrequest:ver1")

@javax.xml.ws.BindingType(value = "http://cxf.apache.org/bindings/xformat")


public class Customer extends Thread implements
CustomerrequestPT {
CustomerRequestType requesttype;
CustomerAccountType accountinfo;
String programname;
Notice the two annotations. That's really it for exposing this as a Web Service. Now for the important part. The interface was auto generated by some of the bundled tools in the Celtix distribution. It is important to note that the implementation interface was generated from the WSDL (which was written first) and not vice versa.

Joe Mckendrick points out that tools can make it easy to generate your interface definition (WSDL) from an existing implementation. I think the generally accepted best practice is to develop the WSDL and XML Schemas first. Hopefully following that approach will lead to a less brittle interface that has the right granularity. It should also help reduce the potential number of interoperability issues that can arise from auto-generation of Web Services from existing code.

As far as Celtix goes, if you are looking for an Open-Source ESB to mess around with, I have found Celtix's to be straight forward to work with so far. I haven't really done anything over than some content based routing tests and fail-over routing.

No comments: