Issue
I'm using Spring for DI. I write as follows at applicationContext.xml for Wicket, Hibernate and JMS. The issue is caused by jmsListener start before wicketApplication.<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <!-- The wicket application bean --> <bean id="wicketApplication" class="my.project.MyWicketApplication" /> <!-- specifies the place holder for resources of the project --> <bean id="placeholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="ignoreUnresolvablePlaceholders" value="false" /> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> <property name="ignoreResourceNotFound" value="false" /> <property name="locations"> <list> <value>classpath*:/application.properties</value> </list> </property> </bean> <!-- JMS beans --> <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="tcp://localhost:61616"/> </bean> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> </bean> <bean id="destination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg index="0" value="ServerReceiveQueue"/> </bean> <bean id="jmsListener" class="my.project.jms.JmsListener"/> <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <property name="destination" ref="destination"/> <property name="messageListener" ref="jmsListener"/> </bean> <!-- Data source, specifies the jdbc connection--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"> <value>${jdbc.driver}</value> </property> <property name="url"> <value>${jdbc.url}</value> </property> <property name="username"> <value>${jdbc.username}</value> </property> <property name="password"> <value>${jdbc.password}</value> </property> </bean> <!-- Transaction manager --> <tx:annotation-driven transaction-manager="txManager" /> <!-- setup transaction manager --> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> <!-- Hibernate session factory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.connection.pool_size">5</prop> <prop key="hibernate.show_sql">false</prop> </props> </property> <property name="packagesToScan"> <list> <value>my.project.domain</value> </list> </property> </bean> <context:component-scan base-package="my.project" /> </beans>
The detail of issues..
"jmsListener" is instanciated before PropertyPlaceholderConfigurer start. When jmsListener start it receives some messages. And register some information at another class which has @Service annotation. But, after wicket application start, *maybe* Spring DI by PropertyPlaceholderConfigurer also instanciate several beans which have @Service annotation. And two instance which is instanciated not by PropertyPlaceholderConfigurer and by PropertyPlaceholderConfigurer seems to have different name. That means, even if the data was stored in a static object, it is not shared among them. So the wicket application can not access the data which jmsListener receives.Solution
I delay the start of jmsListener. Set autoStartup to "false" and call start() inside WicketApplication#init().<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <property name="destination" ref="destination"/> <property name="messageListener" ref="jmsListener"/> <property name="autoStartup" value="false"/> </bean>
public class MyWicketApplication extends WebApplication { @SpringBean private DefaultMessageListenerContainer jmsContainer; @Override protected void init() { super.init(); InjectorHolder.getInjector().inject(this); jmsContainer.start(); } }
Are there more smarter ways to solve the issue?
No comments:
Post a Comment