The Spring Web Services project is used for creating document-driven Web services. I decided to create a simple web service that takes a value and returns a value (i.e. no logic - just data transfer) .
The focus of Spring is to allow for contract-first SOAP service development. Accordingly I defined a simple WSDL document detailing my web services.
RandomService.xsd:
Step 1 is to create a Server project to host our web-service. I did this in Eclipse creating a dynamic web project.
Step 2 is to configure the Server side to handle our requests. Handler in Java Enterprise is at its simplest a servlet. Just like the DispatcherServlet which acts as a front controller receiving all requests and then delegating to controllers, spring ws uses the MessageDispatcherServlet. As per the code documentation:
Step 3 is telling our controller the details of the requests it needs to handle. In our example we would like our controller to handle all requests starting with "Service". Hence the servlet-mapping:
As can be seen most of the jars are the same that we use in a normal web application. New jars of interest are:
The focus of Spring is to allow for contract-first SOAP service development. Accordingly I defined a simple WSDL document detailing my web services.
<?xml version="1.0" encoding = "UTF-8" ?> <wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:random="http://ws.com/Service/xsd/random-schema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws.com/Service/samplews-ns" targetNamespace="http://ws.com/Service/samplews-ns"> <wsdl:types> <xs:schema> <xs:import namespace="http://ws.com/Service/xsd/random-schema" schemaLocation="xsd/RandomService.xsd" /> </xs:schema> </wsdl:types> <wsdl:message name="GetRandomRequest"> <wsdl:part element="random:GetRandomRequest" name="GetRandomRequest" /> </wsdl:message> <wsdl:message name="GetRandomResponse"> <wsdl:part element="random:GetRandomResponse" name="GetRandomResponse" /> </wsdl:message> <wsdl:message name="GetRandomFault"> <wsdl:part element="random:GetRandomFault" name="GetRandomFault" /> </wsdl:message> <wsdl:portType name="SampleServiceOperationsPortType"> <wsdl:operation name="random"> <wsdl:documentation>Returns a random value </wsdl:documentation> <wsdl:input message="tns:GetRandomRequest" name="GetRandomRequest" /> <wsdl:output message="tns:GetRandomResponse" name="GetRandomResponse" /> <wsdl:fault message="tns:GetRandomFault" name="GetRandomFault" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name="SampleServiceOperationsPortTypeSoap" type="tns:SampleServiceOperationsPortType"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="random"> <soap:operation soapAction="/Service/random" /> <wsdl:input name="GetRandomRequest"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="GetRandomResponse"> <soap:body use="literal" /> </wsdl:output> <wsdl:fault name="GetRandomFault"> <soap:fault use="literal" name="GetRandomFault" /> </wsdl:fault> </wsdl:operation> </wsdl:binding> <wsdl:service name="SampleServiceOperationsPortTypeSoap"> <wsdl:port binding="tns:SampleServiceOperationsPortTypeSoap" name="SampleServiceOperationsPortTypeSoap"> <soap:address location="/Service/ws-operations" /> </wsdl:port> </wsdl:service> </wsdl:definitions>As can be seen the wsdl defines a single operation which takes a GetRandomRequest object as input and returns a GetRandomResponse as output. In case of failure the operation returns a fault object of type GetRandomFault. The details of the these object is in an accompanying XSD file.
RandomService.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:random="http://ws.com/Service/xsd/random-schema" targetNamespace="http://ws.com/Service/xsd/random-schema"> <xs:element name="GetRandomRequest"> <xs:complexType> <xs:all> <xs:element name="name" type="xs:string" maxOccurs="1" minOccurs="1" /> </xs:all> </xs:complexType> </xs:element> <xs:element name="GetRandomResponse"> <xs:complexType> <xs:all> <xs:element name="value" type="xs:int" maxOccurs="1" minOccurs="1" /> </xs:all> </xs:complexType> </xs:element> <xs:element name="GetRandomFault"> <xs:complexType> <xs:all> <xs:element name="faultMessage" type="xs:string" maxOccurs="1" minOccurs="1" /> </xs:all> </xs:complexType> </xs:element> </xs:schema>Now that the contract is defined the next step is to implement the webservice via Spring:
Step 1 is to create a Server project to host our web-service. I did this in Eclipse creating a dynamic web project.
Step 2 is to configure the Server side to handle our requests. Handler in Java Enterprise is at its simplest a servlet. Just like the DispatcherServlet which acts as a front controller receiving all requests and then delegating to controllers, spring ws uses the MessageDispatcherServlet. As per the code documentation:
Servlet for simplified dispatching of Web service messages. This servlet is a convenient alternative to the standard Spring-MVC DispatcherServlet with separate WebServiceMessageReceiverHandlerAdapter, MessageDispatcher, and WsdlDefinitionHandlerAdapter instances. This servlet automatically detects EndpointAdapters, EndpointMappings, and EndpointExceptionResolvers by type.The servlet acts like a front controller for our web service, receiving all requests and then delegating them to appropriate endpoints (Controllers in the web service world).
<servlet> <servlet-name>spring-ws</servlet-name> <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class> <init-param> <param-name>transformWsdlLocations</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>This is from the docs: When the transformWsdlLocations init-param is set to true in this servlet's configuration in web.xml, all location attributes in the WSDL definitions will reflect the URL of the incoming request.
Step 3 is telling our controller the details of the requests it needs to handle. In our example we would like our controller to handle all requests starting with "Service". Hence the servlet-mapping:
<servlet-mapping> <!-- For the End Points --> <servlet-name>spring-ws</servlet-name> <url-pattern>/Service/*</url-pattern> </servlet-mapping>Step 4 involved adding the jars necessary for the code to execute:
As can be seen most of the jars are the same that we use in a normal web application. New jars of interest are:
- wsdl4j-1.6.1.jar - Is the reference implementation for JSR110 'JWSDL' (jcp.org).(WSDL4J allows the creation, representation, and manipulation of WSDL documents.) In this jar, the package javax.wsdl.* includes all the interfaces while the package com.ibm.* includes all the
implementations. - spring-ws-core - This is the Spring Web Services Core package.
- spring-xml - The jar is a utility jar that includes various XML support classes for Spring Web Services.
- spring-oxm -The jar provides for Object/XML Mapping, or O/X mapping. It is the act of converting an XML document to and from an object
Thanks for writing such a good article, I stumbled onto your blog and read a few post. I like your style of writing... Auto Detailing Irvine
ReplyDelete