:toclevels: 10

[[common]]
= Shared components

This chapter explores the components that are shared between client- and server-side Spring-WS development.
These interfaces and classes represent the building blocks of Spring-WS, so you need to understand what they do, even if you do not use them directly.

[[web-service-messages]]
== Web Service Messages

This section describes the messages and message factories that Spring-WS uses.

[[web-service-message]]
=== `WebServiceMessage`

One of the core interfaces of Spring-WS is the `WebServiceMessage`.
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 `javax.xml.transform.Source` or a `javax.xml.transform.Result`.
`Source` and `Result` are tagging interfaces that represent an abstraction over XML input and output.
Concrete implementations wrap various XML representations, as indicated in the following table:

[cols="2", options="header"]
|===
| Source or Result implementation
| Wrapped XML representation

| `javax.xml.transform.dom.DOMSource`
| `org.w3c.dom.Node`

| `javax.xml.transform.dom.DOMResult`
| `org.w3c.dom.Node`

| `javax.xml.transform.sax.SAXSource`
| `org.xml.sax.InputSource` and `org.xml.sax.XMLReader`

| `javax.xml.transform.sax.SAXResult`
| `org.xml.sax.ContentHandler`

| `javax.xml.transform.stream.StreamSource`
| `java.io.File`, `java.io.InputStream`, or `java.io.Reader`

| `javax.xml.transform.stream.StreamResult`
| `java.io.File`, `java.io.OutputStream`, or `java.io.Writer`
|===

In addition to reading from and writing to the payload, a web service message can write itself to an output stream.

[[soap-message]]
=== `SoapMessage`

`SoapMessage` is a subclass of `WebServiceMessage`.
It contains SOAP-specific methods, such as getting SOAP Headers, SOAP Faults, and so on.
Generally, your code should not be dependent on `SoapMessage`, because the content of the SOAP Body (the payload of the message) can be obtained by using `getPayloadSource()` and `getPayloadResult()` in the `WebServiceMessage`.
Only when it is necessary to perform SOAP-specific actions (such as adding a header, getting an attachment, and so on) should you need to cast `WebServiceMessage` to `SoapMessage`.

[[message-factories]]
=== Message Factories

Concrete message implementations are created by a `WebServiceMessageFactory`.
This factory can create an empty message or read a message from an input stream.
One concrete implementations of `WebServiceMessageFactory` is provided based on SAAJ, the SOAP with Attachments API for Java.

==== `SaajSoapMessageFactory`

The `SaajSoapMessageFactory` uses the SOAP with Attachments API for Java (SAAJ) to create `SoapMessage` implementations.
SAAJ is part of J2EE 1.4, so it should be supported under most modern application servers.
Here is an overview of the SAAJ versions supplied by common application servers:

[cols="2", options="header"]
|===
| Application Server
| SAAJ Version

| BEA WebLogic 8
| 1.1

| BEA WebLogic 9
| 1.1/1.2^1^

| IBM WebSphere 6
| 1.2

| SUN Glassfish 1
| 1.3

2+|^1^Weblogic 9 has a known bug in the SAAJ 1.2 implementation: it implements all the 1.2 interfaces but throws an `UnsupportedOperationException` when called.
Spring-WS has a workaround: It uses SAAJ 1.1 when operating on WebLogic 9.
|===

Additionally, Java SE 6 includes SAAJ 1.3.
You can wire up a `SaajSoapMessageFactory` as follows:

====
[source,xml]
----
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
----
====

NOTE: SAAJ is based on DOM, the Document Object Model.
This means that all SOAP messages are stored in memory.
For larger SOAP messages, this may not be performant.

[[soap_11_or_12]]
==== SOAP 1.1 or 1.2

`SaajSoapMessageFactory` has a `soapVersion` property, where you can inject a `SoapVersion` constant.
By default, the version is 1.1, but you can set it to 1.2:

====
[source,xml]
----
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:util="http://www.springframework.org/schema/util"
       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/util
       http://www.springframework.org/schema/util/spring-util-2.0.xsd">

    <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
        <property name="soapVersion">
            <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12"/>
        </property>
    </bean>

</beans>
----
====

In the preceding example, we define a `SaajSoapMessageFactory` that accepts only SOAP 1.2 messages.

[WARNING]
====
Even though both versions of SOAP are quite similar in format, the 1.2 version is not backwards compatible with 1.1, because it uses a different XML namespace.
Other major differences between SOAP 1.1 and 1.2 include the different structure of a fault and the fact that `SOAPAction` HTTP headers are effectively deprecated, though they still work.

One important thing to note with SOAP version numbers (or WS-* specification version numbers in general) is that the latest version of a specification is generally not the most popular version.
For SOAP, this means that (currently) the best version to use is 1.1.
Version 1.2 might become more popular in the future, but 1.1 is currently the safest bet.
====

[[message-context]]
=== `MessageContext`

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.

In Spring-WS, such a conversation is contained in a `MessageContext`, which has properties to get request and response messages.
On the client-side, the message context is created by the <<client-web-service-template,`WebServiceTemplate`>>.
On the server-side, the message context is read from the transport-specific input stream.
For example, in HTTP, it is read from the `HttpServletRequest`, and the response is written back to the `HttpServletResponse`.

[[transport-context]]
== `TransportContext`

One of the key properties of the SOAP protocol is that it tries to be transport-agnostic.
This is why, for instance, Spring-WS does not support mapping messages to endpoints by HTTP request URL but rather by message content.

However, it is sometimes necessary to get access to the underlying transport, either on the client or the server side.
For this, Spring-WS has the `TransportContext`.
The transport context allows access to the underlying `WebServiceConnection`, which typically is a `HttpServletConnection` on the server side or a `HttpUrlConnection` or `CommonsHttpConnection` on the client side.
For example, you can obtain the IP address of the current request in a server-side endpoint or interceptor:

====
[source,java]
----
TransportContext context = TransportContextHolder.getTransportContext();
HttpServletConnection connection = (HttpServletConnection )context.getConnection();
HttpServletRequest request = connection.getHttpServletRequest();
String ipAddress = request.getRemoteAddr();
----
====

[[xpath]]
== Handling XML With XPath

One of the best ways to handle XML is to use XPath.
Quoting <<effective-xml>>, item 35:

[quote, Elliotte Rusty Harold]
XPath is a fourth generation declarative language that allows you to specify which nodes you want to process without specifying exactly how the processor is supposed to navigate to those nodes.
XPath's data model is very well designed to support exactly what almost all developers want from XML.
For instance, it merges all adjacent text including that in CDATA sections, allows values to be calculated that skip over comments and processing instructions` and include text from child and descendant elements, and requires all external entity references to be resolved.
In practice, XPath expressions tend to be much more robust against unexpected but perhaps insignificant changes in the input document.

Spring-WS has two ways to use XPath within your application: the faster `XPathExpression` or the more flexible `XPathOperations`.

[[xpath-expression]]
=== `XPathExpression`

The `XPathExpression` is an abstraction over a compiled XPath expression, such as the Java 5 `javax.xml.xpath.XPathExpression` interface or the Jaxen `XPath` class.
To construct an expression in an application context, you can use `XPathExpressionFactoryBean`.
The following example uses this factory bean:

====
[source,xml]
----
<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">

    <bean id="nameExpression" class="org.springframework.xml.xpath.XPathExpressionFactoryBean">
        <property name="expression" value="/Contacts/Contact/Name"/>
    </bean>

    <bean id="myEndpoint" class="sample.MyXPathClass">
        <constructor-arg ref="nameExpression"/>
    </bean>

</beans>
----
====

The preceding expression does not use namespaces, but we could set those by using the `namespaces` property of the factory bean.
The expression can be used in the code as follows:

====
[source,java]
----
package sample;

public class MyXPathClass {

    private final XPathExpression nameExpression;

    public MyXPathClass(XPathExpression nameExpression) {
        this.nameExpression = nameExpression;
    }

    public void doXPath(Document document) {
        String name = nameExpression.evaluateAsString(document.getDocumentElement());
        System.out.println("Name: " + name);
    }

}
----
====

For a more flexible approach, you can use a `NodeMapper`, which is similar to the `RowMapper` in Spring's JDBC support.
The following example shows how to use it:

====
[source,java]
----
package sample;

public class MyXPathClass  {

   private final XPathExpression contactExpression;

   public MyXPathClass(XPathExpression contactExpression) {
      this.contactExpression = contactExpression;
   }

   public void doXPath(Document document) {
      List contacts = contactExpression.evaluate(document,
        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());
           }
        });
      PlainText Section qName; // do something with the list of Contact objects
   }
}
----
====

Similar to mapping rows in Spring JDBC's `RowMapper`, each result node is mapped by using an anonymous inner class.
In this case, we create a `Contact` object, which we use later on.

[[xpath-template]]
=== `XPathOperations`

The `XPathExpression` lets you evaluate only a single, pre-compiled expression.
A more flexible, though slower, alternative is the `XPathOperations`.
This class follows the common template pattern used throughout Spring (`JdbcTemplate`, `JmsTemplate`, and others).
The following listing shows an example:

====
[source,java,subs="verbatim,quotes"]
----
package sample;

public class MyXPathClass {

    private XPathOperations template = new Jaxp13XPathTemplate();

    public void doXPath(Source source) {
        String name = template.evaluateAsString("/Contacts/Contact/Name", request);
        _// do something with name_
    }

}
----
====

[[logging]]
== Message Logging and Tracing

When developing or debugging a web service, it can be quite useful to look at the content of a (SOAP) message when it arrives, or before it is sent.
Spring-WS offer this functionality, through the standard Commons Logging interface.

To log all server-side messages, set the `org.springframework.ws.server.MessageTracing` logger level to `DEBUG` or `TRACE`.
On the `DEBUG` level, only the payload root element is logged.
On the `TRACE` level, the entire message content is logged.
If you want to log only sent messages, use the `org.springframework.ws.server.MessageTracing.sent` logger.
Similarly, you can use `org.springframework.ws.server.MessageTracing.received` to log only received messages.

On the client-side, similar loggers exist: `org.springframework.ws.client.MessageTracing.sent` and `org.springframework.ws.client.MessageTracing.received`.

The following example of a `log4j2.properties` configuration file logs the full content of sent messages on the client side and only the payload root element for client-side received messages.
On the server-side, the payload root is logged for both sent and received messages:

====
[source]
----
appender.console.name=STDOUT
appender.console.type=Console
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=%-5p [%c{3}] %m%n

rootLogger=DEBUG,STDOUT
logger.org.springframework.ws.client.MessageTracing.sent=TRACE
logger.org.springframework.ws.client.MessageTracing.received=DEBUG
logger.org.springframework.ws.server.MessageTracing=DEBUG

----
====

With this configuration, a typical output is:

====
----
TRACE [client.MessageTracing.sent] Sent request [<SOAP-ENV:Envelope xmlns:SOAP-ENV="...
DEBUG [server.MessageTracing.received] Received request [SaajSoapMessage {http://example.com}request] ...
DEBUG [server.MessageTracing.sent] Sent response [SaajSoapMessage {http://example.com}response] ...
DEBUG [client.MessageTracing.received] Received response [SaajSoapMessage {http://example.com}response] ...
----
====
