Announcement Announcement Module
Collapse
No announcement yet.
Dispatcher has no subscribers under CI-725, Spring 3.0 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dispatcher has no subscribers under CI-725, Spring 3.0

    I have a scenario where I use on Server 1 (S1) a jms:outbound-channel-adaptor to send messgaes to S2.

    When S1 starts, which is deployed as a war inside an ear, it first performs a database query to see if there is any data that requires recovering.

    Under spring-integration 2 M1, with approrpiate spring 3 this worked correctly (after I ensured recovery was part of an InitializingBean rather than trigggered
    via a start operation).

    Yesterday i upgrade spring and therefore to a nightly build of spring integration (725) for compatibility.

    However now when the container starts, and recovery records are found, the message is pushed out but a "Dispatcher has no subscribers message" is encountered.


    Code:
    Caused by: org.springframework.integration.message.MessageDeliveryException: failed to send Message to channel 'dispatchXdmDataItemInputChannel'
    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:188)
    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:153)
    	at org.springframework.integration.channel.MessageChannelTemplate.doSend(MessageChannelTemplate.java:224)
    	at org.springframework.integration.channel.MessageChannelTemplate.send(MessageChannelTemplate.java:181)
    	at org.springframework.integration.gateway.AbstractMessagingGateway.send(AbstractMessagingGateway.java:126)
    	at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:210)
    	at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:176)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    	at $Proxy43.dispatch(Unknown Source)
    	at com.jdv.xdm.xdma.Dispatcher.dispatch(Dispatcher.java:177)
    	at com.jdv.xdm.xdma.Dispatcher.start(Dispatcher.java:110)
    	at com.jdv.xdm.xdma.Dispatcher.afterPropertiesSet(Dispatcher.java:130)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$5.run(AbstractAutowireCapableBeanFactory.java:1451)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1449)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1398)
    	... 148 more
    Caused by: java.lang.IllegalStateException: Dispatcher has no subscribers.
    	at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:97)
    	at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:90)
    	at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:43)
    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:180)

    If this exception occurs then the container fails to start.

    If instead i disable recovery mode (ie dont recover on initialisation) but instead trigger it manually from JMX it will work. Therefore i know my bean
    configuration is correct and its more of a lifecycle issue.

    Any ideas?

    Some config thats in use:

    Code:
     <beans:bean id="dispatcherCORE" class="com.jdv.xdm.xdma.Dispatcher" destroy-method="stop" depends-on="dispatcherGateway">
            <beans:property name="QOwner" value="CORE" />
            <beans:property name="dao" ref="xdmDao" />
            <beans:property name="iddao" ref="idDao" />
            <beans:property name="dispatcherGateway" ref="dispatcherGateway" />
    
            <beans:property name="messageContainer">
                <beans:bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
                     <beans:property name="connectionFactory">
                        <beans:bean class="org.springframework.jms.connection.SingleConnectionFactory">
                            <beans:property name="targetConnectionFactory" ref="connectionFactory"/>
                        </beans:bean>
                    </beans:property>
                    <beans:property name="destination" ref="xdmCoreSourceQueue"/>
                    <beans:property name="messageListener" ref="dispatcherCORE" />
                    <beans:property name="autoStartup" value="false" />
                </beans:bean>
            </beans:property>
            <beans:property name="startWithRecoveryMode" value="true" />
        </beans:bean>
    
    
    
      <integration:gateway id="dispatcherGateway" service-interface="com.jdv.xdm.xdma.DispatcherGateway" />
           <integration:channel id="dispatchXdmDataItemInputChannel" />
           <jms:outbound-channel-adapter destination="xdmSendQueue"
                                          channel="dispatchXdmDataItemInputChannel"
                                          />
    
            <integration:channel id="dispatchXdmDataItemJmsInputChannel" />

  • #2
    From the debugger, when triggered manaully after startup (through jmx) handler is there, see this screenshot:

    http://i.imgur.com/fdqIg.png

    When the call is made as part of the InitializingBean the handlers size is 0 and hence the error.

    Comment


    • #3
      I also tried a couple of different things, @Autowired to inject the dispatcherGateway and also inside the Dispatcher class used an explicit applicationContext.getBean call, but the same issue still occurred.

      Comment


      • #4
        Apparently in the latest version the subscription happens later than before, and that causes your error. You should make sure your component is initialized only after SI is fully loaded.

        For this particular type of use case you can use LifeCycle or ApplicationContextEvents. Those allow you to intercept state changes after the initialization.

        The fact that it worked before is luck, not a feature. You could get the result you want with depends-on hacks, but that will likely couple your config to a specific version of the framework.

        Hope this helps.

        Comment


        • #5
          The Spring Integration components now implement the new (as of Spring 3.0) SmartLifecycle interface which enables "phases" for lifecycle execution. Any component implementing that interface will be started in ascending order (as indicated by the phase value) and stopped in descending order.

          The endpoints that are connected to "subscribable" channels (where dispatchers are involved) now start in the earliest possible phase. However, those same components used to start upon initialization. The old *more eager* behavior was necessary when there was no support for ordered lifecycle processing. Now that SmartLifecycle does enable that, we are able to treat lifecycle consistently while relying on the order (subscribers register before pollers start).

          If possible, you could implement SmartLifecycle and set a phase value that is greater than Integer.MIN_VALUE.

          Let me know if that explanation is clear and/or if you have any more questions.

          Comment


          • #6
            Thanks will give it a try, however due to Christmas period won't be able to try it until beginning of January. Will post the results when i do.

            Thanks for the assistance.

            Comment

            Working...
            X