From c78913270162287671830f3cf949d791103a7cbb Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Mon, 14 Jan 2008 13:21:56 +0000 Subject: [PATCH] SWS-261 --- src/docbkx/server.xml | 834 ++++++++++++++++++++++++++++++------------ 1 file changed, 594 insertions(+), 240 deletions(-) diff --git a/src/docbkx/server.xml b/src/docbkx/server.xml index 9a786480..842c885f 100644 --- a/src/docbkx/server.xml +++ b/src/docbkx/server.xml @@ -7,38 +7,50 @@ Introduction Spring-WS's server-side support is designed around a - MessageDispatcher that dispatches incoming + MessageDispatcher + that dispatches incoming messages to endpoints, with configurable endpoint mappings, response generation, and endpoint interception. - The simplest endpoint is a PayloadEndpoint, which just offers the - Source invoke(Source request) method. You are of course free to + The simplest endpoint is aPayloadEndpoint, which just offers the + Source invoke(Source request) + method. You are of course free to implement this interface directly, but you will probably prefer to extend one of the included abstract implementations such as - AbstractDomPayloadEndpoint, AbstractSaxPayloadEndpoint, and + AbstractDomPayloadEndpoint,AbstractSaxPayloadEndpoint, and AbstractMarshallingPayloadEndpoint. Alternatively, there is a endpoint development that uses Java 5 annotations, such as - @Endpoint for marking a POJO as endpoint, and marking a method with - @PayloadRoot or @SoapAction. + @Endpoint + for marking a POJO as endpoint, and marking a method with + @PayloadRoot + or@SoapAction. - Spring-WS's XML handling is extremely flexible. An endpoint can choose from - a large amount of XML handling libraries supported by Spring-WS, including the DOM family (W3C DOM, JDOM, - dom4j, and XOM), SAX or StAX for faster performance, XPath to extract information from the message, or even - marshalling techniques (JAXB, Castor, XMLBeans, JiBX, or XStream) to convert - the XML to objects and vice-versa. + Spring-WS's XML handling is extremely flexible. An endpoint can choose from + a large amount of XML handling libraries supported by Spring-WS, including the DOM family (W3C DOM, JDOM, + dom4j, and XOM), SAX or StAX for faster performance, XPath to extract information from the message, or even + marshalling techniques + (JAXB, Castor, XMLBeans, JiBX, or XStream) to convert + the XML to objects and vice-versa.
- The <classname>MessageDispatcher</classname> + The + <classname>MessageDispatcher</classname> + 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, allowing you to + endpoints. Spring-WS's + MessageDispatcher + is extremely flexible, allowing you to use any sort of class as an endpoint, as long as it can be configured in the Spring IoC container. - In a way, the message dispatcher resembles Spring's DispatcherServlet, the - Front Controller used in Spring Web MVC. + In a way, the message dispatcher resembles Spring'sDispatcherServlet, the + Front Controller + used in Spring Web MVC. - The processing and dispatching flow of the MessageDispatcher is illustrated in the + The processing and dispatching flow of the + MessageDispatcher + is illustrated in the following sequence diagram. @@ -53,22 +65,27 @@ - When a MessageDispatcher is set up for use and a request comes in for that - specific dispatcher, said MessageDispatcher starts processing the request. The - list below describes the complete process a request goes through when handled by a - MessageDispatcher: + When a + MessageDispatcher + is set up for use and a request comes in for that + specific dispatcher, said + MessageDispatcher + starts processing the request. The + list below describes the complete process a request goes through when handled by a + MessageDispatcher: - An appropriate endpoint is searched for using the configured EndpointMapping(s). + An appropriate endpoint is searched for using the configuredEndpointMapping(s). If an endpoint is found, the invocation chain associated with the endpoint (preprocessors, postprocessors, and endpoints) will be executed in order to create a response. - An appropriate adapter is searched for the endpoint. The MessageDispatcher + An appropriate adapter is searched for the endpoint. The + MessageDispatcher delegates to this adapter to invoke the endpoint. @@ -86,7 +103,9 @@ custom behaviors (such as returning a SOAP Fault) in case such exceptions get thrown. - The MessageDispatcher has several properties, for setting endpoint adapters, + The + MessageDispatcher + has several properties, for setting endpoint adapters, mappings, exception resolvers. However, setting these properties is not required, since the dispatcher will automatically detect all of @@ -94,13 +113,14 @@ should these properties be set. - The message dispatcher operates on a message context, and not + The message dispatcher operates on amessage context, and not 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 + into aMessageContext. 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 . + HandlerInterceptor, so that the + MessageDispatcher + can be wired in a standardDispatcherServlet. There is a more convenient way to do + this, however, which is shown in.
@@ -110,20 +130,33 @@ a custom servlet is supplied, but it is also possible to send messages over JMS, and even email.
- <classname>MessageDispatcherServlet</classname> + + <classname>MessageDispatcherServlet</classname> + - The MessageDispatcherServlet is a standard Servlet + The + MessageDispatcherServlet + is a standard + Servlet which - conveniently extends from the standard Spring Web DispatcherServlet, and wraps - a MessageDispatcher. As such, it combines the attributes of these into one: - as a MessageDispatcher, it follows the same request handling flow as described + conveniently extends from the standard Spring WebDispatcherServlet, and wraps + aMessageDispatcher. As such, it combines the attributes of these into one: + as aMessageDispatcher, 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 will have to be mapped using a URL mapping in the same web.xml file. This is + MessageDispatcherServlet + is configured in the + web.xml + of + your web application. Requests that you want the + MessageDispatcherServlet + to + handle will have to be mapped using a URL mapping in the same + web.xml + file. This is standard Java EE servlet configuration; an example of such a - MessageDispatcherServlet declaration and mapping can be found below. + MessageDispatcherServlet + declaration and mapping can be found below. @@ -140,13 +173,22 @@ ]]> - In the example above, all requests will be handled by the 'spring-ws' + In the example above, all requests will be handled by the + 'spring-ws' MessageDispatcherServlet. This is only the first step in setting up Spring Web Services, because the various component beans used by the Spring-WS framework also need to be - configured; this configuration consists of standard Spring XML <bean/> - definitions. Because the MessageDispatcherServlet is a standard Spring - DispatcherServlet, it will look for a file named - [servlet-name]-servlet.xml in the WEB-INF directory + configured; this configuration consists of standard Spring XML + <bean/> + definitions. Because the + MessageDispatcherServlet + is a standard Spring + DispatcherServlet, it will + look for a file named + [servlet-name]-servlet.xml + + in the + WEB-INF + directory of your web application and create the beans defined there in a Spring container. In the example above, that means that it looks for '/WEB-INF/spring-ws-servlet.xml'. This file will contain all of the SWS-specific beans such as endpoints, marshallers and suchlike. @@ -154,10 +196,14 @@
Automatic WSDL exposure - The MessageDispatcherServlet will automatically detect any - WsdlDefinition beans defined in it's Spring container. All such - WsdlDefinition beans that are detected will also be exposed via - a WsdlDefinitionHandlerAdapter; this is a very convenient way to expose your + The + MessageDispatcherServlet + will automatically detect any + WsdlDefinition + beans defined in it's Spring container. All such + WsdlDefinition + beans that are detected will also be exposed via + aWsdlDefinitionHandlerAdapter; this is a very convenient way to expose your WSDL to clients simply by just defining some beans. @@ -171,20 +217,24 @@ ]]> The WSDL defined in the 'Orders.wsdl' file can then be accessed via - GET requests to a URL of the following form (substitute the host, port and + GET + requests to a URL of the following form (substitute the host, port and servlet context path as appropriate). - Another cool feature of the MessageDispatcherServlet (or more correctly the + Another cool feature of the + MessageDispatcherServlet + (or more correctly the WsdlDefinitionHandlerAdapter) is that it is able to transform the value of the 'location' of all the WSDL that it exposes to reflect the URL of the incoming request. Please note that this 'location' transformation feature is - off by default.To switch this feature on, you just need to specify an - initialization parameter to the MessageDispatcherServlet, like so: + off + by default.To switch this feature on, you just need to specify an + initialization parameter to theMessageDispatcherServlet, like so: @@ -204,13 +254,15 @@ ]]> - Consult the class-level Javadoc on the WsdlDefinitionHandlerAdapter class + Consult the class-level Javadoc on the + WsdlDefinitionHandlerAdapter + class which explains the whole transformation process in more detail. As an alternative to writing the WSDL by hand, and exposing it with the SimpleWsdl11Definition, Spring Web Services can also generate a WSDL - from an XSD schema. This is the approach shown in . + from an XSD schema. This is the approach shown in. The next application context snippet shows how to create such a dynamic WSDL file: ]]> - The DynamicWsdl11Definition uses a - Wsdl11DefinitionBuilder implementation + The + DynamicWsdl11Definition + uses a + Wsdl11DefinitionBuilder + implementation to generate a WSDL the first time it is requested. - Typically, we use a XsdBasedSoap11Wsdl4jDefinitionBuilder, which builds - a WSDL from a XSD schema. This builder iterates over all element elements - found in the schema, and creates a message for elements that end with the - defined request or response suffix. The default request suffix is Request; - the default response suffix is Response, though these can be changed by - setting the requestSuffix and responseSuffix + Typically, we use aXsdBasedSoap11Wsdl4jDefinitionBuilder, which builds + a WSDL from a XSD schema. This builder iterates over all + element + elements + found in the schema, and creates a + message + for elements that end with the + defined request or response suffix. The default request suffix isRequest; + the default response suffix isResponse, though these can be changed by + setting the + requestSuffix + and + responseSuffix properties, respectively. Next, the builder combines the request and response messages into a WSDL - operations, and builds a portType based on the operations. + operations, and builds a + portType + based on the operations. - For instance, if our Orders.xsd schema defines the - GetOrdersRequest and GetOrdersResponse elements, the - XsdBasedSoap11Wsdl4jDefinitionBuilder will create a - GetOrdersRequest and GetOrdersResponse message, and a - GetOrders operation, which is put in a Orders port type. + For instance, if our + Orders.xsd + schema defines the + GetOrdersRequest + and + GetOrdersResponse + elements, the + XsdBasedSoap11Wsdl4jDefinitionBuilder + will create a + GetOrdersRequest + and + GetOrdersResponse + message, and a + GetOrders + operation, which is put in a + Orders + port type.
- Wiring up Spring-WS in a <classname>DispatcherServlet</classname> + Wiring up Spring-WS in a + <classname>DispatcherServlet</classname> + - As an alternative to the MessageDispatcherServlet, you can wire up a - MessageDispatcher in a standard, Spring-Web MVC + As an alternative to theMessageDispatcherServlet, you can wire up a + MessageDispatcher + in a standard, Spring-Web MVC DispatcherServlet. - By default, the DispatcherServlet can only delegate to + By default, the + DispatcherServlet + can only delegate to Controllers, but we can instruct it to delegate to a - MessageDispatcher by adding a - WebServiceMessageReceiverHandlerAdapter to the servlet's web application + MessageDispatcher + by adding a + WebServiceMessageReceiverHandlerAdapter + to the servlet's web application context: @@ -271,21 +354,56 @@ ]]> - Note that by explicitely adding the WebServiceMessageReceiverHandlerAdapter, + Note that by explicitely adding theWebServiceMessageReceiverHandlerAdapter, the dispatcher servlet does not load the default adapters, and is unable to handle standard Spring-MVC Controllers. Therefore, we add the - SimpleControllerHandlerAdapter at the end. + SimpleControllerHandlerAdapter + at the end. + + + By default, the Spring MVC + DispatcherServlet + configures the following + handler adapters in version 2.5: + + + + org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter + + + + + org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter + + + + + org.springframework.web.servlet.mvc.throwaway.ThrowawayControllerHandlerAdapter + + + + + org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter + + + + +
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 to and - MessageDispatcher to operate. The following piece of configuration - shows this: + Spring framework. Spring Web Services provides the + WebServiceMessageListener + to plug in to aMessageListenerContainer. This message listener requires a + WebServiceMessageFactory + to and + MessageDispatcher + to operate. The following piece of configuration + shows this: + @@ -317,43 +435,62 @@ ]]> - As an alternative to the WebServiceMessageListener, Spring Web Services provides - a WebServiceMessageDrivenBean, an EJB + As an alternative to theWebServiceMessageListener, Spring Web Services provides + aWebServiceMessageDrivenBean, an EJB MessageDrivenBean. For more information on EJB, refer to the class level - Javadocs of the WebServiceMessageDrivenBean. + Javadocs of theWebServiceMessageDrivenBean.
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, + functionality is provided through the + MailMessageReceiver + class. This class + monitors a POP3 or IMAP folder, converts the email to aWebServiceMessage, sends any response using SMTP. The host names can be configured 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 a SMTP server). + and a + transportUri, which indicates the server to use for sending responses (typically a SMTP server). - How the MailMessageReceiver monitors incoming messages can be configured with - a pluggable strategy: the MonitoringStrategy. By default, a polling + How the + MailMessageReceiver + monitors incoming messages can be configured with + a pluggable strategy: theMonitoringStrategy. By default, a polling strategy is used, where the incoming folder is polled for new messages every five minutes. This interval - can be changed by setting the pollingInterval property on the strategy. - By default, all MonitoringStrategy implementations delete the handled - messages; this can be changed by setting the deleteMessages property. + can be changed by setting the + pollingInterval + property on the strategy. + By default, all + MonitoringStrategy + implementations delete the handled + messages; this can be changed by setting the + deleteMessages + property. As an alternative to the polling approaches, which are quite inefficient, there is a monitoring strategy - that uses IMAP IDLE. The IDLE command is an optional + that uses IMAPIDLE. The + IDLE + command is an optional expansion of the IMAP email protocol that allows the mail server to send new message updates to the - MailMessageReceiver asynchronously. If you use a IMAP server that supports the - IDLE command, you can plug in the ImapIdleMonitoringStrategy - into the monitoringStrategy property. + MailMessageReceiver + asynchronously. If you use a IMAP server that supports the + IDLE + command, you can plug in the + ImapIdleMonitoringStrategy + into the + monitoringStrategy + property. In addition to a supporting server, you will need to use JavaMail version 1.4.1 or higher. The following piece of configuration shows how to use the server-side email support, overiding the default polling interval to a value which checks every 30 seconds - (30.000 milliseconds): + (30.000 milliseconds): + @@ -392,31 +529,43 @@ request message and uses that input to invoke a method on the business service (typically). The result of that service invocation is represented as a response message. Spring-WS has a wide variety of endpoints, using various ways to handle the XML message, and to create a response. - + The basis for most endpoints in Spring Web Services is the - org.springframework.ws.server.endpoint.PayloadEndpoint interface, the source + org.springframework.ws.server.endpoint.PayloadEndpoint + interface, the source code of which is listed below. /** - * Invokes an operation. - */ +}]]> + - As you can see, the PayloadEndpoint interface defines a single method that + As you can see, the + PayloadEndpoint + interface defines a single method that is invoked with the XML payload of a request (typically the contents of the SOAP Body, see - ). The returned Source, if any, is stored in the - response XML message. While the PayloadEndpoint interface is quite abstract, + ). The returnedSource, if any, is stored in the + response XML message. While the + PayloadEndpoint + interface is quite abstract, Spring-WS offers a lot of endpoint implementations out of the box that already contain a lot of the - functionality you might need. The PayloadEndpoint interface just defines the + functionality you might need. The + PayloadEndpoint + interface just defines the most basic responsibility required of every endpoint; namely handling a request and returning a response. - Alternatively, there is the MessageEndpoint, which operates on a - whole MessageContext rather than just + Alternatively, there is theMessageEndpoint, which operates on a + whole + + MessageContext + + rather than just the payload. Typically, your code should not be dependent on messages, because the payload should contain the information of interest. Only when it is necessary to perform actions on the message as a whole, such as adding a SOAP header, get an attachment, and so forth, should you need to implement @@ -424,14 +573,23 @@ endpoint interceptor.
- <classname>AbstractDomPayloadEndpoint</classname> and other DOM endpoints + + <classname>AbstractDomPayloadEndpoint</classname> + and other DOM endpoints + One of the most basic ways to handle the incoming XML payload is by using a DOM (Document Object Model) - API. By extending from AbstractDomPayloadEndpoint, you can use the - org.w3c.dom.Element and related classes to handle the request and create the - response. When using the AbstractDomPayloadEndpoint as the baseclass for your - endpoints you only have to override the invokeInternal(Element, Document) - method, implement your logic, and return an Element if a response is + API. By extending fromAbstractDomPayloadEndpoint, you can use the + org.w3c.dom.Element + and related classes to handle the request and create the + response. When using the + AbstractDomPayloadEndpoint + as the baseclass for your + endpoints you only have to override the + invokeInternal(Element, Document) + method, implement your logic, and return an + Element + if a response is necessary. Here is a short example consisting of a class and a declaration in the application context. - + ]]> The above class and the declaration in the application context are all you need besides setting up an - endpoint mapping (see the section entitled ) to get this very + endpoint mapping (see the section entitled) to get this very simple endpoint working. The SOAP message handled by this endpoint will look something like: @@ -469,10 +627,13 @@ public class SampleEndpoint extends AbstractDomPayloadEndpoint { Hello ]]> -]]> +]]> + Though it could also handle the following Plain Old XML (POX) message, since we are only working on - the payload of the message, and do not care whether it is SOAP or POX. + the + payload + of the message, and do not care whether it is SOAP or POX. Hello @@ -486,34 +647,50 @@ public class SampleEndpoint extends AbstractDomPayloadEndpoint { Hello World! ]]> -]]> +]]> + - Besides the AbstractDomPayloadEndpoint, which uses W3C DOM, there are other + Besides theAbstractDomPayloadEndpoint, which uses W3C DOM, there are other base classes which use alternative DOM APIs. Spring Web Services supports most DOM APIs, so that you can use the one you are familiar with. For instance, the - AbstractJDomPayloadEndpoint allows you to use JDOM, and the - AbstractXomPayloadEndpoint uses XOM to handle the XML. All of these endpoints - have an invokeInternal method similar to above. + AbstractJDomPayloadEndpoint + allows you to use JDOM, and the + AbstractXomPayloadEndpoint + uses XOM to handle the XML. All of these endpoints + have an + invokeInternal + method similar to above. Also, consider using Spring-WS's XPath support to extract the information you need out of the payload. - (See the section entitled for details.) + (See the section entitled + + for details.)
- <classname>AbstractMarshallingPayloadEndpoint</classname> + + <classname>AbstractMarshallingPayloadEndpoint</classname> + Rather than handling XML directly using DOM, you can use marshalling to convert the payload of the XML message into a Java Object. Spring Web Services offers the - AbstractMarshallingPayloadEndpoint for this purpose, which is built on the - marshalling abstraction described in . The - AbstractMarshallingPayloadEndpoint has two properties: - marshaller and unmarshaller, in which you can inject in the + AbstractMarshallingPayloadEndpoint + for this purpose, which is built on the + marshalling abstraction described in. The + AbstractMarshallingPayloadEndpoint + has two properties: + marshaller + andunmarshaller, in which you can inject in the constructor or by setters. - When extending from AbstractMarshallingPayloadEndpoint, you have to override - the invokeInternal(Object) method, where the passed - Object represents the unmarshalled request payload, and return an - Object that will be marshalled into the response payload. Here is an + When extending fromAbstractMarshallingPayloadEndpoint, you have to override + the + invokeInternal(Object) + method, where the passed + Object + represents the unmarshalled request payload, and return an + Object + that will be marshalled into the response payload. Here is an example: - + @@ -554,15 +731,25 @@ public class MarshallingOrderEndpoint extends AbstractMarshallingPayloadEndpoint ]]><!-- Other beans, such as the endpoint mapping -->]]> +]]> + - In this sample, we configure a Jaxb2Marshaller for the - OrderRequest and Order classes, and inject that + In this sample, we configure a + Jaxb2Marshaller + for the + OrderRequest + and + Order + classes, and inject that marshaller together with the - DefaultOrderService into our endpoint. This business service is not shown, but + DefaultOrderService + into our endpoint. This business service is not shown, but it is a normal transactional service, probably using DAOs to obtain data from a database. - In the invokeInternal method, we cast the request object to an - OrderRequest object, which is the JAXB object representing the payload of the + In the + invokeInternal + method, we cast the request object to an + OrderRequest + object, which is the JAXB object representing the payload of the request. Using the identifier of that request, we obtain an order from our business service and return it. The returned object is marshalled into XML, and used as the payload of the response message. The SOAP request handled by this endpoint will look like: @@ -591,13 +778,16 @@ public class MarshallingOrderEndpoint extends AbstractMarshallingPayloadEndpoint ]]> - Instead of JAXB 2, we could have used any of the other marshallers described in . + Instead of JAXB 2, we could have used any of the other marshallers described in. The only thing that would change in the above example is the configuration of the - marshaller bean. + marshaller + bean.
- <interfacename>@Endpoint</interfacename> + + <interfacename>@Endpoint</interfacename> + The previous two programming models were based on inheritance, and handled individual XML messages. Spring Web Services offer another endpoint with which you can aggregate multiple handling into one @@ -629,16 +819,29 @@ public class AnnotationOrderEndpoint { }]]> - By annotating the class with @Endpoint, you mark it as a Spring-WS + By annotating the class with@Endpoint, you mark it as a Spring-WS endpoint. Because the endpoint class can have multiple request handling methods, we need to instruct Spring-WS which method to invoke for which request. This is done using the - @PayloadRoot annotation: the getOrder method - will be invoked for requests with a orderRequest local name and a - http://samples namespace URI; the order method for requests with - a order local name. For more information about these annotations, refer to + @PayloadRoot + annotation: the + getOrder + method + will be invoked for requests with a + orderRequest + local name and a + http://samples + namespace URI; the + order + method for requests with + a + order + local name. For more information about these annotations, refer to . - We also need to configure Spring-WS to support the JAXB objects OrderRequest and - Order by defining a Jaxb2Marshaller: + We also need to configure Spring-WS to support the JAXB objects + OrderRequest + and + Order + by defining aJaxb2Marshaller: @@ -665,17 +868,26 @@ public class AnnotationOrderEndpoint { ]]> - The GenericMarshallingMethodEndpointAdapter converts the incoming + The + GenericMarshallingMethodEndpointAdapter + converts the incoming XML messages to marshalled objects used as parameters and return value; the - PayloadRootAnnotationMethodEndpointMapping is the mapping that detects and - handles the @PayloadRoot annotations. + PayloadRootAnnotationMethodEndpointMapping + is the mapping that detects and + handles the + @PayloadRoot + annotations.
- <interfacename>@XPathParam</interfacename> + + <interfacename>@XPathParam</interfacename> + - As an alternative to using marshalling, we could have used XPath to + As an alternative to using marshalling, we could have used + XPath + to extract the information out of the incoming XML request. Spring-WS offers another annotation for - this purpose: @XPathParam. You simply annotate one or more method + this purpose:@XPathParam. You simply annotate one or more method parameter with this annotation (each), and each such annotated parameter will be bound to the evaluation of that annotation. Here is an example: @@ -697,15 +909,23 @@ public class AnnotationOrderEndpoint { } @PayloadRoot(localPart = "orderRequest", namespace = "http://samples") - public Source getOrder(]]>// create Source from order and return it + // create + Source + from order and return it + + +}]]> + Since we use the prefix 's' in our XPath expression, we must bind it to the - http://samples namespace: + http://samples + namespace: @@ -725,16 +945,41 @@ public class AnnotationOrderEndpoint { ]]>]]> +]]> + - Using the @XPathParam, you can bind to all the data types supported by + Using the@XPathParam, you can bind to all the data types supported by XPath: - boolean or Boolean - double or Double - String - Node - NodeList + + + boolean + or + Boolean + + + + + double + or + Double + + + + + String + + + + + Node + + + + + NodeList + +
@@ -745,44 +990,67 @@ public class AnnotationOrderEndpoint { The endpoint mapping is responsible for mapping incoming messages to appropriate endpoints. There are some endpoint mappings you can use out of the box, for example, the - PayloadRootQNameEndpointMapping or the + PayloadRootQNameEndpointMapping + or the SoapActionEndpointMapping, but let's first examine the general concept of an EndpointMapping. - An EndpointMapping delivers a EndpointInvocationChain, + An + EndpointMapping + delivers aEndpointInvocationChain, which contains the endpoint that matches the incoming request, and may also contain a list of endpoint interceptors that will be applied to the request and response. When a request comes in, the - MessageDispatcher will hand it over to the endpoint mapping to let it inspect the - request and come up with an appropriate EndpointInvocationChain. Then - the MessageDispatcher will invoke the endpoint and any interceptors in the chain. + MessageDispatcher + will hand it over to the endpoint mapping to let it inspect the + request and come up with an appropriateEndpointInvocationChain. Then + the + MessageDispatcher + will invoke the endpoint and any interceptors in the chain. The concept of configurable endpoint mappings that can optionally contain interceptors (which can manipulate the request or the response, or both) is extremely powerful. A lot of supporting functionality can be built - into custom EndpointMappings. For example, there could be a custom endpoint + into customEndpointMappings. For example, there could be a custom endpoint mapping that chooses an endpoint not only based on the contents of a message, but also on a specific SOAP header (or indeed multiple SOAP headers). - Most endpoint mappings inherit from the AbstractEndpointMapping, which offers an + Most endpoint mappings inherit from theAbstractEndpointMapping, which offers an 'interceptors' property, which is the list of interceptors to use. - EndpointInterceptors are discussed in + EndpointInterceptors + are discussed in . Additionally, there is the - 'defaultEndpoint', which is the default endpoint to use, when this endpoint mapping does + ' + defaultEndpoint', which is the default endpoint to use, when this endpoint mapping does not result in a matching endpoint.
- <classname>PayloadRootQNameEndpointMapping</classname> + + <classname>PayloadRootQNameEndpointMapping</classname> + - The PayloadRootQNameEndpointMapping will use the qualified name of the root + The + PayloadRootQNameEndpointMapping + will use the qualified name of the root element of the request payload to determine the endpoint that handles it. A qualified name consists of - a namespace URI and a local part, the combination of which + a + namespace URI + and alocal part, the combination of which should be unique within the mapping. Here is an example: - ]]><!-- no 'id' required, EndpointMapping beans are automatically detected by the MessageDispatcher --> + <!-- no + 'id' + required, + EndpointMapping + beans are automatically detected by the + MessageDispatcher + --> + + @@ -799,22 +1067,37 @@ public class AnnotationOrderEndpoint { -]]> +]]> + - The qualified name is expressed as { + namespace URI + } + + The qualified name is expressed as + { + + namespace URI + + } + + local part. Thus, the endpoint mapping above routes requests for which have a payload root element with - namespace http://samples and local part orderRequest to the - 'getOrderEndpoint'. Requests with a local part order will - be routed to the 'createOrderEndpoint'. + namespace + http://samples + and local part + orderRequest + to the + 'getOrderEndpoint'. Requests with a local part + order + will + be routed to the'createOrderEndpoint'.
- <classname>SoapActionEndpointMapping</classname> + + <classname>SoapActionEndpointMapping</classname> + Rather than base the routing on the contents of the message with the - PayloadRootQNameEndpointMapping, you can use the SOAPAction + PayloadRootQNameEndpointMapping, you can use the + SOAPAction HTTP header to route messages. Every client sends this header when making a SOAP request, and the - header value used for a request is defined in the WSDL. By making the SOAPAction + header value used for a request is defined in the WSDL. By making the + SOAPAction unique per operation, you can use it as a discriminator. Here is an example: @@ -836,9 +1119,13 @@ public class AnnotationOrderEndpoint { ]]> - The mapping above routes requests which have a SOAPAction of - http://samples/RequestOrder to the 'getOrderEndpoint'. Requests with - http://samples/CreateOrder will be routed to the 'createController'. + The mapping above routes requests which have a + SOAPAction + of + http://samples/RequestOrder + to the'getOrderEndpoint'. Requests with + http://samples/CreateOrder + will be routed to the'createController'. @@ -848,35 +1135,54 @@ public class AnnotationOrderEndpoint {
- <classname>MethodEndpointMapping</classname> + + <classname>MethodEndpointMapping</classname> + - As explained in , the @Endpoint style + As explained in, the + @Endpoint + style allows you to handle multiple requests in one endpoint class. This is the responsibility of the MethodEndpointMapping. Similar to the endpoint mapping described above, this mapping determines which method is to be invoked for an incoming request message. There are two endpoint mappings that can direct requests to methods: the - PayloadRootAnnotationMethodEndpointMapping and the + PayloadRootAnnotationMethodEndpointMapping + and the SoapActionAnnotationMethodEndpointMapping, both of which are very similar to their non-method counterparts described above. - The PayloadRootAnnotationMethodEndpointMapping uses the - @PayloadRoot annotation, with the localPart and - namespace elements, to mark methods with a particular qualified + The + PayloadRootAnnotationMethodEndpointMapping + uses the + @PayloadRoot + annotation, with the + localPart + and + namespace + elements, to mark methods with a particular qualified name. Whenever a message comes in which has this qualified name for the payload root element, the - method will be invoked. For an example, see above. + method will be invoked. For an example, seeabove. - Alternatively, the SoapActionAnnotationMethodEndpointMapping uses the - @SoapAction annotation to mark methods with a particular SOAP Action. - Whenever a message comes in which has this SOAPAction header, the + Alternatively, the + SoapActionAnnotationMethodEndpointMapping + uses the + @SoapAction + annotation to mark methods with a particular SOAP Action. + Whenever a message comes in which has this + SOAPAction + header, the method will be invoked.
- Intercepting requests - the <interfacename>EndpointInterceptor</interfacename> interface + Intercepting requests - the + <interfacename>EndpointInterceptor</interfacename> + 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 @@ -884,37 +1190,58 @@ public class AnnotationOrderEndpoint { Interceptors located in the endpoint mapping must implement the - EndpointInterceptor interface from the - org.springframework.ws.server package. This interface defines three methods, one that - can be used for handling the request message before the actual + EndpointInterceptor + interface from the + org.springframework.ws.server + package. This interface defines three methods, one that + can be used for handling the request message + before + the actual endpoint will be executed, one that can be used for handling a normal response message, and one that - can be used for handling fault messages, both of which will be called after the + can be used for handling fault messages, both of which will be called + after + the endpoint is executed. These three methods should provide enough flexibility to do all kinds of pre- and post-processing. - The handleRequest(..) method on the interceptor returns a boolean value. You + The + handleRequest(..) + method on the interceptor returns a boolean value. You can use this method to interrupt or continue the processing of the invocation chain. When this method - returns true, the endpoint execution chain will continue, when it returns - false, the MessageDispatcher interprets this to mean that + returnstrue, the endpoint execution chain will continue, when it returns + false, the + MessageDispatcher + interprets this to mean that the interceptor itself has taken care of things and does not continue executing the other interceptors and the actual endpoint - in the invocation chain. The handleResponse(..) and - handleFault(..) methods also have a boolean return value. When these methods - return false, the response will not be sent back to the client. + in the invocation chain. The + handleResponse(..) + and + handleFault(..) + methods also have a boolean return value. When these methods + returnfalse, the response will not be sent back to the client. - There are a number of standard EndpointInterceptor implementations you - can use in your Web service. Additionally, there is the XwsSecurityInterceptor, - which is described in . + There are a number of standard + EndpointInterceptor + implementations you + can use in your Web service. Additionally, there is theXwsSecurityInterceptor, + which is described in.
- <classname>PayloadLoggingInterceptor</classname> and - <classname>SoapEnvelopeLoggingInterceptor</classname> + + <classname>PayloadLoggingInterceptor</classname> + and + <classname>SoapEnvelopeLoggingInterceptor</classname> + When developing a Web service, it can be useful to log the incoming and outgoing XML messages. - SWS facilitates this with the PayloadLoggingInterceptor and - SoapEnvelopeLoggingInterceptor classes. The former logs just the payload of + SWS facilitates this with the + PayloadLoggingInterceptor + and + SoapEnvelopeLoggingInterceptor + classes. The former logs just the payload of the message to the Commons Logging Log; the latter logs the entire SOAP envelope, including SOAP headers. The following example shows you how to define them in an endpoint mapping: @@ -939,12 +1266,16 @@ public class AnnotationOrderEndpoint { ]]> Both of these interceptors have two properties: 'logRequest' and - 'logResponse', which can be set to false to disable logging + 'logResponse', which can be set to + false + to disable logging for either request or response messages.
- <classname>PayloadValidatingInterceptor</classname> + + <classname>PayloadValidatingInterceptor</classname> + 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 @@ -956,16 +1287,23 @@ public class AnnotationOrderEndpoint { Note that request validation may sound like a good idea, but makes the resulting Web service very strict. Usually, it is not really important whether the request validates, only if the endpoint can get sufficient information to fullfill a request. Validating the response - is a good idea, because the endpoint should adhere to its schema. + is + a good idea, because the endpoint should adhere to its schema. Remember Postel's Law: Be conservative in what you do; be liberal in what you accept from others. - Here is an example that uses the PayloadValidatingInterceptor; in this - example, we use the schema in /WEB-INF/orders.xsd to validate the response, but - not the request. Note that the PayloadValidatingInterceptor can also accept - multiple schemas using the schemas property. + Here is an example that uses thePayloadValidatingInterceptor; in this + example, we use the schema in + /WEB-INF/orders.xsd + to validate the response, but + not the request. Note that the + PayloadValidatingInterceptor + can also accept + multiple schemas using the + schemas + property. @@ -975,7 +1313,9 @@ public class AnnotationOrderEndpoint { ]]>
- <classname>PayloadTransformingInterceptor</classname> + + <classname>PayloadTransformingInterceptor</classname> + To transform the payload to another XML format, Spring Web Services offers the PayloadTransformingInterceptor. This endpoint interceptor is based on XSLT @@ -989,8 +1329,8 @@ public class AnnotationOrderEndpoint { ]]> - We are simply transforming requests using /WEB-INF/oldRequests.xslt, and - response messages using /WEB-INF/oldResponses.xslt. Note that, since + We are simply transforming requests using/WEB-INF/oldRequests.xslt, and + response messages using/WEB-INF/oldResponses.xslt. Note that, since endpoint interceptors are registered at the endpoint mapping level, you can simply create a endpoint mapping that applies to the "old style" messages, and add the interceptor to that mapping. Hence, the transformation will apply only to these "old style" message. @@ -1001,10 +1341,12 @@ public class AnnotationOrderEndpoint {
Handling Exceptions - Spring-WS provides EndpointExceptionResolvers to ease the pain of unexpected + Spring-WS provides + EndpointExceptionResolvers + to ease the pain of unexpected exceptions occurring while your message is being processed by an endpoint which matched the request. Endpoint exception resolvers somewhat resemble the exception mappings that can be - defined in the web application descriptor web.xml. + defined in the web application descriptorweb.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 @@ -1012,18 +1354,23 @@ public class AnnotationOrderEndpoint { example by returning a SOAP fault with a specific fault code and string. - Endpoint exception resolvers are automatically picked up by the MessageDispatcher, + Endpoint exception resolvers are automatically picked up by theMessageDispatcher, so no explicit configuration is necessary. - Besides implementing the EndpointExceptionResolver interface, which is only a - matter of implementing the resolveException(MessageContext, endpoint, Exception) + 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 default implementations. - The simplest implementation is the SimpleSoapExceptionResolver, which just + The simplest implementation is theSimpleSoapExceptionResolver, which just creates a SOAP 1.1 Server or SOAP 1.2 Receiver Fault, and uses the exception message as the fault string. - The SoapFaultMappingExceptionResolver is a more sophisticated implementation. + The + SoapFaultMappingExceptionResolver + is a more sophisticated implementation. This resolver enables you to take the class name of any exception that might be thrown and map it to a SOAP Fault, like so: @@ -1038,10 +1385,12 @@ public class AnnotationOrderEndpoint { ]]> - The key values and default endpoint use the format faultCode,faultString,locale, where + The key values and default endpoint use the formatfaultCode,faultString,locale, where only the fault code is required. If the fault string is not set, it will default to the exception message. If the language is not set, it will default to English. The above configuration will map exceptions of - type ValidationFailureException to a client-side SOAP Fault with a fault string + type + ValidationFailureException + to a client-side SOAP Fault with a fault string "Invalid request", as can be seen in the following response: @@ -1051,11 +1400,13 @@ public class AnnotationOrderEndpoint { Invalid request ]]> -]]> +]]> + If any other exception occurs, it will return the default fault: a server-side fault with the exception message as fault string. - Finally, it is also possible to annotate exception classes with the @SoapFault + Finally, it is also possible to annotate exception classes with the + @SoapFault annotation, to indicate the SOAP Fault that should be returned whenever that exception is thrown. The elements of the annotation include a fault code enumeration, fault string or reason, and language. Here is an example exception: @@ -1073,8 +1424,11 @@ public class MyBusinessException extends Exception { } }]]> - Whenever the MyBusinessException is thrown with the constructor string - "Oops!" during endpoint invocation, it will result in the following response: + Whenever the + MyBusinessException + is thrown with the constructor string + "Oops!" + during endpoint invocation, it will result in the following response: