0
votes

I am learning JMS with spring boot and nice to know that spring boot comes with embed Active MQ JMS broker.

I started from spring page on how to achieve this and it works like charm. Now i went little further and create two separate spring boot application one containing jms sender code and another containing receiver code.

I tried starting and application failed as both application are using same port for JMS. I fixed this by including this on one application

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

But now sender is sending message successfully but receiver is doing nothing. I search on stackoverflow and look at this and this. And they are saying:

If you want to use JMS in production, it would be much wiser to avoid using Spring Boot embedded JMS brokers and host it separately. So 3 node setup would be preferred for PROD.

So my questions are: 1. What is the purpose of putting both jms sender and receiver on same application? Is there any practical example 2. Is it really not possible to use spring boot embedded JMS to communicate two separate application.

1

1 Answers

1
votes

You might have sender and receiver in the same application if requests arrive in bursts and you want to save them somewhere before they are processed, in case of a server crash. You typically still wouldn't use an embedded broker for that.

Embedded brokers are usually used for testing only.

You can, however, run an embedded broker that is accessible externally; simply fire up a BrokerService as you have, but the other app needs to connect with the tcp://... address, not the vm://....

EDIT

App1:

@SpringBootApplication
@RestController
public class So52654109Application {

    public static void main(String[] args) {
        SpringApplication.run(So52654109Application.class, args);
    }

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

    @Autowired
    private JmsTemplate template;

    @RequestMapping(path = "/foo/{id}")
    public String foo(@PathVariable String id) {
        template.convertAndSend("someQueue", id);
        return id + ": thank you for your request, we'll send an email to the address on file when complete";
    }

}

App2:

application.properties

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

and

@SpringBootApplication
public class So526541091Application {

    public static void main(String[] args) {
        SpringApplication.run(So526541091Application.class, args);
    }

    @JmsListener(destination = "someQueue")
    public void process(String id) {
        System.out.println("Processing request for id");
    }

}

Clearly, for a simple app like this you might just run the listener in the first app.

However, since there is no persistence of messages with this configuration, you would likely use an external broker for a production app (or enable persistence).