5

I have two spring-boot applications. in receiver-application's Application.java I have:

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

and in Receiver.java ...

@JmsListener(destination = "myQueue", containerFactory = "myFactory")
public void receiveMessage(String tradeString) throws JSONException, IOException {
    tradeImpl = new ObjectMapper().readValue(tradeString, TradeImpl.class);
}

In sender-application I simply use:

public void send(trade) {
   String queueName = "myQueue";
   String tradeString = new ObjectMapper().writeValueAsString(trade);
   jmsTemplate.convertAndSend(queueName, tradeString);
}

So I'm just sending the message to the queue name specified in receiver-application. I get the following in the logs

Failed to start JMX connector Cannot bind to URL [rmi://localhost:1099>/jmxrmi]: javax.naming.NameAlreadyBoundException: jmxrmi [Root exception is java.rmi.AlreadyBoundException:

I have read the following post and didn't find it very encouraging:

Spring boot - sharing embedded JMS broker with separate service

It concludes with:

But As I mentioned I didn't make this working before and not sure if it is possible. Didn't find in Spring Boot docs explicit message it doesn't work in this combination.

I suspect the idea behind embedded Spring Boot JMS broker is to allow local in memory integration testing only, not to expose embedded JMS brokers to the outside world.

Does anybody know if what I want to do is indeed possible? And if not, are there any suggestions on how I can achieve messaging between to spring-boot apps using embedded brokers?

Community
  • 1
  • 1
Johnny Alpha
  • 758
  • 1
  • 8
  • 35
  • 1
    If you have 2 spring boot apps and ActiveMQ embedded this is meant that AMQ is embedded in one of the two spring app no ? Why not using external standalone AMQ ? – Hassen Bennour Dec 28 '16 at 20:25
  • I could do, but think I'll go that way as a last resort! I have a real burning curiosity to find out if there is a way to message between the apps using the embedded route! I'm certainly not married to AMQ, so I'm open to other embedded solutions. – Johnny Alpha Dec 28 '16 at 20:52

2 Answers2

6

If your 2 spring boot apps are on the same jvm you simply have to add in application.properties of only one of the two :

spring.activemq.broker-url=vm://localhost

Spring Boot can also configure a ConnectionFactory when it detects that ActiveMQ is available on the classpath. If the broker is present, an embedded broker is started and configured automatically (as long as no broker URL is specified through configuration).

If your 2 spring boot apps are on 2 differents jvm: In one spring boot app you need to have :

In pom.xml

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-activemq -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-activemq</artifactId>
        <version>1.4.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
    </dependency>

In the second one :

In application.properties

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

In pom.xml

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jms</artifactId>
</dependency>

For the case that you have 2 jvm, 1 for each app, By default spring boot will configure AMQ with only vm connector, in the first app you need to add tcp connector like this :

@Bean(initMethod = "start", destroyMethod = "stop")
public BrokerService broker() throws Exception {
    final BrokerService broker = new BrokerService();
    broker.addConnector("tcp://localhost:61616");
    broker.addConnector("vm://localhost");
    broker.setPersistent(false);
    return broker;
}
Hassen Bennour
  • 3,885
  • 2
  • 12
  • 20
1

Try to specify spring.activemq.brokerUrl=tcp://localhost:61616 for the producer application.

This way an embedded ActiveMQ Broker will be disabled and a connection to another started on the 61616 port will be performed.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Added, but the application now responds with: 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", Do I need to make any additions to my consumer's application.properties too? – Johnny Alpha Dec 28 '16 at 22:08
  • Yeah... Looks like `broker.addConnector( "tcp://localhost:61616" ); broker.addConnector("vm://localhost:0");` should be there. See another answer on the matter. – Artem Bilan Dec 28 '16 at 22:17
  • The `VMTransportFactory` doesn't expose a `port` to listen to. – Artem Bilan Dec 28 '16 at 22:17