XML Support - Dealing with XML Payloads
Introduction Spring Integration's XML support extends the core of Spring Integration with the following components: Marshalling Transformer Unmarshalling Transformer Xslt Transformer XPath Transformer XPath Splitter XPath Router XPath Header Enricher XPath Filter Validating Filter These components are designed to make working with XML messages in Spring Integration simple. The provided messaging components are designed to work with XML represented in a range of formats including instances of java.lang.String, org.w3c.dom.Document and javax.xml.transform.Source. It should be noted however that where a DOM representation is required, for example in order to evaluate an XPath expression, the String payload will be converted into the required type and then converted back again to String. Components that require an instance of DocumentBuilder will create a namespace-aware instance if one is not provided. In cases where you require greater control over document creation, you can provide an appropriately configured instance of DocumentBuilder.
Namespace Support All components within the Spring Integration XML module provide namespace support. In order to enable namespace support, you need to import the respective schema for the Spring Integration XML Module. A typical setup is shown below: ]]>
XPath Expressions Many of the components within the Spring Integration XML module work with XPath Expressions. Each of those components will either reference an XPath Expression that has been defined as top-level element or via a nested <xpath-expression/> element. All forms of XPath expressions result in the creation of an XPathExpression using the Spring org.springframework.xml.xpath.XPathExpressionFactory. When creating XPath expressions, the best XPath implementation that is available on the classpath is being used, either JAXP 1.3+ or Jaxen, whereby JAXP is preferred. Spring Integration under the covers uses the XPath functionality as provided by the Spring Web Services project (http://www.springsource.org/spring-web-services). Specifically, Spring Web Services' XML module (spring-xml-x.x.x.jar) is being used. Therefore, for a deeper understanding, please refer to the respective documentation as well at: http://static.springsource.org/spring-ws/sites/2.0/reference/html/common.html#xpath Here is an overview of all available configuration parameters of the xpath-expression element: ]]> ]]>]]> Defines an XPath xpression. Required. The Identifier of the underlying bean definition. Will be an instance of org.springframework.xml.xpath.XPathExpression Optional. Reference to a map containing namespaces. The key of the map defines the namespace prefix and the value of the map sets the namespace URI. It is not valid to specify both this attribute and the map sub element, or setting the ns-prefix and ns-uri attribute. Optional. Allows you to set the namspace prefix directly as and attribute on the XPath expression element. If you set ns-prefix, you must also set the ns-uri attribute. Optional. Allows you to set the namspace URI directly as an attribute on the XPath expression element. If you set ns-uri, you must also set the ns-prefix attribute. Optional. Defines a map containing namespaces. Only one map child element is allowed. The key of the map defines the namespace prefix and the value of the map sets the namespace URI. It is not valid to specify both this sub-element and the map attribute, or setting the ns-prefix and ns-uri attributes. Optional.
Providing Namespaces (Optional) to XPath Expressions For the XPath Expression Element, namespace information can be optionally provided as configuration parameters. As such, namespaces can be defined using one of the following 3 choices: Reference a map using the namespace-map attribute Provide a map of namespaces using the map sub-element Specifying the ns-prefix and the ns-uri attribute All three options are mutially exlusive. Only one option can be set. Below, please find several different usage examples on how to use XPath expressions using the XML namespace support including the various option for setting the XML namespaces as discussed above. ]]>
Using XPath Expressions with Default Namespaces When working with default nanmespaces, you may run into situations that behave differently than originally expected. Let's assume we have the following XML document: 0321200683 2 1590596439 1 ]]> This document is not declaring any namespace. Therefore, applying the following XPath Expression will work as expected: ]]> You might expect that the same expression will also work for the following XML file. It looks exactly the same as the previous example but in addition it also declares a default namespace: http://www.example.org/orders 0321200683 2 1590596439 1 ]]> However, the XPath Expression used previously will fail in this case. In order to solve this issue, you must provide a namespace prefix and a namespace URI using either the ns-prefix and ns-uri attibute or by providing a namespace-map attribute instead. The namespace URI must match the namespace declared in your XML document, which in this example is http://www.example.org/orders. The namespace prefix, however, can be arbitrarily chosen. In fact, just providing an empty String will actually work (Null is not allowed). In the case of a namespace prefix consisting of an empty String, your Xpath Expression will use a colon (":") to indicate the default namespace. If you leave the colon off, the XPath expression will not match. The following XPath Expression will match agains the XML document above: ]]> Of course you can also provide any other arbitrarily chosen namespace prefix. The following XPath expression using the myorder namespace prefix will match also: ]]> It is important to remember that the namespace URI is the really important piece of information to declare, not the prefix itself. The Jaxen FAQ summarizes the point very well: In XPath 1.0, all unprefixed names are unqualified. There is no requirement that the prefixes used in the XPath expression are the same as the prefixes used in the document being queried. Only the namespace URIs need to match, not the prefixes.
Transforming XML Payloads
Configuring Transformers as Beans This section will explain the workings of the following transformers and how to configure them as beans: UnmarshallingTransformer MarshallingTransformer XsltPayloadTransformer All of the provided XML transformers extend AbstractTransformer or AbstractPayloadTransformer and therefore implement Transformer. When configuring XML transformers as beans in Spring Integration, you would normally configure the Transformer in conjunction with either a MessageTransformingChannelInterceptor or a MessageTransformingHandler. This allows the transformer to be used as either an interceptor, which transforms the message as it is sent or received to the Channel, or as an Endpoint. Finally, the namespace support will be discussed, which allows for the simple configuration of the transformers as elements in XML.
UnmarshallingTransformer An UnmarshallingTransformer allows an XML Source to be unmarshalled using implementations of the Spring OXM Unmarshaller. Spring's Object/XML Mapping support provides several implementations supporting marshalling and unmarshalling using JAXB, Castor and JiBX amongst others. The unmarshaller requires an instance of Source. If the message payload is not an instance of Source, conversion will be attempted. Currently String, File and org.w3c.dom.Document payloads are supported. Custom conversion to a Source is also supported by injecting an implementation of a SourceFactory. If a SourceFactory is not set explicitly, the property on the UnmarshallingTransformer will by default be set to a DomSourceFactory. ]]>
MarshallingTransformer The MarshallingTransformer allows an object graph to be converted into XML using a Spring OXM Marshaller. By default the MarshallingTransformer will return a DomResult. However, the type of result can be controlled by configuring an alternative ResultFactory such as StringResultFactory. In many cases it will be more convenient to transform the payload into an alternative XML format. To achieve this, configure a ResultTransformer. Two implementations are provided, one which converts to String and another which converts to Document. ]]> By default, the MarshallingTransformer will pass the payload Object to the Marshaller, but if its boolean extractPayload property is set to false, the entire Message instance will be passed to the Marshaller instead. That may be useful for certain custom implementations of the Marshaller interface, but typically the payload is the appropriate source Object for marshalling when delegating to any of the various out-of-the-box Marshaller implementations.
XsltPayloadTransformer XsltPayloadTransformer transforms XML payloads using Extensible Stylesheet Language Transformations (XSLT). The transformer's constructor requires an instance of either Resource or Templates to be passed in. Passing in a Templates instance allows for greater configuration of the TransformerFactory used to create the template instance. As with the UnmarshallingTransformer, the XsltPayloadTransformer will do the actual XSLT transformation using instances of Source. Therefore, if the message payload is not an instance of Source, conversion will be attempted. String and Document payloads are supported directly. Custom conversion to a Source is also supported by injecting an implementation of a SourceFactory. If a SourceFactory is not set explicitly, the property on the XsltPayloadTransformer will by default be set to a DomSourceFactory. By default, the XsltPayloadTransformer will create a message with a Result payload, similar to the XmlPayloadMarshallingTransformer. This can be customised by providing a ResultFactory and/or a ResultTransformer. ]]>
ResultTransformers Both the MarshallingTransformer and the XsltPayloadTransformer allow you to specify a ResultTransformer. Thus, if the Marshalling or XSLT transformation returns a Result, than you have the option to also use a ResultTransformer to transform the Result into another format. Spring Integration provides 2 concrete ResultTransformer implementations: ResultToDocumentTransformer ResultToStringTransformer Using ResultTransformers with the MarshallingTransformer By default, the MarshallingTransformer will always return a Result. By specifying a ResultTransformer, you can customize the type of payload returned. Using ResultTransformers with the XsltPayloadTransformer The behavior is slighly more complex for the XsltPayloadTransformer. By default, if the input payload is an instance of String or Document the resultTransformer property is ignored. However, if the input payload is a Source or any other type, then the resultTransformer property is applied. Additionally, you can set the property alwaysUseResultFactory to true, which will also cause the specified resultTransformer to being used. For more information and examples, please see
Namespace Support for XML Transformers Namespace support for all XML transformers is provided in the Spring Integration XML namespace, a template for which can be seen below. The namespace support for transformers creates an instance of either EventDrivenConsumer or PollingConsumer according to the type of the provided input channel. The namespace support is designed to reduce the amount of XML configuration by allowing the creation of an endpoint and transformer using one element. UnmarshallingTransformer The namespace support for the UnmarshallingTransformer is shown below. Since the namespace is now creating an endpoint instance rather than a transformer, a poller can also be nested within the element to control the polling of the input channel. ]]> MarshallingTransformer The namespace support for the marshalling transformer requires an input-channel, output-channel and a reference to a marshaller. The optional result-type attribute can be used to control the type of result created. Valid values are StringResult or DomResult (the default). ]]> Where the provided result types are not sufficient, a reference to a custom implementation of ResultFactory can be provided as an alternative to setting the result-type attribute, using the result-factory attribute. The attributes result-type and result-factory are mutually exclusive. Internally, the result types StringResult and DomResult are represented by the ResultFactorys StringResultFactory and DomResultFactory respectively. XsltPayloadTransformer Namespace support for the XsltPayloadTransformer allows you to either pass in a Resource, in order to create the Templates instance, or alternatively, you can pass in a precreated Templates instance as a reference. In common with the marshalling transformer, the type of the result output can be controlled by specifying either the result-factory or result-type attribute. A result-transfomer attribute can also be used to reference an implementation of ResultTransfomer where conversion of the result is required before sending. If you specify the result-factory or the result-type attribute, then the alwaysUseResultFactory property on the underlying XsltPayloadTransformer will be set to true by the XsltPayloadTransformerParser. ]]> Often you may need to have access to Message data, such as the Message Headers, in order to assist with transformation. For example, you may need to get access to certain Message Headers and pass them on as parameters to a transformer (e.g., transformer.setParameter(..)). Spring Integration provides two convenient ways to accomplish this, as illustrated in following example: ]]> If message header names match 1:1 to parameter names, you can simply use xslt-param-headers attribute. There you can also use wildcards for simple pattern matching, which supports the following simple pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy". You can also configure individual Xslt parameters via the <xslt-param/> sub element. There you can use either the expression or value attribute. The expression attribute should be any valid SpEL expression with Message being the root object of the expression evaluation context. The value attribute, just like any value in Spring beans, allows you to specify simple scalar values. You can also use property placeholders (e.g., ${some.value}). So as you can see, with the expression and value attribute, Xslt parameters could now be mapped to any accessible part of the Message as well as any literal value.
Namespace Configuration and ResultTransformers The usage of ResultTransformers was previously introduced in . The following example illustrates several special use-cases using XML namespace configuration. First, we define the ResultTransformer: ]]> This ResultTransformer will accept either a StringResult or a DOMResult as input and converts the input into a Document. Now, let's declare the transformer: ]]> If the incoming message's payload is of type Source, then as first step the Result is determined using the ResultFactory. As we did not specify a ResultFactory, the default DomResultFactory is used, meaning that the transformation will yield a DomResult. However, as we specified a ResultTransformer, it will be used and the resulting Message payload will be of type Document. If the incoming message's payload is of type String, the payload after the Xslt transformation will be a String. Similarly, if the incoming message's payload is of type Document, the payload after the Xslt transformation will be a Document. The specified ResultTransformer will be ignored with String or Document payloads. If the message payload is neither a Source, String or Document, as a fallback option, it is attempted to create a Source using the default SourceFactory. As we did not specify a SourceFactory explicitly using the source-factory attribute, the default DomSourceFactory is used. If successful, the XSLT transformation is executed as if the payload was of type Source, which we described in the previous paragraphs. The DomSourceFactory supports the creation of a DOMSource from a either Document, File or String payloads. The next transformer declaration adds a result-type attribute using StringResult as its value. First, the result-type is internally represented by the StringResultFactory. Thus, you could have also added a reference to a StringResultFactory, using the result-factory attribute, which would haven been the same. ]]> Because we are using a ResultFactory, the alwaysUseResultFactory property of the XsltPayloadTransformer class will be implicitly set to true. Consequently, the referenced ResultToDocumentTransformer will be used. Therefore, if you transform a payload of type String, the resulting payload will be of type Document.
Transforming XML Messages Using XPath When it comes to message transformation XPath is a great way to transform Messages that have XML payloads by defining XPath transformers via <xpath-transformer/> element. Simple XPath transformation Let's look at the following transformer configuration: ]]> . . . and Message message = MessageBuilder.withPayload("").build();]]> After sending this message to the 'inputChannel' the XPath transformer configured above will transform this XML Message to a simple Message with payload of 'John Doe' all based on the simple XPath Expression specified in the xpath-expression attribute. XPath also has the capability to perform simple conversion of extracted elements to a desired type. Valid return types are defined in javax.xml.xpath.XPathConstants and follows the conversion rules specified by the javax.xml.xpath.XPath interface. The following constants are defined by the XPathConstants class: BOOLEAN, DOM_OBJECT_MODEL, NODE, NODESET, NUMBER, STRING You can configure the desired type by simply using the evaluation-type attribute of the <xpath-transformer/> element. ]]> Node Mappers If you need to provide custom mapping for the node extracted by the XPath expression simply provide a reference to the implementation of the org.springframework.xml.xpath.NodeMapper - an interface used by XPathOperations implementations for mapping Node objects on a per-node basis. To provide a reference to a NodeMapper simply use node-mapper attribute: ]]> . . . and Sample NodeMapper implementation: XML Payload Converter You can also use an implementation of the org.springframework.integration.xml.XmlPayloadConverter to provide more granular transformation: ]]> . . . and Sample XmlPayloadConverter implementation: "))); } catch (Exception e) { throw new IllegalStateException(e); } } // public Document convertToDocument(Object object) { throw new UnsupportedOperationException(); } }]]> The DefaultXmlPayloadConverter is used if this reference is not provided, and it should be sufficient in most cases since it can convert from Node, Document, Source, File, and String typed payloads. If you need to extend beyond the capabilities of that default implementation, then an upstream Transformer is probably a better option than providing a reference to a custom implementation of this strategy here.
Splitting XML Messages XPathMessageSplitter supports messages with either String or Document payloads. The splitter uses the provided XPath expression to split the payload into a number of nodes. By default this will result in each Node instance becoming the payload of a new message. Where it is preferred that each message be a Document the createDocuments flag can be set. Where a String payload is passed in the payload will be converted then split before being converted back to a number of String messages. The XPath splitter implements MessageHandler and should therefore be configured in conjunction with an appropriate endpoint (see the namespace support below for a simpler configuration alternative). ]]> XPath splitter namespace support allows the creation of a Message Endpoint with an input channel and output channel. ]]>
Routing XML Messages Using XPath Similar to SpEL-based routers, Spring Integration provides support for routing messages based on XPath expressions, allowing you to create a Message Endpoint with an input channel but no output channel. Instead, one or more output channels are determined dynamically. ]]> For an overview of attributes that are common among Routers, please see chapter: Internally XPath expressions will be evaluated as NODESET type and converted to a List<String> representing channel names. Typically such a list will contain a single channel name. However, based on the results of an XPath Expression, the XPath router can also take on the characteristics of a Recipient List Router if the XPath Expression returns more then one value. In that case, the List<String> will contain more then one channel name and consequently Messages will be sent to all channels in the list. Thus, assuming that the XML file passed to the router configured below contains many responder sub-elements representing channel names, the message will be sent to all of those channels. ]]> If the returned values do not represent the channel names directly, additional mapping parameters can be specified, in order to map those returned values to actual channel names. For example if the /request/responders expression results in two values responderA and responderB but you don't want to couple the responder names to channel names, you may provide additional mapping configuration such as the following: ]]> As already mentioned, the default evaluation type for XPath expressions is NODESET, which is converted to a List<String> of channel names, therefore handling single channel scenarios as well as multiple ones. Nonetheless, certain XPath expressions may evaluate as String type from the very beginning. Take for example the following XPath Expression: This expression will return the name of the root node. It will resulting in an exception, if the default evaluation type NODESET is being used. For these scenarious, you may use the evaluate-as-string attribute, which will allow you to manage the evaluation type. It is FALSE by default, however if set to TRUE, the String evaluation type will be used. To provide some background information: XPath 1.0 specifies 4 data types: Node-sets Strings Number Boolean When the XPath Router evaluates expressions using the optional evaluate-as-string attribute, the return value is determined per the string() function as defined in the XPath specification. This means that if the expression selects multiple nodes, it will return the string value of the first node. For further information, please see: Specification: XML Path Language (XPath) Version 1.0: http://www.w3.org/TR/xpath/ XPath specification - string() function: http://www.w3.org/TR/xpath/#function-string For example if we want to route based on the name of the root node, we can use the following configuration: ]]>
XML Payload Converter For XPath Routers, you can also specify the Converter to use when converting payloads prior to XPath evaluation. As such, the XPath Router supports custom implementations of the XmlPayloadConverter strategy, and when configuring an xpath-router element in XML, a reference to such an implementation may be provided via the converter attribute. If this reference is not explicitly provided, the DefaultXmlPayloadConverter is used. It should be sufficient in most cases, since it can convert from Node, Document, Source, File, and String typed payloads. If you need to extend beyond the capabilities of that default implementation, then an upstream Transformer is generally a better option in most cases, rather than providing a reference to a custom implementation of this strategy here.
XPath Header Enricher The XPath Header Enricher defines a Header Enricher Message Transformer that evaluates XPath expressions against the message payload and inserts the result of the evaluation into a messsage header. Please see below for an overview of all available configuration parameters: ]]> ]]> ]]>]]> Specify the default boolean value for whether to overwrite existing header values. This will only take effect for sub-elements that do not provide their own 'overwrite' attribute. If the 'default- overwrite' attribute is not provided, then the specified header values will NOT overwrite any existing ones with the same header names. Optional. Id for the underlying bean definition. Optional. The receiving Message channel of this endpoint. Optional. Channel to which enriched messages shall be send to. Optional. Specify whether null values, such as might be returned from an expression evaluation, should be skipped. The default value is true. Set this to false if a null value should trigger removal of the corresponding header instead. Optional. Optional. The name of the header to be enriched. Mandatory. The result type expected from the XPath evaluation. This will be the type of the header value. The following values are allowed: BOOLEAN_RESULT, STRING_RESULT, NUMBER_RESULT, NODE_RESULT and NODE_LIST_RESULT. Defaults internally to XPathEvaluationType.STRING_RESULT if not set. Optional. Boolean value to indicate whether this header value should overwrite an existing header value for the same name if already present on the input Message. The XPath Expression as a String. Either this attribute or xpath-expression-ref must be provided, but not both. The XPath Expression reference. Either this attribute or xpath-expression must be provided, but not both.
Using the XPath Filter This component defines an XPath-based Message Filter. Under the covers this components uses a MessageFilter that wraps an instance of AbstractXPathMessageSelector. Please also refer to the chapter on Message Filters for further details. In order to use the XPath Filter you must as a minimum provide an XPath Expression either by declaring the xpath-expression sub-element or by referencing an XPath Expression using the xpath-expression-ref attribute. If the provided XPath expression will evaluate to a boolean value, no further configuration parameters are necessary. However, if the XPath expression will evaluate to a String, the match-value attribute should be specified against which the evaluation result will be matched. There are three options for the match-type: exact - correspond to equals on java.lang.String. The underlying implementation uses a StringValueTestXPathMessageSelector case-insensitive - correspond to equals-ignore-case on java.lang.String. The underlying implementation uses a StringValueTestXPathMessageSelector regex - matches operations one java.lang.String. The underlying implementation uses a RegexTestXPathMessageSelector When providing a 'match-type' value of 'regex', the value provided with thos match-value attribute must be a valid Regular Expression. In prior versions of Spring Integration the functionality of the XPath Filter was configured using the xpath-selector element. However, in order to provide a more consistent behavior within the Spring Integration Framework, the xpath-selector element is deprecated as of version 2.1. Please use <xpath-filter> instead. It provides the same set of functionality. In fact it still uses the same MessageSelectors internally. ]]> ]]> ]]>]]> Message Channel where you want rejected messages to be sent. Optional. Id for the underlying bean definition. Optional. The receiving Message channel of this endpoint. Optional. Type of match to apply between the XPath evaluation result and the match-value. Default is exact. Optional. String value to be matched against the XPath evaluation result. If this attribute is not provided, then the XPath evaluation MUST produce a boolean result directly. Optional. The channel to which Messages that matched the filter criterias shall be dispatched to. Optional. By default, this property is set to false and rejected Messages (Messages that did not match the filter criteria) will be silently dropped. However, if set to true message rejection will result in an error condition and the exception will be propagated upstream to the caller. Optional. Reference to an XPath expression instance to evaluate. This sub-element sets the XPath expression to be evaluated. If this is not defined you MUST define the xpath-expression-ref attribute. Also, only one xpath-expression element can be set. Optional.
XML Validating Filter The XML Validating Filter allows you to validate incoming messages against provided schema instances. The following schema types are supported: xml-schema (http://www.w3.org/2001/XMLSchema) relax-ng (http://relaxng.org/ns/structure/1.0) Messages that fail validation can either be silently dropped or they can be forwarded to a definable discard-channel. Furthermore you can configure this filter to throw an Exception in case validation fails. Please see below for an overview of all available configuration parameters: ]]> ]]>]]> Message Channel where you want rejected messages to be sent. Optional. Id for the underlying bean definition. Optional. The receiving Message channel of this endpoint. Optional. Message Channel where you want accepted messages to be sent. Optional. Sets the location of the schema to validate the Message's payload against. Internally uses the org.springframework.core.io.Resource interface. You can set this attribute or the xml-validator attribute but not both. Optional. Sets the schema type. Can be either xml-schema or relax-ng. Optional. If not set it defaults to xml-schema which internally translates to org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML If true a MessageRejectedException is thrown in case validation fails for the provided Message's payload. Optional. Defaults to false if not set. Reference to a custom sorg.springframework.xml.validation.XmlValidator strategy. You can set this attribute or the schema-location attribute but not both. Optional. Optional.