Reputation: 1238
I have spring application in which I am trying to connect to JMS activemq server. my context file content looks as below:
<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 server does not initialize the spring context at the startup.
I can set autoStartup to false and then spring intializes the context, but then 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 re-connect to this JMS server if it goes down.
Upvotes: 3
Views: 8402
Reputation: 1238
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 (i.e. StartStopJmsBatch As suggested above) and only piece that 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 specify the interval between recovery attempts, in milliseconds.
Upvotes: 2
Reputation: 2121
The Message Listener has a function start(). With that function you can start the Listener manually in your program.
As for the loop: We had a similiar problem where we had to start and stop the listener at given times due to inavailability of system components and we realised it with scheduled jobs.
Below is an example for starting the 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. It is scheduled with spring's scheduling mechanism (take a look here at chapter 28.4 especially) as for the cron expression syntax take a look here
Alternative
An alternative would be to use Spring's DefaultMessageListenerContainer (take a look here) which has a self recovery function build in and which should initialize the spring context even if the JMS server isn't available at application start.
Upvotes: 4