Search This Blog

Tuesday, 7 May 2013

Contract First web service with CXF

In the post on Spring web services, I had used a contract first approach for development. This being the only style supported by Spring.
JAX-WS and also CXF on the other hand support both code first and contact first approaches.
I decided to use the same wsdl file from my Spring post:
<?xml version="1.0"  encoding = "UTF-8" ?>
<wsdl:definitions xmlns:xs=""

   <xs:import namespace=""
    schemaLocation="xsd/RandomService.xsd" />

 <wsdl:message name="GetRandomRequest">
  <wsdl:part element="random:GetRandomRequest" name="GetRandomRequest" />
 <wsdl:message name="GetRandomResponse">
  <wsdl:part element="random:GetRandomResponse" name="GetRandomResponse" />

 <wsdl:portType name="SampleServiceOperationsPortType">
  <wsdl:operation name="random">
   <wsdl:documentation>Returns a random value from the application
   <wsdl:input message="tns:GetRandomRequest" name="GetRandomRequest" />
   <wsdl:output message="tns:GetRandomResponse" name="GetRandomResponse" />

 <wsdl:binding name="SampleServiceOperationsPortTypeSoap"
  <soap:binding style="document"
   transport="" />
  <wsdl:operation name="random">
   <soap:operation soapAction="/Service/random" />
   <wsdl:input name="GetRandomRequest">
    <soap:body use="literal" />
   <wsdl:output name="GetRandomResponse">
    <soap:body use="literal" />

 <wsdl:service name="SampleServiceOperationsPortTypeSoap">
  <wsdl:port binding="tns:SampleServiceOperationsPortTypeSoap"
   <soap:address location="randomService" />
The included xsd file is as below:
<xs:schema xmlns:xs=""

    <xs:element name="GetRandomRequest">
                <xs:element name="name" type="xs:string" maxOccurs="1"
                    minOccurs="1" />
    <xs:element name="GetRandomResponse">
                <xs:element name="value" type="xs:int" maxOccurs="1"
                    minOccurs="1" />
    <xs:element name="GetRandomFault">
                <xs:element name="faultMessage" type="xs:string"
                    maxOccurs="1" minOccurs="1" />
Now that the contract has been defined we need to generate the source code from the same.
I used the wsdl2java command from CXF for the same.
>wsdl2java -ant -impl -server -d . random.wsdl
Navigate to the folder with the wsdl file and execute the command:
This results in the files being generated by CXF:

The Service Endpoint Interface generated by the tool is :
@WebService(name = "SampleServiceOperationsPortType",targetNamespace = "")
@XmlSeeAlso({ })
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface SampleServiceOperationsPortType {

  * Returns a random value
 @WebResult(name = "GetRandomResponse", 
   targetNamespace = "", 
   partName = "GetRandomResponse")
 @WebMethod(action = "/Service/random")
 public random(
   @WebParam(partName = "GetRandomRequest", name = "GetRandomRequest", 
    targetNamespace = "") getRandomRequest);
Interesting point is that maximum annotation details is added to the interface. The documentation element details have been added to the code comments.
The Implementation is as below:
@javax.jws.WebService(serviceName = "SampleServiceOperationsPortTypeSoap", 
  portName = "SampleServiceOperationsPortTypeSoap", 
  targetNamespace = "", 
  wsdlLocation = "random.wsdl", 
  endpointInterface = "")
public class SampleServiceOperationsPortTypeImpl implements
  SampleServiceOperationsPortType {

 private static final Logger LOG = Logger

  * (non-Javadoc)
  * @see
  * .ws.service.xsd.random_schema.GetRandomRequest getRandomRequest )*
 public random( getRandomRequest) {"Executing operation random");
  try { _return = null;
   return _return;
  } catch (java.lang.Exception ex) {
   throw new RuntimeException(ex);

Here the webservice annotation provides the SOAP details. The method is incomplete. I had to make some minor code changes to the below: _return = new GetRandomResponse();
_return.setValue((int) (Math.random()*165));
There are two more files that were generated:
  1. SampleServiceOperationsPortTypeSoap – This is a web-service client built using pure JAX-WS APIs
  2. SampleServiceOperationsPortType_SampleServiceOperationsPortTypeSoap_Server – This uses the Endpoint API to publish the webservice
Now to add these files to a web project and execute it. 
I added a jax-ws endpoint bean ( a spring configuration file placed in the config folder)
<jaxws:endpoint id="randomWs" 
       wsdlLocation="random.wsdl" address="randomService">
  <entry key="schema-validation-enabled" value="true" />
I also added an entry for the CXFServlet in my web.xml:
and tried to access the wsdl file at URL http://localhost:8080/WsdlFirst/services/randomService?wsdl
The wsdl displayed had a change at two points:
  1. It mapped the external xsd to a new URL - http://localhost:8080/WsdlFirst/services/randomService?xsd=xsd/RandomService.xsd.
  2. It modified the soap:address element's location attribute to refer to an absolute URL http://localhost:8080/WsdlFirst/services/randomService
The question that now arises is did CXF use my supplied wsdl or did it generate its own complete version.
To test the above I removed the WebResult, WebMethod and WebParam annotations.
Now if I run the code the details provided in the wsdl file is still reflected. For example the part names appear as set in the wsdl file. Also I modified the operations documentation element in my wsdl and the change was displayed.
So this means CXF uses the wsdl file specified. It will only auto-generate if one is not available.
What if you do not specify the  wsdlLocation attribute ?
I next decided to remove the attribute while retaining my wsdl file on the classpath. CXF continued to use my wsdl file. Thus the attribute can even by avoided. When resolving a wsdl request for a service 'xyz' if CXF finds a wsdl named 'xyz.wsdl' on the classpath it chooses the use the file.
To test my webservice I created a simple client:
public static void main(String[] args) {
 final String endpointAddress = "http://localhost:8080/WsdlFirst/services/randomService";
 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

 factory.setServiceClass(SampleServiceOperationsPortType.class); // the SEI
 SampleServiceOperationsPortType client = (SampleServiceOperationsPortType) factory

 GetRandomRequest randomRequest = new GetRandomRequest();

 GetRandomResponse reply = client.random(randomRequest);
 System.out.println("Server said: " + reply.getValue());
The logs indicate successful execution:
Server said: 36


  1. Ηavе you eveг thought abnout
    creаting an ebook orr gueѕt authoring on other blοgs?
    I haνе a blοg baѕed on the samе ѕubjectѕ you discusѕ аnd ωould lоve to haѵe
    you ѕhare ѕοmе ѕtοгіеs/іnfoгmatiοn.
    I know my ѵiewеrs wоuld value уour work.
    If yоu аrе even гemοtely іnteresteԁ, feеl freе to senԁ mе an e-mаil.

    Feel free to surf tο my wеbpage: affordable website maintenance services

  2. Thanks. This article was very helpful.

  3. Nice post, very useful.. Thank you so much

  4. This comment has been removed by the author.