I have an application built on WebLogic 11b (10.3.4) using MDBs. I'm trying to convert these to Spring MDPs. Here is the MDB in question:
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "ejbName", propertyValue = "RecipientEventRouterBean"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable") })
public class RecipientEventRouterBean extends TraxMessageRouter {
@Resource
private int appInstance;
@Resource
private String appName;
@Resource(mappedName = "jms/TraxErrorQ")
private Queue errorQueue;
@Resource(name = "TraxCF")
private ConnectionFactory errorQueueConnectionFactory;
@EJB
private Logger loggingService;
@Resource
private int maxJMSXDeliveryCount;
@Resource
private boolean validate;
@EJB
protected RecipientRegistrationService recService;
@Override
@PostConstruct
public void init() {
if (appName == null) {
throw new EJBException("appName is null");
}
try {
super.traxFactory = TraxFactory.getInstance(Application.fromValue(appName));
super.processor = new ObjectFactory().createApplicationInstance();
super.processor.setName(appName);
super.processor.setInstance(this.appInstance);
super.errorQueueConnectionFactory = this.errorQueueConnectionFactory;
super.errorQueue = this.errorQueue;
super.maxJMSXDeliveryCount = this.maxJMSXDeliveryCount;
super.validate = this.validate;
super.loggingService = this.loggingService;
} catch (Exception e) {
throw new EJBException(e);
}
super.init();
}
@Override
protected TraxMessageService getTraxMessageService() {
return recService;
}
}
The parent of the MDB, TraxMessageRouter, implements the MessageListener interface.
I've created the MDP beans in the jms-applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Spring JMS Destination Resolver -->
<bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="cache" value="true" />
</bean>
<!-- Spring JMS Queue Connection Factory leveraging a single connection -->
<!-- SingleConnectionFactory will return the same Connection on all createConnection calls and ignore calls to close -->
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jms/TraxCF" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
</bean>
<bean id="jmsSender" class="com.mycompany.web.service.jms.JMSSender">
<property name="jmsTemplate" ref="jmsTemplate" />
</bean>
<bean id="jmsReceiver" class="com.mycompany.web.service.jms.JMSReceiver">
<property name="jmsTemplate" ref="jmsTemplate" />
</bean>
<bean id="jmsQueue" class="javax.jms.Topic" />
<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="com.mycompany.messaging.RecipientEventRouterBean" />
<!-- and this is the message listener container -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="jmsQueue"/>
<property name="messageListener" ref="messageListener" />
</bean>
</beans>
How do I convert the @MessageDriven annotation into the proper Spring syntax? Can I just comment it out now?
I have several more EventRouterBeans. Do they all get bean declarations in the jms-ApplicationContext.xml or can I add the parent, TraxMessageRouter, to the xml?
What other changes to the config files need to be done? Is there a good guide on how to transition from MDBs to MDPs? Is there a good guide on how to transition from EJB 3 to Spring?
It almost looks like ok to me. Here are a few hints:
@MessageDriven
annotation as you have configured the container alreadyjmsQueue
is wrong. As you are using weblogic, you should either locate the queue using JNDI (like you did for the connection factory) or you should provide the (jndi) name of the queue using the destinationName
property (that accepts a String
and not a javax.jms.Destination
)You need one declaration per message listener that you want to deploy. Perhaps you should go the xml namespace route to share those settings?
<jms:listener-container connectionFactory="connectionFactory"
destinationResolver="jmsDestinationResolver">
<jms:listener ... />
<jms:listener ... />
</jms:listener-container>
This will create two listener containers (i.e. one container per jms:listener
entry).
Note also that Spring 4.1 is going to provide a better declarative approach where you can just annotate a method of any Spring managed bean. Check this blog post for more information. 4.1.0.RC2 has been released so you can try it out now.