Spring - JMS, how to start JMS after application and keep trying to connect if it goes down

I have a spring app where I am trying to connect to a JMS activemq server. the content of my context file looks like this:

<bean id="amqPowerConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <constructor-arg index="0" value="${power.messagebrokerurl}"/>
</bean>

<bean id="powerConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
    <constructor-arg ref="amqPowerConnectionFactory"/>
</bean>

<bean id="timeSeriesChangesContainer" class="org.springframework.jms.listener.SimpleMessageListenerContainer">
    <property name="connectionFactory" ref="powerConnectionFactory"/>
    <property name="destination" ref="powerEventQueue"/>
    <property name="messageListener" ref="timeSeriesDataAdapter"/>
</bean>

      

But if the JMS server is down, then the server does not initialize the spring context on startup.

I can set autoStartup to false and then spring initializes the context, but how do I start this listener manually?

<bean id="timeSeriesChangesContainer" class="org.springframework.jms.listener.SimpleMessageListenerContainer">
    <property name="connectionFactory" ref="powerConnectionFactory"/>
    <property name="destination" ref="powerEventQueue"/>
    <property name="messageListener" ref="timeSeriesDataAdapter"/>
    <property name="autoStartup" value="false"/>
</bean>

      

Also I need to code a continuous loop where it will try to reconnect to this JMS server if it goes down.

+3


source to share


2 answers


The message listener has a start () function. With this function, you can start the Listener manually in your program.

As for the loop: we had a similar problem where we had to start and stop the listener at a given time due to the unavailability of system components, and we implemented it with scheduled jobs.

Below is an example of starting a listener through a scheduled job:

Update:



import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class StartStopJmsBatch {

private static final Logger LOG = LoggerFactory.getLogger(StartStopJmsBatch.class);

@Autowired
private DefaultMessageListenerContainer messageListenerContainer;

@Scheduled(cron = "0 0 * * * *")
public void startJmsConsumer() {
    if (!messageListenerContainer.isRunning()) {
        LOG.info("Started JmsListenerContainer");
        messageListenerContainer.start();
    }
}
}

      

I added the rest of the class. Planned with spring scheduling engine ( see here in chapter 28.4) how for cron expression syntax see here

Alternative

An alternative could be to use the spring DefaultMessageListenerContainer ( see here ) which has a self-healing feature built in and which should initialize the spring context even if the JMS server is not available when the application starts.

+3


source


Thanks @Wuteb for the answer, I finally switched from SimpleMessageListenerContainer to DefaultMessageListenerContainer as you said and then there is no need to add any class (like StartStopJmsBatch as suggested above) and only the part we have to add is

<bean id="timeSeriesChangesContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="powerConnectionFactory"/>
    <property name="destination" ref="powerEventQueue"/>
    <property name="messageListener" ref="timeSeriesDataAdapter"/>
    <property name="recoveryInterval" value="500"/>
</bean>

      



where recoveryInterval specifies the interval between recovery attempts, in milliseconds.

+1


source







All Articles