Merge pull request #80 from markfisher/INT-2124

add support for 'converter' on <xpath-router>
This commit is contained in:
Mark Fisher
2011-10-04 15:55:03 -04:00
6 changed files with 104 additions and 9 deletions

View File

@@ -295,8 +295,14 @@
</int-xml:xpath-router>
]]></programlisting>
</para>
<para>The XPath Router does support 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.
However, 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.</para>
</section>
@@ -395,7 +401,7 @@
<emphasis>XML Payload Converter</emphasis>
</para>
<para>
You can also use implementation of the <classname>org.springframework.integration.xml.XmlPayloadConverter</classname> to
You can also use an implementation of the <classname>org.springframework.integration.xml.XmlPayloadConverter</classname> to
provide more granular transformation:
<programlisting language="xml"><![CDATA[<int-xml:xpath-transformer input-channel="customConverterInput" xpath-expression="/test/@type"
converter="testXmlPayloadConverter" output-channel="output"/>
@@ -421,6 +427,12 @@
}
}]]></programlisting>
</para>
<para>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.</para>
<para>
<emphasis>Combination of SpEL and XPath expressions</emphasis>
</para>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -60,6 +60,7 @@ public class XPathRouterParser extends AbstractRouterParser {
else {
xpathRouterBuilder.addConstructorArgReference(xPathExpressionRef);
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(xpathRouterBuilder, element, "converter");
return xpathRouterBuilder.getBeanDefinition();
}

View File

@@ -225,6 +225,11 @@
<xsd:annotation>
<xsd:documentation>
Specify the XmlPayloadConverter to use when converting a Message payload prior to XPath evaluation.
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.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
@@ -399,6 +404,23 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="converter" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Specify the Converter to use when converting payloads prior to XPath evaluation.
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.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.xml.XmlPayloadConverter" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel-resolver" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:appinfo>

View File

@@ -225,6 +225,11 @@
<xsd:annotation>
<xsd:documentation>
Specify the XmlPayloadConverter to use when converting a Message payload prior to XPath evaluation.
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.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
@@ -411,6 +416,23 @@
</xsd:element>
</xsd:sequence>
<xsd:attributeGroup ref="integration:topLevelRouterAttributeGroup"/>
<xsd:attribute name="converter" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Specify the Converter to use when converting payloads prior to XPath evaluation.
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.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.xml.XmlPayloadConverter"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -20,14 +20,18 @@ import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertEquals;
import org.w3c.dom.Document;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.core.PollableChannel;
@@ -36,9 +40,9 @@ import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.xml.DefaultXmlPayloadConverter;
import org.springframework.integration.xml.util.XmlTestUtil;
import org.springframework.test.context.ContextConfiguration;
import org.w3c.dom.Document;
/**
* @author Jonas Partner
@@ -235,7 +239,31 @@ public class XPathRouterParserTests {
GenericMessage<Document> docMessage = new GenericMessage<Document>(doc);
inputChannel.send(docMessage);
assertNotNull(channelA.receive(10));
}
@Test
public void testWithCustomXmlPayloadConverter() throws Exception {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("XPathRouterTests-context.xml", this.getClass());
MessageChannel inputChannel = ac.getBean("customConverterChannel", MessageChannel.class);
PollableChannel channelZ = ac.getBean("channelZ", PollableChannel.class);
GenericMessage<String> message = new GenericMessage<String>("<name>channelA</name>");
inputChannel.send(message);
Message<?> result = channelZ.receive(0);
assertNotNull(result);
assertEquals("<name>channelA</name>", result.getPayload());
}
@SuppressWarnings("unused")
private static class TestXmlPayloadConverter extends DefaultXmlPayloadConverter {
@Override
public Document convertToDocument(Object object) {
if (object instanceof String) {
object = ((String) object).replace("A", "Z");
}
return super.convertToDocument(object);
}
}
}

View File

@@ -4,8 +4,8 @@
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-xml="http://www.springframework.org/schema/integration/xml"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
http://www.springframework.org/schema/integration/xml http://www.springframework.org/schema/integration/xml/spring-integration-xml-2.0.xsd">
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/integration/xml http://www.springframework.org/schema/integration/xml/spring-integration-xml-2.1.xsd">
<int-xml:xpath-router id="xpathRouterEmpty" input-channel="xpathRouterEmptyChannel">
@@ -26,6 +26,10 @@
<int-xml:mapping value="channelA" channel="channelA"/>
<int-xml:mapping value="channelB" channel="channelA"/>
</int-xml:xpath-router>
<int-xml:xpath-router id="xpathRouterWithCustomConverter" input-channel="customConverterChannel" evaluate-as-string="true" converter="testConverter">
<int-xml:xpath-expression expression="/name"/>
</int-xml:xpath-router>
<int:channel id="channelA">
<int:queue/>
@@ -35,4 +39,10 @@
<int:queue/>
</int:channel>
<int:channel id="channelZ">
<int:queue/>
</int:channel>
<bean id="testConverter" class="org.springframework.integration.xml.config.XPathRouterParserTests$TestXmlPayloadConverter"/>
</beans>