There's one master Spring file, and two subsiduary files that contain environment specific properties.
The main file is below (minus the data source):
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="exposeTransactionAwareSessionFactory" value="false"/>
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>com/tersesystems/blog/dao/hibernate/PostImpl.hbm.xml</value>
<value>com/tersesystems/blog/dao/hibernate/CommentImpl.hbm.xml</value>
<value>com/tersesystems/blog/dao/hibernate/CategoryImpl.hbm.xml</value>
<value>com/tersesystems/blog/dao/hibernate/MemberImpl.hbm.xml</value>
<value>com/tersesystems/blog/dao/hibernate/MediaImpl.hbm.xml</value>
<value>org/appfuse/model/Role.hbm.xml</value>
<value>org/appfuse/model/User.hbm.xml</value>
<value>org/appfuse/model/UserCookie.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties" ref="hibernatePropertiesBean"/>
</bean>Note the references to the hibernatePropertiesBean. This is an instance of PropertiesFactoryBean that will be defined in the environment Spring file.
The JTA Spring file is defined below:
<bean id="hibernatePropertiesBean" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
<prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.query.substitutions">${hibernate.query.substitutions}</prop>
<!-- Must be enabled for JTA transactions... -->
<prop key="hibernate.transaction.manager_lookup_class">${hibernate.transaction.manager.lookup}</prop>
</props>
</property>
</bean>and the JDBC one is defined likewise. Note that we can't have even an empty property existing for hibernate.transaction.manager.lookup here.
<bean id="hibernatePropertiesBean" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
<prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.query.substitutions">${hibernate.query.substitutions}</prop>
<!-- Do not allow transaction.manager.lookup to be defined here. -->
</props>
</property>
</bean>This doesn't include the changes to the transaction manager or the like, but it gets the point across.
Then, since the servlet isn't around to do it for me, I have to define a hibernate session "in-house" for integration tests:
public void onSetUp() throws Exception
{
super.onSetUp();
ApplicationContext context = applicationContext;
sessionFactory = (SessionFactory) context.getBean("sessionFactory");
sessionFactory.getCurrentSession().beginTransaction();
}
@Override
protected void onTearDown() throws Exception
{
if (transaction != null)
{
transaction.commit();
}
super.onTearDown();
}And now all my integration tests work! Yay!
I used Carlos Sanchez's post as a guide, and have been looking at Alef's Configuration Management with Spring for more information.
Still surprised at how much work it is to override properties in Spring. As far as I know, there's no way you can explicitly say "I'm scribbling over another bean definition" now, apart from where you've explicitly set it up that way with PropertyOverrideConfigurer. Among other things, I don't see any way that you can change a bean's defined class once it's set up, which is something you can do in Nucleus right off the bat.
Still, it works, and I should be thankful I can do integration testing at all. Now to go look at Webwork forms.
Either put these in a static or use TestNG (http://testng.org), which is more appropriate for integration testing anyway.