How to create a contract-first web service (or: how to create a web service that handles XML)
Hello! Today, I´m gonna show you a sample on how to develop a contract-first web service in java. To do so, you are gonna need:
- An Apache Tomcat (or any Application Server that is compatible with JAX-WS)
- A JAX-WS runtime (I used the RI, that I got from here – most application servers already have)
Now, as it is a contract-first web service, we need the contract. I used this one:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://alesaudate.com/webservices" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="blog" targetNamespace="http://alesaudate.com/webservices">
<wsdl:types>
<xsd:schema targetNamespace="http://alesaudate.com/webservices">
<xsd:element name="operation">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="request" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="operationResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="response" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="operation">
<wsdl:part element="tns:operation" name="parameters"/>
</wsdl:message>
<wsdl:message name="operationResponse">
<wsdl:part element="tns:operationResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="blog">
<wsdl:operation name="blogOperation">
<wsdl:input message="tns:operation"/>
<wsdl:output message="tns:operationResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="mySOAPBinding" type="tns:blog">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="blogOperation">
<soap:operation soapAction="http://alesaudate.com/webservices/SampleOperation"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="blogService">
<wsdl:port binding="tns:mySOAPBinding" name="blogSOAP">
<soap:address location="http://localhost:8080/WebServices/provider"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Now, we must provide an implementation class (or, how I like to call, where the magic happens =P ). Here is my implementation:
package com.alesaudate.webservices;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Provider;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.Service.Mode;
@ServiceMode(Mode.MESSAGE)
@WebServiceProvider(portName="blogSOAP",
serviceName="blogService",
targetNamespace="http://alesaudate.com/webservices",
wsdlLocation="WEB-INF/wsdl/blog.wsdl")
public class MySOAPProvider implements Provider<SOAPMessage>{
@Override
public SOAPMessage invoke(SOAPMessage request) {
try {
request.writeTo(System.out);
} catch (Exception e) {
e.printStackTrace();
}
return request;
}
}
Please note that this refers to a WEB-INF directory. So, as you may have guessed by now, it MUST run on a web project (.war). Other forms of java files, like .jar or .ear are unable to run this code.
Now, we must provide what I call “the glue”: files that provide the binding. For the RI implementation, we must provide a file called sun-jaxws.xml and place it under the WEB-INF directory. For our project, it has the following structure:
<endpoints
xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version="2.0">
<endpoint
name="example"
implementation="com.alesaudate.webservices.MySOAPProvider"
wsdl="WEB-INF/wsdl/blog.wsdl"
service="{http://alesaudate.com/webservices}blogService"
port="{http://alesaudate.com/webservices}blogSOAP"
url-pattern="/provider" />
</endpoints>
We also need to insert the right entries into web.xml:
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>provider</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>provider</servlet-name>
<url-pattern>/provider</url-pattern>
</servlet-mapping>
The URL pattern, here, is the address where our web service will answer requests and will provide it´s contract.
Having reached this point so far, we need to place JAX-WS lib´s on the common library directory under Tomcat (for application servers like JBoss, you may skip this step).
And that´s all! Accessing the address http://localhost:8080/WebServices/provider?wsdl has shown me the WSDL that I quoted above, how about you?
You may check the code that I used here at the downloads section.
See ya!