INT-3581: Support selector-expression on WireTap

JIRA: https://jira.spring.io/browse/INT-3581

Move schemas to 4.2.

Add `selector-expression` to `<wire-tap/>`.

INT-3781: Fix What's New

Bump Namespace Version to 4.2
This commit is contained in:
Gary Russell
2015-01-08 14:45:59 +02:00
parent 6b7bbdc326
commit 15eb01169d
68 changed files with 508 additions and 424 deletions

View File

@@ -44,7 +44,7 @@ public abstract class AbstractIntegrationNamespaceHandler implements NamespaceHa
protected final Log logger = LogFactory.getLog(this.getClass());
private static final String VERSION = "4.1";
private static final String VERSION = "4.2";
private final NamespaceHandlerDelegate delegate = new NamespaceHandlerDelegate();

View File

@@ -20,16 +20,21 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.channel.interceptor.WireTap;
import org.springframework.integration.config.ExpressionFactoryBean;
import org.springframework.integration.filter.ExpressionEvaluatingSelector;
import org.springframework.util.StringUtils;
/**
* Parser for the &lt;wire-tap&gt; element.
*
* @author Mark Fisher
* @author Gary Russell
*/
public class WireTapParser implements BeanDefinitionRegisteringParser {
@Override
public String parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(WireTap.class);
String targetRef = element.getAttribute("channel");
if (!StringUtils.hasText(targetRef)) {
@@ -37,9 +42,21 @@ public class WireTapParser implements BeanDefinitionRegisteringParser {
}
builder.addConstructorArgReference(targetRef);
String selectorRef = element.getAttribute("selector");
String selectorExpression = element.getAttribute("selector-expression");
if (StringUtils.hasText(selectorRef) && StringUtils.hasText(selectorExpression)) {
parserContext.getReaderContext().error("Only one of 'selector' or 'selector-expression' is allowed", source);
}
if (StringUtils.hasText(selectorRef)) {
builder.addConstructorArgReference(selectorRef);
}
else if (StringUtils.hasText(selectorExpression)) {
BeanDefinitionBuilder expressionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(ExpressionFactoryBean.class);
expressionBuilder.addConstructorArgValue(selectorExpression);
BeanDefinitionBuilder eemsBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionEvaluatingSelector.class);
eemsBuilder.addConstructorArgValue(expressionBuilder.getBeanDefinition());
builder.addConstructorArgValue(eemsBuilder.getBeanDefinition());
}
String timeout = element.getAttribute("timeout");
if (StringUtils.hasText(timeout)) {
builder.addPropertyValue("timeout", Long.parseLong(timeout));

View File

@@ -1,2 +1,2 @@
http\://www.springframework.org/schema/integration/spring-integration-4.1.xsd=org/springframework/integration/config/xml/spring-integration-4.1.xsd
http\://www.springframework.org/schema/integration/spring-integration.xsd=org/springframework/integration/config/xml/spring-integration-4.1.xsd
http\://www.springframework.org/schema/integration/spring-integration-4.2.xsd=org/springframework/integration/config/xml/spring-integration-4.2.xsd
http\://www.springframework.org/schema/integration/spring-integration.xsd=org/springframework/integration/config/xml/spring-integration-4.2.xsd

View File

@@ -3749,7 +3749,15 @@
<xsd:documentation>
A reference to a bean in the Application Context
which implements MessageSelector that must accept a message for it to be
sent to the intercepting channel
sent to the intercepting channel. Mutually exclusive with 'selector-expression'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="selector-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A boolean expression evaluated against the message to determine whether it should
sent to the intercepting channel. Mutually exclusive with 'selector'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>

View File

@@ -21,7 +21,7 @@
<channel id="withId">
<queue capacity="10"/>
<interceptors>
<wire-tap id="wireTap" channel="wireTapChannel"/>
<wire-tap id="wireTap" channel="wireTapChannel" selector-expression="@booleanTrue" />
</interceptors>
</channel>
@@ -54,4 +54,8 @@
<beans:constructor-arg value="false"/>
</beans:bean>
<beans:bean id="booleanTrue" class="java.lang.Boolean">
<beans:constructor-arg value="true" />
</beans:bean>
</beans:beans>

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.
@@ -16,58 +16,84 @@
package org.springframework.integration.config;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import java.util.Map;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.channel.interceptor.WireTap;
import org.springframework.integration.filter.ExpressionEvaluatingSelector;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.integration.channel.interceptor.WireTap;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mark Fisher
* @author Gary Russell
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class WireTapParserTests {
@Autowired
MessageChannel noSelectors;
@Autowired
MessageChannel accepting;
@Autowired
MessageChannel rejecting;
@Autowired
MessageChannel withId;
@Autowired
PollableChannel wireTapChannel;
@Autowired @Qualifier("wireTap")
WireTap wireTap;
@Autowired
List<WireTap> wireTaps;
@Test
public void simpleWireTap() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"wireTapParserTests.xml", this.getClass());
MessageChannel mainChannel = (MessageChannel) context.getBean("noSelectors");
PollableChannel wireTapChannel = (PollableChannel) context.getBean("wireTapChannel");
assertNull(wireTapChannel.receive(0));
Message<?> original = new GenericMessage<String>("test");
mainChannel.send(original);
noSelectors.send(original);
Message<?> intercepted = wireTapChannel.receive(0);
assertNotNull(intercepted);
assertEquals(original, intercepted);
}
@Test
public void simpleWireTapWithId() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"wireTapParserTests.xml", this.getClass());
WireTap wireTap = (WireTap) context.getBean("wireTap");
assertNotNull(wireTap);
public void simpleWireTapWithIdAndSelectorExpression() {
assertThat(TestUtils.getPropertyValue(wireTap, "selector"), instanceOf(ExpressionEvaluatingSelector.class));
Message<?> original = new GenericMessage<String>("test");
withId.send(original);
Message<?> intercepted = wireTapChannel.receive(0);
assertNotNull(intercepted);
assertEquals(original, intercepted);
}
@Test
public void wireTapWithAcceptingSelector() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"wireTapParserTests.xml", this.getClass());
MessageChannel mainChannel = (MessageChannel) context.getBean("accepting");
PollableChannel wireTapChannel = (PollableChannel) context.getBean("wireTapChannel");
assertNull(wireTapChannel.receive(0));
Message<?> original = new GenericMessage<String>("test");
mainChannel.send(original);
accepting.send(original);
Message<?> intercepted = wireTapChannel.receive(0);
assertNotNull(intercepted);
assertEquals(original, intercepted);
@@ -75,26 +101,19 @@ public class WireTapParserTests {
@Test
public void wireTapWithRejectingSelector() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"wireTapParserTests.xml", this.getClass());
MessageChannel mainChannel = (MessageChannel) context.getBean("rejecting");
PollableChannel wireTapChannel = (PollableChannel) context.getBean("wireTapChannel");
assertNull(wireTapChannel.receive(0));
Message<?> original = new GenericMessage<String>("test");
mainChannel.send(original);
rejecting.send(original);
Message<?> intercepted = wireTapChannel.receive(0);
assertNull(intercepted);
}
@Test
public void wireTapTimeouts() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"wireTapParserTests.xml", this.getClass());
Map<String, WireTap> beans = context.getBeansOfType(WireTap.class);
int defaultTimeoutCount = 0;
int expectedTimeoutCount = 0;
int otherTimeoutCount = 0;
for (WireTap wireTap : beans.values()) {
for (WireTap wireTap : wireTaps) {
long timeout = ((Long) new DirectFieldAccessor(wireTap).getPropertyValue("timeout")).longValue();
if (timeout == 0) {
defaultTimeoutCount++;