web-dev-qa-db-fra.com

Comment configurer l'URL du courtier ActiveMQ intégré avec Spring Boot

J'ai suivi un exemple simple de configuration et d'exécution d'ActiveMQ intégré avec Spring Boot (version 1.4.X). Voici le lien vers l'exemple https://spring.io/guides/gs/messaging-jms/

Ma classe est structurée comme ci-dessous:

@SpringBootApplication
@EnableJms
public class Application {

@Autowired
ConfigurableApplicationContext context;

@Bean
JmsListenerContainerFactory<?> myJmsContainerFactory(ConnectionFactory connectionFactory) {
    SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);

    return factory;
}

@JmsListener(destination = "mailbox-destination", containerFactory = "myJmsContainerFactory")
public void receiveMessage(String message) {
    System.out.println("Message received: " + message);
    context.close();
}

public static void main(String[] args) throws Exception {
    FileSystemUtils.deleteRecursively(new File("active-data"));
    ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

    JmsTemplate template = context.getBean(JmsTemplate.class);
    MessageCreator messageCreator = new MessageCreator() {
        public Message createMessage(Session session) throws JMSException {
            return session.createTextMessage("Test");
        }
    };
    template.send("mailbox-destination", messageCreator);
}
}

Et build.gradle comme ci-dessous:

apply plugin: 'Java'
apply plugin: 'maven'

group = 'jms.activemq'
version = '0.0.1-SNAPSHOT'

description = """jms.activemq"""

sourceCompatibility = 1.5
targetCompatibility = 1.5

repositories {
     maven { url "http://repo.maven.Apache.org/maven2" }
}
dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-activemq', version:'1.4.0.RELEASE'
    testCompile(group: 'org.springframework.boot', name: 'spring-boot-starter-test', version:'1.4.0.RELEASE') {
exclude(module: 'commons-logging')
}
}

Tout fonctionne bien jusqu'à présent (tant que je laisse le fichier application.properties vide), mais si j'essaie de configurer l'URL du courtier (afin que les clients distants puissent se connecter) en ajoutant ce qui suit au fichier application.properties:

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin

Je reçois une exception:

2016-08-03 12:46:00.938  WARN 88180 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'org.springframework.jms.config.internalJmsListenerEndpointRegistry'; nested exception is org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: Java.net.ConnectException: Connection refused: connect
2016-08-03 12:46:00.939  INFO 88180 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2016-08-03 12:46:00.945  INFO 88180 --- [           main] utoConfigurationReportLoggingInitializer :
org.springframework.context.ApplicationContextException: Failed to start bean 'org.springframework.jms.config.internalJmsListenerEndpointRegistry'; nested exception is org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: Java.net.ConnectException: Connection refused: connect
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.Java:176) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.Java:51) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.Java:346) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.Java:149) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.Java:112) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.Java:874) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:544) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.Java:759) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.Java:369) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:313) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:1185) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:1174) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at jms.activemq.Application.main(Application.Java:37) [main/:na]
Caused by: org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: Java.net.ConnectException: Connection refused: connect
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.Java:316) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.Java:169) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.start(AbstractJmsListeningContainer.Java:273) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.config.JmsListenerEndpointRegistry.startIfNecessary(JmsListenerEndpointRegistry.Java:243) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.config.JmsListenerEndpointRegistry.start(JmsListenerEndpointRegistry.Java:206) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.Java:173) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
... 12 common frames omitted
Caused by: javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: Java.net.ConnectException: Connection refused: connect
at org.Apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.Java:36) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.Java:373) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.Java:303) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.Java:243) ~[activemq-client-5.13.4.jar:5.13.4]
at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.Java:180) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.createSharedConnection(AbstractJmsListeningContainer.Java:413) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.establishSharedConnection(AbstractJmsListeningContainer.Java:381) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.doStart(AbstractJmsListeningContainer.Java:285) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.SimpleMessageListenerContainer.doStart(SimpleMessageListenerContainer.Java:210) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.start(AbstractJmsListeningContainer.Java:270) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
... 15 common frames omitted
Caused by: Java.net.ConnectException: Connection refused: connect
at Java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[na:1.8.0_92]
at Java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.Java:85) ~[na:1.8.0_92]
at Java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.Java:350) ~[na:1.8.0_92]
at Java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.Java:206) ~[na:1.8.0_92]
at Java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.Java:188) ~[na:1.8.0_92]
at Java.net.PlainSocketImpl.connect(PlainSocketImpl.Java:172) ~[na:1.8.0_92]
at Java.net.SocksSocketImpl.connect(SocksSocketImpl.Java:392) ~[na:1.8.0_92]
at Java.net.Socket.connect(Socket.Java:589) ~[na:1.8.0_92]
at org.Apache.activemq.transport.tcp.TcpTransport.connect(TcpTransport.Java:525) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.transport.tcp.TcpTransport.doStart(TcpTransport.Java:488) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.util.ServiceSupport.start(ServiceSupport.Java:55) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.transport.AbstractInactivityMonitor.start(AbstractInactivityMonitor.Java:168) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.transport.InactivityMonitor.start(InactivityMonitor.Java:52) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.transport.TransportFilter.start(TransportFilter.Java:58) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.transport.WireFormatNegotiator.start(WireFormatNegotiator.Java:72) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.transport.TransportFilter.start(TransportFilter.Java:58) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.transport.TransportFilter.start(TransportFilter.Java:58) ~[activemq-client-5.13.4.jar:5.13.4]
at org.Apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.Java:353) ~[activemq-client-5.13.4.jar:5.13.4]
... 23 common frames omitted 

J'ai regardé quelques liens et je n'arrive toujours pas à déterminer la cause du problème. J'apprécierais vraiment des informations ou des documents qui pourraient vous aider.

Ma pensée initiale était que Spring Boot lira ces valeurs et les utilisera pour configurer le courtier ActiveMQ, mais semble plutôt utiliser ces valeurs pour se connecter au courtier (le courtier ayant déjà été configuré avec différents paramètres). Comment puis-je changer la configuration du courtier pour que les clients externes (qui ne s'exécutent pas avec la même machine virtuelle Java que le courtier) puissent accéder au courtier à l'aide de tcp: // localhost: 61616

MISE À JOUR:

J'ai suivi l'une des façons d'incorporer un courtier répertorié ici et en mesure d'intégrer un courtier avec l'URL requise et en mesure de s'y connecter. Cependant, il semble que je finisse par avoir deux courtiers, car il semble que Spring Boot continue et en crée un comme auparavant.

Fondamentalement, j'ajoute simplement ce morceau de code et au début de la méthode principale avant d'appeler SpringApplication.run (Application.class, args);

BrokerService broker = new BrokerService();
broker.addConnector("tcp://localhost:61617");
broker.setPersistent(false);
broker.start();

Ne se sent pas du tout bien, ayant deux instances de courtier (je crois) en cours d'exécution.

1) Est-ce la bonne façon d'intégrer un courtier

2) Si oui, comment puis-je empêcher Spring Boot d'en démarrer un autre? (Sans avoir à supprimer la dépendance spring-boot-starter-activemq).

Merci d'avance.

8
Aliyu Fonyuy

Je crois que j'ai compris cela après avoir joué avec ça pendant un certain temps. Je pensais que deux instances étaient en cours d'exécution parce que j'essayais de créer une connexion au courtier intégré DEFAULT (dans le but de déterminer s'il a été créé/existé) comme ci-dessous:

ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");

Mais apparemment, Spring Boot pense qu'il n'existe pas et le crée à ce moment-là.

Donc, pour que seule mon instance créée soit exécutée, tout ce que je devais faire était de fournir une URL que j'avais ajoutée au connecteur lorsque j'ai créé l'instance (dans ce cas tcp://localhost:61616) dans le application.properties fichier comme ci-dessous

spring.activemq.broker-url=tcp://localhost:61616

et Spring Boot se connectera à cette instance et n'en créera pas une autre. En l'absence de l'entrée ci-dessus dans le fichier de propriétés (ou si vous essayez de vous connecter à une instance intégrée à l'aide de vm: // localhost? ... comme je l'ai fait ci-dessus), Spring Boot ira de l'avant et instanciera une pour vous .

J'ai également lu ceci dans la documentation :

Spring Boot peut également configurer une ConnectionFactory lorsqu'il détecte qu'ActiveMQ est disponible sur le chemin de classe. Si le courtier est présent, un courtier intégré est démarré et configuré automatiquement (tant qu'aucune URL de courtier n'est spécifiée lors de la configuration).

Mais à mon avis, ce n'est pas bien expliqué (mais cela m'a quand même fait réfléchir dans la bonne direction).

S'il vous plaît, faites-nous savoir si vous avez eu des conclusions différentes ou si ma conclusion n'est pas correcte. Merci!!!

13
Aliyu Fonyuy