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