INT-2688 Add header-type to xpath-header-enricher
JIRA: https://jira.springsource.org/browse/INT-2688 JIRA: https://jira.springsource.org/browse/INT-3237 Doc Polishing.
This commit is contained in:
committed by
Gary Russell
parent
b817e98a44
commit
16c7ac6134
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,22 +25,21 @@ import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractTransformerParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.xml.transformer.XPathHeaderEnricher;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for <xpath-header-enricher> elements.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
* @since 2.0
|
||||
*/
|
||||
public class XPathHeaderEnricherParser extends AbstractTransformerParser {
|
||||
|
||||
private static final String PACKAGE = "org.springframework.integration.xml.transformer";
|
||||
|
||||
|
||||
@Override
|
||||
protected final String getTransformerClassName() {
|
||||
return PACKAGE + ".XPathHeaderEnricher";
|
||||
return XPathHeaderEnricher.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,8 +60,8 @@ public class XPathHeaderEnricherParser extends AbstractTransformerParser {
|
||||
Element headerElement = (Element) node;
|
||||
String elementName = node.getLocalName();
|
||||
if ("header".equals(elementName)) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
PACKAGE + ".XPathHeaderEnricher$XPathExpressionEvaluatingHeaderValueMessageProcessor");
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(IntegrationNamespaceUtils.BASE_PACKAGE
|
||||
+ ".xml.transformer.XPathHeaderEnricher$XPathExpressionEvaluatingHeaderValueMessageProcessor");
|
||||
String expressionString = headerElement.getAttribute("xpath-expression");
|
||||
String expressionRef = headerElement.getAttribute("xpath-expression-ref");
|
||||
boolean isExpressionString = StringUtils.hasText(expressionString);
|
||||
@@ -79,6 +78,7 @@ public class XPathHeaderEnricherParser extends AbstractTransformerParser {
|
||||
}
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, headerElement, "evaluation-type");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, headerElement, "overwrite");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, headerElement, "header-type");
|
||||
String headerName = headerElement.getAttribute("name");
|
||||
headers.put(headerName, builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
@@ -20,6 +20,14 @@ import java.util.Map;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.transformer.HeaderEnricher;
|
||||
import org.springframework.integration.transformer.support.HeaderValueMessageProcessor;
|
||||
import org.springframework.integration.xml.DefaultXmlPayloadConverter;
|
||||
@@ -37,6 +45,7 @@ import org.springframework.xml.xpath.XPathExpressionFactory;
|
||||
*
|
||||
* @author Jonas Partner
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
* @since 2.0
|
||||
*/
|
||||
public class XPathHeaderEnricher extends HeaderEnricher {
|
||||
@@ -52,17 +61,21 @@ public class XPathHeaderEnricher extends HeaderEnricher {
|
||||
}
|
||||
|
||||
|
||||
static class XPathExpressionEvaluatingHeaderValueMessageProcessor implements HeaderValueMessageProcessor<Object> {
|
||||
static class XPathExpressionEvaluatingHeaderValueMessageProcessor implements HeaderValueMessageProcessor<Object>,
|
||||
BeanFactoryAware {
|
||||
|
||||
private TypeConverter typeConverter = new StandardTypeConverter();
|
||||
|
||||
private final XPathExpression expression;
|
||||
|
||||
private volatile XmlPayloadConverter converter = new DefaultXmlPayloadConverter();
|
||||
|
||||
private volatile XPathEvaluationType evaluationType = XPathEvaluationType.STRING_RESULT;
|
||||
private volatile XPathEvaluationType evaluationType = XPathEvaluationType.STRING_RESULT;
|
||||
|
||||
private volatile TypeDescriptor headerTypeDescriptor;
|
||||
|
||||
private volatile Boolean overwrite = null;
|
||||
|
||||
|
||||
public XPathExpressionEvaluatingHeaderValueMessageProcessor(String expression) {
|
||||
Assert.hasText(expression, "expression must have text");
|
||||
this.expression = XPathExpressionFactory.createXPathExpression(expression);
|
||||
@@ -77,6 +90,12 @@ public class XPathHeaderEnricher extends HeaderEnricher {
|
||||
this.evaluationType = evaluationType;
|
||||
}
|
||||
|
||||
public void setHeaderType(Class<?> headerType) {
|
||||
if (headerType != null) {
|
||||
this.headerTypeDescriptor = TypeDescriptor.valueOf(headerType);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOverwrite(Boolean overwrite) {
|
||||
this.overwrite = overwrite;
|
||||
}
|
||||
@@ -86,6 +105,14 @@ public class XPathHeaderEnricher extends HeaderEnricher {
|
||||
return this.overwrite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
ConversionService conversionService = IntegrationContextUtils.getConversionService(beanFactory);
|
||||
if (conversionService != null) {
|
||||
this.typeConverter = new StandardTypeConverter(conversionService);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object processMessage(Message<?> message) {
|
||||
Node node = converter.convertToNode(message.getPayload());
|
||||
@@ -93,7 +120,12 @@ public class XPathHeaderEnricher extends HeaderEnricher {
|
||||
if (result instanceof String && ((String) result).length() == 0) {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
if (result != null && this.headerTypeDescriptor != null) {
|
||||
return this.typeConverter.convertValue(result, TypeDescriptor.forObject(result), this.headerTypeDescriptor);
|
||||
}
|
||||
else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -441,6 +441,13 @@
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="header-type" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:java.lang.Class"><![CDATA[
|
||||
The fully qualified class name of the header value's expected type.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<!-- XPath Router definition -->
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
<xpath-header-enricher input-channel="input" output-channel="output">
|
||||
<header name="name" xpath-expression="/person/@name" />
|
||||
<header name="age" xpath-expression="/person/@age" evaluation-type="NUMBER_RESULT" />
|
||||
<header name="age" xpath-expression="/person/@age" evaluation-type="NUMBER_RESULT" header-type="int"/>
|
||||
<header name="married" xpath-expression="/person/@married = 'true'" evaluation-type="BOOLEAN_RESULT" />
|
||||
<header name="node-test" xpath-expression="/person/@age" evaluation-type="NODE_RESULT" />
|
||||
<header name="node-list-test" xpath-expression="/person/@*" evaluation-type="NODE_LIST_RESULT" />
|
||||
<header name="ref-test" xpath-expression-ref="testExpression" evaluation-type="NUMBER_RESULT" />
|
||||
<header name="ref-test" xpath-expression-ref="testExpression" evaluation-type="NUMBER_RESULT" />
|
||||
</xpath-header-enricher>
|
||||
|
||||
<xpath-expression id="testExpression" expression="/person/@age * 2"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,16 +28,18 @@ import org.w3c.dom.Node;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@@ -65,7 +67,7 @@ public class XPathHeaderEnricherParserTests {
|
||||
@Test
|
||||
public void numberResult() {
|
||||
Message<?> result = this.getResultMessage();
|
||||
assertEquals(new Double(42), result.getHeaders().get("age"));
|
||||
assertEquals(42, result.getHeaders().get("age"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
<year>2011</year>
|
||||
<year>2012</year>
|
||||
<year>2013</year>
|
||||
<year>2014</year>
|
||||
<holder>
|
||||
GoPivotal, Inc. All Rights Reserved.
|
||||
</holder>
|
||||
|
||||
@@ -20,5 +20,14 @@
|
||||
<ulink url="https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-3.0-to-4.0-Migration-Guide"
|
||||
>Migration Guide</ulink>.
|
||||
</para>
|
||||
<section id="3.0-xpath-header-enricher-header-type">
|
||||
<title>Header Type for XPath Header Enricher</title>
|
||||
<para>
|
||||
The <code>header-type</code> attribute has been introduced for the <code>header</code> sub-element of the
|
||||
<code><int-xml:xpath-header-enricher></code>. This attribute provides the target type for
|
||||
the header value to which the result of the XPath expression evaluation will be converted.
|
||||
For more information see <xref linkend="xml-xpath-header-enricher"/>.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
@@ -1051,9 +1051,10 @@
|
||||
<int:poller></int:poller> ]]><co id="xpath-header-enricher-xml06-co" linkends="xpath-header-enricher-xml06" /><![CDATA[
|
||||
<int-xml:header name="" ]]><co id="xpath-header-enricher-xml07-co" linkends="xpath-header-enricher-xml07" /><![CDATA[
|
||||
evaluation-type="STRING_RESULT" ]]><co id="xpath-header-enricher-xml08-co" linkends="xpath-header-enricher-xml08" /><![CDATA[
|
||||
overwrite="true" ]]><co id="xpath-header-enricher-xml09-co" linkends="xpath-header-enricher-xml09" /><![CDATA[
|
||||
xpath-expression="" ]]><co id="xpath-header-enricher-xml10-co" linkends="xpath-header-enricher-xml10" /><![CDATA[
|
||||
xpath-expression-ref=""/> ]]><co id="xpath-header-enricher-xml11-co" linkends="xpath-header-enricher-xml11" /><![CDATA[
|
||||
header-type="int" ]]><co id="xpath-header-enricher-xml09-co" linkends="xpath-header-enricher-xml09" /><![CDATA[
|
||||
overwrite="true" ]]><co id="xpath-header-enricher-xml10-co" linkends="xpath-header-enricher-xml10" /><![CDATA[
|
||||
xpath-expression="" ]]><co id="xpath-header-enricher-xml11-co" linkends="xpath-header-enricher-xml11" /><![CDATA[
|
||||
xpath-expression-ref=""/> ]]><co id="xpath-header-enricher-xml12-co" linkends="xpath-header-enricher-xml12" /><![CDATA[
|
||||
</int-xml:xpath-header-enricher>]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
@@ -1102,24 +1103,38 @@
|
||||
</callout>
|
||||
<callout arearefs="xpath-header-enricher-xml08-co" id="xpath-header-enricher-xml08">
|
||||
<para>
|
||||
The result type expected from the XPath evaluation. This will be the type of the header value.
|
||||
The result type expected from the XPath evaluation. This will be the type of the header value, if there is no
|
||||
<code>header-type</code> attribute provided.
|
||||
The following values are allowed: BOOLEAN_RESULT, STRING_RESULT, NUMBER_RESULT, NODE_RESULT and NODE_LIST_RESULT.
|
||||
Defaults internally to <code>XPathEvaluationType.STRING_RESULT</code> if not set. <emphasis>Optional</emphasis>.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="xpath-header-enricher-xml09-co" id="xpath-header-enricher-xml09">
|
||||
<para>
|
||||
The fully qualified class name for the header value type. The result of XPath evaluation will be
|
||||
converted to this type using the <interfacename>ConversionService</interfacename>.
|
||||
This allows, for example, a <code>NUMBER_RESULT</code> (a double) to be converted to an
|
||||
<code>Integer</code>. The type can be declared as a primitive (e.g. <code>int</code>) but
|
||||
the result will always be the equivalent wrapper class (e.g. <code>Integer</code>).
|
||||
The same integration <interfacename>ConversionService</interfacename> discussed in
|
||||
<xref linkend="payload-type-conversion"/> is used for the conversion, so conversion to custom
|
||||
types is supported, by adding a custom converter to the service.
|
||||
<emphasis>Optional</emphasis>.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="xpath-header-enricher-xml10-co" id="xpath-header-enricher-xml10">
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="xpath-header-enricher-xml10-co" id="xpath-header-enricher-xml10">
|
||||
<callout arearefs="xpath-header-enricher-xml11-co" id="xpath-header-enricher-xml11">
|
||||
<para>
|
||||
The XPath Expression as a String. Either this attribute or
|
||||
<code>xpath-expression-ref</code> must be provided, but not both.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="xpath-header-enricher-xml11-co" id="xpath-header-enricher-xml11">
|
||||
<callout arearefs="xpath-header-enricher-xml12-co" id="xpath-header-enricher-xml12">
|
||||
<para>
|
||||
The XPath Expression reference. Either this attribute or
|
||||
<code>xpath-expression</code> must be provided, but not both.
|
||||
|
||||
Reference in New Issue
Block a user