Lotsa docs.

This commit is contained in:
Arjen Poutsma
2007-04-23 13:10:15 +00:00
parent d155332ddd
commit 3c03f53d2d
9 changed files with 592 additions and 317 deletions

View File

@@ -53,7 +53,8 @@
In addition to a message sender, the <classname>WebServiceTemplate</classname> requires a Web service
message factory. As explained in <xref linkend="message-factories"/>, there are two message factories
for SOAP: <classname>SaajSoapMessageFactory</classname> and
<classname>AxiomSoapMessageFactory</classname>.
<classname>AxiomSoapMessageFactory</classname>. If no message factory is specified, Spring-WS will
use the <classname>SaajSoapMessageFactory</classname> by default.
</para>
</section>
</section>
@@ -102,9 +103,6 @@ public class WebServiceClient {
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="webServiceClient" class="WebServiceClient">
<property name="messageFactory">
<bean class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
</property>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpUrlConnectionMessageSender">
<property name="url" value="http://localhost:8080/WebService"/>
@@ -116,7 +114,7 @@ public class WebServiceClient {
<para>
This example uses the template to send a hello world message to the web service located at
<uri>http://localhost:8080/WebService</uri>, and writes the result to the console.
The <classname>WebServiceTemplate</classname> is injected with the message factory and sender.
The <classname>WebServiceTemplate</classname> is injected with the message sender.
A zero argument constructor and <property>messageFactory</property> /
<property>messageSender</property> bean properties are provided and can be used for constructing
the instance (using a BeanFactory or plain Java code). Alternatively, consider deriving from

158
src/docbkx/common.xml Normal file
View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="common">
<title>Shared components</title>
<para>
In this chapter, we will explore the the components which are shared between client- and server side
Spring-WS development. These interfaces and classes represent the building blocks of Spring-WS, so
it's important to understand what they do, even if you do not use them directly.
</para>
<section id="web-service-messages">
<title>Web service messages</title>
<section id="web-service-message">
<title><interfacename>WebServiceMessage</interfacename></title>
<para>
One of the core interfaces within Spring Web Services is the
<interfacename>WebServiceMessage</interfacename>. This interface represents a protocol agnostic XML
message. The interface contains methods that provide access to the payload of the message, in the form
of a <interfacename>javax.xml.transform.Source</interfacename> or a
<interfacename>javax.xml.transform.Result</interfacename>. <interfacename>Source</interfacename> and
<interfacename>Result</interfacename> are tagging interfaces that represent an abstraction over XML
input and output. Concrete implementations wrap various XML representations, as indicated in the table
below.
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>Source/Result implementation</entry>
<entry>Wraps XML representation</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<classname>javax.xml.transform.dom.DOMSource</classname>
</entry>
<entry>
<interfacename>org.w3c.dom.Node</interfacename>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.dom.DOMResult</classname>
</entry>
<entry>
<interfacename>org.w3c.dom.Node</interfacename>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.sax.SAXSource</classname>
</entry>
<entry>
<classname>org.xml.sax.InputSource</classname>
and
<interfacename>org.xml.sax.XMLReader</interfacename>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.sax.SAXResult</classname>
</entry>
<entry>
<interfacename>org.xml.sax.ContentHandler</interfacename>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.stream.StreamSource</classname>
</entry>
<entry>
<classname>java.io.File</classname>, <classname>java.io.InputStream</classname>, or
<classname>java.io.Reader</classname>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.stream.StreamResult</classname>
</entry>
<entry>
<classname>java.io.File</classname>, <classname>java.io.OutputStream</classname>, or
<classname>java.io.Writer</classname>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
In addition to reading from and writing to the payload, a Web service message can write itself to an
output stream.
</para>
</section>
<section id="soap-message">
<title><interfacename>SoapMessage</interfacename></title>
<para>
The <interfacename>SoapMessage</interfacename> is an extension of
<interfacename>WebServiceMessage</interfacename>. It contains SOAP-specific methods, such as getting
SOAP Headers, SOAP Faults, etc. Generally, your code should only not be dependent on
<interfacename>SoapMessage</interfacename>, because the content of the SOAP Body can be obtained via
<methodname>getPayloadSource()</methodname> and <methodname>getPayloadResult()</methodname> in the
<interfacename>WebServiceMessage</interfacename>. Only when it is necessary to perform SOAP-specific
actions, such as adding a header, get an attachment, etc., should you need to cast
<interfacename>WebServiceMessage</interfacename> to <interfacename>SoapMessage</interfacename>.
</para>
</section>
<section id="message-factories">
<title>Message Factories</title>
<para>
Concrete message implementation are created by a
<interfacename>WebServiceMessageFactory</interfacename>. This factory can create an empty message, or
read a message based on an input stream.
There are two concrete implementations of <interfacename>WebServiceMessageFactory</interfacename>.
One is based on SAAJ, the SOAP with Attachments API for Java, the other based on Axis 2's AXIOM, the
AXis Object Model.
</para>
<section>
<title><classname>SaajSoapMessageFactory</classname></title>
<para>
The <classname>SaajSoapMessageFactory</classname> uses the SOAP with Attachments API for Java to
create <classname>SoapMessage</classname> implementations. SAAJ is part of J2EE 1.4, so it should be
supported under most modern application servers. You wire up a
<classname>SaajSoapMessageFactory</classname> like so:
<programlisting><![CDATA[
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />]]></programlisting>
</para>
<note>
<para>
SAAJ is based on DOM, the Document Object Model. This means that all SOAP messages are
stored in memory as a whole. For larger SOAP messages, this may not be very performant.
In that case, the <classname>AxiomSoapMessageFactory</classname> might be more applicable.
</para>
</note>
</section>
<section>
<title><classname>AxiomSoapMessageFactory</classname></title>
<para>
The <classname>AxiomSoapMessageFactory</classname> uses the AXis 2 Object Model to create
<interfacename>SoapMessage</interfacename> implementations. AXIOM is based on StAX, the Streaming
API for XML. StAX provides a pull-based mechanism for reading XML messages, which can be more
efficient for larger messages.
</para>
<para>
To increase reading performance on the <classname>AxiomSoapMessageFactory</classname>,
you can set the <property>payloadCaching</property> property to false (default is true).
This this will read the contents of the SOAP body directly from the stream.
When this setting is enabled, the payload can only be read once.
This means that you have to make sure that any preprocessing of the message does not consume it.
</para>
<para>
You use the <classname>AxiomSoapMessageFactory</classname> as follows:
<programlisting><![CDATA[
<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
<property name="payloadCaching" value="true"/>
</bean>]]></programlisting>
</para>
</section>
</section>
</section>
</chapter>

View File

@@ -32,15 +32,51 @@
<toc />
<xi:include href="preface.xml" />
<xi:include href="overview.xml" />
<chapter id="server">
<title>Document-driven Web services with Spring-WS</title>
<para>This chapter will contain the reference for server-side Spring-WS usage.</para>
</chapter>
<!--<xi:include href="server.xml" />-->
<xi:include href="client.xml" />
<xi:include href="security.xml" />
<xi:include href="oxm.xml" />
<xi:include href="bibliography.xml" />
<part>
<title>Introduction</title>
<partintro>
<para>
This first part of the reference documentation gives an overview of Spring Web Services, and the
underlying concepts. We will introduce Spring-WS, and explain the concepts behind contract-first
Web service development.
</para>
</partintro>
<xi:include href="what-is-spring-ws.xml" />
<xi:include href="why-contract-first.xml" />
<xi:include href="tutorial.xml" />
</part>
<part>
<title>Reference</title>
<partintro>
<para>
This part of the reference documentation gives an in-depth look into the various pieces that make up
Spring Web Services.
It consists of a chapter which discusses the parts common to both client- and server-side, a chapter
about writing server-side Web services, about using Web services on the client-side, using WS-Security,
and the flexible Object/XML mapping.
</para>
</partintro>
<xi:include href="common.xml" />
<chapter id="server">
<title>Document-driven Web services with Spring-WS</title>
<para>This chapter will contain the reference for server-side Spring-WS usage.</para>
</chapter>
<!--<xi:include href="server.xml" />-->
<xi:include href="client.xml" />
<xi:include href="security.xml" />
<xi:include href="oxm.xml" />
</part>
<part id="resources">
<title>Other Resources</title>
<partintro>
<para>
In addition to this reference documentation, a number of other resources
exist to help you learn how to use Spring Web Services. These resources are
discussed in this section.
</para>
</partintro>
<xi:include href="bibliography.xml" />
</part>
</book>

View File

@@ -1,142 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="introduction">
<title>Introduction</title>
<section>
<title>Overview</title>
<para>
Spring-WS consists of three separate modules. This chapter discusses each of the modules in turn.
</para>
<para>
The <link linkend="ws">Core</link> package is the central part of the Web services functionality. It
provides the central <classname>WebServiceMessage</classname> and <classname>SoapMessage</classname>
interfaces, the powerful message dispatching, and the various support classes for implementing Web service
endpoints.
</para>
<para>
The <link linkend="security">Security</link> package provides a WS-Security implementation that integrates
with the core Web service package. It allows you to add principal tokens, sign, and decrypt and encrypt SOAP
messages. Addtionally, it allows you to leverage your existing Acegi security implementation for
authentication and authorization.
</para>
<para>
The <link linkend="oxm">OXM</link> package provides integration for popular XML marshalling APIs, including
JAXB 1 and 2. Using the OXM package means that you benefit from a unified exception hierarchy, and can wire
up your favorite XML marshalling technology easily.
</para>
</section>
<section>
<title>Why Spring Web Services?</title>
<para>
There are various other SOAP stacks available, why and where should you use Spring-WS? This section answers
that question by showing what the focus of Spring-WS is.
</para>
<section>
<title>Spring-WS is meant for Public Web Services</title>
<para>
One can distinguish between two different sorts of Web services. Private Web services are not used
outside your application domain. They might form a part of your Enterprise Service Bus, or used as a
means to communicate between a fat .NET client and a J2EE server. When the two sides of the spectrum
(client and server) are under your control, you can easily expose (existing) methods, since you can
(re)generate client code easily.
</para>
<para>
Public Web services provide a separate interface to your application. They are often used by clients
that are outside of your reach. When developing a public Web service, you should really think about the
interface you are providing: it is probably going to be around for a while, and you cannot change it
that often. As such, it is a good idea to place the Web service in a separate layer, thus hiding the
inner workings of the application. As a result, you can change the Web service and the rest of the
appliciation seperately.
</para>
</section>
<section>
<title>Spring-WS makes Web Services First Class Citizens of the Architecture</title>
<para>
Web Services deserve a proper place in an application architecture. Often, they exist as an afterthought
in the application architecture, mostly because existing Java business interfaces are exposed as SOAP
services. One could say that they are "SOAPified". Spring-WS provides a MVC-like framework for
developing a Web service application layer, just like you would develop a layer especially for a Web
user interface using Spring-MVC. Spring-WS also provides useful integration points with you existing
Spring application architecture, such as the Acegi integration.
</para>
</section>
<section>
<title>Spring-WS is Data-Driven</title>
<para>
When Web Services started making their way into the Enterprise Computing world, developers considered
Web Services just another, XML-based remoting protocol. Such remoting frameworks can be used with
relative ease: on the server-side, one simply implements a specific interface such as
<classname>java.rmi.Remote</classname>, and on the client side, a dynamic proxy is used.
Unfortunately, because of this simplicity, remoting architectures have some issues:
<itemizedlist>
<listitem>
<para>
They pretend there is no <emphasis>latency</emphasis> between the client and the server,
while in fact there is both network and application latency,
</para>
</listitem>
<listitem>
<para>
They pretend that client and server have <emphasis>shared memory access</emphasis>, while in
fact data must be both marshalled and unmarshalled,
</para>
</listitem>
<listitem>
<para>
They ignore the possibility of a <emphasis>request or response not reaching its
destination</emphasis>,
</para>
</listitem>
<listitem>
<para>
They enforce a <emphasis>non-concurrent</emphasis> programming model, while in fact a
concurrent approach seems more in place,
</para>
</listitem>
<listitem>
<para>
They enforce a <emphasis>tightly coupled architecture</emphasis>, where changes on the
server-side result in changes on the client-side.
</para>
</listitem>
</itemizedlist>
It is not without reason that Gregor Hohpe calls a distributed architecture a <quote>fairy tale
architecture</quote>: one is made to believe things that simply are not true. To quote <xref
linkend="waldo-94"/>:
<blockquote>
<para>
Objects that interact in a distributed system need to be dealt with in ways that are
intrinsically different from objects that interact in a single address space.
</para>
</blockquote>
</para>
<para>
Instead of being behavior-driven, Spring-WS is data-driven: it focusses on the data being sent, not on a
particular method being invoked.
</para>
</section>
<section>
<title>Spring-WS Focusses on Contract-first Development</title>
<para>
SOAP services are defined in two contracts: the data contract (the XSD schema), and the service contract
(the WSDL). Generating these contracts from Java-code is called <emphasis>contract-last
development</emphasis> <xref linkend="alpine"/> identifies some problems with this approach, most
importantly:
<blockquote>
<para>
There is no way to ensure that a services published interface remains constant over time.
Every redeployment of the service may change the classes, and hence the contract.
</para>
</blockquote>
The alternative of contract-last development is <emphasis>contract-first development</emphasis>.
Using this approach, the service and data contract are leading. Spring-WS focusses on contract-first Web
service development, because is considered to be a best practice. After all, the actual XML that is sent
across the wire is more important than the Java code that is used to implement it.
</para>
</section>
</section>
</chapter>

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -1,157 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="ws">
<title>Creating a Web service with Spring-WS</title>
<section id="web-service-messages">
<title>Web service messages</title>
<section>
<title>
<interfacename>WebServiceMessage</interfacename> and <interfacename>SoapMessage</interfacename>
</title>
<para>
One of the core interfaces within Spring Web Services is the
<interfacename>WebServiceMessage</interfacename>. This interface represents a protocol agnostic XML
message. The interface contains methods that provide access to the payload of the message, in the form
of a <interfacename>javax.xml.transform.Source</interfacename> or a
<interfacename>javax.xml.transform.Result</interfacename>. <interfacename>Source</interfacename> and
<interfacename>Result</interfacename> are tagging interfaces that represent an abstraction over XML
input and output. Concrete implementations wrap various XML representations, as indicated in the table
below.
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>Source/Result implementation</entry>
<entry>Wraps XML representation</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<classname>javax.xml.transform.dom.DOMSource</classname>
</entry>
<entry>
<interfacename>org.w3c.dom.Node</interfacename>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.dom.DOMResult</classname>
</entry>
<entry>
<interfacename>org.w3c.dom.Node</interfacename>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.sax.SAXSource</classname>
</entry>
<entry>
<classname>org.xml.sax.InputSource</classname>
and
<interfacename>org.xml.sax.XMLReader</interfacename>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.sax.SAXResult</classname>
</entry>
<entry>
<interfacename>org.xml.sax.ContentHandler</interfacename>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.stream.StreamSource</classname>
</entry>
<entry>
<classname>java.io.File</classname>, <classname>java.io.InputStream</classname>, or
<classname>java.io.Reader</classname>
</entry>
</row>
<row>
<entry>
<classname>javax.xml.transform.stream.StreamResult</classname>
</entry>
<entry>
<classname>java.io.File</classname>, <classname>java.io.OutputStream</classname>, or
<classname>java.io.Writer</classname>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
In addition to reading from and writing to the payload, a Web service message can write itself to an
output stream.
</para>
<para>
The <interfacename>SoapMessage</interfacename> is an extension of
<interfacename>WebServiceMessage</interfacename>. It contains SOAP-specific methods, such as getting
SOAP Headers, SOAP Faults, etc. Generally, your code should only not be dependent on
<interfacename>SoapMessage</interfacename>, because the content of the SOAP Body can be obtained via
<methodname>getPayloadSource()</methodname> and <methodname>getPayloadResult()</methodname> in the
<interfacename>WebServiceMessage</interfacename>. Only when it is necessary to perform SOAP-specific
actions, such as adding a header, get an attachment, etc., should you need to cast
<interfacename>WebServiceMessage</interfacename> to <interfacename>SoapMessage</interfacename>.
</para>
</section>
<section id="message-factories">
<title>Message Factories</title>
<para>
Concrete message implementation are created by a
<interfacename>WebServiceMessageFactory</interfacename>. This factory can create an empty message, or
read a message based on an input stream.
There are two concrete implementations of <interfacename>WebServiceMessageFactory</interfacename>.
One is based on SAAJ, the SOAP with Attachments API for Java, the other based on Axis 2's AXIOM, the
AXis Object Model.
</para>
<section>
<title><classname>SaajSoapMessageFactory</classname></title>
<para>
The <classname>SaajSoapMessageFactory</classname> uses the SOAP with Attachments API for Java to
create <classname>SoapMessage</classname> implementations. SAAJ is part of J2EE 1.4, so it should be
supported under most modern application servers. You wire up a
<classname>SaajSoapMessageFactory</classname> like so:
<programlisting><![CDATA[
<bean id="messageFactory"
class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
]]></programlisting>
</para>
<note>
<para>
SAAJ is based on DOM, the Document Object Model. This means that all SOAP messages are
stored in memory as a whole. For larger SOAP messages, this may not be very performant.
In that case, the <classname>AxiomSoapMessageFactory</classname> might be more applicable.
</para>
</note>
</section>
<section>
<title><classname>AxiomSoapMessageFactory</classname></title>
<para>
The <classname>AxiomSoapMessageFactory</classname> uses the AXis 2 Object Model to create
<interfacename>SoapMessage</interfacename> implementations. AXIOM uses StAX, the Streaming API for
XML. StAX provides a pull-based mechanism for reading XML messages, which can be more efficient
for larger messages.
</para>
<para>
To increase reading performance on the <classname>AxiomSoapMessageFactory</classname>,
you can set the <property>payloadCaching</property> property to false (default is true).
This this will read the contents of the SOAP body directly from the stream.
When this setting is enabled, the payload can only be read once.
This means that you have to make sure that any preprocessing of the message does not consume it.
</para>
<para>
You use the <classname>AxiomSoapMessageFactory</classname> as follows:
<programlisting><![CDATA[
<bean id="messageFactory"
class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
<property name="payloadCaching" value="true"/>
</bean>]]></programlisting>
</para>
</section>
</section>
</section>
<chapter id="server">
<title>Creating a Web service with Spring-WS</title>
<!--
<section id="ws-introduction">
<title>Introduction</title>

View File

@@ -269,15 +269,17 @@
<section id="tutorial-service-contract">
<title>Service contract</title>
<para>
A service contract is generally expressed as a <literal>WSDL</literal> 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 below.
This sectionwill show you how to write your own WSDL, if you choose not to use this functionality.
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
<xref linkend="tutorial.implementing.endpoint"/>.
You can skip to that section if you want to; the remainder of this section will show you how to write your
own WSDL by hand.
</para>
<para>
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:
<literal>http://mycompany.com/hr/definitions</literal>.
<uri>http://mycompany.com/hr/definitions</uri>.
</para>
<programlisting>
&lt;wsdl:definitions name=&quot;HumanResources&quot;
@@ -483,8 +485,7 @@
The following command creates a Maven2 web application project for us, using the Spring-WS archetype
(i.e. project template)
</para>
<screen>
> mvn archetype:create -DarchetypeGroupId=org.springframework.ws \
<screen>mvn archetype:create -DarchetypeGroupId=org.springframework.ws \
-DarchetypeArtifactId=spring-ws-archetype \
-DarchetypeVersion=1.0-rc1-SNAPSHOT \
-DgroupId=com.mycompany.hr \
@@ -517,12 +518,16 @@
&lt;/web-app&gt;
</programlisting>
<para>
We could have made the servlet more restrictive by using the url pattern <literal>/holidayService</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.
</para>
</section>
<section>
<section id="tutorial.implementing.endpoint">
<title>Implementing the Endpoint</title>
<para>
In Spring-WS, you will implement <emphasis>Endpoints</emphasis> to handle incoming XML messages. There
@@ -631,7 +636,10 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
<para>
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.
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
code less verbose. We use XPath because it is less fragile than marshalling technologies: we don't
care for strict schema conformance, as long as we can find the dates and the name.
</para>
<para>
Here's how we would wire up these classes in our <filename>spring-ws-servlet.xml</filename>
@@ -687,6 +695,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
</para>
<programlistingco>
<areaspec>
<area id="tutorial.wsdl.gen.bean" coords="2"/>
<area id="tutorial.wsdl.gen.schema" coords="5"/>
<area id="tutorial.wsdl.gen.portType" coords="6"/>
<area id="tutorial.wsdl.gen.locationUri" coords="7"/>
@@ -702,6 +711,14 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
</property>
</bean>]]></programlisting>
<calloutlist>
<callout arearefs="tutorial.wsdl.gen.bean">
<para>
The bean id determines the URL where the WSDL can be retrieved. In this case, the bean id is
<varname>holiday</varname>, which means that the WSDL can be retrieved as
<filename>holiday.wsdl</filename> in the servlet context. The full URL will typically be
<uri>http://localhost:8080/holidayService/holiday.wsdl</uri>.
</para>
</callout>
<callout arearefs="tutorial.wsdl.gen.schema">
<para>
The <varname>schema</varname> property is set to the human resource schema we defined in
@@ -723,6 +740,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
</calloutlist>
</programlistingco>
<para>
You can create a WAR file using <command>mvn install</command>.
If you deploy the application, and point your browser at
<ulink url="http://localhost:8080/holidayService/holiday.wsdl">this location</ulink>, you will
see the generated WSDL.

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="what-is-spring-ws">
<title>What is Spring Web Services?</title>
<section>
<title>Introduction</title>
<para>
Spring Web Services (Spring-WS) is a product of the Spring community focused on creating document-driven
Web services.
Spring Web Services aims to facilitate contract-first SOAP service development, allowing for the creation of
flexible web services using one of the many ways to manipulate XML payloads.
The product is based on Spring itself, which means you can use the Spring concepts such as dependency
injection as an integral part of your Web service.
</para>
<para>
People use Spring-WS for many reasons, but most are drawn to it after finding alternative SOAP stacks
lacking when it comes to following Web service best practices.
Spring-WS makes the best practice an easy practice. This includes practices such as the WS-I basic profile,
Contract-First development, and having a loose coupling between contract and implementation.
The other key features of Spring Web services are:
</para>
<formalpara>
<title>Powerful mappings</title>
<para>
You can distribute incoming XML request to any object, depending on message payload, SOAP Action header,
or an XPath expression.
</para>
</formalpara>
<formalpara>
<title>XML API support</title>
<para>
Incoming XML messages can be handled in standard JAXP APIs such as DOM, SAX, and StAX, but also JDOM,
dom4j, XOM, or even marshalling technologies.
</para>
</formalpara>
<formalpara>
<title>Flexible XML Marshalling</title>
<para>
The Object/XML Mapping module in the Spring Web Services distribution supports JAXB 1 and 2, Castor,
XMLBeans, JiBX, and XStream. And because it is a separate module, you can use it in non-Web services code
as well.
</para>
</formalpara>
<formalpara>
<title>Reuses your Spring expertise</title>
<para>
Spring-WS uses Spring application contexts for all configuration, which should help Spring developers
get up-to-speed nice and quickly. Also, the architecture of Spring-WS resembles that of Spring-MVC.
</para>
</formalpara>
<formalpara>
<title>Supports WS-Security</title>
<para>
WS-Security allows you to sign SOAP messages, encrypt and decrypt them, or authenticate against them.
</para>
</formalpara>
<formalpara>
<title>Integrates with Acegi Security</title>
<para>
The WS-Security implementation of Spring Web Services provides integration with
<ulink url="http://acegisecurity.org">Acegi Security</ulink>. This means you can use your existing Acegi
configuration for your SOAP service as well.
</para>
</formalpara>
<formalpara>
<title>Built by Maven</title>
<para>
This assists you in effectively reusing the Spring Web Services artifacts in your own Maven-based projects.
</para>
</formalpara>
<formalpara>
<title>Apache license</title>
<para>
You can confidently use Spring-WS in your project.
</para>
</formalpara>
</section>
<section>
<title>Runtime environment</title>
<para>
Spring Web Services runs within a standard Java 1.3 Runtime Environment. It also supports Java 5.0,
although the Java types which are specific to this release are packaged in a separate modules with the
suffix "tiger" in their JAR filename.
Spring-WS consists of a number of modules, which are described in the remainder of this section.
</para>
<itemizedlist>
<listitem>
<para>
The XML module (<filename>spring-xml.jar</filename>) contains various XML support classes for Spring Web
Services. This module is mainly targeted at the Spring-WS framework itself, and not a Web service
developers.
</para>
</listitem>
<listitem>
<para>
The Core package (<filename>spring-ws-core.jar</filename> and <filename>spring-ws-core-tiger.jar</filename>)
is the central part of the Web services
functionality. It provides the central <link linkend="web-service-messages">
<classname>WebServiceMessage</classname></link> and <link linkend="soap-message">
<classname>SoapMessage</classname></link> interfaces, the <link linkend="server">server-side</link>
framework, with powerful message dispatching, and the various support classes for implementing Web service
endpoints; and the <link linkend="client">client-side</link> <classname>WebServiceTemplate</classname>.
</para>
</listitem>
<listitem>
<para>
The <link linkend="security">Security</link> package (<filename>spring-ws-security.jar</filename>)
provides a WS-Security implementation that integrates
with the core Web service package. It allows you to add principal tokens, sign, and decrypt and encrypt SOAP
messages. Addtionally, it allows you to leverage your existing Acegi security implementation for
authentication and authorization.
</para>
</listitem>
<listitem>
<para>
The <link linkend="oxm">OXM</link> package (<filename>spring-oxm.jar</filename> and
<filename>spring-oxm-tiger.jar</filename>) provides integration for popular XML marshalling APIs, including
JAXB 1 and 2. Using the OXM package means that you benefit from a unified exception hierarchy, and can wire
up your favorite XML marshalling technology easily.
</para>
</listitem>
</itemizedlist>
<para>
The following figure illustrates the modules, and the dependencies between them. Arrows indicate
dependencies, i.e. Spring-WS Core depends on Spring-XML and Spring-X
<mediaobject>
<imageobject role="fo">
<imagedata fileref="src/docbkx/resources/images/spring-deps.png"
format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/spring-deps.png"
format="PNG" align="center"/>
</imageobject>
<caption>
<para>
Dependencies between Spring-WS modules
</para>
</caption>
</mediaobject>
</para>
</section>
</chapter>

View File

@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="why-contract-first">
<title>Why Contract First?</title>
<section>
<title>Introduction</title>
<para>
When creating Web services, there are two development styles: <emphasis>Contract Last</emphasis> and
<emphasis>Contract First</emphasis>. When using a contract-last approach, you start with the Java code, and
let the Web service contract (<acronym>WSDL</acronym>, see sidebar) be generated from that.
When using contract-first, you start with the WSDL contract, and use Java to implement said contract.
</para>
<sidebar>
<title>What is WSDL?</title>
<para>
WSDL stands for Web Services Description Language. A WSDL file is an XML document that describes a Web
service. It specifies the location of the service and the operations (or methods) the service exposes.
For more information about WSDL, refer to the
<ulink url="http://www.w3.org/TR/wsdl">WSDL specification</ulink>, or read the
<ulink url="http://www.w3schools.com/wsdl/">WSDL tutorial</ulink>
</para>
</sidebar>
<para>
Spring-WS only supports the contract-first development style. This section explains why.
</para>
</section>
<section>
<title>Object/XML Impedance Mismatch</title>
<para>
Similar to the field of ORM, where we have an
<ulink url="http://en.wikipedia.org/wiki/Object-Relational_impedance_mismatch">Object/Relational impedance mismatch</ulink>,
there is a similar problem when converting Java objects to XML.
At first glance, the O/X mapping problem appears simple: create an XML element for each Java object,
converting all Java properties and fields to sub-elements or attributes. However, things are not so
simple as they appear: there is a fundamental difference between hierarchical languages such as XML
(and especially XSD) and the graph model of Java<footnote>
<para>Most of the contents in this section was inspired by <xref linkend="alpine"/> and
<xref linkend="effective-enterprise-java"/>.</para></footnote>.
</para>
<section>
<title>XSD extensions</title>
<para>
In Java, the only way to change the behavior of a class is to subclass it, adding the new behavior to
that subclass. In XSD, you can extend a data type by restricting it: i.e. constraning the valid values
for the elements and attributes.
For instance, consider the following example:<programlisting><![CDATA[
<simpleType name="AirportCode">
<restriction base="string">
<pattern value="[A-Z][A-Z][A-Z]"/>
</restriction>
</simpleType>]]></programlisting>
This type restricts a XSD string by ways of a regular expression, allowing only three upper case
letters. If this type is converted to Java, we will end up with an ordinary
<classname>java.lang.String</classname>; the regular expression is lost in the conversion process,
because Java does not allow for these sorts of extensions.
</para>
</section>
<section>
<title>Unportable types</title>
<para>
One of the most important goals of a Web service is to be interoperable: to support multiple platforms
such as Java, .NET, Python, etc. Because all of these languages have different class libraries, you
must use some common, interlingual format to communicate between them. That format is XML, which is
supported by all of these languages.
</para>
<para>
Because of this conversion, you must make sure that you use portable types in your service
implementation. Consider, for example, a service that returns a
<classname>java.util.TreeMap</classname>, like so:<programlisting><![CDATA[
public Map getFlights() {
// use a tree map, to make sure it's sorted
TreeMap map = new TreeMap();
map.put("KL1117", "Stockholm");
...
return map;
}]]></programlisting>
Undoubtedly, the contents of this map can be converted into some sort of
XML, but since there is no <emphasis>standard</emphasis> way to describe a map in XML, it will be
proprietary. Also, even if it can be converted to XML, many platforms do not have a data structure
similar to the <classname>TreeMap</classname>. So when a .NET client accesses your Web service, it
will probably end up with a <classname>System.Collections.Hashtable</classname>, which has different
semantics.
</para>
<para>
This problem is also present when working on the client side. Consider the following XSD snippet, which
describes a service contract:<programlisting><![CDATA[
<element name="GetFlightsRequest">
<complexType>
<all>
<element name="departureDate" type="date"/>
<element name="from" type="string"/>
<element name="to" type="string"/>
</all>
</complexType>
</element>]]></programlisting>
This contract defines a request that takes an <type>date</type>, which is a XSD datatype representing
a year, month, and day. If we call this service from Java, we will probably use
either a <classname>java.util.Data</classname> or <classname>java.util.Calendar</classname>. However,
both of these classes actually describe times, rather than dates. So, we will actually send data that
represents the fourth of April 2007 at midnight (<literal>2007-04-04T00:00:00</literal>), which is not
the same as <literal>2007-04-04</literal>.
</para>
</section>
<section>
<title>Cyclic graphs</title>
<para>
Imagine we have the following simple class structure:<programlisting><![CDATA[
public class Flight {
private String number;
private List<Passenger> passengers;
// getters and setters omitted
}
public class Passenger {
private String name;
private Flight flight;
// getters and setters omitted
}]]></programlisting>
This is a cyclic graph: the <classname>Flight</classname> refers to the <classname>Passenger</classname>,
which refers to the <classname>Flight</classname> again. Cyclic graphs like these are quite common in
Java. If we took a naive approach to converting this to XML, we will end up with something
like:<programlisting><![CDATA[
<flight number="KL1117">
<passengers>
<passenger>
<name>Arjen Poutsma</name>
<flight number="KL1117">
<passengers>
<passenger>
<name>Arjen Poutsma</name>
<flight number="KL1117">
<passengers>
<passenger>
<name>Arjen Poutsma</name>
...]]></programlisting>
which will take a pretty long time to finish, because there is no stop condition for this loop.
</para>
<para>
One way to solve this problem is to use references to objects that were already marshalled, like
so:<programlisting><![CDATA[
<flight number="KL1117">
<passengers>
<passenger>
<name>Arjen Poutsma</name>
<flight href="KL1117" />
</passenger>
...
</passengers>
</flight>]]></programlisting>
This solves the recursiveness problem, but introduces new ones. For one, you cannot use an XML validator
to validate this structure. Another issue is that the standard way to use these references in the SOAP
(RPC/encoded) has been deprecated in favor of document/literal.
</para>
</section>
<para>
These are just a few of the problems when dealing with O/X mapping. It is important to respect these issues
when writing Web services. The best way to respect them is to focus on the XML completely, while using Java
as an implementation language. This is what contract-first is all about.
</para>
</section>
<section>
<title>Contract-first versus Contract-last</title>
<para>
Besides the Object/XML Mapping issues mentioned in the previous section, there are other reasons for
preferring a contract-first development style.
</para>
<section>
<title>Fragility</title>
<para>
If you use a contract-last development style, you will have no guarantee that the contract stays
constant over time. Each redeployment of the service can possibly result in a different contract.
Additionally, an upgrade of the SOAP stack used, or a migration to a different SOAP stack can also
change said contract.
</para>
<para>
In order for a contract to be useful, it must remain constant for as long as possible. If a contract
changes, you will have to contact all of the users of your service, and instruct them to get the new
version of the contract.
</para>
</section>
<section>
<title>Performance</title>
<para>
When Java is automatically transformed into XML, there is no way to be sure as to what is sent across
the wire. An object might reference another object, which refers to another, etc. In the end, half of
your virtual machine might be converted into XML, which will result in a slow service.
</para>
<para>
When using contract-first, you explicitly describe what XML is sent where, thus making sure that it is
exactly what you want.
</para>
</section>
<section>
<title>Versioning</title>
<para>
Even though a contract must remain constant for as long as possible, they <emphasis>do</emphasis> need
to be changed sometimes. In Java, this typically result in a new Java interface, such as
<interfacename>AirlineService2</interfacename>, and a (new) implementation of that interface. Of
course, the old service must be kept around, because there might be clients who have not migrated
yet.
</para>
<para>
If using contract-first, we can have a looser coupling between contract and implementation. Such a
looser coupling allows us to implement both versions of the contract in one class. We could, for
instance, use an XSLT to convert any "old-style" messages to the "new-style" messages.
</para>
</section>
</section>
</chapter>