Having issues autowiring a sessionfactory bean with spring mvc and hibernate

AndyAdamantium picture AndyAdamantium · Jul 31, 2013 · Viewed 9k times · Source

I am trying to implement auto-wiring into my project, but it seems that my application isn't seeing my SessionFactory definition in my application-context.xml when I am running it.

I'm probably missing something really obvious, though I've tried several solutions from posts having similar issues with no success.

I am using Spring MVC and Hibernate.

Here is my application-context.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:annotation-config />
    <context:component-scan base-package="arlua" />

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

    <bean id="serverDatasource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName">
            <value>oracle.jdbc.driver.OracleDriver</value>
        </property>
        <property name="url">
            <value>url</value>
        </property>
        <property name="username">
            <value>${user}</value>
        </property>
        <property name="password">
            <value>${pwd}</value>
        </property>
    </bean>

    <bean id="propertyPlaceholderConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
    </bean>

    <bean id="mySessionFactory"
        class="org.springframework.orm.hibernate3.annotation.LocalSessionFactoryBean">
        <property name="mappingResources">
            <list>
                <value>mapping/user_info.hbm.xml</value>
                <value>mapping/login.hbm.xml</value>
                <value>mapping/linked_accounts.hbm.xml</value>
                <value>mapping/application_instance.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
        <property name="dataSource" ref="serverDatasource"/>
    </bean>

    <bean id = "userInfoDaoImpl" class="arlua.dao.impl.UserInfoDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

    <bean id = "loginDaoImpl" class="arlua.dao.impl.LoginDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

    <bean id = "linkedAccountsDaoImpl" class="arlua.dao.impl.LinkedAccountsDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>
    <!--
    <bean id = "applicationInstanceDaoImpl" class="arlua.dao.impl.ApplicationInstanceDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>
     -->
    <!--  *************  TRANSACTION MANAGEMENT USING AOP **************** -->

    <bean id="myTransactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory"/>    
    </bean>

    <aop:config>
        <aop:pointcut id="allMethods" expression="execution(* arlua.dao.TableEntityFetchDao.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="allMethods"/>
    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="myTransactionManager">
        <tx:attributes>
            <tx:method name="saveEntity"
                propagation = "REQUIRES_NEW"
                isolation = "READ_COMMITTED"
                rollback-for = "Exception"/>
            <tx:method name="updateEntity"
                propagation = "REQUIRES_NEW"
                isolation = "READ_COMMITTED"
                rollback-for = "Exception"/>
            <tx:method name="getEntity"
                propagation = "REQUIRES_NEW"
                isolation = "READ_COMMITTED"
                rollback-for = "Exception"/>
            <tx:method name="getAllEntities"
                propagation = "REQUIRES_NEW"
                isolation = "READ_COMMITTED"
                rollback-for = "Exception"/>
        </tx:attributes>
    </tx:advice>

</beans>

Here is the controller class where I am trying to autowire.

package arlua.controller;

import arlua.dao.TableEntityFetchDao;
import arlua.dao.impl.ApplicationInstanceDaoImpl;
import arlua.service.SearchCriteria;
import arlua.service.UserAction;
import arlua.tables.ApplicationInstanceTable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

@Controller
@SessionAttributes
public class SearchAppController{
    @Autowired public ApplicationInstanceDaoImpl applicationInstanceDaoImpl;

    private String input;
    private ApplicationInstanceTable oldApp, newApp;

    @RequestMapping(value = "/search_app_instance", method = RequestMethod.POST)
    public String mySearchMethod(@ModelAttribute("search_criteria") SearchCriteria search){
        input = search.getInput();

        if(input != null)
            input = input.toUpperCase();

        return "redirect:search_app_instance";
    }

    @RequestMapping("/search_app_instance")
    public ModelAndView mySuccessMethod(){
        ModelAndView model = new ModelAndView("search_app_instance");

            //Check and Make sure that the app exists
            //ApplicationContext factory = 
            //  new ClassPathXmlApplicationContext("spring-namespace.xml");
            //TableEntityFetchDao urd = (TableEntityFetchDao)factory.getBean("applicationInstanceDaoImpl");
            try{
                ApplicationInstanceTable app = 
                    (ApplicationInstanceTable) applicationInstanceDaoImpl.getEntity(input);
                oldApp = app;
                //Load app data into table
                model.addObject("app_id", app.getApplication_id());
                model.addObject("name", app.getName());
                model.addObject("default_exp_period", app.getDefault_expiration_period());
                model.addObject("server", app.getServer());
                model.addObject("description", app.getDescription());
                model.addObject("active", app.getActive());
                model.addObject("conn_string", app.getConn_string());
                model.addObject("creation_date", app.getCreation_date().getTime());
                model.addObject("error", "");
            }
            catch(Exception e){
                if(input != null)
                {
                    model.addObject("error", "Application could not be found.");
                    input = "";
                }
            }

        return model;
    }


    @RequestMapping(value = "/app_actions", method = RequestMethod.POST)
    public String userActionsMethod(@ModelAttribute("user_action") UserAction action, 
            @ModelAttribute("app_info") ApplicationInstanceTable app_info){
        if(action.getAction().equals("update_info"))
        {
            newApp = app_info;
            return "redirect:update_app_info";
        }
        return "redirect:search_app_instance";
    }

    @RequestMapping("/update_app_info")
    public ModelAndView updateInfoMethod(){
        ModelAndView model = new ModelAndView("search_app_instance");

            ApplicationContext factory = 
                new ClassPathXmlApplicationContext("spring-namespace.xml");
            TableEntityFetchDao urd = (TableEntityFetchDao)factory.getBean("applicationInstanceDaoImpl");
            newApp.setApplication_id(oldApp.getApplication_id());
            newApp.setCreation_date(oldApp.getCreation_date());
            urd.updateEntity(newApp);

        model.addObject("msg", "Application '" + newApp.getApplication_id() + "' modified successfully.");
        return model;
    }

}

ApplicationInstanceDaoImpl Class

package arlua.dao.impl;

import arlua.dao.TableEntityFetchDao;
import arlua.tables.ApplicationInstanceTable;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;

@Repository("applicationInstanceDaoImpl")
public class ApplicationInstanceDaoImpl extends TableEntityFetchDao{

    public SessionFactory mySessionFactory;

    @Resource(name = "mySessionFactory")
    public void setMySessionFactory(SessionFactory mySessionFactory){
        this.mySessionFactory = mySessionFactory;
    }

    public void saveEntity(Object applicationInstance) {
        this.mySessionFactory.getCurrentSession().save((ApplicationInstanceTable)applicationInstance);
    }

    public ApplicationInstanceTable getEntity(Object application_id) {
        return (ApplicationInstanceTable)this.mySessionFactory.getCurrentSession().
            get(ApplicationInstanceTable.class, (String)application_id);
    }

    public void updateEntity(Object applicationInstance) {
        this.mySessionFactory.getCurrentSession().update((ApplicationInstanceTable)applicationInstance);
    }

    public void deleteEntity(Object applicationInstance) {
        this.mySessionFactory.getCurrentSession().delete((ApplicationInstanceTable)applicationInstance);
    }

    public List<?> getAllEntities() {
        return this.mySessionFactory.getCurrentSession().createQuery
            ("FROM application_instance").list();
    }
}

TableEntityFetchDao class

package arlua.dao;

import java.util.List;

import org.hibernate.SessionFactory;

/*
This class will serve as a generic blueprint for all of the other data access implementation classes
that are used to perform basic CRUD operations on the arlua tables (ie UserInfoDaoImpl).
 */
public abstract class TableEntityFetchDao {

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory){
        this.sessionFactory = sessionFactory;
    }

    public abstract void saveEntity(final Object entity);

    public abstract Object getEntity(final Object key);

    public abstract void updateEntity(final Object entity);

    public abstract void deleteEntity(final Object entity);

    public abstract List<?> getAllEntities();
}

Here is most of my stack trace.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchAppController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public arlua.dao.impl.ApplicationInstanceDaoImpl arlua.controller.SearchAppController.applicationInstanceDaoImpl; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applicationInstanceDaoImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mySessionFactory' is defined
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
    at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
    at org.apache.catalina.core.StandardService.start(StandardService.java:525)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchAppController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public arlua.dao.impl.ApplicationInstanceDaoImpl arlua.controller.SearchAppController.applicationInstanceDaoImpl; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applicationInstanceDaoImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mySessionFactory' is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1075)
    at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:383)
    at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:362)
    at org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping.detectHandlers(AbstractDetectingUrlHandlerMapping.java:82)
    at org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping.initApplicationContext(AbstractDetectingUrlHandlerMapping.java:58)
    at org.springframework.context.support.ApplicationObjectSupport.initApplicationContext(ApplicationObjectSupport.java:119)
    at org.springframework.web.context.support.WebApplicationObjectSupport.initApplicationContext(WebApplicationObjectSupport.java:72)
    at org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)
    at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:106)
    at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:85)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:394)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1413)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    ... 26 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public arlua.dao.impl.ApplicationInstanceDaoImpl arlua.controller.SearchAppController.applicationInstanceDaoImpl; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applicationInstanceDaoImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mySessionFactory' is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
    ... 46 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applicationInstanceDaoImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mySessionFactory' is defined
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:300)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:844)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:786)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
    ... 48 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mySessionFactory' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:527)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1083)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:274)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:435)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:409)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:541)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:156)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:297)
    ... 59 more

Edit: I ended up fixing my problem by autowiring into the interface TableEntityFetchDao rather than the class that was implementing it, ApplicationInstanceDaoImpl.

So, this

@Autowired public ApplicationInstanceDaoImpl applicationInstanceDaoImpl;

Became this

@Autowired public TableEntityFetchDao applicationInstanceDao;

And that seemed to fix my problem.

Answer

Paulius Matulionis picture Paulius Matulionis · Jul 31, 2013

Instead of:

@Resource(name = "mySessionFactory")
public void setMySessionFactory(SessionFactory mySessionFactory){
    this.mySessionFactory = mySessionFactory;
}

Use:

@Autowired
private SessionFactory mySessionFactory;

EDIT

As of the bellow comment:

Not sure why method is not working but my guess is that the parent TableEntityFetchDao class has the setter of session factory, then ApplicationInstanceDaoImpl - child class overrides it and spring for some reason does not like it, if TableEntityFetchDao would be an interface, setter would be injected, as @Resource serves the same purpose as @Autowired difference is that @Resource allows to specify the name of the bean which is injected, and @Autowire allows you mark the bean as not required.

To get @Resource working I would try to remove setter method from the parent class. Either way it makes no sense of having it there as it is not used. Also sessionFactory field. This can be removed as well. Then class contains only abstract methods and can be made an interface. Also I would annotate TableEntityFetchDao with @Service annotation for better understanding that it is a service-layer class.