Spring Annotations -java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required in spring+hibernate

Hmahwish picture Hmahwish · Sep 17, 2013 · Viewed 8.4k times · Source

I am getting the error as in the question. My Dao Implement Class is as follows :

package com.argus.intenew;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

@Autowired
AnnotationSessionFactoryBean sessionFactory;
    public UserDaoImpl() {
    }

    public AnnotationSessionFactoryBean getCurrentSessionFactory() {
        return sessionFactory;
    }

    public void  setCurrentSessionFactory(AnnotationSessionFactoryBean sessionfactory) {
        this.sessionFactory = sessionfactory;
    }

    @Override
    public void addUser(UserMap userMap) {
        System.out.println("33333333333333333333");
        getHibernateTemplate().save(userMap);
    }

    @Override
    public List<User> findAllUser() {
        return getHibernateTemplate().find("from User");
    }

    @Override
    public void deleteUser(UserMap user) {
        getHibernateTemplate().delete(user);
    }

    @Override
    public void updateUser(UserMap user) {
        getHibernateTemplate().update(user);
    }
}

And my configuration class is as follows:

package com.argus.intenew;

import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;

@Configuration
@ComponentScan(basePackages = {"com.argus.intenew"})
public class Webconfig  {
    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "org.hibernate.dialect.MySQLDialect ";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "true";

    @Bean
    public DataSource dataSource() {
        System.out.println("----------InDATAsource------------");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/MyUser");
        dataSource.setUsername("root");
        dataSource.setPassword("XXX");
        System.out.println("----------OutofDATAsource------------");
        return dataSource;
    }

    @Bean
    public AnnotationSessionFactoryBean sessionFactory() {
        System.out.println("----------InsessionFactory------------");
        AnnotationSessionFactoryBean sessionFactory = new AnnotationSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        String[] pckage={"com.argus.intenew"};
        sessionFactory.setPackagesToScan(pckage);
        sessionFactory.setHibernateProperties(hibProperties());
        System.out.println("----------Outof session------------");
        return sessionFactory;
    }

    private Properties hibProperties() {
        System.out.println("----------InhipProp------------");
        Properties properties = new Properties();
        properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, "org.hibernate.dialect.MySQLDialect ");
        properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, "true");
        System.out.println("----------outofhip------------");
        return properties;
    }

    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory().getObject());

        return transactionManager;
   }

   @Bean
   public UserBoImpl userBo() {
       System.out.println("----------InUserBo------------");
       UserBoImpl userBo= new UserBoImpl();
       userBo.setUserDao(userDao());
       System.out.println("----------OutofUserbo------------");
       return userBo;
   }

   @Bean
   public UserDaoImpl userDao() {
       System.out.println("----------InUserDao------------");
       UserDaoImpl userDao=new UserDaoImpl();
       userDao.setCurrentSessionFactory(sessionFactory());
       System.out.println("----------OutofUserDao------------");
       return userDao;
   }
}

Anyone please help and tell me what is the correct way to do this with annotations. Here I am not using any xml file.

Answer

superEb picture superEb · Sep 17, 2013

Your DAO implementation is not leveraging its superclass correctly.

  1. You're injecting a Spring FactoryBean<SessionFactory> when it really needs a Hibernate SessionFactory.
  2. It's not actually using the injected dependency.
  3. You're attempting to use HibernateDaoSupport#getHibernateTemplate() without giving it a reference to a SessionFactory or a HibernateTemplate.

Note that HibernateDaoSupport will create its own HibernateTemplate as long as you give it a SessionFactory.

I suggest you make the following changes:

  1. Remove AnnotationSessionFactoryBean sessionFactory from UserDaoImpl
  2. Fix configuration of UserDaoImpl by leveraging its inherited setSessionFactory(SessionFactory) method

So you actually end up with this DAO code:

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    @Override
    public void addUser(UserMap userMap) {
        getHibernateTemplate().save(userMap);
    }
    @Override
    public List<User> findAllUser() {
        return getHibernateTemplate().find("from User");
    }
    @Override
    public void deleteUser(UserMap user) {
        getHibernateTemplate().delete(user);
    }
    @Override
    public void updateUser(UserMap user) {
        getHibernateTemplate().update(user);
    }
}

And this configuration code:

@Configuration
@ComponentScan(basePackages = {"com.argus.intenew"})  
public class Webconfig  {
    //snip...
    @Bean
    public UserDaoImpl userDao() {
        UserDaoImpl userDao=new UserDaoImpl();
        userDao.setSessionFactory(sessionFactory().getObject());
        return userDao;
    }
}

Note that it's ok to return the FactoryBean from the sessionFactory() configuration method since Spring will detect and utilize its lifecycle methods (via InitializingBean and DisposableBean), but you need to accommodate by calling the FactoryBean method getObject() yourself.