INT-2626 Fix RLR parser
Fix RecipientListRouterParser to extend from AbstractRouterParser, thus eliminating the problem described in INT-2626. Previously, the router was a top level bean and, since it is an @ManagedResource, the mbean exporter eagerly instantiated it (and its Recipients) before the ChannelInitializer ran. Now, it is an anonymous inner bean inside a FB, so the exporter no longer "finds" it, thus deferring the Recipient instantiation until the router itself is instantiated via its FB, which will be after the C.I. runs. This is all fine, with one caveat - previously the RLR is made available as an MBean - now it is not, unless you ALSO add the int-jmx:mbean-exporter. However, the MBean is very basic, with no attributes and a single operation 'setShouldTrack()', so the risk is extremely low and the workaround is to add the IntegrationMBeanExporter. INT-2626 polished based on PR comments
This commit is contained in:
committed by
Gary Russell
parent
2a04ee0806
commit
246a202661
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2012 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,36 +25,37 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.filter.ExpressionEvaluatingSelector;
|
||||
import org.springframework.integration.router.RecipientListRouter;
|
||||
import org.springframework.integration.router.RecipientListRouter.Recipient;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Parser for the <recipient-list-router/> element.
|
||||
*
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public class RecipientListRouterParser extends AbstractConsumerEndpointParser {
|
||||
public class RecipientListRouterParser extends AbstractRouterParser {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder recipientListRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".router.RecipientListRouter");
|
||||
protected BeanDefinition doParseRouter(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder recipientListRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(RecipientListRouter.class);
|
||||
List<Element> childElements = DomUtils.getChildElementsByTagName(element, "recipient");
|
||||
Assert.notEmpty(childElements,
|
||||
"At least one recipient channel must be defined (e.g., <recipient channel=\"channel1\"/>).");
|
||||
ManagedList recipientList = new ManagedList();
|
||||
for (Element childElement : childElements) {
|
||||
BeanDefinitionBuilder recipientBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.router.RecipientListRouter.Recipient");
|
||||
BeanDefinitionBuilder recipientBuilder = BeanDefinitionBuilder.genericBeanDefinition(Recipient.class);
|
||||
recipientBuilder.addConstructorArgReference(childElement.getAttribute("channel"));
|
||||
String expression = childElement.getAttribute("selector-expression");
|
||||
if (StringUtils.hasText(expression)) {
|
||||
BeanDefinition selectorDef = new RootBeanDefinition(
|
||||
"org.springframework.integration.filter.ExpressionEvaluatingSelector");
|
||||
BeanDefinition selectorDef = new RootBeanDefinition(ExpressionEvaluatingSelector.class);
|
||||
selectorDef.getConstructorArgumentValues().addGenericArgumentValue(expression);
|
||||
String selectorBeanName = parserContext.getReaderContext().registerWithGeneratedName(selectorDef);
|
||||
recipientBuilder.addConstructorArgReference(selectorBeanName);
|
||||
@@ -62,11 +63,7 @@ public class RecipientListRouterParser extends AbstractConsumerEndpointParser {
|
||||
recipientList.add(recipientBuilder.getBeanDefinition());
|
||||
}
|
||||
recipientListRouterBuilder.addPropertyValue("recipients", recipientList);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(recipientListRouterBuilder, element, "timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(recipientListRouterBuilder, element, "ignore-send-failures");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(recipientListRouterBuilder, element, "apply-sequence");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(recipientListRouterBuilder, element, "default-output-channel");
|
||||
return recipientListRouterBuilder;
|
||||
return recipientListRouterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:int-jmx="http://www.springframework.org/schema/integration/jmx"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/jmx http://www.springframework.org/schema/integration/jmx/spring-integration-jmx.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:mbean-server />
|
||||
<context:mbean-export />
|
||||
|
||||
<int:recipient-list-router input-channel="command"
|
||||
default-output-channel="nullChannel">
|
||||
<int:recipient channel="controlBusChannel"
|
||||
selector-expression="payload.contains('stop')" />
|
||||
</int:recipient-list-router>
|
||||
|
||||
<int:control-bus input-channel="controlBusChannel" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration_.mbeanexporterhelper;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public class INT_2626Tests {
|
||||
|
||||
@Test // This context failed to load before the INT-2626 fix was applied
|
||||
public void testInt2626(){
|
||||
new ClassPathXmlApplicationContext("INT-2626-config.xml", this.getClass());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user