From 16c7ac6134a5639e0d0404064ff7adc260483e43 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Tue, 21 Jan 2014 16:03:21 +0200 Subject: [PATCH] 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. --- .../xml/config/XPathHeaderEnricherParser.java | 14 +++---- .../xml/transformer/XPathHeaderEnricher.java | 40 +++++++++++++++++-- .../xml/config/spring-integration-xml-4.0.xsd | 7 ++++ ...XPathHeaderEnricherParserTests-context.xml | 4 +- .../XPathHeaderEnricherParserTests.java | 10 +++-- src/reference/docbook/index.xml | 1 + src/reference/docbook/whats-new.xml | 9 +++++ src/reference/docbook/xml.xml | 27 ++++++++++--- 8 files changed, 89 insertions(+), 23 deletions(-) diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathHeaderEnricherParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathHeaderEnricherParser.java index 4e1df1e79e..1ae830f95b 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathHeaderEnricherParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathHeaderEnricherParser.java @@ -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()); } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XPathHeaderEnricher.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XPathHeaderEnricher.java index 5b7b374e3c..a848150611 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XPathHeaderEnricher.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XPathHeaderEnricher.java @@ -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 { + static class XPathExpressionEvaluatingHeaderValueMessageProcessor implements HeaderValueMessageProcessor, + 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; + } } } diff --git a/spring-integration-xml/src/main/resources/org/springframework/integration/xml/config/spring-integration-xml-4.0.xsd b/spring-integration-xml/src/main/resources/org/springframework/integration/xml/config/spring-integration-xml-4.0.xsd index 940c14bef3..57ca763388 100644 --- a/spring-integration-xml/src/main/resources/org/springframework/integration/xml/config/spring-integration-xml-4.0.xsd +++ b/spring-integration-xml/src/main/resources/org/springframework/integration/xml/config/spring-integration-xml-4.0.xsd @@ -441,6 +441,13 @@ + + + + + diff --git a/spring-integration-xml/src/test/java/org/springframework/integration/xml/config/XPathHeaderEnricherParserTests-context.xml b/spring-integration-xml/src/test/java/org/springframework/integration/xml/config/XPathHeaderEnricherParserTests-context.xml index 75efb2ea2b..e337495159 100644 --- a/spring-integration-xml/src/test/java/org/springframework/integration/xml/config/XPathHeaderEnricherParserTests-context.xml +++ b/spring-integration-xml/src/test/java/org/springframework/integration/xml/config/XPathHeaderEnricherParserTests-context.xml @@ -16,11 +16,11 @@
-
+
-
+
diff --git a/spring-integration-xml/src/test/java/org/springframework/integration/xml/config/XPathHeaderEnricherParserTests.java b/spring-integration-xml/src/test/java/org/springframework/integration/xml/config/XPathHeaderEnricherParserTests.java index 329e874dd5..e227c1a4be 100644 --- a/spring-integration-xml/src/test/java/org/springframework/integration/xml/config/XPathHeaderEnricherParserTests.java +++ b/spring-integration-xml/src/test/java/org/springframework/integration/xml/config/XPathHeaderEnricherParserTests.java @@ -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 diff --git a/src/reference/docbook/index.xml b/src/reference/docbook/index.xml index 62b8d4a7eb..de8b8b7f1e 100644 --- a/src/reference/docbook/index.xml +++ b/src/reference/docbook/index.xml @@ -54,6 +54,7 @@ 2011 2012 2013 + 2014 GoPivotal, Inc. All Rights Reserved. diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml index 40577f7c5c..7fccdfdb40 100644 --- a/src/reference/docbook/whats-new.xml +++ b/src/reference/docbook/whats-new.xml @@ -20,5 +20,14 @@ Migration Guide. +
+ Header Type for XPath Header Enricher + + The header-type attribute has been introduced for the header sub-element of the + <int-xml:xpath-header-enricher>. 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 . + +
diff --git a/src/reference/docbook/xml.xml b/src/reference/docbook/xml.xml index 6bd803a776..819d0026d0 100644 --- a/src/reference/docbook/xml.xml +++ b/src/reference/docbook/xml.xml @@ -1051,9 +1051,10 @@ ]]> ]]> ]]>]]> @@ -1102,24 +1103,38 @@ - 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 + header-type attribute provided. 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. + + The fully qualified class name for the header value type. The result of XPath evaluation will be + converted to this type using the ConversionService. + This allows, for example, a NUMBER_RESULT (a double) to be converted to an + Integer. The type can be declared as a primitive (e.g. int) but + the result will always be the equivalent wrapper class (e.g. Integer). + The same integration ConversionService discussed in + is used for the conversion, so conversion to custom + types is supported, by adding a custom converter to the service. + 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.