0

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.

user9735824
  • 1,196
  • 5
  • 19
  • 36

1 Answers1

1

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).

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • I am sorry but I could not understand your answer. Could you please elaborate. – user9735824 Oct 04 '18 at 20:47
  • Which part don't you understand? – Gary Russell Oct 04 '18 at 20:48
  • first part and third part. Second paragraph is self explanatory. – user9735824 Oct 04 '18 at 20:49
  • Thank you. But still my receiver is not able to get message. I followed whatever you explained i am getting error : [ERROR]~2018-10-04-16.31.14.313CDT~~~~~ o.s.j.l.DefaultMessageListenerContainer Could not refresh JMS Connection for destination 'OrderTransactionQueue' - retrying using FixedBackOff{interval=5000, currentAttempts=15, maxAttempts=unlimited}. Cause: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused: connect – user9735824 Oct 04 '18 at 21:32
  • Did you `start()` the broker (that is missing from your original question - see my answer)? – Gary Russell Oct 04 '18 at 21:34
  • I did now and I am getting different error. I am sending model object and they are under different package name on two different application and now i am getting class not found exception. – user9735824 Oct 04 '18 at 21:41
  • Then you can't use Java Serialization, switch to something like JSON. spring-jms provides a `MappingJackson2MessageConverter` which can be configured to map from the source type to the destination type. See its javadocs; if you can't figure out how to use it, you should ask a new question. The admins here don't like extended discussions in comments, – Gary Russell Oct 04 '18 at 21:49