Spring Web Services (Spring-WS) developed by the spring community focuses on the creation of document-driven Web services. It facilitates the contract-first SOAP Service Development. It can manipulate XML payloads in many ways. Spring Web Services aims to give loose coupling between the WSDL contract and its JAVA based implementation.
Features of Spring Web Services:
- XML Mapping to Objects: Requests based on XML can be mapped to any object with the help of the information stored in the Message Payload, SOAP Action Header, or using an XPath Expression.
- Multiple API Support to parse XML: It supports from the standard JAXP APIs (DOM, SAX, StAX) to parse the incoming XML requests, it also supports other libraries like JDOM, dom4j, XOM.
- Multiple API Support to marshal XML: Spring Web Services supports Castor, XMLBeans, JiBX, and XStream libraries using its Object/XML Mapping module.
- Spring-based configurations: Spring Web Services also uses the Spring Application Contexts for its configurations that are having a similar architecture like that of the Spring Web MVC.
- Integrated WS-Security module: With the help of the WS-Security module, you can Sign, Encrypt, Decrypt SOAP Messages, or Authenticate them.
- Support for Acegi Security: With the help of the WS-Security implementation of Spring Web Services, Acegi configuration can also be used for your SOAP services.
The architecture of Spring Web Services:
- Spring-WS Core: This is the primary module, and it contains the Central Interfaces like WebServiceMessage and SoapMessage, the server-side framework, powerful message dispatching capability, and also support classes to implement Web service endpoints. It also contains Web Service consumer clients as WebServiceTemplate.
- Spring-WS Support: This module contains supports for JMS, emails, etc.
- Spring-WS Security: This module contains a WS-Security implementation integrated with the core Web Service Module. Also, we can add principal tokens, sign, encrypt, and decrypt SOAP messages. It allows using the existing Spring Security Implementation for authentication and authorization.
- Spring XML: It contains XML support classes for Spring Web Services. It is internally used by the Spring-WS framework.
- Spring OXM: It contains support classes for XML vs. Object Mapping.
How to create a Spring WS Application?
Here, we are going to write a simple Spring WS Application which will book leave in an HR Portal.
Step 1: Spring-WS follows the Contract-first approach, which means that you should have your XML Structures ready before writing any JAVA based implementation code. So first, we will design the XML Constructs.
Leave.xml
<Leave xmlns = "http://example.com/hr/schemas"> <StartDate>2020-06-23</StartDate> <EndDate>2020-06-27</EndDate> </Leave>
Employee.xml
<Employee xmlns = "http://example.com/hr/schemas”> <Number>404</Number> <FirstName>Mahesh</FirstName> <LastName>Parashar</LastName> </Employee>
LeaveResquest.xml
<Employee xmlns = "http://example.com/hr/schemas”> <Leave> <StartDate>2020-07-03</StartDate> <EndDate>2020-07-07</EndDate> </Leave> <Employee> <Number>404</Number> <FirstName>Mahesh</FirstName> <LastName>Parashar</LastName> </Employee> </LeaveRequest>
hr.xsd
<xs:schema xmlns:xs = "https://www.w3.org/2001/XMLSchema" xmlns:hr = "https://example.com/hr/schemas" elementFormDefault = "qualified" targetNamespace = "https://example.com/hr/schemas"> <xs:element name = "LeaveRequest"> <xs:complexType> <xs:all> <xs:element name = "Leave" type = "hr:LeaveType"/> <xs:element name = "Employee" type = "hr:EmployeeType"/> </xs:all> </xs:complexType> </xs:element> <xs:complexType name = "LeaveType"> <xs:sequence> <xs:element name = "StartDate" type = "xs:date"/> <xs:element name = "EndDate" type = "xs:date"/> </xs:sequence> </xs:complexType> <xs:complexType name = "EmployeeType"> <xs:sequence> <xs:element name = "Number" type = "xs:integer"/> <xs:element name = "FirstName" type = "xs:string"/> <xs:element name = "LastName" type = "xs:string"/> </xs:sequence> </xs:complexType> </xs:schema>
Step 2: Open the command console. Go to the C:/MVN directory and execute the below command.
Step 3: Go to the directory C:/MVN and you will see a project named leaveService. Update the pom.xml file and add HumanResourceService.java and HumanResourceServiceImpl.java in:
Then open the folder
pom.xml
<?xml version = "1.0" encoding = "UTF-8"?> <project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.hr</groupId> <artifactId>leaveService</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>leaveService Spring-WS Application</name> <url>http://www.springframework.org/spring-ws</url> <build> <finalName>leaveService</finalName> </build> <dependencies> <dependency> <groupId>org.springframework.ws</groupId> <artifactId>spring-ws-core</artifactId> <version>2.4.0.RELEASE</version> </dependency> <dependency> <groupId>jdom</groupId> <artifactId>jdom</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>1.6.2</version> </dependency> </dependencies> </project>
HumanResourceService.java
package com.example.hr.service; import java.util.Date; public interface HumanResourceService { void bookLeave(Date startDate, Date endDate, String name); }
package com.example.hr.service; import java.util.Date; import org.springframework.stereotype.Service; @Service public class HumanResourceServiceImpl implements HumanResourceService { public void bookLeave(Date startDate, Date endDate, String name) { System.out.println("Booking holiday for [" + startDate + "-" + endDate + "] for [" + name + "] "); } }
LeaveEndPoint.java
package com.example.hr.ws; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ws.server.endpoint.annotation.Endpoint; import org.springframework.ws.server.endpoint.annotation.PayloadRoot; import org.springframework.ws.server.endpoint.annotation.RequestPayload; import com.example.hr.service.HumanResourceService; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.Namespace; import org.jdom.xpath.XPath; @Endpoint public class LeaveEndpoint { private static final String NAMESPACE_URI = "http://example.com/hr/schemas"; private XPath startDateExpression; private XPath endDateExpression; private XPath nameExpression; private HumanResourceService humanResourceService; @Autowired public LeaveEndpoint(HumanResourceService humanResourceService) throws JDOMException { this.humanResourceService = humanResourceService; Namespace namespace = Namespace.getNamespace("hr", NAMESPACE_URI); startDateExpression = XPath.newInstance("//hr:StartDate"); startDateExpression.addNamespace(namespace); endDateExpression = XPath.newInstance("//hr:EndDate"); endDateExpression.addNamespace(namespace); nameExpression = XPath.newInstance("concat(//hr:FirstName,' ',//hr:LastName)"); nameExpression.addNamespace(namespace); } @PayloadRoot(namespace = NAMESPACE_URI, localPart = "LeaveRequest") public void handleLeaveRequest(@RequestPayload Element leaveRequest) throws Exception { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date startDate = dateFormat.parse(startDateExpression.valueOf(leaveRequest)); Date endDate = dateFormat.parse(endDateExpression.valueOf(leaveRequest)); String name = nameExpression.valueOf(leaveRequest); humanResourceService.bookLeave(startDate, endDate, name); } }
/WEB_INF/spring-ws-servlet.xml
<beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:context = "http://www.springframework.org/schema/context" xmlns:sws = "http://www.springframework.org/schema/web-services" xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package = "com.example.hr"/> <bean id = "humanResourceService" class = "com.example.hr.service.HumanResourceServiceImpl" /> <sws:annotation-driven/> <sws:dynamic-wsdl id = "leave" portTypeName = "HumanResource" locationUri = "/leaveService/" targetNamespace = "http://example.com/hr/definitions"> <sws:xsd location = "/WEB-INF/hr.xsd"/> </sws:dynamic-wsdl> </beans>
/WEB_INF/web.xml
<web-app xmlns = "http://java.sun.com/xml/ns/j2ee" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version = "2.4"> <display-name>Example HR Leave Service</display-name> <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> </servlet> <servlet-mapping> <servlet-name>spring-ws</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
/WEB_INF/hr.wsd
<xs:schema xmlns:xs = "http://www.w3.org/2001/XMLSchema" xmlns:hr = "http://example.com/hr/schemas" elementFormDefault = "qualified" targetNamespace = "http://example.com/hr/schemas"> <xs:element name = "LeaveRequest"> <xs:complexType> <xs:all> <xs:element name = "Leave" type = "hr:LeaveType"/> <xs:element name = "Employee" type = "hr:EmployeeType"/> </xs:all> </xs:complexType> </xs:element> <xs:complexType name = "LeaveType"> <xs:sequence> <xs:element name = "StartDate" type = "xs:date"/> <xs:element name = "EndDate" type = "xs:date"/> </xs:sequence> </xs:complexType> <xs:complexType name = "EmployeeType"> <xs:sequence> <xs:element name = "Number" type = "xs:integer"/> <xs:element name = "FirstName" type = "xs:string"/> <xs:element name = "LastName" type = "xs:string"/> </xs:sequence> </xs:complexType> </xs:schema>
Step 4: Open the command console, and go the directory C:\MVN\leaveService and execute the below mvn command:
C:\MVN\leaveService>mvn clean package
Step 5: Open Eclipse IDE. Go to File > Import > Option. Select the option Maven Projects and click on the Next button.
Select the location of the leaveService project. Click on the Finish button.
Step 6: Export the application by right-clicking on the project > Export > WAR File. Save it in the Tomcat’s webapp folder. Start the Tomcat and go to the URL http://localhost:8080/leaveService/leave.wsdl.
If everything works fine then you will see the below output on the screen with the document tree:
One Response