Announcement Announcement Module
Collapse
No announcement yet.
Autowired failed - Bean=Null - in WebApp Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Autowired failed - Bean=Null - in WebApp

    Hi,

    I'm trying to get my beans autowired within a WebApp. My application is using Spring+Stripes+Hibernate. I think the problem is the spring context. Basically, I would like to access my DAO using @autowired annotation, directly from my Stripes' Bean (=UserActionBean.java). The code compile, it looks like the paths of the config files are OK. The content of the WAR file is also OK. But at the runtime I'm still getting an Null Pointer Exp when i'm trying to access my DAO (userDao).


    my current configuration looks like:

    Web.xml

    Code:
    ....	
    ....
    	<listener>
    	    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    	
    	<context-param>
    	    <param-name>contextConfigLocation</param-name>
    	    <param-value>/WEB-INF/applicationContext.xml</param-value>   
    	</context-param>	
    </web-app>
    applicationContext.xml

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
           
    	<import resource="classpath:bean/annotatedClasses.xml"/>
    	<import resource="classpath:dao/dao.xml"/>
    	<import resource="classpath:db/server-thin.xml"/>                       
    </beans>
    dao.xml

    Code:
    <?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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
               http://www.springframework.org/schema/beans/spring-beans-2.5.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="com.XXX.data.dao"/ -->
    
    	<!-- Transaction Manager -->	  	
      	<bean id="parentDao" abstract="true">
      		<property name="sessionFactory">
    			<ref bean="sessionFactory" />			
    		</property>
      	</bean>
      	
    	<!-- Beans for DAO and Service  -->
    	<bean id="eventDao" class="com.myapp.data.dao.impl.EventDaoImpl" parent="parentDao"/>
    	
    	<bean id="userDao" class="com.myapp.data.dao.impl.UserDaoImpl"  parent="parentDao"/>			
    </beans>
    UserActionBean.java (where I'm trying to use my DAOs via autowired)


    Code:
    /**
     * 
     * @author Foo
     */
    @UrlBinding("/user.action")
    public class UserActionBean implements ActionBean {
    	
    	@Autowired
    	private ActionBeanContext context;
    	
    	@Autowired
    	private UserDaoImpl userDao;
    
    	private String loginField;
    	
    	private String passwordField;	
    	
    	public ActionBeanContext getContext() {
    		return context;
    	}
    
    	public void setContext(ActionBeanContext context) {
    		this.context = context;
    	}		
    	
    	public String getLoginField() {
    		return loginField;
    	}
    
    	public void setLoginField(String loginField) {
    		this.loginField = loginField;
    	}
    
    	public String getPasswordField() {
    		return passwordField;
    	}
    
    	public void setPasswordField(String passwordField) {
    		this.passwordField = passwordField;
    	}
    
    	public UserDaoImpl getUserDao() {
    		return userDao;
    	}
    
    	public void setUserDao(UserDaoImpl userDao) {
    		this.userDao = userDao;
    	}
    
    	/**
         * Action: getM
         */	
    	@DefaultHandler
    	@HandlesEvent("login") 
        public Resolution loginJSP() {			
    		try {																			
    			List<User> myList = userDao.findAll();  // return NULL !
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    					
    		return new ForwardResolution("/WEB-INF/jsps/HomeActionView.jsp");
    	}
    }
    Am I doing something wrong or am I missing something?

    Thanks for your helps !
    Last edited by foo; Apr 2nd, 2010, 06:45 PM.

  • #2
    Hi,

    Pls try defining <context:annotation-config/> in the controller bean application context and not in the dao.xml. This element looks for annotations on beans in the same application context it is defined in.

    -Hetal

    Comment


    • #3
      Resolved.

      Hi,

      Sorry for the delayed answer and thanks for the suggestion. Finally, there is no problem with the Spring configuration. The problem is because of Stripes (ActionBeans) which do not handles Spring 2.5 annotations including @autowired with the standard SpringInterceptor definition.

      Code:
       <init-param>
           <param-name>Interceptor.Classes</param-name>
           <param-value>net.sourceforge.stripes.integration.spring.SpringInterceptor</param-value>
       </init-param>
      In order to be able to have this @autowired working inside your ActionBean, you need to use a customized SpringInterceptor which looks like:

      HTML Code:
      import net.sourceforge.stripes.action.*;
      import net.sourceforge.stripes.controller.*;
      import net.sourceforge.stripes.util.*;
      import org.springframework.beans.factory.config.*;
      import org.springframework.context.*;
      import org.springframework.util.*;
      import org.springframework.web.context.support.*;
      import javax.servlet.*;
       
      @Intercepts(LifecycleStage.ActionBeanResolution)
      public class Spring25Interceptor implements Interceptor
      {
          private static final Log log = Log.getInstance(Spring25Interceptor.class);
       
          public Resolution intercept(ExecutionContext context) throws Exception
          {
              Resolution resolution = context.proceed();
              log.debug("Running Spring dependency injection for instance of ", context.getActionBean().getClass().getSimpleName());
              ServletContext servletContext = StripesFilter.getConfiguration().getServletContext();
              ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
              AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
              beanFactory.autowireBeanProperties(context.getActionBean(), AutowireCapableBeanFactory.AUTOWIRE_NO, false);
              beanFactory.initializeBean(context.getActionBean(), StringUtils.uncapitalize(context.getActionBean().getClass().getSimpleName()));
              return resolution;
          }
      }
      So create or download this Spring25Interceptor and put it in your project. Then update your web.xml in order to use this specific interceptor:

      Code:
       <init-param>
           <param-name>Interceptor.Classes</param-name>
           <param-value>mypackage.stripes.integration.spring.Spring25Interceptor</param-value>
       </init-param>
      It works. I have found the solution here: http://blog.carbonfive.com/author/christian/page/2

      Cheers.

      Comment

      Working...
      X