Spring Web Services Tutorial on Spring WS First Application

let us start writing an actual soap based web service with spring-ws framework. before we start writing our first example using the spring-ws framework, we have to ensure that the spring-ws environment is setup properly as explained in spring web services - environment setup chapter. we are assuming that the readers have some basic working knowledge with the eclipse ide.

therefore, let us proceed to write a simple spring ws application which will expose a web service method to book a leave in an hr portal.

contract-first approach

spring-ws uses the contract-first approach, which means we should have our xml structures ready before writing any java based implementation code. we are defining a leaverequest object, which has sub-objects – leave and employee.

following are the required xml constructs −

leave.xml

<leave xmlns = "http://tutorialspoint.com/hr/schemas">
   <startdate>2016-07-03</startdate>
   <enddate>2016-07-07</enddate>
</leave>

employee.xml

<employee xmlns = "http://tutorialspoint.com/hr/schemas">
   <number>404</number>
   <firstname>mahesh</firstname>
   <lastname>parashar</lastname>
</employee>

leaverequest.xml

<leaverequest xmlns = "http://tutorialspoint.com/hr/schemas">
   <leave>
      <startdate>2016-07-03</startdate>
      <enddate>2016-07-07</enddate>
   </leave>
   
   <employee>
      <number>404</number>
      <firstname>mahesh</firstname>
      <lastname>parashar</lastname>
   </employee>
</leaverequest>

hr.xsd

<xs:schema xmlns:xs = "http://www.w3.org/2001/xmlschema"
   xmlns:hr = "http://tutorialspoint.com/hr/schemas"
   elementformdefault = "qualified"
   targetnamespace = "http://tutorialspoint.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>

create the project

let us now open a command console, go the c:\mvn directory and execute the following mvn command.

c:\mvn>mvn archetype:generate -darchetypegroupid = org.springframework.ws
-darchetypeartifactid = spring-ws-archetype -dgroupid = com.tutorialspoint.hr
-dartifactid = leaveservice

maven will start processing and will create the complete java application project structure.

[info] scanning for projects...
[info]
[info] ------------------------------------------------------------------------
[info] building maven stub project (no pom) 1
[info] ------------------------------------------------------------------------
[info]
[info] using property: groupid = com.tutorialspoint.hr
[info] using property: artifactid = leaveservice
define value for property 'version':  1.0-snapshot: :
[info] using property: package = com.tutorialspoint.hr
confirm properties configuration:
groupid: com.tutorialspoint.hr
artifactid: leaveservice
version: 1.0-snapshot
package: com.tutorialspoint.hr
 y: :
[info] -------------------------------------------------------------------------
---
[info] using following parameters for creating project from old (1.x) archetype:
 spring-ws-archetype:2.0.0-m1
[info] -------------------------------------------------------------------------
---
[info] parameter: groupid, value: com.tutorialspoint.hr
[info] parameter: packagename, value: com.tutorialspoint.hr
[info] parameter: package, value: com.tutorialspoint.hr
[info] parameter: artifactid, value: leaveservice
[info] parameter: basedir, value: c:\mvn
[info] parameter: version, value: 1.0-snapshot
[info] project created from old (1.x) archetype in dir: c:\mvn\leaveservice
[info] ------------------------------------------------------------------------
[info] build success
[info] ------------------------------------------------------------------------
[info] total time: 35.989 s
[info] finished at: 2017-01-21t11:18:31+05:30
[info] final memory: 17m/178m
[info] ------------------------------------------------------------------------

now go to c:/mvn directory. we will see a java application project created named leaveservice (as specified in artifactid). update the pom.xml and add humanresourceservice.java and humanresourceserviceimpl.java in the following folder – c:\mvn\leaveservice\src\main\java\com\tutorialspoint\hr\service folder. once that is done, then add leaveendpoint.java in the following folder – c:\mvn\leaveservice\src\main\java\com\tutorialspoint\hr\ws 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.tutorialspoint.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.tutorialspoint.hr.service;

import java.util.date;

public interface humanresourceservice {
   void bookleave(date startdate, date enddate, string name);
}

humanresourceserviceimpl.java

package com.tutorialspoint.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.tutorialspoint.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.tutorialspoint.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://tutorialspoint.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.tutorialspoint.hr"/>
   <bean id = "humanresourceservice"
      class = "com.tutorialspoint.hr.service.humanresourceserviceimpl" />
   <sws:annotation-driven/>

   <sws:dynamic-wsdl id = "leave"
      porttypename = "humanresource"
      locationuri = "/leaveservice/"
      targetnamespace = "http://tutorialspoint.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>tutorialspoint 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.xsd

<xs:schema xmlns:xs = "http://www.w3.org/2001/xmlschema"
   xmlns:hr = "http://tutorialspoint.com/hr/schemas"
   elementformdefault = "qualified"
   targetnamespace = "http://tutorialspoint.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>

build the project

let us now open the command console, go the c:\mvn\leaveservice directory and execute the following mvn command.

c:\mvn\leaveservice>mvn clean package

maven will start building the project.

[info] scanning for projects...
[info]
[info] ------------------------------------------------------------------------
[info] building leaveservice spring-ws application 1.0-snapshot
[info] ------------------------------------------------------------------------
[info]
[info] --- maven-clean-plugin:2.5:clean (default-clean) @ leaveservice ---
[info] deleting c:\mvn\leaveservice\target
[info]
[info] --- maven-resources-plugin:2.6:resources (default-resources) @ leaveservi
ce ---
[warning] using platform encoding (cp1252 actually) to copy filtered resources,
i.e. build is platform dependent!
[info] copying 0 resource
[info]
[info] --- maven-compiler-plugin:3.1:compile (default-compile) @ leaveservice --
-
[info] changes detected - recompiling the module!
[warning] file encoding has not been set, using platform encoding cp1252, i.e. b
uild is platform dependent!
[info] compiling 3 source files to c:\mvn\leaveservice\target\classes
[info]
[info] --- maven-resources-plugin:2.6:testresources (default-testresources) @ le
aveservice ---
[warning] using platform encoding (cp1252 actually) to copy filtered resources,
i.e. build is platform dependent!
[info] skip non existing resourcedirectory c:\mvn\leaveservice\src\test\resource
s
[info]
[info] --- maven-compiler-plugin:3.1:testcompile (default-testcompile) @ leavese
rvice ---
[info] no sources to compile
[info]
[info] --- maven-surefire-plugin:2.12.4:test (default-test) @ leaveservice ---
[info] no tests to run.
[info]
[info] --- maven-war-plugin:2.2:war (default-war) @ leaveservice ---
[info] packaging webapp
[info] assembling webapp [leaveservice] in [c:\mvn\leaveservice\target\leaveserv
ice]
[info] processing war project
[info] copying webapp resources [c:\mvn\leaveservice\src\main\webapp]
[info] webapp assembled in [7159 msecs]
[info] building war: c:\mvn\leaveservice\target\leaveservice.war
[info] web-inf\web.xml already added, skipping
[info] ------------------------------------------------------------------------
[info] build success
[info] ------------------------------------------------------------------------
[info] total time: 19.667 s
[info] finished at: 2017-01-21t11:56:43+05:30
[info] final memory: 18m/173m
[info] ------------------------------------------------------------------------

import project in eclipse

follow the steps given below to import the project in eclipse.

  • open eclipse.

  • select file → import → option.

  • select maven projects option. click on next button.

  • select project location, where leaveservice project was created using maven.

  • click finish button.

run the project

once we are done with creating source and configuration files, export the application. right click on the application, use export → war file option and save the leaveservice.war file in tomcat's webapps folder.

start the tomcat server and ensure we are able to access other webpages from the webapps folder using a standard browser. try to access the url – http://localhost:8080/leaveservice/leave.wsdl, if everything is ok with the spring web application, we should see the following screen.

first application result