1

While trying to get sessionFactory.getCurrentSession() debugger shows that sessionFactory is null. I assume Spring 3 fails to inject sessionFactory into this class although all configuration seems to be in place. How to fix it?

ServiceOrderDAO:

@Transactional
public class ServiceOrderDAO{

@Autowired
    static
SessionFactory sessionFactory;

    public static List<ServiceOrderEntity> search(params...){
         Session localSession = sessionFactory.getCurrentSession();
        ...
    }
}

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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.1.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <context:annotation-config />

    <mvc:annotation-driven/>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="" />
        <property name="suffix" value=".jsp" />
    </bean>


    <context:component-scan base-package="controller" />
    <context:component-scan base-package="dao" />
    <context:component-scan base-package="service" />

    <context:property-placeholder location="classpath:dbConnection.properties" />

    <tx:annotation-driven transaction-manager="transactionManager"/>


    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="model" />
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <!--<bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>-->

    <bean id="dataSource"  class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.user}" />
        <property name="password" value="${jdbc.pass}" />
    </bean>


    <bean id="jdbcTemplateBean" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

</beans>
J.Olufsen
  • 13,415
  • 44
  • 120
  • 185
  • 1
    Why is your sessionFactory field static? Seems like a smell to me. You [can't inject static fields directly via Spring](http://stackoverflow.com/questions/7253694/spring-how-to-inject-a-value-to-static-field). – John Jun 16 '14 at 14:00
  • sessionFactory field is static because it gets called from static DAO method. Why static is not a good idea? – J.Olufsen Jun 16 '14 at 14:05
  • 1
    @RCola and why is the dao method static ? – NimChimpsky Jun 16 '14 at 14:09
  • @NimChimpsky, kind of legacy code, development started before spring/hibernate frameworks were attached... – J.Olufsen Jun 16 '14 at 14:24
  • 1
    @RCola Static methods are [problematic to testing](http://googletesting.blogspot.com/2008/12/static-methods-are-death-to-testability.html). Also, if you want to use Spring and the IoC pattern in general, then you want to abstract your implementation of dependencies away from the dependent classes. In your case it means you want to let Spring create the SessionFactory and set it on your DAO instead of having your DAO create or get an instance of SessionFactory on its own. – Erik Gillespie Jun 16 '14 at 14:25

2 Answers2

3

There are a few things I think you'll want to touch up:

  • SessionFactory shouldn't be static, nor should your search method be static if you're trying to treat that class as a Spring bean.
  • Add a @Component or @Repository annotation to the class. I don't think Spring will autowire classes that are missing a stereotype annotation on the class.
  • You should consider moving your @Transactional annotation to the method so you can provide more fine-grained propagation. For example, your search method may not require a transaction so you may want to use @Transactional(propagation = Propagation.SUPPORTS). Check out the Spring documentation for additional info that explains the various annotations and where/how to annotate transactions.
Erik Gillespie
  • 3,929
  • 2
  • 31
  • 48
3

sessionFactory being static definitely is the cause of the problem. You can't inject static fields with spring.

Going under the covers, the static fields gets initialized by classloader, before the constructor gets called, and therefore before spring gets chance to inject anything.

And your service class should be transactional, not your dao. And yes you need to annotate with @Component or @Service or similar.

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311