January 20, 2006 01:46
Programming, Java, Blog
Hokay. I have a workable configuration environment now.

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.

« New ATG functionality | Home | Hibernate vs. Spring »

Are you aware that your setUp() is being invoked before *every* test method? What a waste.

Either put these in a static or use TestNG (http://testng.org), which is more appropriate for integration testing anyway.

I'd rather be using TestNG, but the Spring integration test classes don't work with it. See the earlier posts.

name
url