Rob
Rob

Reputation: 4234

Spring @Autowired injection doesn't work : DAO is always null

I am working on an EAR with actions handled by Struts and beans by Spring. This EAR includes 3 .jar files, the references of the commons files (DS/US/DAO), and a .war, myProjectWeb.

Code :

The Struts action (in myProjectWeb) :

public class MyAction extends DispatchAction {

    private IMyPreferencesDS myPreferences;

    protected ActionForward executeAction(ActionMapping mapping, ActionForm form, 
        HttpServletRequest request, HttpServletResponse response) throws Exception {
        // newValue is got from my form
        myPreferences.updatePreferences(newValue);
    }
}

The different DSs (in myProject-commons) :

IMyPreferencesDS :

public interface IMyPreferencesDS extends IAbstractDSGeneric<MyDTO> {

    void updatePreferences(String newValue) throws JrafDomainException;

}

MyPreferencesDS :

public class MyPreferencesDS implements IMyPreferencesDS {

    @PersistenceContext(unitName="myPersistenceUnit")
    private EntityManager entityManager;

    @Autowired
    @Qualifier("myPreferencesDAOBean")
    private IMyPreferencesDAO mainDao;

    @Transactional(rollbackFor = JrafDomainRollbackException.class, 
        noRollbackFor = JrafDomainNoRollbackException.class)
    public void updatePreferences(String newValue) throws JrafDomainException {

        mainDao.setNewPreferencesValue(newValue);

    }
}

IMyPreferencesDAO :

public interface IMyPreferencesDAO extends IAbstractDAOGeneric<MyEntity> {

    void setNewPreferencesValue(String newValue) throws JrafDaoException;

}

MyPreferencesDAO :

public class MyPreferencesDAO extends AbstractDAOGenericImpl<MyEntity> implements IMyPreferencesDAO {

    public void setNewPreferencesValue(String newValue) throws JrafDaoException {
        StringBuilder strQuery = new StringBuilder();
        strQuery.append("update MYBASE.MYTABLE ");
        strQuery.append("set");
        strQuery.append(" PREFS=:newValue, ");

        final Query myQuery = getEntityManager().createNativeQuery(strQuery.toString(), MyEntity.class);
        myQuery.setParameter("newValue", newValue);

        try {
            return myQuery.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Config :

In myProjectWeb :

struts-config :

<form-bean name="MyForm" type="com.my.MyForm"/>
<action input="/media/modificationPopup.jsp" name="MyForm" path="/media/prefModif" 
    scope="request" type="org.springframework.web.struts.DelegatingActionProxy" 
    validate="true"/>

actions-dependencies :

<bean name="/media/prefModif" class="com.my.action.MyAction" scope="singleton">
    <property name="myPreferences" ref="myPreferencesDS" />
</bean> 

application-context-spring :

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-2.5.xsd 
    http://www.springframework.org/schema/jee 
    http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

    <!-- Enterprise layer's dependencies -->
    <import resource="classpath:ioc/0-ref-commons-enterpriselayer-dependencies.xml" />

    <bean id="springLocator" class="com.afklm.jraf.bootstrap.locator.SpringLocator"></bean>

    <bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
        <property name="persistenceXmlLocations">
            <list>
                <value>classpath*:META-INF/persistence-web.xml</value>
            </list>
        </property>
    </bean>

    <bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitManager" ref="persistenceUnitManager" />
        <property name="persistenceUnitName" value="myPersistenceUnit" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="myEmf" />
    </bean>

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

    <context:component-scan base-package="com.my.action" /> 
</beans>

0-ref-commons-enterpriselayer-dependencies.xml is contained into the commons jar :

<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.0.xsd">
    <import resource="1-ref-commons-ds-dependencies.xml"/>
    <import resource="2-ref-commons-us-dependencies.xml"/>
    <import resource="3-ref-commons-daos-dependencies.xml"/>
</beans>

It contains the requested DS and DAO, like this :

In 1-ref-commons-ds-dependencies.xml

<!-- MyPreferencesDS Component -->
<bean id="myPreferencesDS" class="com.commons.ds.MyPreferencesDS" scope="prototype">
</bean>

In 3-ref-commons-daos-dependencies.xml

<!-- MyPreferencesDAO Component -->
<bean id="myPreferencesDAOBean" class="com.commons.daos.MyPreferencesDAO" scope="prototype">
</bean>

All the libs are in my EAR :

enter image description here

And imported into my Web .war :

enter image description here

My EAR's module assembling :

enter image description here

Ok here it is... But when I try to call this line in MyPreferencesDS :

mainDao.setNewPreferencesValue(newValue);

mainDao is always null and I get a NullPointerException... Seems like the @Autowired injection doesn't work there.

Thanks for your help...

Upvotes: 1

Views: 1452

Answers (2)

Bharath
Bharath

Reputation: 259

You are not scanning "com.commons" package. Since "com.commons.ds.MyPreferencesDS" is in that package, spring will not even it needs to autowire beans of this package. you may want to try the below line in application-context-spring:

<context:component-scan base-package="com.my.action, com.commons" />

if you dont want all the packages under "com.commons" and be more specific about what packages that are scanned and list all of them:

<context:component-scan base-package="com.my.action, com.commons.ds, com.commons.daos" />

Upvotes: 0

StanislavL
StanislavL

Reputation: 57421

Ypu have a mixture of @Autowiring and direct assigning via xml.

Your myAction doesn't have autowired preferences. You set it via ref

<bean name="/media/prefModif" class="com.my.action.MyAction" scope="singleton">
    <property name="myPreferences" ref="myPreferencesDS" />
</bean> 

So define the dao ref the same way by ref.

<bean id="myPreferencesDS" class="com.commons.ds.MyPreferencesDS" scope="prototype">
    <property name="mainDao" ref="myPreferencesDAOBean" />
</bean>

Or use @Autowire to inject preferences into the Action

Upvotes: 1

Related Questions