Lotsa docs.
This commit is contained in:
@@ -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
158
src/docbkx/common.xml
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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 service’s 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>
|
||||
BIN
src/docbkx/resources/images/spring-deps.png
Normal file
BIN
src/docbkx/resources/images/spring-deps.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
<wsdl:definitions name="HumanResources"
|
||||
@@ -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 @@
|
||||
|
||||
</web-app>
|
||||
</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.
|
||||
|
||||
144
src/docbkx/what-is-spring-ws.xml
Normal file
144
src/docbkx/what-is-spring-ws.xml
Normal 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>
|
||||
212
src/docbkx/why-contract-first.xml
Normal file
212
src/docbkx/why-contract-first.xml
Normal 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>
|
||||
Reference in New Issue
Block a user