Search code examples
spring-xd

Error deploying more than one stream with a router 1.3.0


I am encountering the following issue on the 1.3.0 release:

xd:>stream create test1 --definition 'http | router --script="file:/tmp/file1.groovy"' --deploy

this deployes fine.

xd:>stream create test2 --definition 'http --port=9999 | router --script="file:/tmp/file2.groovy"' --deploy

Here is the log trace for the second stream:

2015-11-20T16:57:45-0800 1.3.0.RELEASE ERROR DeploymentsPathChildrenCache-0 container.DeploymentListener - Exception deploying module org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [org.springframework.integration.config.RouterFactoryBean#0] with key 'org.springframework.integration.config.RouterFactoryBean#0'; nested exception is javax.management.InstanceAlreadyExistsException: org.springframework.integration.router:name=org.springframework.integration.config.RouterFactoryBean#0,type=MethodInvokingRouter at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:625) ~[spring-context-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:550) ~[spring-context-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.springframework.jmx.export.MBeanExporter.afterSingletonsInstantiated(MBeanExporter.java:432) ~[spring-context-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:792) ~[spring-beans-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835) ~[spring-context-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) ~[spring-context-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE] at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:139) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE] at org.springframework.xd.module.core.SimpleModule.initialize(SimpleModule.java:213) ~[spring-xd-module-1.3.0.RELEASE.jar:1.3.0.RELEASE] at org.springframework.xd.dirt.module.ModuleDeployer.doDeploy(ModuleDeployer.java:217) ~[spring-xd-dirt-1.3.0.RELEASE.jar:1.3.0.RELEASE] at org.springframework.xd.dirt.module.ModuleDeployer.deploy(ModuleDeployer.java:200) ~[spring-xd-dirt-1.3.0.RELEASE.jar:1.3.0.RELEASE] at org.springframework.xd.dirt.server.container.DeploymentListener.deployModule(DeploymentListener.java:365) [spring-xd-dirt-1.3.0.RELEASE.jar:1.3.0.RELEASE] at org.springframework.xd.dirt.server.container.DeploymentListener.deployStreamModule(DeploymentListener.java:334) [spring-xd-dirt-1.3.0.RELEASE.jar:1.3.0.RELEASE] at org.springframework.xd.dirt.server.container.DeploymentListener.onChildAdded(DeploymentListener.java:181) [spring-xd-dirt-1.3.0.RELEASE.jar:1.3.0.RELEASE] at org.springframework.xd.dirt.server.container.DeploymentListener.childEvent(DeploymentListener.java:149) [spring-xd-dirt-1.3.0.RELEASE.jar:1.3.0.RELEASE] at org.apache.curator.framework.recipes.cache.PathChildrenCache$5.apply(PathChildrenCache.java:509) [curator-recipes-2.6.0.jar:na] at org.apache.curator.framework.recipes.cache.PathChildrenCache$5.apply(PathChildrenCache.java:503) [curator-recipes-2.6.0.jar:na] at org.apache.curator.framework.listen.ListenerContainer$1.run(ListenerContainer.java:92) [curator-framework-2.6.0.jar:na] at com.google.common.util.concurrent.MoreExecutors$SameThreadExecutorService.execute(MoreExecutors.java:297) [guava-16.0.1.jar:na] at org.apache.curator.framework.listen.ListenerContainer.forEach(ListenerContainer.java:83) [curator-framework-2.6.0.jar:na] at org.apache.curator.framework.recipes.cache.PathChildrenCache.callListeners(PathChildrenCache.java:500) [curator-recipes-2.6.0.jar:na] at org.apache.curator.framework.recipes.cache.EventOperation.invoke(EventOperation.java:35) [curator-recipes-2.6.0.jar:na] at org.apache.curator.framework.recipes.cache.PathChildrenCache$10.run(PathChildrenCache.java:762) [curator-recipes-2.6.0.jar:na] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_45] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_45] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_45] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_45] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_45] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_45] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45] Caused by: javax.management.InstanceAlreadyExistsException: org.springframework.integration.router:name=org.springframework.integration.config.RouterFactoryBean#0,type=MethodInvokingRouter at com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:437) ~[na:1.8.0_45] at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerWithRepository(DefaultMBeanServerInterceptor.java:1898) ~[na:1.8.0_45] at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:966) ~[na:1.8.0_45] at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:900) ~[na:1.8.0_45] at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:324) ~[na:1.8.0_45] at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522) ~[na:1.8.0_45] at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:195) ~[spring-context-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:678) ~[spring-context-4.2.2.RELEASE.jar:4.2.2.RELEASE] at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:615) ~[spring-context-4.2.2.RELEASE.jar:4.2.2.RELEASE] ... 30 common frames omitted 2015-11-20T16:57:45-0800 1.3.0.RELEASE INFO DeploymentsPathChildrenCache-0 container.DeploymentListener - Path cache event: path=/deployments/modules/allocated/e38af683-03a1-4f46-abd9-abccb8aae1f3/test2.sink.router.1, type=CHILD_REMOVED 2015-11-20T16:57:45-0800 1.3.0.RELEASE INFO DeploymentsPathChildrenCache-0 container.DeploymentListener - Undeploying module [ModuleDescriptor@56110771 moduleName = 'router', moduleLabel = 'router', group = 'test2', sourceChannelName = [null], sinkChannelName = [null], index = 1, type = sink, parameters = map['script' -> 'file:/tmp/dirt/att-example/groovy/transfer.router.cps.groovy'], children = list[[empty]]]


Solution

  • It's a bug - please open a JIRA issue. JIRA Issue here.

    I haven't come up with a work-around (so far), aside from disabling JMX.

    For some reason, the main spring MBean exporter is trying to export the router; normally, the IntegrationMBeanExporter disables that (when present).

    EDIT

    Here's a work-around...

    Create this file and put it under xd/config as

    xd/config/META-INF/spring-xd/plugins/jmx/mbean-exporters.xml ...

    <?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:int-jmx="http://www.springframework.org/schema/integration/jmx"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="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/util http://www.springframework.org/schema/util/spring-util.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:mbean-export default-domain="xd.${xd.stream.name:${xd.job.name:}}" />
    
        <int-jmx:mbean-export object-naming-strategy="moduleObjectNamingStrategy" />
    
        <!-- TODO: Add BatchMbeanExporter -->
        <util:properties id="objectNameProperties">
            <prop key="group">${xd.group.name}</prop>
            <prop key="label">${xd.module.label}</prop>
            <prop key="type">${xd.module.type}</prop>
            <prop key="sequence">${xd.module.sequence}</prop>
        </util:properties>
    
        <bean id="moduleObjectNamingStrategy"
            class="org.springframework.xd.dirt.module.jmx.ModuleObjectNamingStrategy">
            <constructor-arg name="domain" value="xd.${xd.stream.name:${xd.job.name:}}" />
            <constructor-arg name="objectNameProperties" ref="objectNameProperties" />
        </bean>
    
    </beans>
    

    This replaces the standard file and makes the stream name part of the MBean domain so the MBean names are unique. The only difference to the standard file is the addition of the default-domain to the context mbean exporter.

    We still need to address the underlying issue as to why the normal exporter does not have that bean suppressed, but this should get you going.