Spring: BeanCreationException

13,497

Solution 1

Use the @PostConstruct tag and get the session then. Your beans will only be injected after your UserDaoImpl is created and @PostConstruct method will only be called by Spring after all your beans are injected.

@Service
public class UserDaoImpl implements UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    private Session session;

    public UserDaoImpl() {
    }

    @PostConstruct
    public void init() {
        this.session = sessionFactory.getCurrentSession();
    }
    ...
}

Another way (better in my opnion) is inject by constructor and getting the current session only when you need it.

    ...
    private final SessionFactory sessionFactory;

    @Autowired
    public UserDaoImpl(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    private Session currentSession() {
        return this.sessionFactory.getCurrentSession();
    }

EDIT: Use the second way preferably, because if you get the session only after construct, calls to your DAO won't work once that session is expired. Always use SessionFactory#getCurrentSession() when starting make calls at your transactional methods.

Solution 2

As Ralf points out, the constructor is executed too early and Spring did not inject anything at this point.

Further, you may not hold a reference to Session as it relies on the SessionContext mechanism, which in turn may be thread bound or servlet request bound. Your bean may has a wider scope (e.g. singleton) and you will permanently store the session from the first caller or something!

I suggest to always get the session from sessionFactory when needed inside the bean.

Share:
13,497
Mr. Polywhirl
Author by

Mr. Polywhirl

Languages (Ordered by proficiency): Server:   java, c++, python, c#* Web:      javascript, actionscript, php, perl DB:        mysql, mongodb Other:    pascal, mips64, lisp* Markup: html, markdown, mxml, xml

Updated on June 04, 2022

Comments

  • Mr. Polywhirl
    Mr. Polywhirl almost 2 years

    I am trying to get the session from the session factory to use with my CRUD methods. I tried to set the session in the constructor, but the bean has not been initialized by then. How do I initialize it after the bean is created?

    Stacktrace

    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDaoImpl' defined in file [/home/ryan/workspace/com-byteslounge-spring-tx/target/classes/com/byteslounge/spring/tx/dao/impl/UserDaoImpl.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.byteslounge.spring.tx.dao.impl.UserDaoImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1011)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:957)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
        at com.byteslounge.spring.tx.Main.main(Main.java:19)
    Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.byteslounge.spring.tx.dao.impl.UserDaoImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1004)
        ... 13 more
    Caused by: java.lang.NullPointerException
        at com.byteslounge.spring.tx.dao.impl.UserDaoImpl.<init>(UserDaoImpl.java:24)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
        ... 15 more
    

    UserDaoImpl.java

    package com.byteslounge.spring.tx.dao.impl;
    
    import java.util.List;
    
    import org.hibernate.Criteria;
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.byteslounge.spring.tx.dao.UserDao;
    import com.byteslounge.spring.tx.domain.User;
    
    @Service
    public class UserDaoImpl implements UserDao {
    
        @Autowired
        private SessionFactory sessionFactory;
    
        private Session session;
    
        public UserDaoImpl() {
            session = sessionFactory.getCurrentSession();
        }
    
        public SessionFactory getSessionFactory() {
            return this.sessionFactory;
        }
    
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    
        public void insertUser(User user) {
            session.save(user);
        }
    
        public void removeUserByName(String username) {
            User user = null;
            try {
                getUser(username);
            } catch (IndexOutOfBoundsException e) {
                System.out.println(username + " does not exist!");
            } finally {
                if (user != null)
                    session.delete(user);
            }
        }
    
        public User getUserById(int userId) {
            return (User) session.get(User.class, userId);
        }
    
        public User getUser(String username) {
            // Query query = sessionFactory.getCurrentSession().createQuery("from User where username = :username");
            // query.setParameter("username", username);
    
            Query query = session.getNamedQuery(User.FIND_USER_BY_USERNAME).setString("username", username);
            return (User) query.list().get(0);
        }
    
        @SuppressWarnings("unchecked")
        public List<User> getUsers() {
            Criteria criteria = session.createCriteria(User.class);
            return criteria.list();
        }
    }
    

    applicationContext.xml

    <?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:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <tx:annotation-driven />
    
        <context:component-scan base-package="com.byteslounge.spring.tx.dao.impl" />
        <context:component-scan base-package="com.byteslounge.spring.tx.user.impl" />
    
        <bean
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location">
                <value>database.properties</value>
            </property>
        </bean>
    
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="driverClassName" value="${jdbc.driverClassName}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
        </bean>
    
        <bean id="sessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                    <prop key="hibernate.show_sql">true</prop>
                </props>
            </property>
            <property name="packagesToScan" value="com.byteslounge.spring.tx.domain" />
        </bean>
    
        <bean id="transactionManager"
            class="org.springframework.orm.hibernate4.HibernateTransactionManager"
            p:sessionFactory-ref="sessionFactory">
        </bean>
    
    </beans>
    
  • Caesar Ralf
    Caesar Ralf almost 11 years
    @Mr.Polywhirl mark as an answer then, please :) glad I could help
  • Mr. Polywhirl
    Mr. Polywhirl almost 11 years
    Sorry, I was working on something else. I had to wait to accept.