What is Spring Web Services (WS)?
Spring Web Services (Spring-WS) is a product of the Spring community focused on creating document-driven Web services. Spring Web Services aims to facilitate contract-first SOAP service development, allowing for the creation of flexible web services using one of the many ways to manipulate XML payloads. The product is based on Spring itself, which means you can use the Spring concepts such as dependency injection as an integral part of your Web service.
Source: Spring WS Reference 2.0
What is Contract-First development?
When creating Web services, there are two development styles: Contract Last and Contract First. When using a contract-last approach, you start with the Java code, and let the Web service contract (WSDL, see sidebar) be generated from that. When using contract-first, you start with the WSDL contract, and use Java to implement said contract.For an in-depth look of Spring WS, I suggest my readers to visit the Spring WS Reference 2.0 and the Spring WS API 2.0.0.RC2
Source: Spring WS Reference 2.0
Unlike with my previous tutorials, there's no Spring MVC here. However, we will still use some of the convenient tools from Spring MVC like the @Service annotation.
We begin by defining our requirements. We have a magazine business. Our business partner has clients that needs to subscribe with our magazine. To expose this feature, we decided to use a web service. Our contract is that the clients will send the following information:
subscription code name emailOur web service will send a reply if the subscription is successful or not. The reply will contain the following elements:
status code descriptionSince all web services are ultimately XML message, we need to define the format of our messages. We will create an XSD file. If you're not familiar with XSD, please see the excellent XSD tutorial w3schools.com XML Schema Tutorial.
Here's our XSD document:
subscription.xsd
This XSD is composed of simple and complex element types. Each simple element has been assigned with restriction. In this way we can filter data even before it comes to our service. It's also a good way to validate XML data. Spring WS will handle the validation based on these restrictions.
When the client sends a request, we receive an XML document. Using Java's object-oriented approach and XML approach is not really convenient when manipulating information. Therefore we will use marshalling techniques to map the XML document with a corresponding Java object.
First let's see the actual XML document that is sent to us by the client:
Take note that this XML format is not arbitrary! The client has to honor the format that we declared in the XSD document.
Let's map this document to a SubscriptionRequest class:
SubscriptionRequest
For every request sent by the client, we send a response. We declare a SubscriptionResponse object:
Our marshaller will automatically convert this class into an XML document. If you look at the XSD file, we have declared a subscriptionResponse element.
This has been declared so that the client who is reading our WSDL will see what kind of response he will receive. Hence, the Contract-First development.
When the client receives a response, this is what he actually gets:
Our class has been automatically converted to XML.
To convert Java objects to XML and vice-versa we use Castor as our marshaller/unmarshaller implementation. For more info about Castor, check the reference guide Castor XML Mapping. There are other marshallers available, such as JAXB and JiBX. Check the Spring WS Reference Guide Chapter 8. Marshalling XML using O/X Mapper for more info.
To use Castor we need to declare a mapping file:
castor-mapping.xml
We're done with our contract. We now start the actual development!
The programming model of Spring WS 2 is similar with the programming model of Spring 3 MVC. Keep that in mind. In Spring MVC, to declare a controller, we mark the name of the class with @Controller and @RequestMapping. For example:
In Spring WS, we have a corresponding controller as well. Actually, it's called an endpoint. To declare an endpoint, we mark it with @Endpoint. For example:
In Spring MVC, to expose a method for a particular request, we add the @RequestMapping annotation and the associated URI template value and the type of method. For example:
In Spring WS, to expose a method for a particular service request, we add the @PayloadRoot annotation and the associated localPart and namespace values. For example:
The method is also annotated with @ResponsePayload, indicating that the return value ( SubscriptionResponse) is used as the payload of the response message. The method takes a SubscriptionRequest as a parameter, annotated with @RequestPayload. This means that the payload of the message is passed on this method as a DOM element. If you have omitted these two annotations, you will encounter a "java.lang.IllegalStateException: No adapter for endpoint".
Let's now declare our SubscriptionEndpoint class:
SubscriptionEndpoint
This endpoint has one method named processSubscription. It takes a SubscriptionRequest and delegates the processing to a SubscriptionService. If the subscription is successful a SUCCESS response is sent. If it failed, a FAILURE response is sent.
Here's the SubscriptionService:
SubscriptionService
We're done will all our classes. What's left are the XML configurations. We start by declaring the web.xml file:
In a normal Spring MVC application, we dispatch all request to a DispatcherServlet. With Spring WS, we use the MessageDispatcherServlet instead. If you examine carefully the servlet element, we've declared an init-param. This is required to dynamically convert WSDLs regardless where you deploy it. There's no need to manually set the URL of your WSDL anymore, though you still can.
In the web.xml we declared a servlet-name spring. By convention, we must declare a spring-servlet.xml as well.
spring-servlet.xml
These beans activate Spring's annotation support and some of Spring 3 MVC's convenient annotations like @Service. At the bottom portion we import an external configuration file spring-ws.xml. This contains all the Spring WS specific configuration. In a normal Spring project, it's typical to have multiple XML configs. To lessen the XML hell experience, it's advisable we group related configurations in their owned XML file.
Here's spring-ws.xml:
spring-ws.xml
This configuration uses the latest Spring WS 2.0.0 RC2 features (unlike if you're still using 1.5.9).
What's new with Spring WS 2.0.0 RC2?
The most important new feature in this release is the update of the Spring-WS XML namespace, which now contains <sws:annotation-driven/> and <sws:interceptors/> elements (similar to the Spring-MVC namespace), and <sws:static-wsdl/> and <sws:dynamic-wsdl/> for exporting your WSDLs.It's worth mentioning in the spring-ws.xml, we're using a pluggable endpoint adapter
Source: SpringSource Forum: Spring Web Services 2.0.0 RC2 released
DefaultMethodEndpointAdapterand a marshalling method processor
MarshallingPayloadMethodProcessorIf you visit some of the popular Spring WS tutorials, they still use the old GenericMarshallingMethodEndpointAdapter. However, this is already deprecated in favor of a pluggable adapter.
Class GenericMarshallingMethodEndpointAdapterThat concludes our Spring WS development. We've managed to setup a simple Spring 3 WS application using the latest Spring WS 2.0.0.RC2 build. We've utilized the latest annotation features. We've also leveraged Spring 3 MVC's programming model.
Deprecated. as of Spring Web Services 2.0, in favor of DefaultMethodEndpointAdapter and MarshallingPayloadMethodProcessor.
See Spring WS API 2.0.0 GenericMarshallingMethodEndpointAdapter
To test the application, you will need to deploy it in a server, like Tomcat. For the client, unless you know how to develop a Web Service client, I advise my readers to use Soap UI for testing. They have a free version at http://soapui.org/. It's also one of the recommended tools at the official Spring Web Services site at http://static.springsource.org/spring-ws/sites/2.0/resources.html.
Here's a sample screenshot using SOAP UI to test the application:
To access the service endpoint, use the following URL:
http://localhost:8080/spring-ws-standalone/krams/wsTo access the WSDL, use the following URL (you can use Firefox to check this out):
http://localhost:8080/spring-ws-standalone/krams/ws/subscription.wsdlThe best way to learn further is to try the actual application.
Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-ws-2-0-0-rc2-tutorial/
You can download the project as a Maven build. Look for the spring-ws-standalone.zip in the Download sections.
You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run
If you want to learn more about Spring MVC and integration with other technologies, feel free to read my other tutorials in the Tutorials section.
Share the joy:
|
Subscribe by reader Subscribe by email Share
Hi
ReplyDeleteThis is a great article. looks very long and tedious also. did you follow any examples provided to comeup with this article ?
@Anonymous, nope. I didn't follow any examples for RC2. I just ported my old implementation from 1.5 to 2.0.RC2. It's a fairly new release, so it's safe to say, this might be the first article utilizing this RC2. I had to read the source code, specially the DefaultMethodEndpointAdapter and MarshallingPayloadMethodProcessor. Well, I did follow the provided samples for 1.5 but not for 2.0. Regarding the length, I prefer to make it detailed to help out also the newbies.
ReplyDeleteJust to says thanks.... I couldn't get the MarshallingPayloadMethodProcessor working correctly. However looking at your Spring-WS config file helped me sort it.
ReplyDeleteHi,
ReplyDeleteI really enjoy your tutorials. They are really good. However when I tried this one: "Spring WS: A Tutorial Using the Latest 2.0.0 RC2 Build" I get this error when I invoke the service in SOAPUI.
Request:
hello
John
john@gmail.com
Response:
SOAP-ENV:Server
argument type mismatch
Can you plz help me out?
Thanks.
Just to say thanks for your time and effort in making the tutorial simple and clear.
ReplyDeleteThanks again!
You are one of the roses in the world which makes life looks beautiful.
Thank you, found your post on the spring forums.
ReplyDeleteIf you want that the example work you have to add the following lines in the the web.xml file:
ReplyDeletecontextConfigLocation
\WEB-INF\spring-servlet.xml
I get the following error in SOAP UI: ERROR:org.apache.http.conn.HttpHostConnectException: Connection to http://127.0.0.1:8888 refused
ReplyDeleteAnyone a suggestion?
I deployed the spring-ws-standalone.war to the tomcat webapps directory.
Thanks
Hi,
ReplyDeleteWhen I run this project, I got these errors. Could you please help me ASAP?
1. ignored XML validation warning: org.xml.sax.SAXParseException:
Failed to read schema document 'http://www.springframework.org/schema/web-services/web-services-2.0.xsd'
2. Context initialization failed:
org.springframework.beans.factory.parsing.BeanDefinitionParsingException:
Configuration problem: Failed to import bean definitions from relative location [spring-ws.xml]
3. Caused by: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException:
Line 33 in XML document from ServletContext resource [/WEB-INF/spring-ws.xml] is invalid;
4. Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.c:
The matching wildcard is strict, but no declaration can be found for element 'sws:annotation-driven'.
3 year passed, this article is still very valuable. It comes with very detail information! I don't understand people say it is too long. Krams, please write more articles like this, definitely people will thank you.
ReplyDeleteExcellent article. And I got it working with Spring 3.2.0, Spring-WS 2.2.0 and Castor 1.3.3 on TomEE.
ReplyDeleteThank you : )
ReplyDeleteExcellent and rare article: thank a lot. I have been struggling to make the HumanResourceService (http://docs.spring.io/spring-ws/site/reference/html/tutorial.html#tutorial.xsd) of work without any success but your example rocks. 5 years of age and still relevant and working.
ReplyDeleteThanks a lot. I am able to view the wsdl file; now I tried to invoke the webservice using curl with the following command:
ReplyDeletecurl --header "content-type: text/xml" -d @subscriptionrequest1 http://127.0.0.1:9090/spring-ws-standalone/krams/ws/
where the content of subscriptionrequest1 contents the following :
1234567
John Smith
johnsmith@yahoo.com
I got a :
com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source:
any idea of how to fix this issue.
It was indeed valuable in understanding a spring web service app!!
ReplyDeleteThanks for sharing this valuable information with us keep blogging
ReplyDeleteDigital Marketing Course in Vizag
Seo Training in Vizag
Digital Marketing Course in Vijayawada
Digital Marketing Course in Tirupati
Digital Marketing Course in Guntur
Seo Services in Vizag
I gotta favorite this site it seems extremely helpful very helpful 토토사이트
ReplyDeleteYou should take part in a contest for one of the best blogs on the web. I will recommend this site! 바카라사이트
ReplyDelete