First pass through the tutorial, linking things up, correcting typos, etc.
Will add some actual content later ;)
This commit is contained in:
@@ -6,34 +6,39 @@
|
||||
<section>
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
This tutorial shows you how to write contract-first Web services, i.e. starting with the XML Schema/WSDL
|
||||
contract instead of Java code. Spring Web Services focuses on this development style, and this tutorial
|
||||
helps you get started. Note that the first part of this tutorial contains almost no Spring-WS specific
|
||||
information: it is mostly about XML, XSD, and WSDL. The second part focusses on implementing this contract
|
||||
using Spring-WS.
|
||||
This tutorial shows you how to write
|
||||
<link linkend="why-contract-first">contract-first Web services</link>, that is,
|
||||
developing web services that start with the XML Schema/WSDL contract first
|
||||
followed by the Java code second. Spring-WS focuses on this development style,
|
||||
and this tutorial will help you get started. Note that the first part of this
|
||||
tutorial contains almost no Spring-WS specific information: it is mostly about
|
||||
XML, XSD, and WSDL. The <link linkend="tutorial-creating-project">second part</link>
|
||||
focusses on implementing this contract using Spring-WS .
|
||||
</para>
|
||||
<para>
|
||||
In this tutorial, we will define a Web service that is created by a Human Resources department. Clients can
|
||||
send holiday request forms to this service to book a holiday.
|
||||
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. The fact that Java is used to implement the Web service
|
||||
is an implementation detail. An important detail, but a detail nonetheless.
|
||||
</para>
|
||||
<para>
|
||||
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. The fact that Java is used to implement the Web service is an
|
||||
implementation detail. An important detail, but a detail nonetheless.
|
||||
In this tutorial, we will define a Web service that is created by a Human Resources
|
||||
department. Clients can send holiday request forms to this service to book a holiday.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Messages</title>
|
||||
<para>
|
||||
In this section, we will focus on the actual XML messages that are sent to and from the service. We will
|
||||
start out by determining what these messages look like.
|
||||
In this section, we will focus on the actual XML messages that are sent to
|
||||
and from the Web service. We will start out by determining what these messages
|
||||
look like.
|
||||
</para>
|
||||
<section>
|
||||
<title>Holiday</title>
|
||||
<para>
|
||||
In the scenario, we have to deal with holiday requests, so it makes sense to determine what a holiday
|
||||
looks like:
|
||||
In the scenario, we have to deal with holiday requests, so it makes sense
|
||||
to determine what a holiday looks like in XML:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<Holiday xmlns="http://mycompany.com/hr/schemas">
|
||||
@@ -41,16 +46,19 @@
|
||||
<EndDate>2006-07-07</EndDate>
|
||||
</Holiday>]]></programlisting>
|
||||
<para>
|
||||
A holiday consists of a start date and an end date. We decided to use the standard
|
||||
<ulink url="http://www.cl.cam.ac.uk/~mgk25/iso-time.html">ISO 8601</ulink> date format for the dates,
|
||||
because that will save a lot of parsing hassle. We also added a namespace to the element, to make sure
|
||||
our elements can used within other XML documents.
|
||||
A holiday consists of a start date and an end date. We have also decided to
|
||||
use the standard
|
||||
<ulink url="http://www.cl.cam.ac.uk/~mgk25/iso-time.html">ISO 8601</ulink>
|
||||
date format for the dates, because that will save a lot of parsing hassle.
|
||||
We have also added a namespace to the element, to make sure our elements
|
||||
can used within other XML documents.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Employee</title>
|
||||
<para>
|
||||
There is also the notion of an employee in the scenario. Here's what it looks like:
|
||||
There is also the notion of an employee in the scenario. Here is what it
|
||||
looks like in XML:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<Employee xmlns="http://mycompany.com/hr/schemas">
|
||||
@@ -59,15 +67,17 @@
|
||||
<LastName>Poutsma</LastName>
|
||||
</Employee>]]></programlisting>
|
||||
<para>
|
||||
We have used the same namespace as before. If this employee element could be used in other scenarios, it
|
||||
might make sense to use a different namespace, such as
|
||||
We have used the same namespace as before. If this
|
||||
<literal><Employee/></literal> element could be used in other
|
||||
scenarios, it might make sense to use a different namespace, such as
|
||||
<literal>http://mycompany.com/employees/schemas</literal>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>HolidayRequest</title>
|
||||
<para>
|
||||
Both the holiday and employee element can be put in a <literal>HolidayRequest</literal>:
|
||||
Both the holiday and employee element can be put in a
|
||||
<literal><HolidayRequest/></literal>:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<HolidayRequest xmlns="http://mycompany.com/hr/schemas">
|
||||
@@ -82,18 +92,21 @@
|
||||
</Employee>
|
||||
</HolidayRequest>]]></programlisting>
|
||||
<para>
|
||||
The order of the two elements does not matter: <literal>Employee</literal> 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 <emphasis>data-driven</emphasis> approach.
|
||||
The order of the two elements does not matter: <literal><Employee/></literal>
|
||||
could have been the first element just as well. What is important is
|
||||
that all of the data is there. In fact, the data is the only thing
|
||||
that is important: we are taking a <emphasis>data-driven</emphasis>
|
||||
approach.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section id="tutorial.xsd">
|
||||
<title>Data Contract</title>
|
||||
<para>
|
||||
Now that we have seen some examples of the XML data that we will use, it makes sense to formalize this into
|
||||
a schema. This data contract defines the message format we accept.
|
||||
There are four different ways of defining such a contract for XML:
|
||||
Now that we have seen some examples of the XML data that we will use,
|
||||
it makes sense to formalize this into a schema. This data contract
|
||||
defines the message format we accept. There are four different ways
|
||||
of defining such a contract for XML:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>DTDs</para></listitem>
|
||||
@@ -102,63 +115,67 @@
|
||||
<listitem><para><ulink url="http://www.schematron.com/">Schematron</ulink></para></listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
DTDs have limited namespaces support, so they are not suitable for Web services. Relax NG and Schematron are
|
||||
certainly easier than XSDs. Unfortunately, they are not so widely supported across platforms. We will use
|
||||
XML Schema.
|
||||
DTDs have limited namespace support, so they are not suitable for Web
|
||||
services. Relax NG and Schematron certainly are easier than XML Schema.
|
||||
Unfortunately, they are not so widely supported across platforms. We
|
||||
will use XML Schema.
|
||||
</para>
|
||||
<para>
|
||||
By far the easiest way to create a XSD is to infer it from sample documents. Any good XML editor or Java IDE
|
||||
offers this functionality. Basically, these tools use some sample XML documents, and generate a schema from
|
||||
it that validates them all. The end result certainly needs to be polished up, but it's a great starting
|
||||
point.
|
||||
By far the easiest way to create an XSD is to infer it from sample
|
||||
documents. Any good XML editor or Java IDE offers this functionality.
|
||||
Basically, these tools use some sample XML documents, and generate a
|
||||
schema from it that validates them all. The end result certainly needs
|
||||
to be polished up, but it's a great starting point.
|
||||
</para>
|
||||
<para>
|
||||
Using the sample described above, we end up with the following generated schema:
|
||||
Using the sample described above, we end up with the following
|
||||
generated schema:
|
||||
</para>
|
||||
<programlisting>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified"
|
||||
targetNamespace="http://mycompany.com/hr/schemas"
|
||||
xmlns:hr="http://mycompany.com/hr/schemas">
|
||||
<emphasis><xs:element name="HolidayRequest"></emphasis>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="hr:Holiday"/>
|
||||
<xs:element ref="hr:Employee"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<emphasis><xs:element name="Holiday"></emphasis>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="hr:StartDate"/>
|
||||
<xs:element ref="hr:EndDate"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<emphasis><xs:element name="StartDate" type="xs:NMTOKEN"/>
|
||||
<xs:element name="EndDate" type="xs:NMTOKEN"/>
|
||||
<xs:element name="Employee"></emphasis>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="hr:Number"/>
|
||||
<xs:element ref="hr:FirstName"/>
|
||||
<xs:element ref="hr:LastName"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<emphasis><xs:element name="Number" type="xs:integer"/>
|
||||
<xs:element name="FirstName" type="xs:NCName"/>
|
||||
<xs:element name="LastName" type="xs:NCName"/></emphasis>
|
||||
</xs:schema></programlisting>
|
||||
<programlisting><![CDATA[<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified"
|
||||
targetNamespace="http://mycompany.com/hr/schemas"
|
||||
xmlns:hr="http://mycompany.com/hr/schemas">
|
||||
<emphasis><xs:element name="HolidayRequest"></emphasis>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="hr:Holiday"/>
|
||||
<xs:element ref="hr:Employee"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<emphasis><xs:element name="Holiday"></emphasis>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="hr:StartDate"/>
|
||||
<xs:element ref="hr:EndDate"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<emphasis><xs:element name="StartDate" type="xs:NMTOKEN"/>
|
||||
<xs:element name="EndDate" type="xs:NMTOKEN"/>
|
||||
<xs:element name="Employee"></emphasis>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="hr:Number"/>
|
||||
<xs:element ref="hr:FirstName"/>
|
||||
<xs:element ref="hr:LastName"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<emphasis><xs:element name="Number" type="xs:integer"/>
|
||||
<xs:element name="FirstName" type="xs:NCName"/>
|
||||
<xs:element name="LastName" type="xs:NCName"/></emphasis>
|
||||
</xs:schema>]]></programlisting>
|
||||
<para>
|
||||
This generated schema obviously can be improved. The first thing to notice is that every type has a root-level
|
||||
element declaration. This means that the Web service should be able to accept all of these elements as data. This is not
|
||||
desirable: we only want to accept a <literal>HolidayRequest</literal>. By removing the wrapping element tags
|
||||
(thus keeping the types), and inlining the results, we can accomplish this.
|
||||
This generated schema obviously can be improved. The first thing
|
||||
to notice is that every type has a root-level element declaration.
|
||||
This means that the Web service should be able to accept all of
|
||||
these elements as data. This is not desirable: we only want to
|
||||
accept a <literal><HolidayRequest/></literal>. By removing
|
||||
the wrapping element tags (thus keeping the types), and inlining
|
||||
the results, we can accomplish this.
|
||||
</para>
|
||||
<programlisting>
|
||||
<![CDATA[<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
<programlisting><![CDATA[<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">
|
||||
@@ -185,8 +202,8 @@
|
||||
</xs:complexType>
|
||||
</xs:schema>]]></programlisting>
|
||||
<para>
|
||||
The schema still has one problem: with a schema like this, you can expect the following messages to
|
||||
validate:
|
||||
The schema still has one problem: with a schema like this, you
|
||||
can expect the following messages to validate:
|
||||
</para>
|
||||
<programlisting>
|
||||
<![CDATA[<HolidayRequest xmlns="http://mycompany.com/hr/schemas">
|
||||
@@ -194,14 +211,18 @@
|
||||
<StartDate>this is not a date</StartDate>
|
||||
<EndDate>neither is this</EndDate>
|
||||
</Holiday>
|
||||
...
|
||||
]]><lineannotation><!-- ... --></lineannotation><![CDATA[
|
||||
</HolidayRequest>]]></programlisting>
|
||||
<para>
|
||||
Clearly, we must make sure that the start and end date are really dates. XML Schema has an excellent built-in
|
||||
<literal>date</literal> type which we can use. We also change the <literal>NCName</literal>s to
|
||||
Clearly, we must make sure that the start and end date are really dates.
|
||||
XML Schema has an excellent built-in <literal>date</literal> type which
|
||||
we can use. We also change the <literal>NCName</literal>s to
|
||||
<literal>string</literal>s. Finally, we change the <literal>sequence</literal> in
|
||||
<literal>HolidayRequest</literal> to <literal>all</literal>. This tells the XML parser that the order of
|
||||
<literal>Holiday</literal> and <literal>Employee</literal> is not significant. Our final XSD looks like this:
|
||||
<literal><HolidayRequest/></literal> to <literal>all</literal>.
|
||||
This tells the XML parser that the order of
|
||||
<literal><Holiday/></literal> and
|
||||
<literal><Employee/></literal> is not significant. Our final
|
||||
XSD now looks like this:
|
||||
</para>
|
||||
<programlistingco>
|
||||
<areaspec>
|
||||
@@ -215,8 +236,7 @@
|
||||
<area id="tutorial.xsd.strings.2" coords="24"/>
|
||||
</areaset>
|
||||
</areaspec>
|
||||
<programlisting>
|
||||
<![CDATA[<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
<programlisting><![CDATA[<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">
|
||||
@@ -245,19 +265,20 @@
|
||||
<calloutlist>
|
||||
<callout arearefs="tutorial.xsd.all">
|
||||
<para>
|
||||
<literal>all</literal> tells the XML parser that the order of <literal>Holiday</literal> and
|
||||
<literal>Employee</literal> is not significant.
|
||||
<literal>all</literal> tells the XML parser that the order of
|
||||
<literal><Holiday/></literal> and
|
||||
<literal><Employee/></literal> is not significant.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="tutorial.xsd.dates">
|
||||
<para>
|
||||
We use the <literal>xsd:date</literal> data type, which consist of a year, month, and day, for
|
||||
<literal>StartDate</literal> and <literal>EndDate</literal>.
|
||||
<literal><StartDate/></literal> and <literal><EndDate/></literal>.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="tutorial.xsd.strings">
|
||||
<para>
|
||||
<literal>xsd:string</literal> is used for first and last name.
|
||||
<literal>xsd:string</literal> is used for the first and last name.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
@@ -271,7 +292,7 @@
|
||||
<para>
|
||||
A service contract is generally expressed as a <ulink url="http://www.w3.org/TR/wsdl">WSDL</ulink> file.
|
||||
Note that in Spring-WS, <emphasis>writing the WSDL by hand is not required</emphasis>. Based on the XSD and
|
||||
some conventions, Spring-WS can create the WSDL for you, as explained in
|
||||
some conventions, Spring-WS can create the WSDL for you, as explained in the section entitled
|
||||
<xref linkend="tutorial.implementing.endpoint"/>.
|
||||
You can skip to <link linkend="tutorial-creating-project">the next section</link> if you want to; the
|
||||
remainder of this section will show you how to write your own WSDL by hand.
|
||||
@@ -281,8 +302,7 @@
|
||||
separate the schema from the definition, we will use a separate namespace for the WSDL definitions:
|
||||
<uri>http://mycompany.com/hr/definitions</uri>.
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
||||
<programlisting><![CDATA[<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
||||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
xmlns:schema="http://mycompany.com/hr/schemas"
|
||||
xmlns:tns="http://mycompany.com/hr/definitions"
|
||||
@@ -294,14 +314,14 @@
|
||||
</wsdl:types>]]></programlisting>
|
||||
<para>
|
||||
Next, we add our messages based on the written schema types. We only have one message: one with the
|
||||
<literal>HolidayRequest</literal> we put in the schema:
|
||||
<literal><HolidayRequest/></literal> we put in the schema:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<wsdl:message name="HolidayRequest">
|
||||
<wsdl:part element="schema:HolidayRequest" name="HolidayRequest"/>
|
||||
</wsdl:message>]]></programlisting>
|
||||
<para>
|
||||
We add the message to a port type as operation:
|
||||
We add the message to a port type as an operation:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<wsdl:portType name="HumanResource">
|
||||
@@ -486,12 +506,12 @@
|
||||
|
||||
</web-app>]]></programlisting>
|
||||
<para>
|
||||
We could have made the servlet more restrictive by using the url pattern <literal>/humanresources</literal>,
|
||||
but this will suffice for now.
|
||||
(We could have made the servlet more restrictive by using the url pattern <literal>/humanresources</literal>,
|
||||
but this will suffice for now.)
|
||||
</para>
|
||||
<para>
|
||||
Additionally, there is <filename>WEB-INF/spring-ws-servlet.xml</filename>, which is a Spring application
|
||||
context that will contain the Spring-WS bean definitions.
|
||||
Additionally, there is <filename>WEB-INF/spring-ws-servlet.xml</filename>, which is the Spring application
|
||||
context configuration file that will contain the Spring-WS bean definitions.
|
||||
</para>
|
||||
</section>
|
||||
<section id="tutorial.implementing.endpoint">
|
||||
@@ -500,9 +520,9 @@
|
||||
In Spring-WS, you will implement <emphasis>Endpoints</emphasis> to handle incoming XML messages. There
|
||||
are two flavors of endpoints: <link linkend="message-endpoint">message endpoints</link> and
|
||||
<link linkend="payload-endpoint">payload endpoints.</link>.
|
||||
Message endpoint gives access to the entire XML message, including SOAP headers, etc. Typically, the
|
||||
endpoint will only be interested in the <emphasis>payload</emphasis> of the message, i.e. the contents
|
||||
of the SOAP body. In that case, creating a payload endpoint makes more sense.
|
||||
<emphasis>Message endpoints</emphasis> give access to the entire XML message, including SOAP headers. Typically, the
|
||||
endpoint will only be interested in the <emphasis>payload</emphasis> of the message, that is the contents
|
||||
of the SOAP body. In that case, creating a <emphasis>payload endpoint</emphasis> makes more sense.
|
||||
</para>
|
||||
<section>
|
||||
<title>Handling the XML Message</title>
|
||||
@@ -539,7 +559,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
|
||||
private XPath nameExpression;
|
||||
|
||||
private HumanResourceService humanResourceService;
|
||||
private final HumanResourceService humanResourceService;
|
||||
|
||||
public HolidayEndpoint(HumanResourceService humanResourceService) {
|
||||
this.humanResourceService = humanResourceService;
|
||||
@@ -567,7 +587,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
<para>
|
||||
The <classname>HolidayEndpoint</classname> requires the
|
||||
<interfacename>HumanResourceService</interfacename> business service to operate, so we
|
||||
use the constructor to inject it. Next, we set up XPath expressions
|
||||
inject the dependency via the constructor. Next, we set up XPath expressions
|
||||
using the JDOM API. There are three expressions: <literal>//hr:StartDate</literal> for
|
||||
extracting the <literal><StartDate></literal> text value,
|
||||
<literal>//hr:EndDate</literal> for
|
||||
@@ -577,14 +597,14 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
</callout>
|
||||
<callout arearefs="tutorial.endpoint.invokeInternal">
|
||||
<para>
|
||||
The <methodname>invokeInternal</methodname> method is a template method, which gets passed
|
||||
with the <literal>HolidayRequest</literal> element from the incoming XML message. We
|
||||
The <methodname>invokeInternal(..)</methodname> method is a template method, which gets passed
|
||||
with the <literal><HolidayRequest/></literal> element from the incoming XML message. We
|
||||
use the XPath expressions to extract the string values from the XML messages,
|
||||
and convert these values to <classname>Date</classname> objects using a
|
||||
<classname>SimpleDateFormat</classname>. With these values, we invoke a method on the
|
||||
business service. Typically, this will result in result in a database transaction being
|
||||
business service. Typically, this will result in a database transaction being
|
||||
started, and some records being altered in the database. Finally, we return
|
||||
<literal>null</literal>, which indicates to Spring-WS that we don't want to send a
|
||||
<literal>null</literal>, which indicates to Spring-WS that we do not 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.
|
||||
</para>
|
||||
@@ -592,7 +612,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
</calloutlist>
|
||||
</programlistingco>
|
||||
<para>
|
||||
Using JDOM is just one of the options to handle the XML, other options include DOM, dom4j, XOM,
|
||||
Using JDOM is just one of the options to handle the XML: other options include DOM, dom4j, XOM,
|
||||
SAX, and StAX, but also <link linkend="oxm">marshalling techniques</link> like JAXB, Castor, XMLBeans,
|
||||
JiBX, and XStream. We chose JDOM because it gives us access to the raw XML, and because it
|
||||
is based on classes (not interfaces and factory methods as with W3C DOM and dom4j), which makes the
|
||||
@@ -600,11 +620,10 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
care for strict schema conformance, as long as we can find the dates and the name.
|
||||
</para>
|
||||
<para>
|
||||
Because we use JDOM, we must add some dependencies to the <filename>pom.xml</filename>, which is in the
|
||||
Because we use JDOM, we must add some dependencies to the Maven <filename>pom.xml</filename>, which is in the
|
||||
root of our project directory. Here is the relevant section of the POM:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<dependencies>
|
||||
<programlisting><![CDATA[<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ws</groupId>
|
||||
<artifactId>spring-ws-core</artifactId>
|
||||
@@ -632,14 +651,12 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
<version>1.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependencies>
|
||||
]]></programlisting>
|
||||
<dependencies>]]></programlisting>
|
||||
<para>
|
||||
Here is how we would wire up these classes in our <filename>spring-ws-servlet.xml</filename>
|
||||
application context:
|
||||
Here is how we would configure these classes in our <filename>spring-ws-servlet.xml</filename>
|
||||
application context configuration file:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<beans xmlns="http://www.springframework.org/schema/beans">
|
||||
<programlisting><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans">
|
||||
|
||||
<bean id="holidayEndpoint" class="com.mycompany.hr.ws.HolidayEndpoint">
|
||||
<constructor-arg ref="hrService"/>
|
||||
@@ -655,8 +672,8 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
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
|
||||
<interfacename>EndpointMapping</interfacename>. In this tutorial, we will route messages based on
|
||||
their content, by using a <classname>PayloadRootQNameEndpointMapping</classname>. Here's how we
|
||||
wire it up in <filename>spring-ws-servlet.xml</filename>:
|
||||
their content, by using a <classname>PayloadRootQNameEndpointMapping</classname>. Here is how we
|
||||
configure a <classname>PayloadRootQNameEndpointMapping</classname> in <filename>spring-ws-servlet.xml</filename>:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
|
||||
@@ -670,12 +687,12 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
</property>
|
||||
</bean>]]></programlisting>
|
||||
<para>
|
||||
This means that whenever a XML message comes in with the namespace
|
||||
This means that whenever an XML message is received with the namespace
|
||||
<literal>http://mycompany.com/hr/schemas</literal> and the
|
||||
<literal>HolidayRequest</literal> local name, it will be routed to the
|
||||
<varname>holidayEndpoint</varname>.
|
||||
It also adds a <classname>PayloadLoggingInterceptor</classname>,
|
||||
that dumps incoming and outgoing messages to the log.
|
||||
(It also adds a <classname>PayloadLoggingInterceptor</classname>,
|
||||
that dumps incoming and outgoing messages to the log.)
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
@@ -731,7 +748,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
We set the location where the service can be reached:
|
||||
<uri>http://localhost:8080/holidayService</uri>. For development, this will suffice, but
|
||||
obviously we need to change this to <uri>http://mycompany.com/humanresources</uri> when going
|
||||
live. One way to keep this to accomplish this would be to use Spring
|
||||
live. A common way to to accomplish this is to use a Spring
|
||||
<classname>PropertyPlaceholderConfigurer</classname>.
|
||||
</para>
|
||||
</callout>
|
||||
@@ -745,7 +762,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
</programlistingco>
|
||||
<para>
|
||||
You can create a WAR file using <command>mvn install</command>.
|
||||
If you deploy the application, and point your browser at
|
||||
If you deploy the application (to Tomcat, Jetty, etc.), and point your browser at
|
||||
<ulink url="http://localhost:8080/holidayService/holiday.wsdl">this location</ulink>, you will
|
||||
see the generated WSDL. This WSDL is ready to be used by clients, such as
|
||||
<ulink url="http://www.soapui.org/">soapUI</ulink>, or other SOAP frameworks.
|
||||
@@ -753,7 +770,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
</section>
|
||||
<para>
|
||||
That concludes this tutorial. The tutorial code can be found in the full distribution of Spring-WS.
|
||||
The next step would be to look at the echo sample application, that is part
|
||||
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, you can read the rest of the reference documentation.
|
||||
|
||||
Reference in New Issue
Block a user