Create a Contract-First Spring Web Service
Contract-First Web Service is to develop web services by starting with the XML Schema/WSDL contract first followed by the Java code second.
Implementation
- Create the XML Schema.
- Define the XML Schema for the Request and Response messages.
- Save the XML Schema as "lucky.xsd" under the folder "WEB-INF/xsd".
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://com.blogspot.adaprognotebook/LuckyService/"
elementFormDefault="qualified">
<xsd:element name="LuckyRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="LuckyResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="message" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
- Create and define the service interface in Java.
LuckyService.java
package main.java.com.blogspot.adaprognotebook.service;
public interface LuckyService {
String sayLuckyMessage(String name);
}
LuckyServiceImpl.java
package main.java.com.blogspot.adaprognotebook.service;
public class LuckyServiceImpl implements LuckyService {
@Override
public String sayLuckyMessage(String name) {
if (name == null || name.trim().isEmpty()) {
return "Tell me you name~~~";
}
int number = (int)(Math.random()*100);
return "Hello : " + name + "! Your lucky number is " + number + ".";
}
}
- Create the Object/XML binding.
- Create POJO classes for the Request (LuckyRequest.java) and Response (LuckyResponse.java) in Java.
LuckyRequest.java
package com.blogspot.adaprognotebook.message;
public class LuckyRequest
{
private String name;
public LuckyRequest() {
super();
}
public LuckyRequest(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
LuckyResponse.java
package com.blogspot.adaprognotebook.message;
public class LuckyResponse
{
private String message;
public LuckyResponse() {
super();
}
public LuckyResponse(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- Define the Object/XML binding using JiBX for the purpose of marshalling and unmarshalling for the above model classes.
binding.xml
<binding name="binding" package="com.blogspot.adaprognotebook.message" trim-whitespace="true">
<namespace uri="http://localhost:8080/luckyservice/" default="elements"/>
<mapping class="com.blogspot.adaprognotebook.message.LuckyRequest" name="LuckyRequest">
<value style="element" name="name" get-method="getName" set-method="setName"/>
</mapping>
<mapping class="com.blogspot.adaprognotebook.message.LuckyResponse" name="LuckyResponse">
<value style="element" name="message" get-method="getMessage" set-method="setMessage"/>
</mapping>
- Configure Spring's Application Context.
WEB-INF/spring/applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="payloadMapping"
class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="endpointMap">
<map>
<entry
key="{http://localhost:8080/luckyservice/}/LuckyRequest"
value-ref="luckyServiceEndpoint" />
</map>
</property>
</bean>
<bean id="luckyService" class="com.blogspot.adaprognotebook.service.LuckyServiceImpl" />
<bean id="luckyServiceEndpoint"
class="com.blogspot.adaprognotebook.endpoint.LuckyServiceEndpoint">
<property name="marshaller" ref="marshaller" />
<property name="unmarshaller" ref="unmarshaller" />
<property name="luckyService" ref="luckyService" />
</bean>
<bean id="marshaller"
class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass"
value="com.blogspot.adaprognotebook.message.LuckyResponse" />
</bean>
<bean id="unmarshaller"
class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass"
value="com.blogspot.adaprognotebook.message.LuckyRequest" />
</bean>
<bean id="LuckyRequest"
class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
<property name="schema" ref="schema" />
<property name="portTypeName" value="Hello" />
<property name="locationUri"
value="http://localhost:8080/luckyservice/services/LuckyRequest" />
</bean>
<bean id="schema"
class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="/WEB-INF/xsd/lucky.xsd" />
</bean>
</beans>
- Define the Endpoint.
package com.blogspot.adaprognotebook.endpoint;
import com.blogspot.adaprognotebook.message.HelloRequest;
import com.blogspot.adaprognotebook.message.HelloResponse;
import com.blogspot.adaprognotebook.service.HelloService;
import org.springframework.ws.server.endpoint.AbstractMarshallingPayloadEndpoint;
@SuppressWarnings("deprecation")
public class HelloServiceEndpoint extends AbstractMarshallingPayloadEndpoint {
private HelloService helloService;
protected Object invokeInternal(Object requestObject) throws Exception {
HelloRequest request = (HelloRequest) requestObject;
String name = request.getName();
return new HelloResponse(helloService.sayhello(name));
}
public HelloService getHelloService() {
return helloService;
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
}
- Deploy the web service to Web Server like Jetty.
- View the generated WSDL at http://localhost:8080/luckyservice/LuckyRequest.wsdl.
<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions targetNamespace="http://localhost:8080/luckyservice/" xmlns:sch="http://localhost:8080/luckyservice/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://localhost:8080/luckyservice/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xsd:schema elementFormDefault="qualified" targetNamespace="http://localhost:8080/luckyservice/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="LuckyRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="LuckyResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="message" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="LuckyResponse">
<wsdl:part element="sch:LuckyResponse" name="LuckyResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="LuckyRequest">
<wsdl:part element="sch:LuckyRequest" name="LuckyRequest">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="Lucky">
<wsdl:operation name="Lucky">
<wsdl:input message="sch:LuckyRequest" name="LuckyRequest">
</wsdl:input>
<wsdl:output message="sch:LuckyResponse" name="LuckyResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="LuckySoap11" type="sch:Lucky">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Lucky">
<soap:operation soapAction=""/>
<wsdl:input name="LuckyRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="LuckyResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="LuckyService">
<wsdl:port binding="sch:LuckySoap11" name="LuckySoap11">
<soap:address location="http://localhost:8080/luckyservice/services/LuckyRequest"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
- Test the web service using tools like SOAP UI.