Spring boot - sharing embedded JMS broker with separate service

Smajl

I have two services which should communicate with each other via ActiveMQ. Everything works nicely when I have the receiver and sender in one service but when I split them, I got a strange activemq exception.

This is configuration of service A:

@EnableScheduling
@SpringBootApplication
@EnableJms
public class App extends SpringBootServletInitializer {

  private static final Logger log = LoggerFactory.getLogger(App.class);

  @Autowired
  private static JmsTemplate jms;

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

}

Sending messages:

  @Autowired
  private JmsTemplate jms;

  public void sendTicket(Reservation reservation) {
    log.debug("---------------sending message----------------");
    // Send a message
    jms.send("mailbox-destination", new MessageCreator() {
      public ObjectMessage createMessage(Session session) throws JMSException {
        ObjectMessage message = session.createObjectMessage();
        message.setObject(reservation);
        return message;
      }
    });
  }

The JMS is configured as in-memory queue:

spring.activemq.in-memory=true
spring.activemq.pooled=false

Service B is similar but id does not define the JmsContainerFactory. It only has the receiver:

@Component
public class Receiver {

  private static final Logger log = LoggerFactory.getLogger(Receiver.class);

  /**
   * Receive a message with reservation and print it out as a e-ticket.
   * 
   * @param reservation
   */
  @JmsListener(destination = "mailbox-destination")
  public void receiveMessage(Reservation reservation) {
    log.info("Received <" + reservation.getId() + ">");
  }
}

Service A have JMS and ActiveMQ broker as maven dependencies:

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

        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-broker</artifactId>
        </dependency>

Service B has only the JMS dependency.

Could you give me a hint how to share the bean between both services and send messages between them? I am completely new to this topic.

I am getting the following exception when receiving a message

org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is javax.jms.JMSException: Could not create Transport. Reason: javax.management.InstanceAlreadyExistsException: org.apache.activemq:type=Broker,brokerName=localhost

EDIT: If I remove the broker dependency from one of the services, the Tomcat does not even start:

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:917)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:439)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:769)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:625)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:351)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:485)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:925)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:871)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 6 common frames omitted
luboskrnac

JMS server were historically standalone applications deployed separately and consumer as well as listener of the message were communicating with this server. So there are typically three separate applications in JMS equation.

Now Spring Boot allows embed Active MQ JMS broker (JMS server) into your Spring Boot application. But if you configure your Spring Boot service each one with it's own embedded JMS broker, these two JMS brokers are totally separate, don't know about each other and are not connected in any way.

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.

Edit:

I suspect I was wrong when with my previous way to share embedded JMS broker. Looking at Spring Docs it doesn't seem to be possible with ActiveMQ:

spring.activemq.broker-url= # URL of the ActiveMQ broker. Auto-generated by default. For instance tcp://localhost:61616

spring.activemq.in-memory=true # Specify if the default broker URL should be in memory. Ignored if an explicit broker has been specified.

I was trying it with HornetQ when I was working on these Spring Enterprise examples, but I can't find such config now. So I bet I had problems and ended up using separate third node.

If you want to further try it, I would

  1. Switch to HornetQ or Artemis
  2. Remove broker dependency from service B and leave there only spring-jms dependency (so that there would be only JMS client dependencies available)
  3. Try to poke with these HornetQ properties to try to have embedded instance that is exposed via port:

    spring.hornetq.mode=embedded
    spring.hornetq.port=5445
    

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.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Spring Boot WebSocket with embedded ActiveMQ Broker

From Dev

How to configure embedded ActiveMQ Broker URL with Spring Boot

From Dev

How to configure embedded ActiveMQ Broker URL with Spring Boot

From Dev

How to service external static HTML files in Spring Boot Embedded tomcat?

From Dev

Embedded Redis for Spring Boot

From Dev

Spring boot - Embedded Tomcat

From Dev

queue jms [wso2] message broker. callback service

From Dev

how to set jms broker using spring4 and ActiveMQ?

From Dev

Spring-jms. How to customize broker url for rabbitmq?

From Dev

Spring Boot same broker messages repeated to console

From Dev

Spring-Boot Embedded Wars

From Dev

Spring Boot + GWT embedded configuraiton

From Dev

non embedded postgresql in spring boot

From Dev

spring boot xa transaction datasource and jms

From Java

Spring Boot application as a Service

From Dev

Spring Boot Service unrecognized

From Dev

SOAP service in spring boot

From Dev

Embedded AMQP Java Broker

From Dev

Spring Boot WebSocket Rabbitmq Stomp Broker Not Keeping Connection

From Dev

Spring-Boot and Kafka : How to handle broker not available?

From Dev

Is it possible for Spring-XD to listen to more than one JMS broker at a time?

From Dev

JMS Broker receives the message as null

From Dev

Spring boot WAR size with different embedded servers

From Dev

Spring Boot + IntelliJ + Embedded Database = Headache

From Java

SymmetricDS in Embedded mode in Spring boot app as client

From Dev

spring boot war without tomcat embedded

From Dev

Spring Boot non-embedded Derby database?

From Dev

How to set Handler for embedded Jetty in Spring Boot?

From Dev

Spring boot without embedded servlet container

Related Related

HotTag

Archive