Spring-Web Service 2 Using JAXB and Maven Complete Tutorial
Note : This tutorial only covers simple setup and working code for Spring Web Service using Maven and JAXB.
Prerequisites
JDK 1.6
Eclipse Hellos
M2e plugin for Maven (get it from Eclipse marketplace)
Tomcat 7.0
JAXB plugin for Eclipse (get it from
http://java.net/downloads/jaxb-workshop/IDE%20plugins/org.jvnet.jaxbw.zip)
or
JAXB Maven plugin (ref :
http://www.altuure.com/2008/01/22/jaxb-quickstart-via-maven2/ and
http://mojo.codehaus.org/jaxb2-maven-plugin/index.html)
Aim of the experiment
Write a service for HR which will update leave request.
Input
Employee : employee number, first name, last name
Leave : start date, end date
Output
Status : status code, description
Step - 1
Create a maven project in Eclipse.
Here is my
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.mycompany.hr</groupId>
<artifactId>holidayWSService</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>holidayService Spring-WS Application</name>
<url>http://www.springframework.org/spring-ws</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<finalName>holidayService</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<packageName>com.mycompany.hr.jaxb.model</packageName> <!-- The name of your generated source package -->
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<schemaDirectory>${basedir}/src/main/resources/xsd</schemaDirectory>
<clearOutputDir>false</clearOutputDir>
<schemaFiles>hr.xsd</schemaFiles>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-test</artifactId>
<version>2.0.4.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.0.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
My Project structure :
Step 2
Write an
XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:hr="http://mycompany.com/hr/schemas"
elementFormDefault="qualified"
targetNamespace="http://mycompany.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:element name="LeaveResponse">
<xs:complexType>
<xs:all>
<xs:element name="Status" type="hr:StatusType"/>
</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:complexType name="StatusType">
<xs:sequence>
<xs:element name="StatusCode" type="xs:integer"/>
<xs:element name="StatusDesc" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Step 3
Generate domain classes using JAXB
using JAXB Eclipse plugin
or
using Maven plugin
(right click on project ) -> Run As --> Run configuration [Goal s: jaxb2:xjc]
You can run "mvn jaxb2:xjc" through command line as well.
Warning : Please be careful while generating the JAXB files, it may delete your existing required files in the base folder. If it happens, then you may recover those files from Eclipse history, this may not recover fully.
Strp 4
update your configuration files
Here is my
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<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>
Note : 1. "MessageDispatcherServlet" is configured
2. "transformWsdlLocations" marked as true. Please ref to Spring-WS documentaion.
spring-ws-servlet.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:context="http://www.springframework.org/schema/context"
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/oxm
http://www.springframework.org/schema/oxm/spring-oxm-1.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd"
xmlns:oxm="http://www.springframework.org/schema/oxm">
<context:annotation-config />
<context:component-scan base-package="com.mycompany.hr"/>
<sws:annotation-driven/>
<oxm:jaxb2-marshaller id="marshaller"
contextPath="com.mycompany.hr.jaxb.model" />
<!-- <sws:static-wsdl id="hr" location="wsdl/hr.wsdl"/> -->
<!-- If dynamic wsdl need to expose -->
<sws:dynamic-wsdl id="holiday" serviceName="leave"
portTypeName="HumanResource" locationUri="http://localhost:8082/holidayService/"
targetNamespace="http://mycompany.com/hr/definitions">
<sws:xsd location="classpath:/xsd/hr.xsd" />
</sws:dynamic-wsdl>
<bean id="exceptionResolver"
class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
<property name="defaultFault" value="SERVER" />
<property name="exceptionMappings">
<value>
org.springframework.oxm.ValidationFailureException=CLIENT,Invalid request
</value>
</property>
</bean>
</beans>
Note : 1. "<context:annotation-config/>" will look for all the annotated classes.
2. "oxm:jaxb2-marshaller" looks for JAXB generated classes.
3. "sws:dynamic-wsdl" will create the wsdl file dynamically, but it's not recommended , once you get the wsdl from browser , change to static ""sws:static-wsdl" (ref: Spring-WS documentation).
4. id="holiday" in "sws:dynamic-wsdl" , the wsdl will be exposed under "holiday.wsdl" (ref : Step 7)
Step 5
Writing the Endpoint and Service classes
Here is my Endpoint implementation class (
HolidayEndPointImpl.java)
package com.mycompany.hr.ws;
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 org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import com.mycompany.hr.jaxb.model.LeaveRequest;
import com.mycompany.hr.jaxb.model.LeaveResponse;
import com.mycompany.hr.service.HolidayService;
@Endpoint
public class HolidayEndpointImpl implements HolidayEndpoint{
private HolidayService holidayService;
@Autowired
public void setHolidayService(HolidayService holidayService) {
this.holidayService = holidayService;
}
@PayloadRoot(localPart = "LeaveRequest",namespace = "http://mycompany.com/hr/schemas")
@ResponsePayload
public LeaveResponse applyLeave(@RequestPayload LeaveRequest LeaveRequest){
return holidayService.applyHoliday(LeaveRequest);
}
}
Note: LeaveRequest and LeaveResponse classes are JAXB generated classes.
Here is my service implementation class (
HolidayServiceImpl.java)
package com.mycompany.hr.service;
import java.math.BigInteger;
import org.springframework.stereotype.Service;
import com.mycompany.hr.jaxb.model.LeaveRequest;
import com.mycompany.hr.jaxb.model.LeaveResponse;
import com.mycompany.hr.jaxb.model.StatusType;
@Service
public class HolidayServiceImpl implements HolidayService{
@Override
public LeaveResponse applyHoliday(LeaveRequest leaveRequest) {
LeaveResponse leaveResponse = new LeaveResponse();
StatusType statusType = new StatusType();
if(leaveRequest.getLeave() == null){
statusType.setStatusCode(new BigInteger("1000"));
statusType.setStatusDesc("Leave Request Object missing");
leaveResponse.setStatus(statusType);
return leaveResponse;
}
if(leaveRequest.getLeave().getStartDate().compare(leaveRequest.getLeave().getEndDate()) > 0){
statusType.setStatusCode(new BigInteger("2000"));
statusType.setStatusDesc("Start Date should be before End Date");
leaveResponse.setStatus(statusType);
}else{
statusType.setStatusCode(new BigInteger("111"));
statusType.setStatusDesc("SUCCESS");
leaveResponse.setStatus(statusType);
}
return leaveResponse;
}
}
Step 6
Build and deploy in Tomcat
Step 7
Go to
http://localhost:8082/holidayService/holiday.wsdl (I have configured my tomcat for 8082 port)
Now you can see the wsdl file, you can use it for static loading. (ref: Step 4).
Step 8
Test the web-service.
For testing the web-service using Eclipse plugin please ref :
http://www.eclipse.org/webtools/jst/components/ws/1.0/tutorials/WebServiceExplorer/WebServiceExplorer.html