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:
Artem Bilan
2014-01-21 16:03:21 +02:00
committed by Gary Russell
parent b817e98a44
commit 16c7ac6134
8 changed files with 89 additions and 23 deletions

View File

@@ -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());
}

View File

@@ -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;
}
}
}

View File

@@ -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 -->

View File

@@ -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"/>

View File

@@ -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