web-dev-qa-db-fra.com

Spring Boot configurer plusieurs instances ActiveMQ

J'ai l'obligation de déplacer les messages des files d'attente sur une instance ActiveMQ vers une autre instance ActiveMQ. Existe-t-il un moyen de se connecter à deux instances ActiveMQ différentes à l'aide de la configuration de démarrage à ressort?

Dois-je créer plusieurs usines de connexion? Si tel est le cas, comment JmsTemplate sait-il à quelle instance ActiveMQ se connecter?

  @Bean
    public ConnectionFactory connectionFactory() {
        return new ActiveMQConnectionFactory(JMS_BROKER_URL);
    }

Toute aide et exemples de code seraient utiles.

Merci d'avance. GM

11
user2279337

En plus de la réponse de @Chris, vous devez créer différentes instances BrokerService en utilisant différents ports et créer différents ConnectionFactory pour vous connecter à chaque courtier et créer différents JmsTemplate en utilisant ces différentes usines pour envoyer des messages à différents courtiers.

Par exemple :

import javax.jms.ConnectionFactory;
import javax.jms.QueueConnectionFactory;

import org.Apache.activemq.ActiveMQConnectionFactory;
import org.Apache.activemq.broker.BrokerService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;

@Configuration
public class ActiveMQConfigurationForJmsCamelRouteConsumeAndForward {
    public static final String LOCAL_Q = "localQ";
    public static final String REMOTE_Q = "remoteQ";

    @Bean
    public BrokerService broker() throws Exception {
        final BrokerService broker = new BrokerService();
        broker.addConnector("tcp://localhost:5671");
        broker.setBrokerName("broker");
        broker.setUseJmx(false);
        return broker;
    }

    @Bean
    public BrokerService broker2() throws Exception {
        final BrokerService broker = new BrokerService();
        broker.addConnector("tcp://localhost:5672");
        broker.setBrokerName("broker2");
        broker.setUseJmx(false);
        return broker;
    }

    @Bean
    @Primary
    public ConnectionFactory jmsConnectionFactory() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:5671");
        return connectionFactory;
    }

    @Bean
    public QueueConnectionFactory jmsConnectionFactory2() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:5672");
        return connectionFactory;
    }

    @Bean
    @Primary
    public JmsTemplate jmsTemplate() {
        JmsTemplate jmsTemplate = new JmsTemplate();
        jmsTemplate.setConnectionFactory(jmsConnectionFactory());
        jmsTemplate.setDefaultDestinationName(LOCAL_Q);
        return jmsTemplate;
    }

    @Bean
    public JmsTemplate jmsTemplate2() {
        JmsTemplate jmsTemplate = new JmsTemplate();
        jmsTemplate.setConnectionFactory(jmsConnectionFactory2());
        jmsTemplate.setDefaultDestinationName(REMOTE_Q);
        return jmsTemplate;
    }

    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerFactory(ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        return factory;
    }

    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerFactory2(
            @Qualifier("jmsConnectionFactory2") ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        return factory;
    }
}

Pour déplacer des messages d'une instance AMQ vers une autre instance, vous pouvez utiliser JmsBridgeConnectors:

Notez que dans l'exemple ci-dessous, vous ne pouvez pas avoir plusieurs consommateurs dans la file d'attente à partir de laquelle vous souhaitez transférer les messages car Camel ou JmsBridgeConnectors consomment le message et le transfèrent. Si vous souhaitez qu'une seule copie du message soit transférée, vous avez quelques solutions: 1- Convertissez votre file d'attente en un sujet, gérez les messages pour les consommateurs hors ligne par des abonnements durables ou des consommateurs rétroactifs. 2- convertissez votre file d'attente en une file d'attente composite et utilisez DestinationsInterceptors pour copier les messages dans une autre file d'attente. 3- Utilisez NetworkConnector pour les courtiers Networkof

@Bean
public BrokerService broker() throws Exception {
    final BrokerService broker = new BrokerService();
    broker.addConnector("tcp://localhost:5671");
    SimpleJmsQueueConnector simpleJmsQueueConnector = new SimpleJmsQueueConnector();
    OutboundQueueBridge bridge = new OutboundQueueBridge();
    bridge.setLocalQueueName(LOCAL_Q);
    bridge.setOutboundQueueName(REMOTE_Q);
    OutboundQueueBridge[] outboundQueueBridges = new OutboundQueueBridge[] { bridge };
    simpleJmsQueueConnector.getReconnectionPolicy().setMaxSendRetries(ReconnectionPolicy.INFINITE);
    simpleJmsQueueConnector.setOutboundQueueBridges(outboundQueueBridges);
    simpleJmsQueueConnector.setLocalQueueConnectionFactory((QueueConnectionFactory) jmsConnectionFactory());
    simpleJmsQueueConnector.setOutboundQueueConnectionFactory(jmsConnectionFactory2());
    JmsConnector[] jmsConnectors = new JmsConnector[] { simpleJmsQueueConnector };
    broker.setJmsBridgeConnectors(jmsConnectors);
    broker.setBrokerName("broker");
    broker.setUseJmx(false);
    return broker;
}

Ou en utilisant Camel comme ceci ci-dessous:

@Bean
public CamelContext camelContext() throws Exception {
    CamelContext context = new DefaultCamelContext();
    context.addComponent("inboundQueue", ActiveMQComponent.activeMQComponent("tcp://localhost:5671"));
    context.addComponent("outboundQueue", ActiveMQComponent.activeMQComponent("tcp://localhost:5672"));
    context.addRoutes(new RouteBuilder() {
        public void configure() {
            from("inboundQueue:queue:" + LOCAL_Q).to("outboundQueue:queue:" + REMOTE_Q);
        }
    });
    context.start();
    return context;
}

votre producteur doit être comme ça pour utiliser différents JmsTemplates:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.CommandLineRunner;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class Producer implements CommandLineRunner {

    @Autowired
    private JmsTemplate jmsTemplate;

    @Autowired
    @Qualifier("jmsTemplate2")
    private JmsTemplate jmsTemplate2;

    @Override
    public void run(String... args) throws Exception {
        send("Sample message");
    }

    public void send(String msg) {
        this.jmsTemplate.convertAndSend(ActiveMQConfigurationForJmsCamelRouteConsumeAndForward.LOCAL_Q, msg);
        this.jmsTemplate2.convertAndSend(ActiveMQConfigurationForJmsCamelRouteConsumeAndForward.REMOTE_Q, msg);
    }
}

et consommateur:

import javax.jms.Session;

import org.Apache.activemq.ActiveMQSession;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class Consumer {

    @JmsListener(destination = ActiveMQConfigurationForJmsCamelRouteConsumeAndForward.REMOTE_Q, containerFactory = "jmsListenerContainerFactory2")
    public void receiveQueue(Session session, String text) {
        System.out.println(((ActiveMQSession) session).getConnection().getBrokerInfo());
        System.out.println(text);
    }
}
10
Hassen Bennour

Vous devez instancier plusieurs instances de JmsTemplate en tant que Beans dans votre application, puis utiliser une combinaison de @Qualifier et @Primary annotations pour indiquer quelle instance JmsTemplate doit aller où.

Par exemple

@Bean("queue1")
@Primary
public JmsTemplate getQueue1(@Qualifier("connectionFactory1")ConnectionFactory factory...){
...
}

@Bean("queue2")
@Primary
public JmsTemplate getQueue2(@Qualifier("connectionFactory2")ConnectionFactory factory...){
...
}

...

@Autowired
@Qualifier("queue1")
private JmsTemplate queue1;
...

Voir ici pour plus d'informations.

3
Chris Thompson

Vous pouvez utiliser la valeur par défaut Spring Boot pour le consommateur de file d'attente

@JmsListener(destination = “queue.name")
public void consumer(String message) {
    // consume the message
}

Et pour le producteur, vous pouvez créer un autre JmsTemplate @Bean

@Bean
public JmsTemplate jmsTemplate() {
    return new JmsTemplate(new ActiveMQConnectionFactory("tcp://localhost:5671"));
}
0
abbas

De cette façon, vous pouvez enregistrer autant de courtiers/auditeurs que vous le souhaitez dynamiquement:

import org.Apache.activemq.ActiveMQConnectionFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.JmsListenerConfigurer;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerEndpointRegistrar;
import org.springframework.jms.config.SimpleJmsListenerEndpoint;

import javax.jms.Message;
import javax.jms.MessageListener;

@Configuration
public class CustomJmsConfigurer implements JmsListenerConfigurer {

    @Override
    public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
        ActiveMQConnectionFactory amqConnectionFactory = new ActiveMQConnectionFactory();
        amqConnectionFactory.setBrokerURL("brokerUrl");
        amqConnectionFactory.setUserName("user");
        amqConnectionFactory.setPassword("password");
        amqConnectionFactory.setExclusiveConsumer(true);

        DefaultJmsListenerContainerFactory containerFactory = new DefaultJmsListenerContainerFactory();
        containerFactory.setConnectionFactory(amqConnectionFactory);

        SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
        endpoint.setId("someIdentifier");
        endpoint.setDestination("queueName");
        endpoint.setMessageListener(new MessageListener() {

            @Override
            public void onMessage(Message message) {
                // Do your stuff
            }
        });
        registrar.registerEndpoint(endpoint, containerFactory);
    }
}
0
plajko