[SWS-120]
[SWS-125] Documentation corrections.
This commit is contained in:
@@ -7,14 +7,14 @@
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
Spring-WS provides a client-side Web service API that allows for consistent, XML-driven access to Web
|
||||
services. It also allows for use of <link linkend="oxm">marshallers and unmarshallers</link>.
|
||||
services. It also allows for the use of <link linkend="oxm">marshallers and unmarshallers</link>.
|
||||
</para>
|
||||
<para>
|
||||
The package <package>org.springframework.ws.client.core</package> provides the core functionality for using
|
||||
the client-side access API. It contains template classes that simplifies the use of Web services, much like
|
||||
the <classname>JdbcTemplate</classname> does for JDBC. The design principle common to Spring template
|
||||
classes is to provide helper methods to perform common operations and for more sophisticated usage, delegate
|
||||
the essence of the processing task to user implemented callback interfaces. The Web service template
|
||||
to user implemented callback interfaces. The Web service template
|
||||
follows the same design. The classes offer various convenience methods for the sending and receiving of XML
|
||||
messages, marshalling objects to XML before sending, and allows for multiple transports,
|
||||
</para>
|
||||
@@ -82,6 +82,7 @@ import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
public class WebServiceClient {
|
||||
|
||||
private static final String MESSAGE = "<message xmlns=\"http://tempuri.org\">Hello Web Service World</message>";
|
||||
|
||||
private WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
|
||||
|
||||
public void setDefaultUri(String defaultUri) {
|
||||
@@ -95,9 +96,6 @@ public class WebServiceClient {
|
||||
}
|
||||
|
||||
}]]></programlisting>
|
||||
<para>
|
||||
Here is the corresponding configuration:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<beans xmlns="http://www.springframework.org/schema/beans">
|
||||
|
||||
@@ -121,7 +119,7 @@ public class WebServiceClient {
|
||||
<title>Marshalling, sending, receiving, and unmarshalling</title>
|
||||
<para>
|
||||
In order to facilitate the sending of plain Java objects, the <classname>WebServiceTemplate</classname>
|
||||
has a send methods that take an object as an argument for a message's data content.
|
||||
has a number of send methods that take an object as an argument for a message's data content.
|
||||
The method <methodname>marshalSendAndReceive</methodname> in <classname>WebServiceTemplate</classname>
|
||||
delegates the conversion of the request object to XML to a <interface>Marshaller</interface>, and
|
||||
the conversion of the response XML to an object to an <interface>Unmarshaller</interface>.
|
||||
@@ -138,7 +136,7 @@ public class WebServiceClient {
|
||||
<interface>WebServiceMessageCallback</interface>
|
||||
</title>
|
||||
<para>
|
||||
To accommodate the setting of a SOAP headers, and other settings on the message, the
|
||||
To accommodate the setting of SOAP headers, and other settings on the message, the
|
||||
<interfacename>WebServiceMessageCallback</interfacename> interface gives you access to the message
|
||||
after it has been created, but before it is sent. The example below demonstrates how to set the SOAP
|
||||
Action header on a message that is created by marshalling an object.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<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.
|
||||
it is 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>
|
||||
@@ -123,7 +123,7 @@
|
||||
<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.
|
||||
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>
|
||||
@@ -139,8 +139,9 @@
|
||||
<section id="message-context">
|
||||
<title><interfacename>MessageContext</interfacename></title>
|
||||
<para>
|
||||
Typically, messages come in pairs: a request and a response. A request is created on the client-side,
|
||||
which is sent over some transport to the server-side, where a response is generated. This response gets
|
||||
Typically, messages come in pairs: a request and a response. A request
|
||||
is created on the client-side, which is sent over some transport to the
|
||||
server-side, where a response is generated. This response gets
|
||||
sent back to the client, where it is read.
|
||||
</para>
|
||||
<para>
|
||||
@@ -149,8 +150,8 @@
|
||||
messages.
|
||||
On the client-side, the message context is created by the <link linkend="client-web-service-template">
|
||||
<classname>WebServiceTemplate</classname></link>.
|
||||
On the server-side, the message context is read from the transport-specific input stream. In HTTP,
|
||||
it is read from the <interfacename>HttpServletRequest</interfacename> and the response is written back
|
||||
On the server-side, the message context is read from the transport-specific input stream.
|
||||
For example, in HTTP, it is read from the <interfacename>HttpServletRequest</interfacename> and the response is written back
|
||||
to the <interfacename>HttpServletResponse</interfacename>.
|
||||
</para>
|
||||
</section>
|
||||
@@ -158,7 +159,8 @@
|
||||
<section id="xpath">
|
||||
<title>Handling XML With XPath</title>
|
||||
<para>
|
||||
One of the best ways to handle XML is to use XPath. Quoting <xref linkend="effective-xml"/>, item 35:
|
||||
One of the best ways to handle XML is to use XPath.
|
||||
Quoting <xref linkend="effective-xml"/>, item 35:
|
||||
</para>
|
||||
<blockquote>
|
||||
<para>
|
||||
@@ -173,14 +175,14 @@
|
||||
</para>
|
||||
<attribution>Elliotte Rusty Harold</attribution>
|
||||
</blockquote>
|
||||
<para>
|
||||
<para>
|
||||
Spring Web Services has two ways to use XPath within your application: the faster
|
||||
<interfacename>XPathExpression</interfacename> or the more flexible <classname>XPathTemplate</classname>.
|
||||
</para>
|
||||
<section id="xpath-expression">
|
||||
<title><interfacename>XPathExpression</interfacename></title>
|
||||
<para>
|
||||
The <interfacename>XPathExpression</interfacename> is an abstraction over a compiled XPath expressions,
|
||||
The <interfacename>XPathExpression</interfacename> is an abstraction over a compiled XPath expression,
|
||||
such as the Java 5 <interfacename>javax.xml.xpath.XPathExpression</interfacename>, or the Jaxen
|
||||
<classname>XPath</classname> class.
|
||||
To construct an expression in an application context, there is the
|
||||
@@ -189,7 +191,7 @@
|
||||
<programlisting><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<bean id="nameExpression" class="org.springframework.xml.xpath.XPathExpressionFactoryBean">
|
||||
<property name="expression" value="/Contacts/Contact/Name"/>
|
||||
@@ -202,14 +204,14 @@
|
||||
</beans>]]></programlisting>
|
||||
<para>
|
||||
The expression above does not use namespaces, but we could set those using the
|
||||
<property>namespaces</property> property of the factory bean. The expression can be used in the code
|
||||
as follows:
|
||||
<property>namespaces</property> property of the factory bean. The expression
|
||||
can be used in the code as follows:
|
||||
</para>
|
||||
<programlisting><![CDATA[package sample;
|
||||
|
||||
public class MyXPathClass {
|
||||
|
||||
private XPathExpression nameExpression;
|
||||
private final XPathExpression nameExpression;
|
||||
|
||||
public MyXPathClass(XPathExpression nameExpression) {
|
||||
this.nameExpression = nameExpression;
|
||||
@@ -230,24 +232,24 @@ public class MyXPathClass {
|
||||
|
||||
public class MyXPathClass {
|
||||
|
||||
private XPathExpression contactExpression;
|
||||
private final XPathExpression contactExpression;
|
||||
|
||||
public MyXPathClass(XPathExpression contactExpression) {
|
||||
this.contactExpression = contactExpression;
|
||||
}
|
||||
public MyXPathClass(XPathExpression contactExpression) {
|
||||
this.contactExpression = contactExpression;
|
||||
}
|
||||
|
||||
public void doXPath(Document document) {
|
||||
List contacts = nameExpression.evaluate(requestElement,
|
||||
new NodeMapper() {
|
||||
public Object mapNode(Node node, int nodeNum) throws DOMException {
|
||||
Element contactElement = (Element) node;
|
||||
Element nameElement = (Element) contactElement.getElementsByTagName("Name").item(0);
|
||||
Element phoneElement = (Element) contactElement.getElementsByTagName("Phone").item(0);
|
||||
return new Contact(nameElement.getTextContent(), phoneElement.getTextContent());
|
||||
}
|
||||
} );
|
||||
// do something with list of Contact objects
|
||||
}
|
||||
public void doXPath(Document document) {
|
||||
List contacts = nameExpression.evaluate(requestElement,
|
||||
new NodeMapper() {
|
||||
public Object mapNode(Node node, int nodeNum) throws DOMException {
|
||||
Element contactElement = (Element) node;
|
||||
Element nameElement = (Element) contactElement.getElementsByTagName("Name").item(0);
|
||||
Element phoneElement = (Element) contactElement.getElementsByTagName("Phone").item(0);
|
||||
return new Contact(nameElement.getTextContent(), phoneElement.getTextContent());
|
||||
}
|
||||
});
|
||||
]]><lineannotation>// do something with list of <classname>Contact</classname> objects</lineannotation><![CDATA[
|
||||
}
|
||||
}]]></programlisting>
|
||||
<para>
|
||||
Similar to mapping rows in Spring JDBC's <interfacename>RowMapper</interfacename>, each result node is
|
||||
@@ -271,12 +273,13 @@ public class MyXPathClass {
|
||||
|
||||
public void doXPath(Source source) {
|
||||
String name = template.evaluateAsString("/Contacts/Contact/Name", request);
|
||||
// do something with name
|
||||
]]><lineannotation>// do something with name</lineannotation><![CDATA[
|
||||
}
|
||||
|
||||
}]]></programlisting>
|
||||
<para>
|
||||
Of course, the template could have been injected with a constructor argument or a setter.
|
||||
Of course, the template could have been injected with a
|
||||
constructor argument or a setter.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
<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.
|
||||
underlying concepts. Spring-WS is introduced, and the concepts behind contract-first
|
||||
Web service development are explained.
|
||||
</para>
|
||||
</partintro>
|
||||
<xi:include href="what-is-spring-ws.xml" />
|
||||
@@ -49,8 +49,8 @@
|
||||
<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.
|
||||
This part of the reference documentation gives an in-depth look into the various components that
|
||||
comprise 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.
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<title>Preface</title>
|
||||
<para>
|
||||
In the current age of Service Oriented Architectures, more and more people are using Web Services to
|
||||
connect previously unconnected systems. Initially, Web services where considered to be just another way to do
|
||||
a Remote Procedure Call (RPC). Over time, however, people found out that there is a big difference
|
||||
between RPC and Web services. Especially when interoperability with other platforms is important, it is often
|
||||
connect previously unconnected systems. Initially, Web services were considered to be just another way to do
|
||||
a Remote Procedure Call (RPC). Over time however, people found out that there is a big difference
|
||||
between RPCs and Web services. Especially when interoperability with other platforms is important, it is often
|
||||
better to send encapsulated XML documents, containing all the data necessary to process the request.
|
||||
Conceptually, XML-based Web services are better off being compared to message queues rather than remoting
|
||||
solutions.
|
||||
|
||||
@@ -6,25 +6,26 @@
|
||||
<section id="ws-introduction">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
Spring Web Services's server-side support in designed around a <classname>MessageDispatcher</classname>
|
||||
that dispatches incoming messages to endpoints, with configurable endpoint mappings, response generation,
|
||||
and endpoint interception.
|
||||
Spring-WS's server-side support is designed around a
|
||||
<classname>MessageDispatcher</classname> that dispatches incoming
|
||||
messages to endpoints, with configurable endpoint mappings, response
|
||||
generation, and endpoint interception.
|
||||
The simplest endpoint is a <interfacename>PayloadEndpoint</interfacename>, just offering a
|
||||
<literal>Source invoke(Source request)</literal> method. This interface can be implemented for creating an
|
||||
endpoint, but you will prefer the included implementation hierarchy, consisting of, for example
|
||||
<literal>Source invoke(Source request)</literal> method. You are of course free to
|
||||
implement this interface directly, but you will probably prefer to extend one of
|
||||
the included abstract implementations such as
|
||||
<classname>AbstractDomPayloadEndpoint</classname>, <classname>AbstractSaxPayloadEndpoint</classname>, and
|
||||
of course <classname>AbstractMarshallingPayloadEndpoint</classname>. Application endpoints will typically
|
||||
be subclasses of those.
|
||||
<classname>AbstractMarshallingPayloadEndpoint</classname>.
|
||||
Alternatively, there is a endpoint development that uses Java 5 annotations, such as
|
||||
<interfacename>@Endpoint</interfacename> for marking a POJO as endpoint, and marking a method with
|
||||
<interfacename>@PayloadRoot</interfacename> or <interfacename>@SoapAction</interfacename>.
|
||||
</para>
|
||||
<para>
|
||||
Spring-WS's XML handling is extremely flexible. An endpoint can choose from
|
||||
a large amount of XML handling libraries supported by Spring-WS, including the DOM family (W3C DOM, JDOM,
|
||||
dom4j, and XOM), SAX or StAX for faster performance, XPath to extract information from the message, or even
|
||||
<link linkend="oxm">marshalling techniques</link> (JAXB, Castor, XMLBeans, JiBX, or XStream) to convert
|
||||
the XML to objects and vice-versa.
|
||||
</para>
|
||||
<para>
|
||||
Spring-WS's XML handling is extremely flexible. An endpoint can choose from
|
||||
a large amount of XML handling libraries supported by Spring-WS, including the DOM family (W3C DOM, JDOM,
|
||||
dom4j, and XOM), SAX or StAX for faster performance, XPath to extract information from the message, or even
|
||||
<link linkend="oxm">marshalling techniques</link> (JAXB, Castor, XMLBeans, JiBX, or XStream) to convert
|
||||
the XML to objects and vice-versa.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@@ -33,7 +34,7 @@
|
||||
The server-side of Spring-WS is designed around a central class that dispatches incoming XML messages to
|
||||
endpoints. Spring-WS's <classname>MessageDispatcher</classname> is extremely flexible, allowing you to
|
||||
use any sort of class as an endpoint, as long as it can be configured in the Spring IoC container.
|
||||
In a way, the message dispatcher resembles Spring's<classname>DispatcherServlet</classname>, the
|
||||
In a way, the message dispatcher resembles Spring's <classname>DispatcherServlet</classname>, the
|
||||
<quote>Front Controller</quote> used in Spring Web MVC.
|
||||
</para>
|
||||
<para>
|
||||
@@ -55,20 +56,23 @@
|
||||
When a <classname>MessageDispatcher</classname> is set up for use and a request comes in for that
|
||||
specific dispatcher, said <classname>MessageDispatcher</classname> starts processing the request. The
|
||||
list below describes the complete process a request goes through when handled by a
|
||||
<classname>MessageDispatcher</classname>:
|
||||
<classname>MessageDispatcher</classname>:
|
||||
</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
An appropriate endpoint is searched for. If an endpoint is found, the invocation chain associated
|
||||
with the endpoint (preprocessors, postprocessors, and endpoints) will be executed in order to create
|
||||
An appropriate endpoint is searched for using the configured
|
||||
<literal>EndpointMapping(s)</literal>. If an endpoint is found,
|
||||
the invocation chain associated with the endpoint (preprocessors,
|
||||
postprocessors, and endpoints) will be executed in order to create
|
||||
a response.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
An appropriate adapter is searched for the endpoint. The <classname>MessageDispatcher</classname>
|
||||
delegates to this adapter to invoke the endpoint.
|
||||
An appropriate adapter is searched for the endpoint. The
|
||||
<classname>MessageDispatcher</classname> delegates to this adapter
|
||||
to invoke the endpoint.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
@@ -107,7 +111,7 @@
|
||||
The <classname>MessageDispatcherServlet</classname> is a standard <interface>Servlet</interface> which
|
||||
conveniently extends from the standard Spring Web <classname>DispatcherServlet</classname>, and wraps
|
||||
a <classname>MessageDispatcher</classname>. As such, it combines the attributes of these into one:
|
||||
as a <classname>MessageDispatcher</classname>, if follows the same request handling flow as described
|
||||
as a <classname>MessageDispatcher</classname>, it follows the same request handling flow as described
|
||||
in the previous section.
|
||||
As a servlet, the
|
||||
<classname>MessageDispatcherServlet</classname> is configured in the <filename>web.xml</filename> of
|
||||
@@ -129,11 +133,13 @@
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
]]><lineannotation><!-- ... --></lineannotation><![CDATA[
|
||||
|
||||
</web-app>]]></programlisting>
|
||||
<para>
|
||||
In the example above, all requests will be handled by the <literal>'spring-ws'</literal>
|
||||
<classname>MessageDispatcherServlet</classname>. This is only the first step in setting up Spring Web
|
||||
Services; the various endpoint and other beans used by the Spring Web Services framework also need to be
|
||||
Services; the various endpoint and other beans used by the Spring-WS framework also need to be
|
||||
configured.
|
||||
</para>
|
||||
<para>
|
||||
@@ -149,21 +155,21 @@
|
||||
<title>Endpoints</title>
|
||||
<para>
|
||||
Endpoints are the central concept in Spring-WS's server-side support. Endpoints provide access to the
|
||||
application behavior which is typically defined by a business service interface. Endpoint interpret the XML
|
||||
request message and uses that input to invoke a method on the business service. The result of that service
|
||||
application behavior which is typically defined by a business service interface. An endpoint interprets the XML
|
||||
request message and uses that input to invoke a method on the business service (typically). The result of that service
|
||||
invocation is represented as a response message. Spring-WS has a wide variety of endpoints, using various
|
||||
ways to handle the XML message, and to create a response.
|
||||
</para>
|
||||
<para>
|
||||
The basis for most endpoint in Spring Web Services is the
|
||||
The basis for most endpoints in Spring Web Services is the
|
||||
<interfacename>org.springframework.ws.server.endpoint.PayloadEndpoint</interfacename> interface, the source
|
||||
code of which is listed below.
|
||||
</para>
|
||||
<programlisting><![CDATA[public interface PayloadEndpoint {
|
||||
|
||||
/**
|
||||
]]><lineannotation>/**
|
||||
* Invokes an operation.
|
||||
*/
|
||||
*/</lineannotation><![CDATA[
|
||||
Source invoke(Source request) throws Exception;
|
||||
}]]></programlisting>
|
||||
<para>
|
||||
@@ -176,11 +182,11 @@
|
||||
most basic responsibility required of every endpoint; namely handling a request and returning a response.
|
||||
</para>
|
||||
<para>
|
||||
Alternatively, there is the <interfacename>MessageEndpoint</interfacename>, which operated on a
|
||||
Alternatively, there is the <interfacename>MessageEndpoint</interfacename>, which operates on a
|
||||
whole <link linkend="message-context"><interfacename>MessageContext</interfacename></link> rather than just
|
||||
the payload. Typically, your code should only not be dependent on messages, because the payload should
|
||||
contain the interesting information. Only when it is necessary to perform actions on the mesage a whole,
|
||||
such as adding a SOAP header, get an attachment, etc., should you need to cast to implement
|
||||
contain the interesting information. Only when it is necessary to perform actions on the mesage as a whole,
|
||||
such as adding a SOAP header, get an attachment, and so forth, should you need to implement
|
||||
<interfacename>MessageEndpoint</interfacename>, though these actions are usually performed in a
|
||||
<link linkend="server-endpoint-interceptor">endpoint interceptor</link>.
|
||||
</para>
|
||||
@@ -192,7 +198,7 @@
|
||||
<package>org.w3c.dom.Element</package> and related classes to handle the request, and create the
|
||||
response. When using the <classname>AbstractDomPayloadEndpoint</classname> as the baseclass for your
|
||||
endpoints you only have to override the <methodname>invokeInternal(Element, Document)</methodname>
|
||||
method, implement your logic, and return an <interfacename>Element</interfacename> if we want a
|
||||
method, implement your logic, and return an <interfacename>Element</interfacename> if you want a
|
||||
response. Here is a short example consisting of a class and a declaration in the application context.
|
||||
</para>
|
||||
<programlisting><![CDATA[package samples;
|
||||
@@ -220,7 +226,7 @@ public class SampleEndpoint extends AbstractDomPayloadEndpoint {
|
||||
<constructor-arg value="Hello World!"/>
|
||||
</bean>]]></programlisting>
|
||||
<para>
|
||||
The above class and the declaration in the application context is all you need besides setting up a
|
||||
The above class and the declaration in the application context is all you need besides setting up an
|
||||
endpoint mapping (see the section entitled <xref linkend="server-endpoint-mapping" />) to get this very
|
||||
simple endpoint working. The SOAP message handled by this endpoint will look something like:
|
||||
</para>
|
||||
@@ -255,8 +261,8 @@ public class SampleEndpoint extends AbstractDomPayloadEndpoint {
|
||||
<classname>AbstractJDomPayloadEndpoint</classname> allows you to use JDOM, and the
|
||||
<classname>AbstractXomPayloadEndpoint</classname> uses XOM to handle the XML. All of these endpoints
|
||||
have an <methodname>invokeInternal</methodname> method similar to above.
|
||||
Also, consider to use Spring-WS's XPath support to extract the information you need out of the payload,
|
||||
see <xref linkend="xpath"/>.
|
||||
Also, consider using Spring-WS's XPath support to extract the information you need out of the payload.
|
||||
(See the section entitled <xref linkend="xpath"/> for details.)
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@@ -314,7 +320,7 @@ public class MarshallingOrderEndpoint extends AbstractMarshallingPayloadEndpoint
|
||||
|
||||
<bean id="orderService" class="samples.DefaultOrderService"/>
|
||||
|
||||
<!-- Other beans, such as the endpoint mapping -->
|
||||
]]><lineannotation><!-- Other beans, such as the endpoint mapping --></lineannotation><![CDATA[
|
||||
</beans>]]></programlisting>
|
||||
<para>
|
||||
In this sample, we configure a <link linkend="oxm-jaxb2">Jaxb2Marshaller</link> for the
|
||||
@@ -516,16 +522,16 @@ public class AnnotationOrderEndpoint {
|
||||
interceptors that are applied to the request and response. When a request comes in, the
|
||||
<classname>MessageDispatcher</classname> will hand it over to the endpoint mapping to let it inspect the
|
||||
request and come up with an appropriate <classname>EndpointInvocationChain</classname>. Then
|
||||
the <classname>MessageDispatcher</classname> will invoce the endpoint and any interceptors in the chain.
|
||||
the <classname>MessageDispatcher</classname> will invoke the endpoint and any interceptors in the chain.
|
||||
</para>
|
||||
<para>
|
||||
The concept of configurable endpoint mappings that can optionally contain interceptors (which can manipulate
|
||||
the request or the response, or both) is extremely powerful. A lot of supporting functionality can be built
|
||||
into custom <interfacename>EndpointMapping</interfacename>s. Think of a custom endpoint mapping that
|
||||
into custom <interfacename>EndpointMapping</interfacename>s. For example, there could be a custom endpoint mapping that
|
||||
chooses an endpoint not only based on the contents of a message, but also a specific SOAP headers.
|
||||
</para>
|
||||
<para>
|
||||
Most endpoint mappings inherit from the <classname>AbstractEndpointMapping</classname>, which offers a
|
||||
Most endpoint mappings inherit from the <classname>AbstractEndpointMapping</classname>, which offers an
|
||||
<property>interceptors</property> property, which is the list of interceptors to use.
|
||||
<interfacename>EndpointInterceptor</interfacename>s are discussed in
|
||||
<xref linkend="server-endpoint-interceptor"/>. Additionally, there is the
|
||||
@@ -565,9 +571,7 @@ public class AnnotationOrderEndpoint {
|
||||
local part. Thus, the endpoint mapping above routes requests for which have a payload root element with
|
||||
namespace <uri>http://samples</uri> and local part <literal>orderRequest</literal> to the
|
||||
<literal>'getOrderEndpoint'</literal>. Requests with a local part <literal>order</literal> will
|
||||
be routed to the <literal>'createController'</literal>. As a result of this mapping, the SOAP message
|
||||
shown <link linkend="server-order-request">above</link> will be mapped to the
|
||||
<literal>getOrderEndpoint</literal>.
|
||||
be routed to the <literal>'createOrderEndpoint'</literal>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@@ -607,9 +611,9 @@ public class AnnotationOrderEndpoint {
|
||||
<section id="server-method-endpoint-mapping">
|
||||
<title><classname>MethodEndpointMapping</classname></title>
|
||||
<para>
|
||||
As explain in <xref linkend="server-at-endpoint"/>, the <interfacename>@Endpoint</interfacename> model
|
||||
As explained in <xref linkend="server-at-endpoint"/>, the <interfacename>@Endpoint</interfacename> style
|
||||
allows you to handle multiple requests in one endpoint class. This is the responsibility of the
|
||||
<classname>MethodEndpointMapping</classname>. Similar to the endpoint mapping described above, the
|
||||
<classname>MethodEndpointMapping</classname>. Similar to the endpoint mapping described above, this
|
||||
mapping determines which method is to be invoked for an incoming request message.
|
||||
</para>
|
||||
<para>
|
||||
@@ -643,17 +647,18 @@ public class AnnotationOrderEndpoint {
|
||||
Interceptors located in the endpoint mapping must implement
|
||||
<interfacename>EndpointInterceptor</interfacename> from the
|
||||
<package>org.springframework.ws.server</package> package. This interface defines three methods, one that
|
||||
can be used for handling the request message has been determined, <emphasis>before</emphasis> the actual
|
||||
can be used for handling the request message has been determined <emphasis>before</emphasis> the actual
|
||||
endpoint will be executed, one that can be used for handling a normal response message, and one that
|
||||
can be used for handling fault messages, both of which will be called <emphasis>after</emphasis> the
|
||||
endpoint is executed. These three methods should provide enough flexibility to do all kinds of
|
||||
pre- and post-processing.
|
||||
</para>
|
||||
<para>
|
||||
The <methodname>handleRequest(..)</methodname> methods on the interceptor returns a boolean value. You
|
||||
can use this method to break or continue the processing of the invocation chain. When this method
|
||||
The <methodname>handleRequest(..)</methodname> method on the interceptor returns a boolean value. You
|
||||
can use this method to interrupt or continue the processing of the invocation chain. When this method
|
||||
returns <literal>true</literal>, the endpoint execution chain will continue, when it returns
|
||||
<literal>false</literal>, the <classname>MessageDispatcher</classname> assumes the interceptor itself
|
||||
<literal>false</literal>, the <classname>MessageDispatcher</classname> interprets this to mean that
|
||||
the interceptor itself
|
||||
has taken care of things and does not continue executing the other interceptors and the actual endoint
|
||||
in the invocation chain. The <methodname>handleResponse(..)</methodname> and
|
||||
<methodname>handleFault(..)</methodname> methods also have a boolean return value. When these methods
|
||||
@@ -697,7 +702,7 @@ public class AnnotationOrderEndpoint {
|
||||
<para>
|
||||
Both of these interceptors have two properties: <property>logRequest</property> and
|
||||
<property>logResponse</property>, which can be set to <literal>false</literal> to disable logging
|
||||
for either request of response messages.
|
||||
for either request or response messages.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@@ -737,8 +742,8 @@ public class AnnotationOrderEndpoint {
|
||||
<para>
|
||||
To transform the payload to another XML format, Spring Web Services offers the
|
||||
<classname>PayloadTransformingInterceptor</classname>. This endpoint interceptor is based on XSLT
|
||||
stylesheets, and is especially useful when supporting with multiple version of a Web service:
|
||||
you simply can transform the older message format to the new format.
|
||||
stylesheets, and is especially useful when supporting multiple versions of a Web service:
|
||||
you simply can transform the older message format to the newer format.
|
||||
Here is an example to use the <classname>PayloadTransformingInterceptor</classname>:
|
||||
</para>
|
||||
<programlisting><![CDATA[<bean id="transformingInterceptor"
|
||||
@@ -768,17 +773,17 @@ public class AnnotationOrderEndpoint {
|
||||
Furthermore, a programmatic way of handling exceptions gives you many more options for how to respond
|
||||
appropriately.
|
||||
Finally, rather than expose the innards of your application by giving an exception and stack trace, you
|
||||
can handle the exception any way you want, e.g. return a SOAP fault with a specific fault code and string.
|
||||
can handle the exception any way you want, for example return a SOAP fault with a specific fault code and string.
|
||||
</para>
|
||||
<para>
|
||||
Endpoint exception resolvers are automatically picked up by the <classname>MessageDispatcher</classname>, so
|
||||
you don't have to configure them explicitely.
|
||||
you don't have to configure them explicitly.
|
||||
</para>
|
||||
<para>
|
||||
Besides implementing the <classname>EndpointExceptionResolver</classname> interface, which is only a
|
||||
matter of implementing the <methodname>resolveException(MessageContext, endpoint, Exception)</methodname>
|
||||
method, you may also use one of the default implementations.
|
||||
The simples implementation is the <classname>SimpleSoapExceptionResolver</classname>, which simply
|
||||
The simplest implementation is the <classname>SimpleSoapExceptionResolver</classname>, which simply
|
||||
always creates a SOAP 1.1 Server or SOAP 1.2 Receiver Fault, and uses the exception message as the fault
|
||||
string.
|
||||
</para>
|
||||
|
||||
@@ -82,18 +82,18 @@
|
||||
</Employee>
|
||||
</HolidayRequest>]]></programlisting>
|
||||
<para>
|
||||
The order of the two element does not matter: <literal>Employee</literal> could have been the first
|
||||
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.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section id="tutorial.xsd">
|
||||
<title>Data Constract</title>
|
||||
<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.
|
||||
Basically, there are four different ways of defining such a contract for XML:
|
||||
There are four different ways of defining such a contract for XML:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>DTDs</para></listitem>
|
||||
@@ -152,7 +152,7 @@
|
||||
<xs:element name="LastName" type="xs:NCName"/></emphasis>
|
||||
</xs:schema></programlisting>
|
||||
<para>
|
||||
The generated schema can obviously be improved. The first thing to notice is that every type has a root-level
|
||||
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.
|
||||
@@ -263,7 +263,7 @@
|
||||
</calloutlist>
|
||||
</programlistingco>
|
||||
<para>
|
||||
We store this file with as <filename>hr.xsd</filename>.
|
||||
We store this file as <filename>hr.xsd</filename>.
|
||||
</para>
|
||||
</section>
|
||||
<section id="tutorial-service-contract">
|
||||
@@ -450,7 +450,7 @@
|
||||
</para>
|
||||
<para>
|
||||
The following command creates a Maven2 web application project for us, using the Spring-WS archetype
|
||||
(i.e. project template)
|
||||
(that is, project template)
|
||||
</para>
|
||||
<screen>mvn archetype:create -DarchetypeGroupId=org.springframework.ws \
|
||||
-DarchetypeArtifactId=spring-ws-archetype \
|
||||
@@ -462,12 +462,14 @@
|
||||
This command will create a new directory called <filename>holidayService</filename>. In this directory,
|
||||
there is a <filename>src/main/webapp</filename> directory, which will contain the root of the WAR file.
|
||||
You will find the standard web application deployment descriptor <filename>WEB-INF/web.xml</filename> here,
|
||||
which defines a Spring-WS <classname>MessageDispatcherServlet</classname>, and maps all incoming requests
|
||||
which defines a Spring-WS <classname>MessageDispatcherServlet</classname> and maps all incoming requests
|
||||
to this servlet:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
|
||||
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="2.4">
|
||||
|
||||
<display-name>MyCompany HR Holiday Service</display-name>
|
||||
@@ -565,10 +567,9 @@ 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
|
||||
use the constructor to inject it. 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,
|
||||
extracting the <literal><StartDate></literal> text value,
|
||||
<literal>//hr:EndDate</literal> for
|
||||
extracting the end date and <literal>concat(//hr:FirstName,' ',//hr:LastName)</literal>
|
||||
for extracting and concatenating the names of the employee.
|
||||
@@ -634,7 +635,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
<dependencies>
|
||||
]]></programlisting>
|
||||
<para>
|
||||
Here's how we would wire up these classes in our <filename>spring-ws-servlet.xml</filename>
|
||||
Here is how we would wire up these classes in our <filename>spring-ws-servlet.xml</filename>
|
||||
application context:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
@@ -673,8 +674,8 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
<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>PayloadInterceptor</classname>,
|
||||
which 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>
|
||||
@@ -683,7 +684,7 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
<para>
|
||||
Finally, we need to publish the WSDL. As stated in <xref linkend="tutorial-service-contract"/>, we don't
|
||||
need to write a WSDL ourselves; Spring-WS can generate one for us based on some conventions.
|
||||
Here's how we define the generation:
|
||||
Here is how we define the generation:
|
||||
</para>
|
||||
<programlistingco>
|
||||
<areaspec>
|
||||
@@ -746,9 +747,8 @@ public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
|
||||
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.
|
||||
This WSDL is ready to be used by clients, such as <ulink url="http://www.soapui.org/">soapUI</ulink>, or
|
||||
other SOAP frameworks.
|
||||
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.
|
||||
</para>
|
||||
</section>
|
||||
<para>
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
<formalpara>
|
||||
<title>Powerful mappings</title>
|
||||
<para>
|
||||
You can distribute incoming XML request to any object, depending on message payload, SOAP Action header,
|
||||
You can distribute incoming XML requests 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,
|
||||
Incoming XML messages can be handled not only with standard JAXP APIs such as DOM, SAX, and StAX, but also JDOM,
|
||||
dom4j, XOM, or even marshalling technologies.
|
||||
</para>
|
||||
</formalpara>
|
||||
@@ -45,7 +45,7 @@
|
||||
<formalpara>
|
||||
<title>Reuses your Spring expertise</title>
|
||||
<para>
|
||||
Spring-WS uses Spring application contexts for all configuration, which should help Spring developers
|
||||
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>
|
||||
@@ -82,21 +82,23 @@
|
||||
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.
|
||||
</para>
|
||||
<para>
|
||||
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
|
||||
Services. This module is mainly intended for 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">
|
||||
is the central part of the Spring's 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
|
||||
@@ -122,7 +124,7 @@
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
The following figure illustrates the modules, and the dependencies between them. Arrows indicate
|
||||
The following figure illustrates the Spring-WS modules and the dependencies between them. Arrows indicate
|
||||
dependencies, i.e. Spring-WS Core depends on Spring-XML and Spring-OXM.
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</para>
|
||||
</sidebar>
|
||||
<para>
|
||||
Spring-WS only supports the contract-first development style. This section explains why.
|
||||
Spring-WS only supports the contract-first development style, and this section explains why.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@@ -32,7 +32,7 @@
|
||||
<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
|
||||
converting all Java properties and fields to sub-elements or attributes. However, things are not as
|
||||
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
|
||||
@@ -42,7 +42,7 @@
|
||||
<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
|
||||
that subclass. In XSD, you can extend a data type by restricting it: that is, constraining the valid values
|
||||
for the elements and attributes.
|
||||
For instance, consider the following example:<programlisting><![CDATA[
|
||||
<simpleType name="AirportCode">
|
||||
@@ -96,8 +96,8 @@ public Map getFlights() {
|
||||
</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
|
||||
either a <classname>java.util.Date</classname> or <classname>java.util.Calendar</classname>. However,
|
||||
both of these classes actually describe times, rather than dates. So, we will actually end up sending 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>
|
||||
@@ -151,7 +151,7 @@ public class 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
|
||||
to validate this structure. Another issue is that the standard way to use these references in SOAP
|
||||
(RPC/encoded) has been deprecated in favor of document/literal (see WS-I
|
||||
<ulink url="http://www.ws-i.org/Profiles/BasicProfile-1.1.html#SOAP_encodingStyle_Attribute">Basic
|
||||
Profile</ulink>).
|
||||
@@ -199,7 +199,7 @@ public class Passenger {
|
||||
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
|
||||
the objects on the heap in your virtual machine might be converted into XML,
|
||||
which will result in a slow service.
|
||||
which will result in slow response times.
|
||||
</para>
|
||||
<para>
|
||||
When using contract-first, you explicitly describe what XML is sent where, thus making sure that it is
|
||||
@@ -209,7 +209,7 @@ public class Passenger {
|
||||
<section>
|
||||
<title>Reusability</title>
|
||||
<para>
|
||||
Defining your schema in a separate file allows you to reuse that file in different scenario's. If you
|
||||
Defining your schema in a separate file allows you to reuse that file in different scenarios. If you
|
||||
define an <type>AirportCode</type> in a file called <filename>airline.xsd</filename>, like so:
|
||||
</para>
|
||||
<programlisting><![CDATA[
|
||||
@@ -219,7 +219,7 @@ public class Passenger {
|
||||
</restriction>
|
||||
</simpleType>]]></programlisting>
|
||||
<para>
|
||||
You can reuse this definition in other schema's, or even WSDL files, using an
|
||||
You can reuse this definition in other schemas, or even WSDL files, using an
|
||||
<literal>import</literal> statement.
|
||||
</para>
|
||||
</section>
|
||||
@@ -227,7 +227,7 @@ public class Passenger {
|
||||
<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
|
||||
to be changed sometimes. In Java, this typically results 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.
|
||||
@@ -235,7 +235,7 @@ public class Passenger {
|
||||
<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.
|
||||
instance, use an XSLT stylesheet to convert any "old-style" messages to the "new-style" messages.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user