From 246a202661278453a9e82d358821597f84e71236 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 14 Aug 2012 08:11:25 -0400 Subject: [PATCH] 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 --- .../config/xml/RecipientListRouterParser.java | 27 ++++++++---------- .../mbeanexporterhelper/INT-2626-config.xml | 23 +++++++++++++++ .../mbeanexporterhelper/INT_2626Tests.java | 28 +++++++++++++++++++ 3 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 spring-integration-jmx/src/test/java/org/springframework/integration_/mbeanexporterhelper/INT-2626-config.xml create mode 100644 spring-integration-jmx/src/test/java/org/springframework/integration_/mbeanexporterhelper/INT_2626Tests.java diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/RecipientListRouterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/RecipientListRouterParser.java index e34e6b3fcb..f4aedd4bd4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/RecipientListRouterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/RecipientListRouterParser.java @@ -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 childElements = DomUtils.getChildElementsByTagName(element, "recipient"); Assert.notEmpty(childElements, "At least one recipient channel must be defined (e.g., )."); 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(); } } diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration_/mbeanexporterhelper/INT-2626-config.xml b/spring-integration-jmx/src/test/java/org/springframework/integration_/mbeanexporterhelper/INT-2626-config.xml new file mode 100644 index 0000000000..de7dff0fc6 --- /dev/null +++ b/spring-integration-jmx/src/test/java/org/springframework/integration_/mbeanexporterhelper/INT-2626-config.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration_/mbeanexporterhelper/INT_2626Tests.java b/spring-integration-jmx/src/test/java/org/springframework/integration_/mbeanexporterhelper/INT_2626Tests.java new file mode 100644 index 0000000000..40c0aed41f --- /dev/null +++ b/spring-integration-jmx/src/test/java/org/springframework/integration_/mbeanexporterhelper/INT_2626Tests.java @@ -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()); + } +}