In the current age of Service Oriented Architectures, more and more people use web services to 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 that contain all the data necessary to process the request. Conceptually, XML-based web services are better compared to message queues than to remoting solutions. Overall, XML should be considered the platform-neutral representation of data, the *common language* of SOA. When developing or using web services, the focus should be on this XML and not on Java.
Spring Web Services focuses on creating these document-driven web services. Spring Web Services facilitates contract-first SOAP service development, allowing for the creation of flexible web services by using one of the many ways to manipulate XML payloads. Spring-WS provides a powerful [message dispatching framework](#server), a [WS-Security](#security) solution that integrates with your existing application security solution, and a [Client-side API](#client) that follows the familiar Spring template pattern.
# [](#_i_introduction)I. Introduction
# I. Introduction
This first part of the reference documentation [is an overview](#what-is-spring-ws) of Spring Web Services and the underlying concepts. Spring-WS is then introduced, and [the concepts](#why-contract-first) behind contract-first web service development are explained.
## [](#what-is-spring-ws)1. What is Spring Web Services?
## 1. What is Spring Web Services?
### [](#_introduction)1.1. Introduction
### 1.1. Introduction
Spring Web Services (Spring-WS) is a product of the Spring community and is 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 by 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.
...
...
@@ -32,35 +32,35 @@ People use Spring-WS for many reasons, but most are drawn to it after finding al
You can distribute incoming XML requests to any object, depending on message payload, SOAP Action header, or an XPath expression.
#### [](#features-xml-api-support)1.1.2. XML API support
#### 1.1.2. XML API support
Incoming XML messages can be handled not only with standard JAXP APIs such as DOM, SAX, and StAX, but also with JDOM, dom4j, XOM, or even marshalling technologies.
#### [](#features-flexible-xml-marshalling)1.1.3. Flexible XML Marshalling
#### 1.1.3. Flexible XML Marshalling
Spring Web Services builds on the Object/XML Mapping module in the Spring Framework, which supports JAXB 1 and 2, Castor, XMLBeans, JiBX, and XStream.
#### [](#features-reusing-your-spring-expertise)1.1.4. Reusing Your Spring expertise
#### 1.1.4. Reusing Your Spring expertise
Spring-WS uses Spring application contexts for all configuration, which should help Spring developers get up-to-speed quickly. Also, the architecture of Spring-WS resembles that of Spring-MVC.
#### [](#features-support-for-ws-security)1.1.5. Support for WS-Security
#### 1.1.5. Support for WS-Security
WS-Security lets you sign SOAP messages, encrypt and decrypt them, or authenticate against them.
#### [](#features-integration-with-spring-security)1.1.6. Integration with Spring Security
#### 1.1.6. Integration with Spring Security
The WS-Security implementation of Spring Web Services provides integration with Spring Security. This means you can use your existing Spring Security configuration for your SOAP service as well.
When creating web services, there are two development styles: contract-last and contract-first. When you use a contract-last approach, you start with the Java code and let the web service contract (in WSDL — see sidebar) be generated from that. When using contract-first, you start with the WSDL contract and use Java to implement the contract.
...
...
@@ -102,14 +102,14 @@ WSDL stands for Web Service Description Language. A WSDL file is an XML document
Spring-WS supports only the contract-first development style, and this section explains why.
Similar to the field of ORM, where we have an [Object/Relational impedance mismatch](https://en.wikipedia.org/wiki/Object-Relational_impedance_mismatch), converting Java objects to XML has a similar problem. At first glance, the O/X mapping problem appears simple: Create an XML element for each Java object to convert all Java properties and fields to sub-elements or attributes. However, things are not as simple as they appear, because there is a fundamental difference between hierarchical languages, such as XML (and especially XSD), and the graph model of Java.
| |Most of the contents in this section were inspired by [[alpine]](#alpine) and [[effective-enterprise-java]](#effective-enterprise-java).|
In Java, the only way to change the behavior of a class is to subclass it to add the new behavior to 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:
...
...
@@ -123,7 +123,7 @@ In Java, the only way to change the behavior of a class is to subclass it to add
This type restricts a XSD string by way of a regular expression, allowing only three upper case letters. If this type is converted to Java, we end up with an ordinary `java.lang.String`. The regular expression is lost in the conversion process, because Java does not allow for these sorts of extensions.
One of the most important goals of a web service is to be interoperable: to support multiple platforms such as Java, .NET, Python, and others. Because all of these languages have different class libraries, you must use some common, cross-language format to communicate between them. That format is XML, which is supported by all of these languages.
...
...
@@ -157,7 +157,7 @@ This problem is also present when working on the client side. Consider the follo
This contract defines a request that takes an `date`, which is a XSD datatype representing a year, month, and day. If we call this service from Java, we probably use either a `java.util.Date` or `java.util.Calendar`. However, both of these classes actually describe times, rather than dates. So, we actually end up sending data that represents the fourth of April 2007 at midnight (`2007-04-04T00:00:00`), which is not the same as `2007-04-04`.
#### [](#_cyclic_graphs)2.1.3. Cyclic Graphs
#### 2.1.3. Cyclic Graphs
Imagine we have the following class structure:
...
...
@@ -215,7 +215,7 @@ This solves the recursion problem but introduces new ones. For one, you cannot u
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.
### [](#_contract_first_versus_contract_last)2.2. Contract-first Versus Contract-last
### 2.2. Contract-first Versus Contract-last
Besides the Object/XML Mapping issues mentioned in the previous section, there are other reasons for preferring a contract-first development style.
...
...
@@ -227,7 +227,7 @@ Besides the Object/XML Mapping issues mentioned in the previous section, there a
As mentioned earlier, the contract-last development style results in your web service contract (WSDL and your XSD) being generated from your Java contract (usually an interface). If you use this approach, you have no guarantee that the contract stays constant over time. Each time you change your Java contract and redeploy it, there might be subsequent changes to the web service contract.
...
...
@@ -237,13 +237,13 @@ When a web service contract changes, users of the contract have to be instructed
For a contract to be useful, it must remain constant for as long as possible. If a contract changes, you have to contact all the users of your service and instruct them to get the new version of the contract.
When a Java object 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, and so on. In the end, half of the objects on the heap in your virtual machine might be converted into XML, which results in slow response times.
When using contract-first, you explicitly describe what XML is sent where, thus making sure that it is exactly what you want.
Defining your schema in a separate file lets you reuse that file in different scenarios. Consider the definition of an `AirportCode` in a file called `airline.xsd`:
...
...
@@ -257,13 +257,13 @@ Defining your schema in a separate file lets you reuse that file in different sc
You can reuse this definition in other schemas, or even WSDL files, by using an `import` statement.
Even though a contract must remain constant for as long as possible, they do need to be changed sometimes. In Java, this typically results in a new Java interface, such as `AirlineService2`, and a (new) implementation of that interface. Of course, the old service must be kept around, because there might be clients who have not yet migrated.
If using contract-first, we can have a looser coupling between contract and implementation. Such a looser coupling lets us implement both versions of the contract in one class. We could, for instance, use an XSLT stylesheet to convert any “old-style” messages to the “new-style” messages.
## [](#tutorial)3. Writing Contract-First Web Services
## 3. Writing Contract-First Web Services
This tutorial shows you how to write [contract-first web services](#why-contract-first) — that is, how to develop web services that start with the XML Schema or WSDL contract first followed by the Java code second. Spring-WS focuses on this development style, and this tutorial should help you get started. Note that the first part of this tutorial contains almost no Spring-WS specific information. It is mostly about XML, XSD, and WSDL. The [second part](#tutorial-creating-project) focuses on implementing this contract with Spring-WS .
...
...
@@ -271,11 +271,11 @@ The most important thing when doing contract-first web service development is to
In this tutorial, we define a web service that is created by a Human Resources department. Clients can send holiday request forms to this service to book a holiday.
### [](#_messages)3.1. Messages
### 3.1. Messages
In this section, we focus on the actual XML messages that are sent to and from the web service. We start out by determining what these messages look like.
#### [](#_holiday)3.1.1. Holiday
#### 3.1.1. Holiday
In the scenario, we have to deal with holiday requests, so it makes sense to determine what a holiday looks like in XML:
...
...
@@ -288,7 +288,7 @@ In the scenario, we have to deal with holiday requests, so it makes sense to det
A holiday consists of a start date and an end date. We have also decided to use the standard [ISO 8601](https://www.cl.cam.ac.uk/~mgk25/iso-time.html) date format for the dates, because that saves a lot of parsing hassle. We have also added a namespace to the element, to make sure our elements can used within other XML documents.
#### [](#_employee)3.1.2. Employee
#### 3.1.2. Employee
There is also the notion of an employee in the scenario. Here is what it looks like in XML:
...
...
@@ -302,7 +302,7 @@ There is also the notion of an employee in the scenario. Here is what it looks l
We have used the same namespace as before. If this `<Employee/>` element could be used in other scenarios, it might make sense to use a different namespace, such as `[http://example.com/employees/schemas](http://example.com/employees/schemas)`.
#### [](#_holidayrequest)3.1.3. HolidayRequest
#### 3.1.3. HolidayRequest
Both the `holiday` element and the `employee` element can be put in a `<HolidayRequest/>`:
...
...
@@ -322,7 +322,7 @@ Both the `holiday` element and the `employee` element can be put in a `<HolidayR
The order of the two elements does not matter: `<Employee/>` could have been the first element. What matters is that all of the data is there. In fact, the data is the only thing that is important: We take a data-driven approach.
### [](#tutorial.xsd)3.2. Data Contract
### 3.2. Data Contract
Now that we have seen some examples of the XML data that we can use, it makes sense to formalize this into a schema. This data contract defines the message format we accept. There are four different ways of defining such a contract for XML:
...
...
@@ -459,7 +459,7 @@ Clearly, we must make sure that the start and end date are really dates. XML Sch
We store this file as `hr.xsd`.
### [](#tutorial-service-contract)3.3. Service Contract
### 3.3. Service Contract
A service contract is generally expressed as a [WSDL](https://www.w3.org/TR/wsdl) file. Note that, in Spring-WS, writing the WSDL by hand is not required. Based on the XSD and some conventions, Spring-WS can create the WSDL for you, as explained in the section entitled [Implementing the Endpoint](#tutorial-implementing-endpoint). The remainder of this section shows how to write WSDL by hand. You may want to skip to [the next section](#tutorial-creating-project).
...
...
@@ -551,7 +551,7 @@ Adding a concrete part is pretty standard. To do so, refer to the abstract part
The preceding listing shows the final WSDL. We describe how to implement the resulting schema and WSDL in the next section.
### [](#tutorial-creating-project)3.4. Creating the project
### 3.4. Creating the project
In this section, we use [Maven](https://maven.apache.org/) to create the initial project structure for us. Doing so is not required but greatly reduces the amount of code we have to write to setup our HolidayService.
...
...
@@ -596,11 +596,11 @@ In addition to the preceding `WEB-INF/web.xml` file, you also need another, Spri
Once you had the project structure created, you can put the schema and the WSDL from the previous section into `'WEB-INF/'` folder.
### [](#tutorial-implementing-endpoint)3.5. Implementing the Endpoint
### 3.5. Implementing the Endpoint
In Spring-WS, you implement endpoints to handle incoming XML messages. An endpoint is typically created by annotating a class with the `@Endpoint` annotation. In this endpoint class, you can create one or more methods that handle incoming request. The method signatures can be quite flexible. You can include almost any sort of parameter type related to the incoming XML message, as we explain later in this chapter.
#### [](#_handling_the_xml_message)3.5.1. Handling the XML Message
#### 3.5.1. Handling the XML Message
In this sample application, we use [JDom 2](http://www.jdom.org/) to handle the XML message. We also use [XPath](https://www.w3.org/TR/xpath20/), because it lets us select particular parts of the XML JDOM tree without requiring strict schema conformance.
...
...
@@ -724,7 +724,7 @@ Here is how we would configure these classes in our `spring-ws-servlet.xml` Spri
</beans>
```
#### [](#_routing_the_message_to_the_endpoint)3.5.2. Routing the Message to the Endpoint
#### 3.5.2. Routing the Message to the Endpoint
As part of writing the endpoint, we also used the `@PayloadRoot` annotation to indicate which sort of messages can be handled by the `handleHolidayRequest` method. In Spring-WS, this process is the responsibility of an `EndpointMapping`. Here, we route messages based on their content by using a `PayloadRootAnnotationMethodEndpointMapping`. The following listing shows the annotation we used earlier:
...
...
@@ -736,7 +736,7 @@ The annotation shown in the preceding example basically means that whenever an X
There are also other ways to map endpoints to XML messages, which is described in [the next chapter](#common).
#### [](#_providing_the_service_and_stub_implementation)3.5.3. Providing the Service and Stub implementation
#### 3.5.3. Providing the Service and Stub implementation
Now that we have the endpoint, we need `HumanResourceService` and its implementation for use by `HolidayEndpoint`. The following listing shows the `HumanResourceService` interface:
...
...
@@ -770,7 +770,7 @@ public class StubHumanResourceService implements HumanResourceService {
|**1**|The `StubHumanResourceService` is annotated with `@Service`. This marks the class as a business facade, which makes this a candidate for injection by `@Autowired` in `HolidayEndpoint`.|
### [](#tutorial-publishing-wsdl)3.6. Publishing the WSDL
### 3.6. Publishing the WSDL
Finally, we need to publish the WSDL. As stated in [Service Contract](#tutorial-service-contract), we do not need to write a WSDL ourselves. Spring-WS can generate one based on some conventions. Here is how we define the generation:
...
...
@@ -803,19 +803,19 @@ You can create a WAR file by using `mvn install`. If you deploy the application
That concludes this tutorial. The tutorial code can be found in the full distribution of Spring-WS. If you wish to continue, look at the echo sample application that is part of the distribution. After that, look at the airline sample, which is a bit more complicated, because it uses JAXB, WS-Security, Hibernate, and a transactional service layer. Finally, you can read the rest of the reference documentation.
# [](#_ii_reference)II. Reference
# II. Reference
This part of the reference documentation details the various components that comprise Spring Web Services. This includes [a chapter](#common) that discusses the parts common to both client- and server-side WS, a chapter devoted to the specifics of [writing server-side web services](#server), a chapter about using web services on [the client-side](#client), and a chapter on using [WS-Security](#security).
## [](#common)4. Shared components
## 4. 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)4.1. Web Service Messages
### 4.1. Web Service Messages
This section describes the messages and message factories that Spring-WS uses.
One of the core interfaces of Spring Web Services 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:
...
...
@@ -830,15 +830,15 @@ One of the core interfaces of Spring Web Services is the `WebServiceMessage`. Th
In addition to reading from and writing to the payload, a web service message can write itself to an output stream.
#### [](#soap-message)4.1.2. `SoapMessage`
#### 4.1.2. `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`.
Concrete message implementations are created by a `WebServiceMessageFactory`. This factory can create an empty message or read a message from an input stream. There are two concrete implementations of `WebServiceMessageFactory`. One is based on SAAJ, the SOAP with Attachments API for Java. The other is based on Axis 2’s AXIOM (AXis Object Model).
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:
...
...
@@ -859,7 +859,7 @@ Additionally, Java SE 6 includes SAAJ 1.3. You can wire up a `SaajSoapMessageFac
| |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. In that case, the `AxiomSoapMessageFactory` might be more applicable.|
The `AxiomSoapMessageFactory` uses the AXis 2 Object Model (AXIOM) to create `SoapMessage` 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.
...
...
@@ -879,7 +879,7 @@ Full streaming for AXIOM is used when a handler method returns a JAXB2-supported
For more information about full streaming, see the class-level Javadoc for `StreamingWebServiceMessage` and `StreamingPayload`.
##### [](#soap_11_or_12)SOAP 1.1 or 1.2
##### SOAP 1.1 or 1.2
Both the `SaajSoapMessageFactory` and the `AxiomSoapMessageFactory` have 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:
...
...
@@ -906,13 +906,13 @@ In the preceding example, we define a `SaajSoapMessageFactory` that accepts only
| |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.<br/><br/>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.|
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 Web Services, 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 [`WebServiceTemplate`](#client-web-service-template). 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)4.2. `TransportContext`
### 4.2. `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.
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:
...
...
@@ -1007,7 +1007,7 @@ public class MyXPathClass {
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)4.3.2. `XPathTemplate`
#### 4.3.2. `XPathTemplate`
The `XPathExpression` lets you evaluate only a single, pre-compiled expression. A more flexible, though slower, alternative is the `XpathTemplate`. This class follows the common template pattern used throughout Spring (`JdbcTemplate`, `JmsTemplate`, and others). The following listing shows an example:
...
...
@@ -1026,7 +1026,7 @@ public class MyXPathClass {
}
```
### [](#logging)4.4. Message Logging and Tracing
### 4.4. 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 Web Services offer this functionality, through the standard Commons Logging interface.
...
...
@@ -1060,7 +1060,7 @@ DEBUG [server.MessageTracing.sent] Sent response [SaajSoapMessage {http://exampl
DEBUG [client.MessageTracing.received] Received response [SaajSoapMessage {http://example.com}response] ...
```
## [](#server)5. Creating a Web service with Spring-WS
## 5. Creating a Web service with Spring-WS
Spring-WS’s server-side support is designed around a `MessageDispatcher` that dispatches incoming messages to endpoints, with configurable endpoint mappings, response generation, and endpoint interception. Endpoints are typically annotated with the `@Endpoint` annotation and have one or more handling methods. These methods handle incoming XML request messages by inspecting parts of the message (typically the payload) and create some sort of response. You can annotate the method with another annotation, typically `@PayloadRoot`, to indicate what sort of messages it can handle.
...
...
@@ -1074,7 +1074,7 @@ Spring-WS’s XML handling is extremely flexible. An endpoint can choose from a
* Marshalling techniques (JAXB, Castor, XMLBeans, JiBX, or XStream): To convert the XML to objects and vice-versa
### [](#_the_messagedispatcher)5.1. The `MessageDispatcher`
### 5.1. The `MessageDispatcher`
The server-side of Spring-WS is designed around a central class that dispatches incoming XML messages to endpoints. Spring-WS’s `MessageDispatcher` is extremely flexible, letting you 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 `DispatcherServlet`, the
“Front Controller” used in Spring Web MVC.
...
...
@@ -1097,11 +1097,11 @@ The `MessageDispatcher` has several properties for setting endpoint adapters, [m
The message dispatcher operates on a [message context](#message-context) and not on a transport-specific input stream and output stream. As a result, transport-specific requests need to read into a `MessageContext`. For HTTP, this is done with a `WebServiceMessageReceiverHandlerAdapter` (which is a Spring Web `HandlerInterceptor`) so that the `MessageDispatcher` can be wired in a standard `DispatcherServlet`. There is a more convenient way to do this, however, which is shown in [`MessageDispatcherServlet`](#message-dispatcher-servlet).
### [](#_transports)5.2. Transports
### 5.2. Transports
Spring Web Services supports multiple transport protocols. The most common is the HTTP transport, for which a custom servlet is supplied, but you can also send messages over JMS and even email.
The `MessageDispatcherServlet` is a standard `Servlet` that conveniently extends from the standard Spring Web `DispatcherServlet` and wraps a `MessageDispatcher`. As a result, it combines the attributes of these into one. As a `MessageDispatcher`, it follows the same request handling flow as described in the previous section. As a servlet, the `MessageDispatcherServlet` is configured in the `web.xml` of your web application. Requests that you want the `MessageDispatcherServlet` to handle must be mapped by a URL mapping in the same `web.xml` file. This is standard Java EE servlet configuration. The following example shows such a `MessageDispatcherServlet` declaration and mapping:
...
...
@@ -1146,7 +1146,7 @@ public class MyServletInitializer
In the preceding example, we tell Spring that endpoint bean definitions can be found in the `MyEndpointConfig` class (which is a `@Configuration` class). Other bean definitions (typically services, repositories, and so on) can be found in the `MyRootConfig` class. By default, the `AbstractAnnotationConfigMessageDispatcherServletInitializer` maps the servlet to two patterns: `/services` and `*.wsdl`, though you can change this by overriding the `getServletMappings()` method. For more details on the programmatic configuration of the `MessageDispatcherServlet`, refer to the Javadoc of [`AbstractMessageDispatcherServletInitializer`](https://docs.spring.io/spring-ws/docs/current/org/springframework/ws/transport/http/support/AbstractMessageDispatcherServletInitializer.html) and [`AbstractAnnotationConfigMessageDispatcherServletInitializer`](https://docs.spring.io/spring-ws/docs/current/org/springframework/ws/transport/http/support/AbstractAnnotationConfigMessageDispatcherServletInitializer.html).
The `MessageDispatcherServlet` automatically detects any `WsdlDefinition` beans defined in its Spring container. All the `WsdlDefinition` detected beans are also exposed through a `WsdlDefinitionHandlerAdapter`. This is a convenient way to expose your WSDL to clients by defining some beans.
...
...
@@ -1239,7 +1239,7 @@ To use multiple schemas, either by includes or imports, you can put Commons XMLS
Therefore, you should use `<dynamic-wsdl>` only during the development stages of your project. We recommend using your browser to download the generated WSDL, store it in the project, and expose it with `<static-wsdl>`. This is the only way to be really sure that the WSDL does not change over time.
#### [](#_wiring_up_spring_ws_in_a_dispatcherservlet)5.2.2. Wiring up Spring-WS in a `DispatcherServlet`
#### 5.2.2. Wiring up Spring-WS in a `DispatcherServlet`
As an alternative to the `MessageDispatcherServlet`, you can wire up a `MessageDispatcher` in a standard, Spring-Web MVC `DispatcherServlet`. By default, the `DispatcherServlet` can delegate only to `Controllers`, but we can instruct it to delegate to a `MessageDispatcher` by adding a `WebServiceMessageReceiverHandlerAdapter` to the servlet’s web application context:
...
...
@@ -1292,7 +1292,7 @@ In a similar fashion, you can wire a `WsdlDefinitionHandlerAdapter` to make sure
</beans>
```
#### [](#_jms_transport)5.2.3. JMS transport
#### 5.2.3. JMS transport
Spring Web Services supports server-side JMS handling through the JMS functionality provided in the Spring framework. Spring Web Services provides the `WebServiceMessageListener` to plug in to a `MessageListenerContainer`. This message listener requires a `WebServiceMessageFactory` and `MessageDispatcher` to operate. The following configuration example shows this:
...
...
@@ -1329,7 +1329,7 @@ Spring Web Services supports server-side JMS handling through the JMS functional
</beans>
```
#### [](#_email_transport)5.2.4. Email Transport
#### 5.2.4. Email Transport
In addition to HTTP and JMS, Spring Web Services also provides server-side email handling. This functionality is provided through the `MailMessageReceiver` class. This class monitors a POP3 or IMAP folder, converts the email to a `WebServiceMessage`, and sends any response by using SMTP. You can configure the host names through the `storeUri`, which indicates the mail folder to monitor for requests (typically a POP3 or IMAP folder), and a `transportUri`, which indicates the server to use for sending responses (typically an SMTP server).
...
...
@@ -1370,7 +1370,7 @@ The following piece of configuration shows how to use the server-side email supp
</beans>
```
#### [](#_embedded_http_server_transport)5.2.5. Embedded HTTP Server transport
#### 5.2.5. Embedded HTTP Server transport
Spring Web Services provides a transport based on Sun’s JRE 1.6 [HTTP server](http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/index.html). The embedded HTTP Server is a standalone server that is simple to configure. It offers a lighter alternative to conventional servlet containers.
...
...
@@ -1417,7 +1417,7 @@ The following snippet shows a configuration example of the HTTP server transport
For more information on the `SimpleHttpServerFactoryBean`, see the [Javadoc](http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/remoting/support/SimpleHttpServerFactoryBean.html).
#### [](#_xmpp_transport)5.2.6. XMPP transport
#### 5.2.6. XMPP transport
Spring Web Services 2.0 introduced support for XMPP, otherwise known as Jabber. The support is based on the [Smack](https://www.igniterealtime.org/projects/smack/index.jsp) library.
...
...
@@ -1456,11 +1456,11 @@ The following example shows how to set up the server-side XMPP components:
</beans>
```
#### [](#_mtom)5.2.7. MTOM
#### 5.2.7. MTOM
[MTOM](https://en.wikipedia.org/wiki/Message_Transmission_Optimization_Mechanism) is the mechanism for sending binary data to and from Web Services. You can look at how to implement this with Spring WS through the [MTOM sample](https://github.com/spring-projects/spring-ws-samples/tree/main/mtom).
### [](#server-endpoints)5.3. Endpoints
### 5.3. Endpoints
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. An endpoint interprets the XML request message and uses that input to (typically) invoke a method on the business service. The result of that service invocation is represented as a response message. Spring-WS has a wide variety of endpoints and uses various ways to handle the XML message and to create a response.
...
...
@@ -1572,7 +1572,7 @@ In the next couple of sections, a more elaborate description of the `@Endpoint`
Note that all abstract base classes provided in Spring-WS are thread safe, unless otherwise indicated in the class-level Javadoc.
For an endpoint to actually handle incoming XML messages, it needs to have one or more handling methods. Handling methods can take wide range of parameters and return types. However, they typically have one parameter that contains the message payload, and they return the payload of the response message (if any). This section covers which parameter and return types are supported.
...
...
@@ -1590,7 +1590,7 @@ public void order(@RequestPayload Element orderElement) {
The `order` method takes an `Element` (annotated with `@RequestPayload`) as a parameter. This means that the payload of the message is passed on this method as a DOM element. The method has a `void` return type, indicating that no response message is sent.
The handling method typically has one or more parameters that refer to various parts of the incoming XML message. Most commonly, the handling method has a single parameter that maps to the payload of the message, but it can also map to other parts of the request message, such as a SOAP header. This section describes the parameters you can use in your handling method signatures.
...
...
@@ -1632,7 +1632,7 @@ public void handle(@RequestPayload MyJaxb2Object requestObject, @RequestPayload
As you can see, there are a lot of possibilities when it comes to defining how to handle method signatures. You can even extend this mechanism to support your own parameter types. See the Javadoc of [`DefaultMethodEndpointAdapter`](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.html) and [`MethodArgumentResolver`](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/server/endpoint/adapter/method/MethodArgumentResolver.html) to see how.
###### [](#server-xpath-param)`@XPathParam`
###### `@XPathParam`
One parameter type needs some extra explanation: `@XPathParam`. The idea here is that you annotate one or more method parameters with an XPath expression and that each such annotated parameter is bound to the evaluation of the expression. The following example shows how to do so:
...
...
@@ -1681,7 +1681,7 @@ By using the `@XPathParam`, you can bind to all the data types supported by XPat
In addition to this list, you can use any type that can be converted from a `String` by a Spring [conversion service](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#core-convert-ConversionService-API).
To send a response message, the handling needs to specify a return type. If no response message is required, the method can declare a `void` return type. Most commonly, the return type is used to create the payload of the response message. However, you can also map to other parts of the response message. This section describes the return types you can use in your handling method signatures.
...
...
@@ -1702,7 +1702,7 @@ The following table describes the supported return types. It shows the supported
There are a lot of possibilities when it comes to defining handling method signatures. It is even possible to extend this mechanism to support your own parameter types. See the class-level Javadoc of [`DefaultMethodEndpointAdapter`](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.html) and [`MethodReturnValueHandler`](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/server/endpoint/adapter/method/MethodReturnValueHandler.html) to see how.
The endpoint mapping is responsible for mapping incoming messages to appropriate endpoints. Some endpoint mappings are enabled by default — for example, the `PayloadRootAnnotationMethodEndpointMapping` or the `SoapActionAnnotationMethodEndpointMapping`. However, we first need to examine the general concept of an `EndpointMapping`.
...
...
@@ -1720,7 +1720,7 @@ The `PayloadRootAnnotationMethodEndpointMapping` uses the `@PayloadRoot` annotat
Alternatively, the `SoapActionAnnotationMethodEndpointMapping` uses the `@SoapAction` annotation to mark methods with a particular SOAP Action. Whenever a message comes in with this `SOAPAction` header, the method is invoked.
WS-Addressing specifies a transport-neutral routing mechanism. It is based on the `To` and `Action` SOAP headers, which indicate the destination and intent of the SOAP message, respectively. Additionally, WS-Addressing lets you define a return address (for normal messages and for faults) and a unique message identifier, which can be used for correlation. For more information on WS-Addressing, see [https://en.wikipedia.org/wiki/WS-Addressing](https://en.wikipedia.org/wiki/WS-Addressing). The following example shows a WS-Addressing message:
...
...
@@ -1747,7 +1747,7 @@ In the preceding example, the destination is set to `[http://example/com/fabrika
In Spring Web Services, WS-Addressing is implemented as an endpoint mapping. By using this mapping, you associate WS-Addressing actions with endpoints, similar to the `SoapActionAnnotationMethodEndpointMapping` described earlier.
The `AnnotationActionEndpointMapping` is similar to the `SoapActionAnnotationMethodEndpointMapping` but uses WS-Addressing headers instead of the SOAP Action transport header.
...
...
@@ -1788,7 +1788,7 @@ In addition to the `@Action` annotation, you can annotate the class with the `@A
Finally, there is the `messageSenders` property, which is required for sending response messages to non-anonymous, out-of-bound addresses. You can set `MessageSender` implementations in this property, the same as you would on the `WebServiceTemplate`. See [URIs and Transports](#client-transports).
#### [](#server-endpoint-interceptor)5.4.2. Intercepting Requests — the `EndpointInterceptor` Interface
#### 5.4.2. Intercepting Requests — the `EndpointInterceptor` Interface
The endpoint mapping mechanism has the notion of endpoint interceptors. These can be extremely useful when you want to apply specific functionality to certain requests — for example, dealing with security-related SOAP headers or the logging of request and response message.
...
...
@@ -1832,7 +1832,7 @@ The `handleRequest(..)` method on the interceptor returns a boolean value. You c
There are a number of standard `EndpointInterceptor` implementations that you can use in your Web service. Additionally, there is the `XwsSecurityInterceptor`, which is described in [`XwsSecurityInterceptor`](#security-xws-security-interceptor).
##### [](#_payloadlogginginterceptor_and_soapenvelopelogginginterceptor)`PayloadLoggingInterceptor` and `SoapEnvelopeLoggingInterceptor`
##### `PayloadLoggingInterceptor` and `SoapEnvelopeLoggingInterceptor`
When developing a web service, it can be useful to log the incoming and outgoing XML messages. Spring WS facilitates this with the `PayloadLoggingInterceptor` and `SoapEnvelopeLoggingInterceptor` classes. The former logs only the payload of the message to the Commons Logging Log. The latter logs the entire SOAP envelope, including SOAP headers. The following example shows how to define the `PayloadLoggingInterceptor` in an endpoint mapping:
...
...
@@ -1846,7 +1846,7 @@ Both of these interceptors have two properties, `logRequest` and `logResponse`,
You could use the `WsConfigurerAdapter` approach, as described earlier, for the `PayloadLoggingInterceptor` as well.
One of the benefits of using a contract-first development style is that we can use the schema to validate incoming and outgoing XML messages. Spring-WS facilitates this with the `PayloadValidatingInterceptor`. This interceptor requires a reference to one or more W3C XML or RELAX NG schemas and can be set to validate requests, responses, or both.
...
...
@@ -1866,7 +1866,7 @@ The following example uses the `PayloadValidatingInterceptor`. In this example,
Of course, you could use the `WsConfigurerAdapter` approach, as described earlier, for the `PayloadValidatingInterceptor` as well.
To transform the payload to another XML format, Spring Web Services offers the `PayloadTransformingInterceptor`. This endpoint interceptor is based on XSLT style sheets and is especially useful when supporting multiple versions of a web service, because you can transform the older message format to the newer format. The following example uses the `PayloadTransformingInterceptor`:
...
...
@@ -1882,7 +1882,7 @@ In the preceding example, we transform requests by using `/WEB-INF/oldRequests.x
You could use the `WsConfigurerAdapter` approach, as described earlier, for the `PayloadTransformingInterceptor` as well.
Spring-WS provides `EndpointExceptionResolvers` to ease the pain of unexpected exceptions occurring while your message is being processed by an endpoint that matched the request. Endpoint exception resolvers somewhat resemble the exception mappings that can be defined in the web application descriptor `web.xml`. However, they provide a more flexible way to handle exceptions. They provide information about what endpoint was invoked when the exception was thrown. Furthermore, a programmatic way of handling exceptions gives you many more options for how to respond appropriately. Rather than expose the innards of your application by giving an exception and stack trace, you can handle the exception any way you want — for example, by returning a SOAP fault with a specific fault code and string.
...
...
@@ -1890,7 +1890,7 @@ Endpoint exception resolvers are automatically picked up by the `MessageDispatch
Besides implementing the `EndpointExceptionResolver` interface, which is only a matter of implementing the `resolveException(MessageContext, endpoint, Exception)` method, you may also use one of the provided implementations. The simplest implementation is the `SimpleSoapExceptionResolver`, which creates a SOAP 1.1 Server or SOAP 1.2 Receiver fault and uses the exception message as the fault string. The `SimpleSoapExceptionResolver` is the default, but it can be overridden by explicitly adding another resolver.
The `SoapFaultMappingExceptionResolver` is a more sophisticated implementation. This resolver lets you take the class name of any exception that might be thrown and map it to a SOAP Fault:
...
...
@@ -1923,7 +1923,7 @@ The key values and default endpoint use a format of `faultCode,faultString,local
If any other exception occurs, it returns the default fault: a server-side fault with the exception message as the fault string.
#### [](#_using_soapfaultannotationexceptionresolver)5.5.2. Using `SoapFaultAnnotationExceptionResolver`
#### 5.5.2. Using `SoapFaultAnnotationExceptionResolver`
You can also annotate exception classes with the `@SoapFault` annotation, to indicate the SOAP fault that should be returned whenever that exception is thrown. For these annotations to be picked up, you need to add the `SoapFaultAnnotationExceptionResolver` to your application context. The elements of the annotation include a fault code enumeration, fault string or reason, and language. The following example shows such an exception:
...
...
@@ -1955,7 +1955,7 @@ Whenever the `MyBusinessException` is thrown with the constructor string `"Oops!
When it comes to testing your Web service endpoints, you have two possible approaches:
...
...
@@ -1967,7 +1967,7 @@ When it comes to testing your Web service endpoints, you have two possible appro
The first approach can easily be accomplished with mocking frameworks such as EasyMock, JMock, and others. The next section focuses on writing integration tests, using the test features introduced in Spring Web Services 2.0.
Spring Web Services 2.0 introduced support for creating endpoint integration tests. In this context, an endpoint is a class that handles (SOAP) messages (see [Endpoints](#server-endpoints)).
...
...
@@ -2068,7 +2068,7 @@ public class CustomerEndpointIntegrationTest {
|**4**| In a `@Before` method, we create a `MockWebServiceClient` by using the `createClient` factory method. |
|**5**|We send a request by calling `sendRequest()` with a `withPayload()``RequestCreator` provided by the statically imported `RequestCreators` (see [Using `RequestCreator` and `RequestCreators`](#server-test-request-creator)).<br/><br/>We also set up response expectations by calling `andExpect()` with a `payload()``ResponseMatcher` provided by the statically imported `ResponseMatchers` (see [Using `ResponseMatcher` and `ResponseMatchers`](#server-test-response-matcher)).<br/><br/>This part of the test might look a bit confusing, but the code completion features of your IDE are of great help. After typing `sendRequest(`, your IDE can provide you with a list of possible request creating strategies, provided you statically imported `RequestCreators`. The same applies to `andExpect()`, provided you statically imported `ResponseMatchers`.|
#### [](#server-test-request-creator)5.6.2. Using `RequestCreator` and `RequestCreators`
#### 5.6.2. Using `RequestCreator` and `RequestCreators`
Initially, the `MockWebServiceClient` needs to create a request message for the endpoint to consume. The client uses the `RequestCreator` strategy interface for this purpose:
...
...
@@ -2083,7 +2083,7 @@ public interface RequestCreator {
You can write your own implementations of this interface, creating a request message by using the message factory, but you certainly do not have to. The `RequestCreators` class provides a way to create a `RequestCreator` based on a given payload in the `withPayload()` method. You typically statically import `RequestCreators`.
#### [](#server-test-response-matcher)5.6.3. Using `ResponseMatcher` and `ResponseMatchers`
#### 5.6.3. Using `ResponseMatcher` and `ResponseMatchers`
When the request message has been processed by the endpoint and a response has been received, the `MockWebServiceClient` can verify whether this response message meets certain expectations. The client uses the `ResponseMatcher` strategy interface for this purpose:
For more information on the response matchers provided by `ResponseMatchers`, see the [Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/server/ResponseMatchers.html).
## [](#client)6. Using Spring Web Services on the Client
## 6. Using Spring Web Services on the Client
Spring-WS provides a client-side Web service API that allows for consistent, XML-driven access to web services. It also caters to the use of marshallers and unmarshallers so that your service-tier code can deal exclusively with Java objects.
...
...
@@ -2132,19 +2132,19 @@ The `org.springframework.ws.client.core` package provides the core functionality
* Allowing for multiple transport options
### [](#_using_the_client_side_api)6.1. Using the Client-side API
### 6.1. Using the Client-side API
This section describs how to use the client-side API. For how to use the server-side API, see [Creating a Web service with Spring-WS](#server).
The `WebServiceTemplate` is the core class for client-side web service access in Spring-WS. It contains methods for sending `Source` objects and receiving response messages as either `Source` or `Result`. Additionally, it can marshal objects to XML before sending them across a transport and unmarshal any response XML into an object again.
##### [](#client-transports)URIs and Transports
##### URIs and Transports
The `WebServiceTemplate` class uses an URI as the message destination. You can either set a `defaultUri` property on the template itself or explicitly supply a URI when calling a method on the template. The URI is resolved into a `WebServiceMessageSender`, which is responsible for sending the XML message across a transport layer. You can set one or more message senders by using the `messageSender` or `messageSenders` properties of the `WebServiceTemplate` class.
###### [](#_http_transports)HTTP transports
###### HTTP transports
There are two implementations of the `WebServiceMessageSender` interface for sending messages over HTTP. The default implementation is the `HttpUrlConnectionMessageSender`, which uses the facilities provided by Java itself. The alternative is the `HttpComponentsMessageSender`, which uses the [Apache HttpComponents HttpClient](https://hc.apache.org/httpcomponents-client-ga). Use the latter if you need more advanced and easy-to-use functionality (such as authentication, HTTP connection pooling, and so forth).
...
...
@@ -2183,7 +2183,7 @@ The following example shows how to override the default configuration and how to
</bean>
```
###### [](#_jms_transport_2)JMS transport
###### JMS transport
For sending messages over JMS, Spring Web Services provides `JmsMessageSender`. This class uses the facilities of the Spring framework to transform the `WebServiceMessage` into a JMS `Message`, send it on its way on a `Queue` or `Topic`, and receive a response (if any).
...
...
@@ -2215,7 +2215,7 @@ The following example shows how to use the JMS transport in combination with an
</beans>
```
###### [](#_email_transport_2)Email Transport
###### Email Transport
Spring Web Services also provides an email transport, which you can use to send web service messages over SMTP and retrieve them over either POP3 or IMAP. The client-side email functionality is contained in the `MailMessageSender` class. This class creates an email message from the request `WebServiceMessage` and sends it over SMTP. It then waits for a response message to arrive at the incoming POP3 or IMAP server.
...
...
@@ -2243,7 +2243,7 @@ The following example shows how to use the email transport:
</beans>
```
###### [](#_xmpp_transport_2)XMPP Transport
###### XMPP Transport
Spring Web Services 2.0 introduced an XMPP (Jabber) transport, which you can use to send and receive web service messages over XMPP. The client-side XMPP functionality is contained in the `XmppMessageSender` class. This class creates an XMPP message from the request `WebServiceMessage` and sends it over XMPP. It then listens for a response message to arrive.
...
...
@@ -2275,11 +2275,11 @@ The following example shows how to use the XMPP transport:
</beans>
```
##### [](#_message_factories)Message factories
##### Message factories
In addition to a message sender, the `WebServiceTemplate` requires a web service message factory. There are two message factories for SOAP: `SaajSoapMessageFactory` and `AxiomSoapMessageFactory`. If no message factory is specified (by setting the `messageFactory` property), Spring-WS uses the `SaajSoapMessageFactory` by default.
#### [](#_sending_and_receiving_a_webservicemessage)6.1.2. Sending and Receiving a `WebServiceMessage`
#### 6.1.2. Sending and Receiving a `WebServiceMessage`
The `WebServiceTemplate` contains many convenience methods to send and receive web service messages. There are methods that accept and return a `Source` and those that return a `Result`. Additionally, there are methods that marshal and unmarshal objects to XML. The following example sends a simple XML message to a web service:
...
...
@@ -2335,11 +2335,11 @@ The preceding example uses the `WebServiceTemplate` to send a “Hello, World”
Note that the `WebServiceTemplate` class is thread-safe once configured (assuming that all of its dependencies are also thread-safe, which is the case for all of the dependencies that ship with Spring-WS), so multiple objects can use the same shared `WebServiceTemplate` instance. The `WebServiceTemplate` exposes a zero-argument constructor and `messageFactory` and `messageSender` bean properties that you can use to construct the instance (by using a Spring container or plain Java code). Alternatively, consider deriving from Spring-WS’s `WebServiceGatewaySupport` convenience base class, which exposes convenient bean properties to enable easy configuration. (You do not have to extend this base class. It is provided as a convenience class only.)
#### [](#_sending_and_receiving_pojosmarshalling_and_unmarshalling)6.1.3. Sending and Receiving POJOs — Marshalling and Unmarshalling
#### 6.1.3. Sending and Receiving POJOs — Marshalling and Unmarshalling
To facilitate the sending of plain Java objects, the `WebServiceTemplate` has a number of `send(..)` methods that take an `Object` as an argument for a message’s data content. The method `marshalSendAndReceive(..)` in the `WebServiceTemplate` class delegates the conversion of the request object to XML to a `Marshaller` and the conversion of the response XML to an object to an `Unmarshaller`. (For more information about marshalling and unmarshaller, see [the Spring Framework reference documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#oxm-marshaller-unmarshaller).) By using the marshallers, your application code can focus on the business object that is being sent or received and not be concerned with the details of how it is represented as XML. To use the marshalling functionality, you have to set a marshaller and an unmarshaller with the `marshaller` and `unmarshaller` properties of the `WebServiceTemplate` class.
#### [](#_using_webservicemessagecallback)6.1.4. Using `WebServiceMessageCallback`
#### 6.1.4. Using `WebServiceMessageCallback`
To accommodate setting SOAP headers and other settings on the message, the `WebServiceMessageCallback` interface gives you access to the message after it has been created but before it is sent. The following example demonstrates how to set the SOAP action header on a message that is created by marshalling an object:
...
...
@@ -2358,7 +2358,7 @@ public void marshalWithSoapActionHeader(MyObject o) {
| |Note that you can also use the `org.springframework.ws.soap.client.core.SoapActionCallback` to set the SOAP action header.|
In addition to the [server-side WS-Addressing](#server-ws-addressing) support, Spring Web Services also has support for this specification on the client-side.
...
...
@@ -2370,7 +2370,7 @@ The following example sets the `Action` header to `[http://samples/RequestOrder]
webServiceTemplate.marshalSendAndReceive(o, new ActionCallback("http://samples/RequestOrder"));
```
#### [](#_using_webservicemessageextractor)6.1.5. Using `WebServiceMessageExtractor`
#### 6.1.5. Using `WebServiceMessageExtractor`
The `WebServiceMessageExtractor` interface is a low-level callback interface that you have full control over the process to extract an `Object` from a received `WebServiceMessage`. The `WebServiceTemplate` invokes the `extractData(..)` method on a supplied `WebServiceMessageExtractor` while the underlying connection to the serving resource is still open. The following example shows the `WebServiceMessageExtractor` in action:
...
...
@@ -2391,7 +2391,7 @@ public void marshalWithSoapActionHeader(final Source s) {
When it comes to testing your Web service clients (that is, classes that use the `WebServiceTemplate` to access a Web service), you have two possible approaches:
...
...
@@ -2403,7 +2403,7 @@ When it comes to testing your Web service clients (that is, classes that use the
The first approach can easily be accomplished with mocking frameworks, such as EasyMock, JMock, and others. The next section focuses on writing integration tests, using the test features introduced in Spring Web Services 2.0.
Spring Web Services 2.0 introduced support for creating Web service client integration tests. In this context, a client is a class that uses the `WebServiceTemplate` to access a web service.
...
...
@@ -2516,7 +2516,7 @@ public class CustomerClientIntegrationTest {
|**6**| We call `getCustomerCount()` on the `CustomerClient`, thus using the `WebServiceTemplate`. The template has been set up for “testing mode” by now, so no real (HTTP) connection is made by this method call. We also make some JUnit assertions based on the result of the method call. |
|**7**| We call `verify()` on the `MockWebServiceServer`, verifying that the expected message was actually received. |
#### [](#client-test-request-matcher)6.2.2. Using `RequestMatcher` and `RequestMatchers`
#### 6.2.2. Using `RequestMatcher` and `RequestMatchers`
To verify whether the request message meets certain expectations, the `MockWebServiceServer` uses the `RequestMatcher` strategy interface. The contract defined by this interface is as follows:
For more information on the request matchers provided by `RequestMatchers`, see the [Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/client/RequestMatchers.html).
#### [](#client-test-response-creator)6.2.3. Using `ResponseCreator` and `ResponseCreators`
#### 6.2.3. Using `ResponseCreator` and `ResponseCreators`
When the request message has been verified and meets the defined expectations, the `MockWebServiceServer` creates a response message for the `WebServiceTemplate` to consume. The server uses the `ResponseCreator` strategy interface for this purpose:
...
...
@@ -2582,7 +2582,7 @@ The `ResponseCreators` class provides the following responses:
For more information on the request matchers provided by `RequestMatchers`, see the [Javadoc](https://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/test/client/RequestMatchers.html).
## [](#security)7. Securing Your Web services with Spring-WS
## 7. Securing Your Web services with Spring-WS
This chapter explains how to add WS-Security aspects to your Web services. We focus on the three different areas of WS-Security:
...
...
@@ -2597,7 +2597,7 @@ These three areas are implemented by using the `XwsSecurityInterceptor` or `Wss4
| |Note that WS-Security (especially encryption and signing) requires substantial amounts of memory and can decrease performance. If performance is important to you, you might want to consider not using WS-Security or using HTTP-based security.|
The `XwsSecurityInterceptor` is an `EndpointInterceptor` (see [Intercepting Requests — the `EndpointInterceptor` Interface](#server-endpoint-interceptor)) that is based on SUN’s XML and Web Services Security package (XWSS). This WS-Security implementation is part of the Java Web Services Developer Pack ([Java WSDP](http://java.sun.com/webservices/)).
...
...
@@ -2630,7 +2630,7 @@ The following example that shows how to wire up the `XwsSecurityInterceptor`:
This interceptor is configured by using the `securityPolicy.xml` file on the classpath. It uses two callback handlers that are defined later in the file.
#### [](#keystore)7.1.1. Keystores
#### 7.1.1. Keystores
For most cryptographic operations, you an use the standard `java.security.KeyStore` objects. These operations include certificate verification, message signing, signature verification, and encryption. They exclude username and time-stamp verification. This section aims to give you some background knowledge on keystores and the Java tools that you can use to store keys and certificates in a keystore file. This information is mostly not related to Spring-WS but to the general cryptographic features of Java.
...
...
@@ -2642,11 +2642,11 @@ The `java.security.KeyStore` class represents a storage facility for cryptograph
***Trusted certificates**: These X509 certificates are called a “trusted certificate” because the keystore owner trusts that the public key in the certificates does indeed belong to the owner of the certificate. Within WS-Security, these certificates are used for certificate validation, signature verification, and encryption.
##### [](#_using_keytool)Using `keytool`
##### Using `keytool`
The `keytool` program, a key and certificate management utility, is supplied with your Java Virtual Machine. You can use this tool to create new keystores, add new private keys and certificates to them, and so on. It is beyond the scope of this document to provide a full reference of the `keytool` command, but you can find a reference [here](http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/keytool.html) or by using the `keytool -help` command on the command line.
To easily load a keystore by using Spring configuration, you can use the `KeyStoreFactoryBean`. It has a resource location property, which you can set to point to the path of the keystore to load. A password may be given to check the integrity of the keystore data. If a password is not given, integrity checking is not performed. The following listing configures a `KeyStoreFactoryBean`:
...
...
@@ -2660,7 +2660,7 @@ To easily load a keystore by using Spring configuration, you can use the `KeySto
| |If you do not specify the location property, a new, empty keystore is created, which is most likely not what you want.|
To use the keystores within a `XwsSecurityInterceptor`, you need to define a `KeyStoreCallbackHandler`. This callback has three properties with type `keystore`: (`keyStore`,`trustStore`, and `symmetricStore`). The exact stores used by the handler depend on the cryptographic operations that are to be performed by this handler. For private key operation, the `keyStore` is used. For symmetric key operations, the `symmetricStore` is used. For determining trust relationships, the `trustStore` is used. The following table indicates this:
...
...
@@ -2711,11 +2711,11 @@ If you want to use it to decrypt incoming certificates or sign outgoing messages
The following sections indicate where the `KeyStoreCallbackHandler` can be used and which properties to set for particular cryptographic operations.
#### [](#_authentication)7.1.2. Authentication
#### 7.1.2. Authentication
As stated in the [introduction to this chapter](#security), authentication is the task of determining whether a principal is who they claim to be. Within WS-Security, authentication can take two forms: using a username and password token (using either a plain text password or a password digest) or using a X509 certificate.
##### [](#_plain_text_username_authentication)Plain Text Username Authentication
##### Plain Text Username Authentication
The simplest form of username authentication uses plain text passwords. In this scenario, the SOAP message contains a `UsernameToken` element, which itself contains a `Username` element and a `Password` element which contains the plain text password. Plain text authentication can be compared to the basic authentication provided by HTTP servers.
...
...
@@ -2740,7 +2740,7 @@ If the username token is not present, the `XwsSecurityInterceptor` returns a SOA
###### Using `SimplePasswordValidationCallbackHandler`
The simplest password validation handler is the `SimplePasswordValidationCallbackHandler`. This handler validates passwords against an in-memory `Properties` object, which you can specify byusing the `users` property:
...
...
@@ -2757,7 +2757,7 @@ The simplest password validation handler is the `SimplePasswordValidationCallbac
In this case, we are allowing only the user, "Bert", to log in by using the password, "Ernie".
###### Using `SpringPlainTextPasswordValidationCallbackHandler`
The `SpringPlainTextPasswordValidationCallbackHandler` uses [Spring Security](https://spring.io/projects/spring-security) to authenticate users. It is beyond the scope of this document to describe Spring Security, but it is a full-fledged security framework. You can read more about it in the [Spring Security reference documentation](https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/).
...
...
@@ -2783,7 +2783,7 @@ The `SpringPlainTextPasswordValidationCallbackHandler` requires an `Authenticati
###### Using `JaasPlainTextPasswordValidationCallbackHandler`
The `JaasPlainTextPasswordValidationCallbackHandler` is based on the standard [Java Authentication and Authorization Service](http://java.sun.com/products/jaas/). It is beyond the scope of this document to provide a full introduction into JAAS, but a [good tutorial](http://www.javaworld.com/javaworld/jw-09-2002/jw-0913-jaas.html) is available.
...
...
@@ -2800,7 +2800,7 @@ You can wire up a `JaasPlainTextPasswordValidationCallbackHandler` as follows:
In this case, the callback handler uses the `LoginContext` named `MyLoginModule`. This module should be defined in your `jaas.config` file, as explained in the [tutorial mentioned earlier](http://www.javaworld.com/javaworld/jw-09-2002/jw-0913-jaas.html).
When using password digests, the SOAP message also contains a `UsernameToken` element, which itself contains a `Username` element and a `Password` element. The difference is that the password is not sent as plain text, but as a digest. The recipient compares this digest to the digest he calculated from the known password of the user, and, if they are the same, the user is authenticated. This method is comparable to the digest authentication provided by HTTP servers.
...
...
@@ -2816,11 +2816,11 @@ To require that every incoming message contains a `UsernameToken` element with a
If the username token is not present, the `XwsSecurityInterceptor` returns a SOAP fault to the sender. If it is present, it fires a `PasswordValidationCallback` with a `DigestPasswordRequest` to the registered handlers. Within Spring-WS, two classes handle this particular callback: `SimplePasswordValidationCallbackHandler` and `SpringDigestPasswordValidationCallbackHandler`.
###### Using `SimplePasswordValidationCallbackHandler`
The `SimplePasswordValidationCallbackHandler` can handle both plain text passwords as well as password digests. It is described in [Using `SimplePasswordValidationCallbackHandler`](#security-simple-password-validation-callback-handler).
###### Using `SpringDigestPasswordValidationCallbackHandler`
The `SpringDigestPasswordValidationCallbackHandler` requires a Spring Security `UserDetailService` to operate. It uses this service to retrieve the password of the user specified in the token. The digest of the password contained in this details object is then compared with the digest in the message. If they are equal, the user has successfully authenticated, and a `UsernamePasswordAuthenticationToken` is stored in the `SecurityContextHolder`. You can set the service by using the `userDetailsService` property. Additionally, you can set a `userCache` property, to cache loaded user details. The following example shows how to do so:
...
...
@@ -2835,7 +2835,7 @@ The `SpringDigestPasswordValidationCallbackHandler` requires a Spring Security `
A more secure way of authentication uses X509 certificates. In this scenario, the SOAP message contains a`BinarySecurityToken`, which contains a Base 64-encoded version of a X509 certificate. The certificate is used by the recipient to authenticate. The certificate stored in the message is also used to sign the message (see [Verifying Signatures](#security-verifying-signatures)).
...
...
@@ -2860,7 +2860,7 @@ When a message arrives that carries no certificate, the `XwsSecurityInterceptor`
| |In most cases, certificate authentication should be preceded by certificate validation, since you want to authenticate against only valid certificates. Invalid certificates, such as certificates for which the expiration date has passed or which are not in your store of trusted certificates, should be ignored.<br/><br/>In Spring-WS terms, this means that the `SpringCertificateValidationCallbackHandler` or `JaasCertificateValidationCallbackHandler` should be preceded by `KeyStoreCallbackHandler`. This can be accomplished by setting the order of the `callbackHandlers` property in the configuration of the `XwsSecurityInterceptor`:<br/><br/>```<br/><bean id="wsSecurityInterceptor"<br/> class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor"><br/> <property name="policyConfiguration" value="classpath:securityPolicy.xml"/><br/> <property name="callbackHandlers"><br/> <list><br/> <ref bean="keyStoreHandler"/><br/> <ref bean="springSecurityHandler"/><br/> </list><br/> </property><br/></bean><br/>```<br/><br/>Using this setup, the interceptor first determines if the certificate in the message is valid buusing the keystore and then authenticating against it.|
The `KeyStoreCallbackHandler` uses a standard Java keystore to validate certificates. This certificate validation process consists of the following steps: .
...
...
@@ -2887,7 +2887,7 @@ To use the `KeyStoreCallbackHandler` for certificate validation purposes, you mo
Using the setup shown in the preceding example, the certificate that is to be validated must be in the trust store itself or the trust store must contain a certificate authority that issued the certificate.
###### Using `SpringCertificateValidationCallbackHandler`
The `SpringCertificateValidationCallbackHandler` requires an Spring Security `AuthenticationManager` to operate. It uses this manager to authenticate against a `X509AuthenticationToken` that it creates. The configured authentication manager is expected to supply a provider that can handle this token (usually an instance of `X509AuthenticationProvider`). If authentication is successful, the token is stored in the `SecurityContextHolder`. You can set the authentication manager by using the `authenticationManager` property:
...
...
@@ -2918,7 +2918,7 @@ The `SpringCertificateValidationCallbackHandler` requires an Spring Security `Au
In this case, we use a custom user details service to obtain authentication details based on the certificate. See the [Spring Security reference documentation](http://www.springframework.org/security) for more information about authentication against X509 certificates.
###### Using `JaasCertificateValidationCallbackHandler`
The `JaasCertificateValidationCallbackHandler` requires a `loginContextName` to operate. It creates a new JAAS `LoginContext` by using this name and the `X500Principal` of the certificate. This means that this callback handler integrates with any JAAS `LoginModule` that handles X500 principals.
...
...
@@ -2933,11 +2933,11 @@ You can wire up a `JaasCertificateValidationCallbackHandler` as follows:
In this case, the callback handler uses the `LoginContext` named `MyLoginModule`. This module should be defined in your `jaas.config` file and should be able to authenticate against X500 principals.
#### [](#_digital_signatures)7.1.3. Digital Signatures
#### 7.1.3. Digital Signatures
The digital signature of a message is a piece of information based on both the document and the signer’s private key. Two main tasks are related to signatures in WS-Security: verifying signatures and signing messages.
As with [certificate-based authentication](#security-certificate-authentication), a signed message contains a `BinarySecurityToken`, which contains the certificate used to sign the message. Additionally, it contains a `SignedInfo` block, which indicates what part of the message was signed.
...
...
@@ -2951,7 +2951,7 @@ To make sure that all incoming SOAP messages carry a `BinarySecurityToken`, the
If the signature is not present, the `XwsSecurityInterceptor` returns a SOAP fault to the sender. If it is present, it fires a `SignatureVerificationKeyCallback` to the registered handlers. Within Spring-WS, one class handles this particular callback: `KeyStoreCallbackHandler`.
As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler), `KeyStoreCallbackHandler` uses a `java.security.KeyStore` for handling various cryptographic callbacks, including signature verification. For signature verification, the handler uses the `trustStore` property:
...
...
@@ -2968,7 +2968,7 @@ As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler),
</beans>
```
##### [](#_signing_messages)Signing Messages
##### Signing Messages
When signing a message, the `XwsSecurityInterceptor` adds the `BinarySecurityToken` to the message. It also adds a `SignedInfo` block, which indicates what part of the message was signed.
...
...
@@ -2982,7 +2982,7 @@ To sign all outgoing SOAP messages, the security policy file should contain a `S
The `XwsSecurityInterceptor` fires a `SignatureKeyCallback` to the registered handlers. Within Spring-WS, the `KeyStoreCallbackHandler` class handles this particular callback.
As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler), the `KeyStoreCallbackHandler` uses a `java.security.KeyStore` to handle various cryptographic callbacks, including signing messages. For adding signatures, the handler uses the `keyStore` property. Additionally, you must set the `privateKeyPassword` property to unlock the private key used for signing. The following example uses a `KeyStoreCallbackHandler`:
...
...
@@ -3000,11 +3000,11 @@ As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler),
</beans>
```
#### [](#_decryption_and_encryption)7.1.4. Decryption and Encryption
#### 7.1.4. Decryption and Encryption
When encrypting, the message is transformed into a form that can be read only with the appropriate key. The message can be decrypted to reveal the original, readable message.
##### [](#_decryption)Decryption
##### Decryption
To decrypt incoming SOAP messages, the security policy file should contain a `RequireEncryption` element. This element can further carry a `EncryptionTarget` element that indicates which part of the message should be encrypted and a `SymmetricKey` to indicate that a shared secret instead of the regular private key should be used to decrypt the message. You can read a description of the other elements [here](http://java.sun.com/webservices/docs/1.6/tutorial/doc/XWS-SecurityIntro4.html#wp565951). The following example uses a `RequireEncryption` element:
...
...
@@ -3016,7 +3016,7 @@ To decrypt incoming SOAP messages, the security policy file should contain a `Re
If an incoming message is not encrypted, the `XwsSecurityInterceptor` returns a SOAP ault to the sender. If it is present, it fires a `DecryptionKeyCallback` to the registered handlers. Within Spring-WS, the `KeyStoreCallbackHandler` class handles this particular callback.
As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler), the `KeyStoreCallbackHandler` uses a `java.security.KeyStore` to handle various cryptographic callbacks, including decryption. For decryption, the handler uses the `keyStore` property. Additionally, you must set the `privateKeyPassword` property to unlock the private key used for decryption. For decryption based on symmetric keys, it uses the `symmetricStore`. The following example uses `KeyStoreCallbackHandler`:
...
...
@@ -3034,7 +3034,7 @@ As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler),
</beans>
```
##### [](#_encryption)Encryption
##### Encryption
To encrypt outgoing SOAP messages, the security policy file should contain an `Encrypt` element. This element can further carry a `EncryptionTarget` element that indicates which part of the message should be encrypted and a `SymmetricKey` to indicate that a shared secret instead of the regular public key should be used to encrypt the message. You can read a description of the other elements [here](http://java.sun.com/webservices/docs/1.6/tutorial/doc/XWS-SecurityIntro4.html#wp565951). The following example uses an `Encrypt` element:
...
...
@@ -3046,7 +3046,7 @@ To encrypt outgoing SOAP messages, the security policy file should contain an `E
The `XwsSecurityInterceptor` fires an `EncryptionKeyCallback` to the registered handlers to retrieve the encryption information. Within Spring-WS, the `KeyStoreCallbackHandler` class handles this particular callback.
As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler), the `KeyStoreCallbackHandler` uses a `java.security.KeyStore` to handle various cryptographic callbacks, including encryption. For encryption based on public keys, the handler uses the `trustStore` property. For encryption based on symmetric keys, it uses `symmetricStore`. The following example uses `KeyStoreCallbackHandler`:
...
...
@@ -3063,7 +3063,7 @@ As described in [KeyStoreCallbackHandler](#security-key-store-callback-handler),
When a securement or validation action fails, the `XwsSecurityInterceptor` throws a `WsSecuritySecurementException` or `WsSecurityValidationException` respectively. These exceptions bypass the [standard exception handling mechanism](#server-endpoint-exception-resolver) but are handled by the interceptor itself.
...
...
@@ -3074,7 +3074,7 @@ Similarly, `WsSecurityValidationException` exceptions are handled by the `handle
| |Both `handleSecurementException` and `handleValidationException` are protected methods, which you can override to change their default behavior.|
### [](#security-wss4j-security-interceptor)7.2. Using `Wss4jSecurityInterceptor`
### 7.2. Using `Wss4jSecurityInterceptor`
The `Wss4jSecurityInterceptor` is an `EndpointInterceptor` (see [Intercepting Requests — the `EndpointInterceptor` Interface](#server-endpoint-interceptor)) that is based on [Apache’s WSS4J](https://ws.apache.org/wss4j/).
...
...
@@ -3088,7 +3088,7 @@ WSS4J implements the following standards:
This interceptor supports messages created by the `AxiomSoapMessageFactory` and the `SaajSoapMessageFactory`.
WSS4J uses no external configuration file. The interceptor is entirely configured by properties. The validation and securement actions invoked by this interceptor are specified via `validationActions` and `securementActions` properties, respectively. Actions are passed as a space-separated strings. The following listing shows an example configuration:
...
...
@@ -3124,13 +3124,13 @@ The following table shows the available securement actions:
The order of the actions is significant and is enforced by the interceptor. If its security actions were performed in a different order than the one specified by`validationActions`, the interceptor rejects an incoming SOAP message.
#### [](#_handling_digital_certificates)7.2.2. Handling Digital Certificates
#### 7.2.2. Handling Digital Certificates
For cryptographic operations that require interaction with a keystore or certificate handling (signature, encryption, and decryption operations), WSS4J requires an instance of`org.apache.ws.security.components.crypto.Crypto`.
`Crypto` instances can be obtained from WSS4J’s `CryptoFactory` or more conveniently with the Spring-WS`CryptoFactoryBean`.
##### [](#_cryptofactorybean)CryptoFactoryBean
##### CryptoFactoryBean
Spring-WS provides a convenient factory bean, `CryptoFactoryBean`, that constructs and configures `Crypto` instances through strongly typed properties (preferred) or through a `Properties` object.
...
...
@@ -3145,17 +3145,17 @@ The following example configuration uses `CryptoFactoryBean`:
</bean>
```
#### [](#_authentication_2)7.2.3. Authentication
#### 7.2.3. Authentication
This section addresses how to do authentication with `Wss4jSecurityInterceptor`.
Spring-WS provides a set of callback handlers to integrate with Spring Security. Additionally, a simple callback handler, `SimplePasswordValidationCallbackHandler`, is provided to configure users and passwords with an in-memory `Properties` object.
Callback handlers are configured through the `validationCallbackHandler` of the `Wss4jSecurityInterceptor` property.
###### Using `SimplePasswordValidationCallbackHandler`
`SimplePasswordValidationCallbackHandler` validates plain text and digest username tokens against an in-memory `Properties` object. You can configure it as follows:
...
...
@@ -3170,7 +3170,7 @@ Callback handlers are configured through the `validationCallbackHandler` of the
###### Using `SpringSecurityPasswordValidationCallbackHandler`
The `SpringSecurityPasswordValidationCallbackHandler` validates plain text and digest passwords by using a Spring Security `UserDetailService` to operate. It uses this service to retrieve the the password (or a digest of the password) of the user specified in the token. The password (or a digest of the password) contained in this details object is then compared with the digest in the message. If they are equal, the user has successfully authenticated, and a `UsernamePasswordAuthenticationToken` is stored in the`SecurityContextHolder`. You can set the service by using the `userDetailsService`. Additionally, you can set a `userCache` property, to cache loaded user details, as follows:
...
...
@@ -3185,7 +3185,7 @@ The `SpringSecurityPasswordValidationCallbackHandler` validates plain text and d
Adding a username token to an outgoing message is as simple as adding `UsernameToken` to the `securementActions` property of the `Wss4jSecurityInterceptor` and specifying `securementUsername` and`securementPassword`.
...
...
@@ -3215,7 +3215,7 @@ The following example generates a username token with a plain text password, a `
As certificate authentication is akin to digital signatures, WSS4J handles it as part of the signature validation and securement. Specifically, the `securementSignatureKeyIdentifier` property must be set to `DirectReference` in order to instruct WSS4J to generate a `BinarySecurityToken` element containing the X509 certificate and to include it in the outgoing message. The certificate’s name and password are passed through the `securementUsername` and `securementPassword` properties, respectively, as the following example shows:
...
...
@@ -3252,11 +3252,11 @@ At the end of the validation, the interceptor automatically verifies the validit
For more detail, see to [Digital Signatures](#security-wss4j-digital-signatures).
To validate timestamps, add `Timestamp` to the `validationActions` property. You can override timestamp semantics specified by the initiator of the SOAP message by setting `timestampStrict` to `true` and specifying a server-side time-to-live in seconds (default: 300) by setting the `timeToLive` property. The interceptor always rejects already expired timestamps, whatever the value of `timeToLive` is.
...
...
@@ -3270,7 +3270,7 @@ In the following example, the interceptor limits the timestamp validity window t
</bean>
```
##### [](#_adding_timestamps)Adding Timestamps
##### Adding Timestamps
Adding `Timestamp` to the `securementActions` property generates a timestamp header in outgoing messages. The `timestampPrecisionInMilliseconds` property specifies whether the precision of the generated timestamp is in milliseconds. The default value is `true`. The following listing adds a timestamp:
...
...
@@ -3281,11 +3281,11 @@ Adding `Timestamp` to the `securementActions` property generates a timestamp hea
</bean>
```
#### [](#security-wss4j-digital-signatures)7.2.5. Digital Signatures
#### 7.2.5. Digital Signatures
This section describes the various signature options available in the `Wss4jSecurityInterceptor`.
To instruct the `Wss4jSecurityInterceptor`, `validationActions` must contain the `Signature` action. Additionally, the `validationSignatureCrypto` property must point to the keystore containing the public certificates of the initiator:
...
...
@@ -3301,7 +3301,7 @@ To instruct the `Wss4jSecurityInterceptor`, `validationActions` must contain the
</bean>
```
##### [](#_signing_messages_2)Signing Messages
##### Signing Messages
Signing outgoing messages is enabled by adding the `Signature` action to the `securementActions`. The alias and the password of the private key to use are specified by the `securementUsername` and `securementPassword` properties, respectively. `securementSignatureCrypto` must point to the keystore that contains the private key:
...
...
@@ -3336,7 +3336,7 @@ To specify an element without a namespace, use the string, `Null` (case sensitiv
If no other element in the request has a local name of `Body`, the SOAP namespace identifier can be empty (`{}`).
Signature confirmation is enabled by setting `enableSignatureConfirmation` to `true`. Note that the signature confirmation action spans over the request and the response. This implies that `secureResponse` and `validateRequest` must be set to `true` (which is the default value) even if there are no corresponding security actions. The following example sets the `enableSignatureConfirmation` property to `true`:
...
...
@@ -3353,11 +3353,11 @@ Signature confirmation is enabled by setting `enableSignatureConfirmation` to `t
</bean>
```
#### [](#_decryption_and_encryption_2)7.2.6. Decryption and Encryption
#### 7.2.6. Decryption and Encryption
This section describes the various decryption and encryption options available in the `Wss4jSecurityInterceptor`.
##### [](#_decryption_2)Decryption
##### Decryption
Decryption of incoming SOAP messages requires that the `Encrypt` action be added to the `validationActions` property. The rest of the configuration depends on the key information that appears in the message. (This is because WSS4J needs only a Crypto for encypted keys, whereas embedded key name validation is delegated to a callback handler.)
...
...
@@ -3400,7 +3400,7 @@ To support decryption of messages with an embedded key name ( `ds:KeyName` eleme
</bean>
```
##### [](#_encryption_2)Encryption
##### Encryption
Adding `Encrypt` to the `securementActions` enables encryption of outgoing messages. You can set the certificate’s alias to use for the encryption by setting the `securementEncryptionUser` property. The keystore where the certificate resides is accessed through the `securementEncryptionCrypto` property. As encryption relies on public certificates, no password needs to be passed. The following example uses the `securementEncryptionCrypto` property:
...
...
@@ -3457,20 +3457,20 @@ Be aware that the element name, the namespace identifier, and the encryption mod
To specify an element without a namespace, use the value, `Null` (case sensitive), as the namespace name. If no list is specified, the handler encrypts the SOAP Body in `Content` mode by default.
The exception handling of the `Wss4jSecurityInterceptor` is identical to that of the `XwsSecurityInterceptor`. See [Security Exception Handling](#security-xws-exception-handling) for more information.
# [](#resources)III. Other Resources
# III. Other Resources
In addition to this reference documentation, a number of other resources may help you learn how to use Spring Web Services. These additional, third-party resources are enumerated in this section.
## [](#_bibliography)Bibliography
## Bibliography
*[]()[waldo-94] Jim Waldo, Ann Wollrath, and Sam Kendall. *A Note on Distributed Computing*. Springer Verlag. 1994
* [waldo-94] Jim Waldo, Ann Wollrath, and Sam Kendall. *A Note on Distributed Computing*. Springer Verlag. 1994
在当前面向服务的体系结构时代,越来越多的人使用 Web 服务来连接以前未连接的系统。最初,Web 服务被认为是执行远程过程调用的另一种方式。然而,随着时间的推移,人们发现 RPC 和 Web 服务之间存在很大的差异。特别是当与其他平台的互操作性很重要时,通常更好的做法是发送封装的 XML 文档,其中包含处理请求所需的所有数据。从概念上讲,与消息队列相比,基于 XML 的 Web 服务比远程解决方案更好。总的来说,XML 应该被认为是数据的平台中立表示,即 SOA 的*通用语言*。在开发或使用 Web 服务时,重点应该放在这个 XML 上,而不是 Java 上。
Spring Web 服务专注于创建这些文档驱动的 Web 服务。 Spring Web 服务促进了契约优先的 SOAP 服务开发,允许通过使用操纵 XML 有效负载的多种方法之一来创建灵活的 Web 服务。 Spring-WS 提供了一个功能强大的[消息调度框架](#server)、一个与你现有的应用程序安全解决方案集成的[WS-Security](#security)解决方案,以及一个遵循熟悉的 Spring 模板模式的[客户端 API](#client)。
# [](#_i_introduction)一.导言
# 一.导言
这是参考文献[是一个概述](#what-is-spring-ws)的第一部分 Spring Web 服务和底层概念。 Spring-WS 随后被介绍,并且[概念](#why-contract-first)契约优先 Web 服务开发的背后的[概念](#why-contract-first)被解释。
## [](#what-is-spring-ws)1。什么是 Spring Web 服务?
## 1.什么是 Spring Web 服务?
### [](#_introduction)1.1。导言
### 1.1.导言
Spring Web 服务( Spring-WS)是 Spring 社区的产品,并且专注于创建文档驱动的 Web 服务。 Spring Web 服务旨在促进契约优先的 SOAP 服务开发,允许通过使用操纵 XML 有效负载的多种方法之一来创建灵活的 Web 服务。该产品基于 Spring 本身,这意味着你可以使用 Spring 概念(例如依赖注入)作为 Web 服务的一个组成部分。
...
...
@@ -32,35 +32,35 @@ Spring Web 服务( Spring-WS)是 Spring 社区的产品,并且专注于创
*[Apache license](#features-apache-license)
#### [](#features-powerful-mappings)1.1.1。强大的映射
#### 1.1.1.强大的映射
你可以将传入的 XML 请求分发到任何对象,这取决于消息有效负载、SOAP 动作报头或 XPath 表达式。
#### [](#features-xml-api-support)1.1.2。XML API 支持
#### 1.1.2.XML API 支持
传入的 XML 消息不仅可以通过标准的 JAXP API(如 DOM、SAX 和 STAX)来处理,还可以通过 JDOM、DOM4J、XOM 甚至编组技术来处理。
#### [](#features-flexible-xml-marshalling)1.1.3。灵活的 XML 编组
#### 1.1.3.灵活的 XML 编组
Spring Web 服务构建在 Spring 框架中的对象/XML 映射模块上,该模块支持 JAXB1 和 2、Castor、XMLBeans、JiBX 和 XStream。
#### [](#features-reusing-your-spring-expertise)1.1.4。重用你的 Spring 专长
#### 1.1.4.重用你的 Spring 专长
Spring-WS 对所有配置都使用 Spring 应用程序上下文,这应该有助于 Spring 开发人员快速获得最新信息。另外, Spring-WS 的体系结构类似于 Spring-MVC 的体系结构。
在 Spring-WS 中,实现端点来处理传入的 XML 消息。端点通常是通过使用`@Endpoint`注释对类进行注释来创建的。在这个端点类中,你可以创建一个或多个处理传入请求的方法。方法签名可以非常灵活。你可以包括与传入的 XML 消息相关的几乎任何类型的参数类型,正如我们在本章后面所解释的那样。
#### [](#_handling_the_xml_message)3.5.1。处理 XML 消息
#### 3.5.1.处理 XML 消息
在这个示例应用程序中,我们使用[JDom 2](http://www.jdom.org/)来处理 XML 消息。我们还使用[XPath](https://www.w3.org/TR/xpath20/),因为它允许我们选择 XML JDOM 树的特定部分,而不需要严格的模式一致性。
...
...
@@ -724,7 +724,7 @@ public class HolidayEndpoint {
参考文档的这一部分详细介绍了构成 Spring Web 服务的各个组件。其中包括[a chapter](#common),讨论了客户端和服务器端 WS 共有的部分,专门讨论[编写服务器端 Web 服务](#server)的细节的一章,关于在[客户端](#client)上使用 Web 服务的一章,以及关于使用[WS-Security](#security)的一章。
Spring Web 服务的核心接口之一是`WebServiceMessage`。该接口表示与协议无关的 XML 消息。接口包含以`javax.xml.transform.Source`或`javax.xml.transform.Result`的形式提供对消息有效负载的访问的方法。`Source`和`Result`是标记接口,表示对 XML 输入和输出的抽象。具体的实现封装了各种 XML 表示,如下表所示:
...
...
@@ -830,15 +830,15 @@ Spring Web 服务的核心接口之一是`WebServiceMessage`。该接口表示
在 Spring Web 服务中,这样的会话包含在`MessageContext`中,其具有获取请求和响应消息的属性。在客户端,消息上下文由[`WebServiceTemplate`](#client-web-service-template)创建。在服务器端,消息上下文是从特定于传输的输入流中读取的。例如,在 HTTP 中,从`HttpServletRequest`读取,然后将响应写回`HttpServletResponse`。
与 Spring JDBC 的`RowMapper`中的映射行类似,每个结果节点都通过使用匿名内部类进行映射。在这种情况下,我们创建一个`Contact`对象,稍后将使用它。
#### [](#xpath-template)4.3.2。`XPathTemplate`
#### 4.3.2.`XPathTemplate`
`XPathExpression`只允许对单个预编译表达式求值。一个更灵活但更慢的替代方案是`XpathTemplate`。该类遵循通篇 Spring 中使用的公共模板模式(`JdbcTemplate`,`JmsTemplate`,以及其他)。下面的清单展示了一个示例:
...
...
@@ -1026,7 +1026,7 @@ public class MyXPathClass {
}
```
### [](#logging)4.4。消息日志记录和跟踪
### 4.4.消息日志记录和跟踪
在开发或调试 Web 服务时,在消息到达或发送之前查看消息的内容可能非常有用。 Spring Web 服务通过标准的 Commons 日志记录接口提供了这种功能。
...
...
@@ -1060,7 +1060,7 @@ DEBUG [server.MessageTracing.sent] Sent response [SaajSoapMessage {http://exampl
DEBUG [client.MessageTracing.received] Received response [SaajSoapMessage {http://example.com}response] ...
```
## [](#server)5。使用 Spring-WS 创建 Web 服务
## 5.使用 Spring-WS 创建 Web 服务
Spring-WS 的服务器端支持是围绕`MessageDispatcher`设计的,该支持将传入消息分派到端点,具有可配置的端点映射、响应生成和端点拦截。端点通常使用`@Endpoint`注释并具有一个或多个处理方法。这些方法通过检查消息的某些部分(通常是有效负载)并创建某种响应来处理传入的 XML 请求消息。你可以使用另一个注释(通常是`@PayloadRoot`)对方法进行注释,以指示它可以处理哪种类型的消息。
...
...
@@ -1074,7 +1074,7 @@ Spring-WS 的 XML 处理非常灵活。端点可以从 Spring-WS 支持的大量
* 编组技术(JAXB、Castor、XMLBeans、JiBX 或 XStream):将 XML 转换为对象,反之亦然
Spring-WS 的服务器端是围绕一个中心类设计的,该中心类将传入的 XML 消息分派到端点。 Spring-WS 的`MessageDispatcher`非常灵活,允许你使用任何类型的类作为端点,只要它可以在 Spring IOC 容器中进行配置。在某种程度上,消息分配器类似于 Spring 的`DispatcherServlet`,即 Spring Web MVC 中使用的“前置控制器”。
消息调度器对[消息上下文](#message-context)进行操作,而不是对特定于传输的输入流和输出流进行操作。因此,传输特定的请求需要读入`MessageContext`。对于 HTTP,这是用`WebServiceMessageReceiverHandlerAdapter`(这是 Spring web`HandlerInterceptor`)完成的,以便`MessageDispatcher`可以连接到标准`DispatcherServlet`中。然而,还有一种更方便的方法可以做到这一点,它显示在[`MessageDispatcherServlet`](#message-dispatcher- Servlet)中。
### [](#_transports)5.2。运输
### 5.2.运输
Spring Web 服务支持多个传输协议。最常见的是 HTTP 传输,为此提供了自定义 Servlet,但你也可以通过 JMS 甚至电子邮件发送消息。
`MessageDispatcherServlet`是一个标准`Servlet`,它方便地从标准 Spring web`DispatcherServlet`扩展并包装一个`MessageDispatcher`。因此,它将这些属性合并为一个。作为`MessageDispatcher`,它遵循上一节中描述的相同的请求处理流程。作为 Servlet,在 Web 应用程序的`MessageDispatcherServlet`中配置了`web.xml`。要处理`MessageDispatcherServlet`的请求必须通过同一个`web.xml`文件中的 URL 映射来映射。这是标准的 Java EE Servlet 配置。下面的示例显示了这样的`MessageDispatcherServlet`声明和映射:
...
...
@@ -1144,7 +1144,7 @@ public class MyServletInitializer
作为`MessageDispatcherServlet`的替代方案,你可以在标准 Spring-Web MVC`DispatcherServlet`中连接`MessageDispatcher`。默认情况下,`DispatcherServlet`只能委托给`Controllers`,但是我们可以通过在 Servlet 的 Web 应用程序上下文中添加`WebServiceMessageReceiverHandlerAdapter`来指示它委托给`MessageDispatcher`:
...
...
@@ -1290,7 +1290,7 @@ public DefaultWsdl11Definition orders() {
</beans>
```
#### [](#_jms_transport)5.2.3。JMS 运输
#### 5.2.3.JMS 运输
Spring Web 服务通过在 Spring 框架中提供的 JMS 功能支持服务器端 JMS 处理。 Spring Web 服务提供`WebServiceMessageListener`以插入到`MessageListenerContainer`中。此消息侦听器需要`WebServiceMessageFactory`和`MessageDispatcher`才能操作。下面的配置示例展示了这一点:
...
...
@@ -1327,7 +1327,7 @@ Spring Web 服务通过在 Spring 框架中提供的 JMS 功能支持服务器
Spring Web 服务 2.0 引入了对 XMPP 的支持,也称为 Jabber。该支持基于[Smack](https://www.igniterealtime.org/projects/smack/index.jsp)库。
...
...
@@ -1454,11 +1454,11 @@ Spring 用于 XMPP 的 Web 服务支持非常类似于其它传输:有一个
</beans>
```
#### [](#_mtom)5.2.7。姆托姆
#### 5.2.7.姆托姆
[MTOM](https://en.wikipedia.org/wiki/Message_Transmission_Optimization_Mechanism)是用于向 Web 服务发送和从 Web 服务发送二进制数据的机制。你可以通过[MTOM 样本](https://github.com/spring-projects/spring-ws-samples/tree/main/mtom)查看如何使用 Spring WS 实现这一点。
### [](#server-endpoints)5.3。端点
### 5.3.端点
端点是 Spring-WS 服务器端支持的核心概念。端点提供对应用程序行为的访问,该行为通常由业务服务接口定义。端点解释 XML 请求消息,并使用该输入(通常)调用业务服务上的方法。该服务调用的结果表示为响应消息。 Spring-WS 具有各种各样的端点,并且使用各种方式来处理 XML 消息并创建响应。
...
...
@@ -1570,7 +1570,7 @@ public class MyConfiguration extends WsConfigurerAdapter {
Note that all abstract base classes provided in Spring-WS are thread safe, unless otherwise indicated in the class-level Javadoc.
@@ -1679,7 +1679,7 @@ public class AnnotationOrderEndpoint {
除了这个列表之外,你还可以使用可以从`String`转换为 Spring [转换服务](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#core-convert-ConversionService-API)的任何类型。
在开发 Web 服务时,记录传入和传出的 XML 消息可能很有用。 Spring WS 通过`PayloadLoggingInterceptor`和`SoapEnvelopeLoggingInterceptor`类来促进这一点。前者只将消息的有效负载记录到 Commons 日志中。后者记录整个 SOAP 信封,包括 SOAP 头。下面的示例展示了如何在端点映射中定义`PayloadLoggingInterceptor`:
...
...
@@ -1844,7 +1844,7 @@ public class MyWsConfiguration extends WsConfigurerAdapter {
Spring 为了将有效负载转换为另一种 XML 格式,Web 服务提供了`PayloadTransformingInterceptor`。这个端点拦截器基于 XSLT 样式表,在支持 Web 服务的多个版本时特别有用,因为你可以将较旧的消息格式转换为较新的格式。下面的示例使用`PayloadTransformingInterceptor`:
...
...
@@ -1880,7 +1880,7 @@ Spring 为了将有效负载转换为另一种 XML 格式,Web 服务提供了`
|**5**|我们通过调用`sendRequest()`并使用静态导入的`RequestCreators`提供的`RequestCreator`来发送请求(请参见[using`RequestCreator`)和`RequestCreators`(#server-test-request-creator))。<br/><br/>我们还通过调用静态导入的`payload()`提供的`ResponseMatcher`(参见[using`ResponseMatcher`和`ResponseMatchers`(#server-test-response-response-matcher-matcher=“967”))来设置响应期望。但是 IDE 的代码完成功能非常有帮助。在输入`sendRequest(`之后,你的 IDE 可以为你提供一个可能的请求创建策略的列表,前提是静态导入`RequestCreators`。这同样适用于`andExpect()`,前提是静态导入`ResponseMatchers`。|
`WebServiceTemplate`是 Spring-WS 中用于客户端 Web 服务访问的核心类。它包含用于发送`Source`对象和以`Source`或`Result`接收响应消息的方法。此外,它还可以在跨传输发送对象之前将对象封送到 XML,并将任何响应 XML 重新封送到对象中。
##### [](#client-transports)URI 和 Transports
##### URI 和 Transports
`WebServiceTemplate`类使用 URI 作为消息目的地。你可以在模板本身上设置`defaultUri`属性,也可以在调用模板上的方法时显式地提供 URI。URI 解析为`WebServiceMessageSender`,它负责跨传输层发送 XML 消息。你可以使用`messageSender`或`messageSenders`类的属性来设置一个或多个消息发送者。
为了方便普通 Java 对象的发送,`WebServiceTemplate`具有许多`send(..)`方法,这些方法将`Object`作为消息数据内容的参数。在`WebServiceTemplate`类中的方法`send(..)`将请求对象到 XML 的转换委托给`Marshaller`,并将响应 XML 到对象的转换委托给`Unmarshaller`。(有关编组和解组器的更多信息,请参见[the Spring Framework reference documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#oxm-marshaller-unmarshaller)。)通过使用编组器,你的应用程序代码可以专注于正在发送或接收的业务对象,而不必关注它如何表示为 XML 的详细信息。要使用编组功能,必须使用`WebServiceTemplate`类的`marshaller`和`unmarshaller`属性设置编组器和解组器。
`XwsSecurityInterceptor`是一个`EndpointInterceptor`(参见[拦截请求-`EndpointInterceptor`接口](#server-endpoint-interceptor)),它基于 Sun 的 XML 和 Web 服务安全包。这个 WS-Security 实现是 Java Web 服务开发人员包([Java WSDP](http://java.sun.com/webservices/))的一部分。
...
...
@@ -2628,7 +2628,7 @@ public interface ResponseCreator {
`SpringDigestPasswordValidationCallbackHandler`需要 Spring 证券`UserDetailService`才能操作。它使用此服务检索令牌中指定的用户的密码。然后将包含在此 Details 对象中的密码摘要与消息中的摘要进行比较。如果它们相等,则用户已成功地进行了身份验证,并且`UsernamePasswordAuthenticationToken`存储在`SecurityContextHolder`中。你可以使用`userDetailsService`属性设置服务。此外,还可以设置`userCache`属性,以缓存已加载的用户详细信息。下面的示例展示了如何做到这一点:
...
...
@@ -2833,7 +2833,7 @@ public interface ResponseCreator {
`SpringCertificateValidationCallbackHandler`需要 Spring 证券`AuthenticationManager`才能操作。它使用此管理器对它创建的`X509AuthenticationToken`进行身份验证。配置的身份验证管理器需要提供一个能够处理这个令牌的提供者(通常是`X509AuthenticationProvider`的实例)。如果身份验证成功,则将令牌存储在`SecurityContextHolder`中。你可以使用`authenticationManager`属性设置身份验证管理器:
...
...
@@ -2916,7 +2916,7 @@ public interface ResponseCreator {
`SpringSecurityPasswordValidationCallbackHandler`通过使用 Spring 安全性`UserDetailService`来操作,从而验证纯文本和摘要密码。它使用此服务检索令牌中指定的用户的密码(或密码摘要)。然后将这个 Details 对象中包含的密码(或密码摘要)与消息中的摘要进行比较。如果它们相等,则用户已成功地进行了身份验证,并且`UsernamePasswordAuthenticationToken`存储在`SecurityContextHolder`中。你可以使用`userDetailsService`设置服务。此外,你可以设置`userCache`属性,以缓存已加载的用户详细信息,如下所示:
...
...
@@ -3183,7 +3183,7 @@ Spring-WS 提供了一组回调处理程序来与 Spring 安全性集成。此