web-dev-qa-db-fra.com

Spring Integration Dispatcher n'a aucun abonné pour la chaîne

J'utilise l'intégration Spring et son support pour MQTT; J'ai vu la documentation sur l'intégration de Spring et mon scénario de test simple consiste à publier un message sur un sujet MQTT. La documentation Spring se trouve ici: http://docs.spring.io/spring-integration/reference/html/mqtt.html#_configuring_with_Java_configuration_15

J'utilise ces versions:

  • printemps 4.3.4
  • intégration du ressort 4.3.5

J'ai construit cette classe de configuration simple:

@Configuration
@IntegrationComponentScan
public class CommunicationServerApplication
{
    @Bean
    public MqttPahoClientFactory mqttClientFactory()
    {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setServerURIs(mqttServerUris);
        if (StringUtils.hasText(mqttUsername) && StringUtils.hasText(mqttPassword))
        {

            factory.setUserName(mqttUsername);
            factory.setPassword(mqttPassword);
        }
        factory.setConnectionTimeout(mqttConnectionTimeout);
        factory.setKeepAliveInterval(mqttKeepAliveInterval);
        factory.setPersistence(new MqttDefaultFilePersistence(mqttPersistenceFileDirectory));
        return factory;
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel", autoStartup="true")
    public MessageHandler mqttOutbound()
    {
        String clientId = mqttClientId;
        if( !StringUtils.hasText(clientId) )
        {
            clientId = UUID.randomUUID().toString();
        }
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, mqttClientFactory());
        messageHandler.setAsync(true);
        messageHandler.setDefaultTopic(mqttTopic);
        if( mqttQos >= 0 && mqttQos <=2 )
        {

            messageHandler.setDefaultQos(mqttQos);
        }
        return messageHandler;
    }

    @Bean
    public MessageChannel mqttOutboundChannel()
    {
        DirectChannel dc = new DirectChannel();
        return dc;
    }

    @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
    public interface MqttMsgproducer
    {

        void sendToMqtt(String data);
    }
}

Et puis j'ai utilisé ce cas de test simple:

@ContextConfiguration(value ={ "classpath:app-ctx.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class SimpleMqttTestSuite
{
    private static final Logger logger = LoggerFactory.getLogger(SimpleMqttTestSuite.class.getName());
    @Autowired
    private MqttMsgproducer sender;
    @Test
    public void startServerTest()
    {
        try
        {
            sender.sendToMqtt("Hello");
        }
        catch (Exception e)
        {
            logger.error("Error", e);
        }
    }
}

Mon app-ctx.xml est:

<?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:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:oxm="http://www.springframework.org/schema/oxm"
    xsi:schemaLocation="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  
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
    http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="it.olegna.test.integration" />
    <context:property-placeholder location="classpath:configuration.properties"
        order="0" ignore-resource-not-found="true" ignore-unresolvable="true" />    
</beans>

En exécutant le test simple, je rencontre cette erreur:

2016-12-20 10:46:33,889 49967 [nioEventLoopGroup-3-1] ERROR - Errore 
org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'org.springframework.context.support.GenericApplicationContext@2e6a8155.mqttOutboundChannel'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.Java:81) ~[spring-integration-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.Java:423) ~[spring-integration-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.Java:373) ~[spring-integration-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.Java:115) ~[spring-messaging-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.Java:45) ~[spring-messaging-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.Java:105) ~[spring-messaging-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.Java:143) ~[spring-messaging-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.Java:135) ~[spring-messaging-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.Java:375) ~[spring-integration-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.Java:477) ~[spring-integration-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.Java:429) ~[spring-integration-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.Java:420) ~[spring-integration-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.integration.gateway.GatewayCompletableFutureProxyFactoryBean.invoke(GatewayCompletableFutureProxyFactoryBean.Java:65) ~[spring-integration-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:179) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.Java:213) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]

Je ne peux pas comprendre ce qui me manque dans la configuration. Quelqu'un peut-il me donner un pourboire?

merci

Angelo

9
Angelo Immediata

Votre solution est incorrecte - vous ne devez pas vous abonner dans une définition de bean channel. Je crois que votre problème est que vous manquez @EnableIntegration sur la classe.

6
Gary Russell

J'ai résolu mon problème

C'était lié au fait que j'ai construit la Manche mais maintenant le gestionnaire a été abonné

Dans ma classe d'application, j'ai fait ce qui suit:

@Bean
public MessageChannel mqttOutboundChannel()
{
    DirectChannel dc = new DirectChannel();
    dc.subscribe(mqttOutbound());
    return dc;
}

Comme vous pouvez le voir maintenant, j'ajoute manuellement abonnez le bean mqttOutbound (le gestionnaire de messages) au canal

En faisant de cette façon tout fonctionne

J'espère que cela peut aider

Angelo

MISE À JOUR APRÈS RÉPONSE DE Gary Russell

Comme suggéré par Gary Russell, je ne suis pas abonné à la chaîne

J'ai ajouté l'annotation @EnableIntegration

Donc, ma classe d'application est maintenant la suivante:

@Configuration
@IntegrationComponentScan
@EnableIntegration
public class CommunicationServerApplication
{
    @Bean
    public MqttPahoClientFactory mqttClientFactory()
    {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setServerURIs(mqttServerUris);
        if (StringUtils.hasText(mqttUsername) && StringUtils.hasText(mqttPassword))
        {

            factory.setUserName(mqttUsername);
            factory.setPassword(mqttPassword);
        }
        factory.setConnectionTimeout(mqttConnectionTimeout);
        factory.setKeepAliveInterval(mqttKeepAliveInterval);
        factory.setPersistence(new MqttDefaultFilePersistence(mqttPersistenceFileDirectory));
        return factory;
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel", autoStartup="true")
    public MessageHandler mqttOutbound()
    {
        String clientId = mqttClientId;
        if( !StringUtils.hasText(clientId) )
        {
            clientId = UUID.randomUUID().toString();
        }
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, mqttClientFactory());
        messageHandler.setAsync(true);
        messageHandler.setDefaultTopic(mqttTopic);
        if( mqttQos >= 0 && mqttQos <=2 )
        {

            messageHandler.setDefaultQos(mqttQos);
        }
        return messageHandler;
    }

    @Bean
    public MessageChannel mqttOutboundChannel()
    {
        DirectChannel dc = new DirectChannel();
        return dc;
    }

    @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
    public interface MqttMsgproducer
    {

        void sendToMqtt(String data);
    }
}
5
Angelo Immediata