Finished tutorial
This commit is contained in:
@@ -4,9 +4,11 @@
|
||||
|
||||
Introduction
|
||||
|
||||
This is an overall tutorial on how to approach Web services development in contract-first style, i.e. starting with the XML Schema/WSDL contract instead of Java code. Spring Web Services focusses on this development style, and this
|
||||
tutorial helps you get started. Note that this chapter contains almost no Spring-WS specific information: it is mostly
|
||||
about XML, XSD, and WSDL.
|
||||
This is the first part of an overall tutorial on how to approach Web services development in contract-first style,
|
||||
i.e. starting with the XML Schema/WSDL contract instead of Java code. Spring Web Services focusses on this
|
||||
development style, and this tutorial helps you get started. Note that this page contains almost no Spring-WS
|
||||
specific information: it is mostly about XML, XSD, and WSDL. The {{{tutorial2.html}second page}} focusses on
|
||||
implementing this contract using Spring-WS.
|
||||
|
||||
In this tutorial, we will define a Web service that can be used for Human Resources. Clients can send
|
||||
holiday request forms to this service to book a holiday. It is based on a metaphor for Service Oriented Architectures
|
||||
@@ -15,7 +17,8 @@ North}}.
|
||||
|
||||
The most important thing when doing contract-first Web service development is to try and think in terms of
|
||||
XML. This means that Java-language concepts are of lesser importance. It is the XML that is sent across the wire, and
|
||||
you should focus on that.
|
||||
you should focus on that. The fact that Java is used to implement the Web service is an implementation detail. An
|
||||
important detail, but a detail nonetheless.
|
||||
|
||||
The Messages
|
||||
|
||||
@@ -27,7 +30,7 @@ start out by determining what these messages look like.
|
||||
In the scenario, we have to deal with holiday request, so it makes sense to determine what a holiday looks like:
|
||||
|
||||
+-------------------------------------
|
||||
<Holiday xmlns="http://mycompany.com/holidays/schemas">
|
||||
<Holiday xmlns="http://mycompany.com/hr/schemas">
|
||||
<StartDate>2006-07-03</StartDate>
|
||||
<EndDate>2006-07-07</EndDate>
|
||||
</Holiday>
|
||||
@@ -42,7 +45,7 @@ parsing hassle. We also added a namespace to the element, to make sure our eleme
|
||||
There is also the notion of an employee in the scenario. Here's what it looks like:
|
||||
|
||||
+-------------------------------------
|
||||
<Employee xmlns="http://mycompany.com/holidays/schemas">
|
||||
<Employee xmlns="http://mycompany.com/hr/schemas">
|
||||
<Number>42</Number>
|
||||
<FirstName>Arjen</FirstName>
|
||||
<LastName>Poutsma</LastName>
|
||||
@@ -58,7 +61,7 @@ sense to use a different namespace, such as <<<"http://mycompany.com/employees/s
|
||||
Both the holiday and employee element can be put in a <<<HolidayRequest>>>:
|
||||
|
||||
+-------------------------------------
|
||||
<HolidayRequest xmlns="http://mycompany.com/holidays/schemas">
|
||||
<HolidayRequest xmlns="http://mycompany.com/hr/schemas">
|
||||
<Holiday>
|
||||
<StartDate>2006-07-03</StartDate>
|
||||
<EndDate>2006-07-07</EndDate>
|
||||
@@ -73,7 +76,7 @@ sense to use a different namespace, such as <<<"http://mycompany.com/employees/s
|
||||
|
||||
The order of the two element does not matter: <<<Employee>>> could have been the first element just as
|
||||
well. As long as all the data is there; that's what is important. In fact, the data is the only thing that is
|
||||
important: we are taking a <data-driven> approach.
|
||||
important: we are taking a <<data-driven>> approach.
|
||||
|
||||
The Schema
|
||||
|
||||
@@ -102,21 +105,21 @@ point.
|
||||
+-------------------------------------
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified"
|
||||
targetNamespace="http://mycompany.com/holidays/schemas"
|
||||
xmlns:holidays="http://mycompany.com/holidays/schemas">
|
||||
targetNamespace="http://mycompany.com/hr/schemas"
|
||||
xmlns:hr="http://mycompany.com/hr/schemas">
|
||||
<xs:element name="HolidayRequest">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="holidays:Holiday"/>
|
||||
<xs:element ref="holidays:Employee"/>
|
||||
<xs:element ref="hr:Holiday"/>
|
||||
<xs:element ref="hr:Employee"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="Holiday">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="holidays:StartDate"/>
|
||||
<xs:element ref="holidays:EndDate"/>
|
||||
<xs:element ref="hr:StartDate"/>
|
||||
<xs:element ref="hr:EndDate"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
@@ -125,9 +128,9 @@ point.
|
||||
<xs:element name="Employee">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="holidays:Number"/>
|
||||
<xs:element ref="holidays:FirstName"/>
|
||||
<xs:element ref="holidays:LastName"/>
|
||||
<xs:element ref="hr:Number"/>
|
||||
<xs:element ref="hr:FirstName"/>
|
||||
<xs:element ref="hr:LastName"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
@@ -144,14 +147,14 @@ types), and inlining the results, we can accomplish this.
|
||||
|
||||
+-------------------------------------
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:holidays="http://mycompany.com/holidays/schemas"
|
||||
xmlns:hr="http://mycompany.com/hr/schemas"
|
||||
elementFormDefault="qualified"
|
||||
targetNamespace="http://mycompany.com/holidays/schemas">
|
||||
targetNamespace="http://mycompany.com/hr/schemas">
|
||||
<xs:element name="HolidayRequest">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Holiday" <type="holidays:HolidayType">/>
|
||||
<xs:element name="Employee" <type="holidays:EmployeeType">/>
|
||||
<xs:element name="Holiday" type="hr:HolidayType"/>
|
||||
<xs:element name="Employee" type="hr:EmployeeType"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
@@ -175,7 +178,7 @@ types), and inlining the results, we can accomplish this.
|
||||
validate:
|
||||
|
||||
+-------------------------------------
|
||||
<HolidayRequest xmlns="http://mycompany.com/holidays/schemas">
|
||||
<HolidayRequest xmlns="http://mycompany.com/hr/schemas">
|
||||
<Holiday>
|
||||
<StartDate>this is not a date</StartDate>
|
||||
<EndDate>neither is this</EndDate>
|
||||
@@ -191,52 +194,57 @@ validate:
|
||||
|
||||
+-------------------------------------
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:holidays="http://mycompany.com/holidays/schemas"
|
||||
xmlns:hr="http://mycompany.com/hr/schemas"
|
||||
elementFormDefault="qualified"
|
||||
targetNamespace="http://mycompany.com/holidays/schemas">
|
||||
targetNamespace="http://mycompany.com/hr/schemas">
|
||||
<xs:element name="HolidayRequest">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Holiday" type="holidays:HolidayType"/>
|
||||
<xs:element name="Employee" type="holidays:EmployeeType"/>
|
||||
<xs:element name="Holiday" type="hr:HolidayType"/>
|
||||
<xs:element name="Employee" type="hr:EmployeeType"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:complexType name="HolidayType">
|
||||
<xs:sequence>
|
||||
<xs:element name="StartDate" <type="xs:date">/>
|
||||
<xs:element name="EndDate" <type="xs:date">/>
|
||||
<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:element name="FirstName" type="xs:string"/>
|
||||
<xs:element name="LastName" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
+-------------------------------------
|
||||
|
||||
We can store this file with a convenient name such as <<<holidays.xsd>>>.
|
||||
We can store this file with a convenient name such as <<<hr.xsd>>>.
|
||||
|
||||
The WSDL
|
||||
|
||||
Which leaves the WSDL. We start our WSDL with the standard preamble, and by importing our existing XSD. To
|
||||
Which leaves the WSDL. Note that in Spring-WS, <<writing the WSDL by hand is not required>>. Based on the XSD and
|
||||
some conventions, Spring-WS can create the WSDL for you, as explained in the {{{tutorial2.html}next section}} of
|
||||
this tutorial. The rest of this page will show you how to write your own WSDL, if you choose not to use this
|
||||
functionality.
|
||||
|
||||
We start our WSDL with the standard preamble, and by importing our existing XSD. To
|
||||
separate the schema from the definition, we will use a separate namespace for the WSDL definitions:
|
||||
<<<"http://mycompany.com/holidays/definitions">>>.
|
||||
<<<"http://mycompany.com/hr/definitions">>>.
|
||||
|
||||
+-------------------------------------
|
||||
<wsdl:definitions name="HumanResources"
|
||||
targetNamespace="http://mycompany.com/holidays/definitions"
|
||||
xmlns:tns="http://mycompany.com/holidays/definitions"
|
||||
<xmlns:types="http://mycompany.com/holidays/schemas">
|
||||
targetNamespace="http://mycompany.com/hr/definitions"
|
||||
xmlns:tns="http://mycompany.com/hr/definitions"
|
||||
<xmlns:types="http://mycompany.com/hr/schemas">
|
||||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
|
||||
<wsdl:types>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<xsd:import namespace="http://mycompany.com/holidays/schemas"
|
||||
schemaLocation="holidays.xsd"/>
|
||||
<xsd:import namespace="http://mycompany.com/hr/schemas"
|
||||
schemaLocation="hr.xsd"/>
|
||||
</xsd:schema>
|
||||
</wsdl:types>
|
||||
</wsdl:definitions>
|
||||
@@ -247,15 +255,15 @@ separate the schema from the definition, we will use a separate namespace for th
|
||||
|
||||
+-------------------------------------
|
||||
<wsdl:definitions name="HumanResources"
|
||||
targetNamespace="http://mycompany.com/holidays/definitions"
|
||||
xmlns:tns="http://mycompany.com/holidays/definitions"
|
||||
xmlns:types="http://mycompany.com/holidays/schemas"
|
||||
targetNamespace="http://mycompany.com/hr/definitions"
|
||||
xmlns:tns="http://mycompany.com/hr/definitions"
|
||||
xmlns:types="http://mycompany.com/hr/schemas"
|
||||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
|
||||
<wsdl:types>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<xsd:import namespace="http://mycompany.com/holidays/schemas"
|
||||
schemaLocation="holidays.xsd"/>
|
||||
<xsd:import namespace="http://mycompany.com/hr/schemas"
|
||||
schemaLocation="hr.xsd"/>
|
||||
</xsd:schema>
|
||||
</wsdl:types>
|
||||
<wsdl:message name="RequestHolidayInput">>
|
||||
@@ -268,15 +276,15 @@ separate the schema from the definition, we will use a separate namespace for th
|
||||
|
||||
+-------------------------------------
|
||||
<wsdl:definitions name="HumanResources"
|
||||
targetNamespace="http://mycompany.com/holidays/definitions"
|
||||
xmlns:tns="http://mycompany.com/holidays/definitions"
|
||||
xmlns:types="http://mycompany.com/holidays/schemas"
|
||||
targetNamespace="http://mycompany.com/hr/definitions"
|
||||
xmlns:tns="http://mycompany.com/hr/definitions"
|
||||
xmlns:types="http://mycompany.com/hr/schemas"
|
||||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
|
||||
<wsdl:types>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<xsd:import namespace="http://mycompany.com/holidays/schemas"
|
||||
schemaLocation="holidays.xsd"/>
|
||||
<xsd:import namespace="http://mycompany.com/hr/schemas"
|
||||
schemaLocation="hr.xsd"/>
|
||||
</xsd:schema>
|
||||
</wsdl:types>
|
||||
<wsdl:message name="RequestHolidayInput">
|
||||
@@ -301,15 +309,15 @@ you use <document/literal> for the <<<soap:binding>>> elements (anything else is
|
||||
|
||||
+-------------------------------------
|
||||
<wsdl:definitions name="HumanResources"
|
||||
targetNamespace="http://mycompany.com/holidays/definitions"
|
||||
xmlns:tns="http://mycompany.com/holidays/definitions"
|
||||
xmlns:types="http://mycompany.com/holidays/schemas"
|
||||
targetNamespace="http://mycompany.com/hr/definitions"
|
||||
xmlns:tns="http://mycompany.com/hr/definitions"
|
||||
xmlns:types="http://mycompany.com/hr/schemas"
|
||||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
|
||||
<wsdl:types>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<xsd:import namespace="http://mycompany.com/holidays/schemas"
|
||||
schemaLocation="holidays.xsd"/>
|
||||
<xsd:import namespace="http://mycompany.com/hr/schemas"
|
||||
schemaLocation="hr.xsd"/>
|
||||
</xsd:schema>
|
||||
</wsdl:types>
|
||||
<wsdl:message name="RequestHolidayInput">
|
||||
@@ -337,4 +345,4 @@ you use <document/literal> for the <<<soap:binding>>> elements (anything else is
|
||||
</wsdl:definitions>
|
||||
+-------------------------------------
|
||||
|
||||
This is the final WSDL. We will describe how to implement the resulting schema and WSDL in the next chapter.
|
||||
This is the final WSDL. We will describe how to implement the resulting schema and WSDL in the {{{tutorial2.html}next section}}.
|
||||
212
src/site/apt/tutorial/tutorial2.apt
Normal file
212
src/site/apt/tutorial/tutorial2.apt
Normal file
@@ -0,0 +1,212 @@
|
||||
-------------------------------------------------------
|
||||
Implementing Contract-first Web Services with Spring-WS
|
||||
-------------------------------------------------------
|
||||
|
||||
|
||||
Introduction
|
||||
|
||||
This is the second part of a tutorial on how to write contract-first Web services. The first part can be found
|
||||
{{{tutorial1.html}here}}. This second part focusses on implementing the Web service contract using Spring Web Services.
|
||||
|
||||
|
||||
Setup
|
||||
|
||||
In this tutorial, we will be using Maven2 to create the initial project structure for us. Doing so is not required,
|
||||
but greatly reduces the amount of code we have to write to setup our HolidayService.
|
||||
|
||||
The following command creates a Maven2 web application project for us, using the Spring-WS archetype (i.e. project
|
||||
template):
|
||||
|
||||
+-------------------------------------
|
||||
> mvn archetype:create -DarchetypeGroupId=org.springframework.ws \
|
||||
-DarchetypeArtifactId=spring-ws-archetype \
|
||||
-DarchetypeVersion=1.0-m4-SNAPSHOT \
|
||||
-DgroupId=com.mycompany.hr \
|
||||
-DartifactId=holidayService
|
||||
+-------------------------------------
|
||||
|
||||
This command will create a new directory called <<<holidayService>>>. In this project, there is a
|
||||
<<<src/main/webapp>>> directory, which will contain the root of the WAR file. In this directory, you will find
|
||||
the standard web application deployment descriptor <<<WEB-INF/web.xml>>>, which basically defines a Spring-WS
|
||||
<<<MessageDispatcherServlet>>>, and maps all incoming requests to this servlet:
|
||||
|
||||
+-------------------------------------
|
||||
<?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">
|
||||
|
||||
<display-name>MyCompany HR Holiday Service</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>spring-ws</servlet-name>
|
||||
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>spring-ws</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
+-------------------------------------
|
||||
|
||||
|
||||
Next to this file, there is <<<WEB-INF/spring-ws-servlet.xml>>>, which is a Spring application context file that
|
||||
will contain the Spring-WS bean definitions.
|
||||
|
||||
Implementing the Endpoint
|
||||
|
||||
In Spring-WS, you will implement <<Endpoints>> to handle incoming XML messages. There are two flavors of endpoints:
|
||||
{{{http://static.springframework.org/spring-ws/site/apidocs/org/springframework/ws/server/endpoint/MessageEndpoint.html}<<<MessageEndpoints>>>}} and
|
||||
{{{http://static.springframework.org/spring-ws/site/apidocs/org/springframework/ws/server/endpoint/PayloadEndpoint.html}<<<PayloadEndpoints>>>}}.
|
||||
Message endpoint gives access to the entire XML message, including SOAP headers, etc. Typically, however, the
|
||||
endpoint will only be interested in the <<payload>> of the message, i.e. the contents of the SOAP body. In that case,
|
||||
creating a payload endpoint makes more sense.
|
||||
|
||||
* Handling the XML Message
|
||||
|
||||
In this sample application, we are going to use {{{http://www.jdom.org}JDom}} to handle XML message. We are also
|
||||
using {{{http://www.w3schools.com/xpath/}XPath}}, because it allows us to select particular parts of the XML JDOM tree,
|
||||
without requiring strict schema conformance. We extend
|
||||
our endpoint from
|
||||
{{{http://static.springframework.org/spring-ws/site/apidocs/org/springframework/ws/server/endpoint/AbstractJDomPayloadEndpoint.html}<<<AbstractJDomPayloadEndpoint>>>}},
|
||||
because that will give us a JDOM element to execute the XPath queries on:
|
||||
|
||||
+-------------------------------------
|
||||
package com.mycompany.hr.ws;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import com.mycompany.hr.service.HumanResourceService;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jdom.Namespace;
|
||||
import org.jdom.xpath.XPath;
|
||||
import org.springframework.ws.server.endpoint.AbstractJDomPayloadEndpoint;
|
||||
|
||||
public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
|
||||
private XPath startDateExpression;
|
||||
|
||||
private XPath endDateExpression;
|
||||
|
||||
private XPath nameExpression;
|
||||
|
||||
private HumanResourceService humanResourceService;
|
||||
|
||||
public HolidayEndpoint(HumanResourceService humanResourceService) {
|
||||
this.humanResourceService = humanResourceService;
|
||||
}
|
||||
|
||||
public void init() throws JDOMException {
|
||||
Namespace namespace = Namespace.getNamespace("hr", "http://mycompany.com/hr/schemas");
|
||||
startDateExpression = XPath.newInstance("//hr:StartDate");
|
||||
startDateExpression.addNamespace(namespace);
|
||||
endDateExpression = XPath.newInstance("//hr:EndDate");
|
||||
endDateExpression.addNamespace(namespace);
|
||||
nameExpression = XPath.newInstance("//hr:FirstName|//hr:LastName");
|
||||
nameExpression.addNamespace(namespace);
|
||||
}
|
||||
|
||||
protected Element invokeInternal(Element holidayRequest) throws Exception {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
Date startDate = dateFormat.parse(startDateExpression.valueOf(holidayRequest));
|
||||
Date endDate = dateFormat.parse(endDateExpression.valueOf(holidayRequest));
|
||||
String name = nameExpression.valueOf(holidayRequest);
|
||||
|
||||
humanResourceService.bookHoliday(startDate, endDate, name);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+-------------------------------------
|
||||
|
||||
Let's go over the class one method at a time. The HolidayEndpoint requires the HumanResourceService business service
|
||||
to operate, so we use the constructor to inject it. Next, we have the initialization method <<<init>>>, which sets up
|
||||
the XPath expressions using the JDOM API. There are three expressions: <<<//hr:StartDate>>> for extracting the
|
||||
<<<\<StartDate\>>>> text value, <<<//hr:EndDate>>> for extracting the end date, and <<<//hr:FirstName|//hr:LastName>>>
|
||||
for extracting the name of the employee.
|
||||
|
||||
The <<<invokeInternal()>>> method is a template method, which gets passed with the <<<HolidayRequest>>> element
|
||||
from the incoming XML message. Next, we use the XPath expressions to extract the String values from the XML messages,
|
||||
and convert these values to <<<Dates>>> using a <<<SimpleDateFormat>>>. With these values, we invoke a method on the
|
||||
business service. Typically, this will result in result in a database transaction being started, and some records being
|
||||
altered in the database. Finally, we return <<<null>>>, which indicates to Spring-WS that we don't want to send a
|
||||
response message. If we wanted a response message, we could have returned a JDOM Element that represents the payload
|
||||
of the response message.
|
||||
|
||||
Using JDOM is just one of the options to handle the XML, other options include DOM, dom4j, XOM, SAX, and StAX, but
|
||||
also marshalling techniques like JAXB, Castor, XMLBeans, JiBX, and XStream. Refer to the airline sample to see how
|
||||
these are used.
|
||||
|
||||
Here's how we would wire up these classes in our <<<spring-ws-servlet.xml>>> application context:
|
||||
|
||||
+-------------------------------------
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans">
|
||||
|
||||
<bean id="holidayEndpoint" class="com.mycompany.hr.ws.HolidayEndpoint" init-method="init">
|
||||
<constructor-arg ref="hrService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="hrService" class="com.mycompany.hr.service.StubHumanResourceService"/>
|
||||
|
||||
</beans>
|
||||
+-------------------------------------
|
||||
|
||||
* Routing the Message to the Endpoint
|
||||
|
||||
Now that we have written an endpoint that handles the message, we must define how incoming messages are routed to
|
||||
that endpoint. In Spring-WS, this is the responsibility of an <<<EndpointMapping>>>. In this tutorial, we will route
|
||||
messages based on their content, by using a <<<PayloadRootQNameEndpointMapping>>>. Here's how we wire it up in
|
||||
<<<spring-ws-servlet.xml>>>:
|
||||
|
||||
+-------------------------------------
|
||||
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
|
||||
<property name="mappings">
|
||||
<props>
|
||||
<prop key="{http://mycompany.com/hr/schemas}HolidayRequest">holidayEndpoint</prop>
|
||||
</props>
|
||||
</property>
|
||||
<property name="interceptors">
|
||||
<bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>
|
||||
</property>
|
||||
</bean>
|
||||
+-------------------------------------
|
||||
|
||||
This means that whenever a XML message comes in with the namespace <<<http://mycompany.com/hr/schemas>>> and the
|
||||
<<<HolidayRequest>>> local name, it will be routed to the holidayEndpoint. It also adds a <<<PayloadInterceptor>>>,
|
||||
which dumps incoming and outgoing messages to the log.
|
||||
|
||||
Publishing the WSDL
|
||||
|
||||
Finally, we need to publish the WSDL. As stated on the {{{tutorial1.html}previous page}}, we don't need to write a
|
||||
WSDL ourselves; Spring-WS can generate one for us based on some conventions. Here's how we define it:
|
||||
|
||||
+-------------------------------------
|
||||
<bean id="holiday" class="org.springframework.ws.wsdl.wsdl11.DynamicWsdl11Definition">
|
||||
<property name="builder">
|
||||
<bean class="org.springframework.ws.wsdl.wsdl11.builder.XsdBasedSoap11Wsdl4jDefinitionBuilder">
|
||||
<property name="schema" value="/WEB-INF/hr.xsd"/>
|
||||
<property name="portTypeName" value="HumanResource"/>
|
||||
<property name="locationUri" value="http://localhost:8080/holidayService/"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
+-------------------------------------
|
||||
|
||||
The first property we set is the human resource schema we defined on the {{{tutorial1.html}first page}} of this
|
||||
tutorial, <<<hr.xsd>>>: we simply placed the schema in the <<<WEB-INF>>> directory of the application. Next, we define
|
||||
the WSDL port type to be <<<HumanResource>>>. Finally, we set the location where the service can be reached:
|
||||
<<<http://localhost:8080/holidayService>>>.
|
||||
|
||||
If you deploy the application, and point your browser at
|
||||
{{{http://localhost:8080/holidayService/holiday.wsdl}<<<http://localhost:8080/holidayService/holiday.wsdl>>>}}, you will
|
||||
see the generated WSDL. This WSDL is ready to be used by clients, such as {{{http://www.soapui.org/}soapUI}}, or other
|
||||
SOAP frameworks.
|
||||
|
||||
That concludes this tutorial. The next step would be to look at the echo sample application, that is part of the
|
||||
distribution. After that, look at the airline sample, which is a bit more complicated, because it uses JAXB,
|
||||
WS-Security, Hibernate, and a transactional service layer. Finally, refer to the {{{http://static.springframework.org/spring-ws/docs/1.0-m3/reference/html/index.html}reference documentation}}.
|
||||
Reference in New Issue
Block a user