I'm trying to setup spring's DefaultMessageListenerContainer class to redeliver messages after an exception is thrown or session.rollback() is called. I am also trying to get this running on glassfish 3.1.2 web profile.
When calling session.rollback() in the onMessage() method of my SessionAwareMessageListener, I get an exception with the message saying: MessageDispatcher - [C4024]: The session is not transacted. I don't see this problem with ActiveMQ, but of course that configuration is different because I'm not using it in an application server.
Has anyone here gotten this working? My configuration follows:
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">com.sun.enterprise.naming.SerialInitContextFactory</prop>
<prop key="java.naming.provider.url">${jms.jndicontext.url}</prop>
<prop key="java.naming.factory.state">com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl</prop>
<prop key="java.naming.factory.url.pkgs">com.sun.enterprise.naming</prop>
</props>
</property>
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="${jms.connection.factory}" />
</bean>
<bean id="jmsTemplate"
class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="defaultDestination" ref="jmsServiceQueue"/>
</bean>
<bean id="jmsServiceProducer"
class="net.exchangesolutions.services.messaging.service.jms.JmsMessageServiceProducerImpl">
<property name="serviceTemplate" ref="jmsTemplate"/>
<property name="serviceDestination" ref="jmsServiceQueue"/>
</bean>
<bean id="myMessageListener"
class="com.myorg.jms.MessageDispatcher"/>
<bean id="jmsServiceContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destination" ref="jmsServiceQueue"/>
<property name="messageListener" ref="myMessageListener"/>
<property name="errorHandler" ref="jmsErrorHandler" />
<property name="receiveTimeout" value="180000"/>
<property name="concurrentConsumers" value="1"/>
<property name="cacheLevelName" value="CACHE_NONE"/>
<property name="pubSubNoLocal" value="true"/>
<property name="sessionTransacted" value="true"/>
<property name="sessionAcknowledgeMode" value="2" />
<property name="transactionManager" ref="jmsTransactionManager"/>
</bean>
<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
Setting the acknowledge="auto", the message is acknowledged before listener execution, so the message is deleted from queue.
I have also achieved the DLQ scenario in Spring Application by doing the following changes to your code.
First, we set the acknowledge="transacted" (Since we want guaranteed redelivery in case of exception thrown and Trans acknowledgment for successful listener execution)
<jms:listener-container container-type="default" connection-factory="connectionFactory" acknowledge=" transacted">
Next, since we want to throw the JMSException, we are implementing SessionAwareMessageListener.
public class MyMessageQueueListener implements SessionAwareMessageListener {
public void onMessage( Message message , Session session ) throws JMSException {
//DO something
if(success){
//Do nothing – so the transaction acknowledged
} else {
//throw exception - So it redelivers
throw new JMSException("..exception");
}
}
}
I have tested this. This seems working fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With