views:

522

answers:

3

Is it possible to Autowire an object in a Validation class? I keep getting null for the object that is supposed to be Autowired...

+4  A: 

Are your Validation class an enabled Spring bean ??? If not, you always will get null for your object autowired. Make sure you have enabled your Validation class.

And do not forget enable The Annotation config bean post-processor (see <context:annotation-config /> element)

<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"&gt;
    <context:annotation-config />
</beans>

How to enable your Validation class as a managed Spring bean. Either

By using xml (As shown above)

<beans ...>
    <bean class="AccessRequestValidator"/>
    <context:annotation-config />
</beans>

By using annotation instead (Notice @Component just above class)

@Component
public class AccessRequestValidator implements Validator {

}

But to enable Spring annotated component scanning, you must enable a bean-post processor (notice <context:component-scan element)

<beans ...>
    <context:annotation-config />
    <context:component-scan base-package="<PUT_RIGHT_HERE_WHICH_ROOT_PACKAGE_SHOULD_SPRING_LOOK_FOR_ANY_ANNOTATED_BEAN>"/>
</beans>

Inside your Controller, just do it (Do not use new operator)

Choose one of the following strategies

public class MyController implements Controller {

    /**
      * You can use FIELD @Autowired
      */
    @Autowired
    private AccessRequestValidator accessRequestValidator;

    /**
      * You can use PROPERTY @Autowired
      */
    private AccessRequestValidator accessRequestValidator;
    private @Autowired void setAccessRequestValidator(AccessRequestValidator accessRequestValidator) {
        this.accessRequestValidator = accessRequestValidator;
    }

    /**
      * You can use CONSTRUCTOR @Autowired
      */
    private AccessRequestValidator accessRequestValidator;

    @Autowired
    public MyController(AccessRequestValidator accessRequestValidator) {
        this.accessRequestValidator = accessRequestValidator;
    }   

}

UPDATE

Your web app structure should looks like

<CONTEXT-NAME>/
       WEB-INF/
           web.xml
           <SPRING-SERVLET-NAME>-servlet.xml
           business-context.xml
           classes/
               /com
                   /wuntee
                       /taac
                           /validator
                               AccessRequestValidator.class
           lib/
               /**
                 * libraries needed by your project goes here
                 */

Your web.xml should looks like (NOTICE contextConfigLocation context-param and ContextLoaderListener)

<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                       http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"&gt;
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!--If your business-context.xml lives in the root of classpath-->
        <!--replace by classpath:business-context.xml-->
        <param-value>
            /WEB-INF/business-context.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name><SPRING-SERVLET-NAME></servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name><SPRING-SERVLET-NAME></servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
</web-app>

Your <SPRING-SERVLET-NAME>-servlet.xml should looks like (Notice i am using Spring 2.5 - replace if you are using 3.0)

 <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"&gt;
    <!--ANY HANDLER MAPPING-->
    <!--ANY VIEW RESOLVER-->
    <context:component-scan base-package="com.wuntee.taac"/>
    <context:annotation-config/>
</beans>
Arthur Ronald F D Garcia
I think he's referring to validator classes that are *not* managed by Spring, in which case `annotation-config` won't make a difference.
skaffman
i am not sure what you mean by 'managed/not-managed by spring'... i have a class that implements Validator and is used in the Controller like: AccessRequestValidator validator = new AccessRequestValidator(); validator.validate(accessRequestBean, result);
wuntee
@wuntee You really do not have a Spring managed bean. If you create some instance by using new operator, how can Spring manage your instance ? I will show you how to get your goal
Arthur Ronald F D Garcia
A: 

Trying to follow what you show above, I am still getting a null pointer:

context.xml:

<context:annotation-config />
<context:component-scan base-package="com.wuntee.taac"/>

AccessRequestValidator.java

package com.wuntee.taac.validator;

@Component
public class AccessRequestValidator implements Validator {

    @Autowired
    private UserAccessCache userAccessCache;
...
}

business-context.xml:

   <bean id="userAccessCache" class="com.wuntee.taac.controller.UserAccessCache">
        <property name="cadaDao" ref="cadaDao" />
        <property name="adDao" ref="adDao" />
   </bean>

Does the scanner recursively scan the tree?

wuntee
Strange, I'm seeing the same thing in my project now. A @Component-annotated Validator with an @Autowired field, but it's never wired up and remains null.
Haakon
Update: I found my mistake. In my controller, I had an @InitBinder method with this code:binder.setValidator(new FooValidator());So while Spring managed *a* FooValidator, I set my controller to use a different, unmanaged one. I just changed it to an autowired FooValidator.
Haakon
A: 

I am having a similar issue! I instantiate my controller from a test class and I configured my mock services in my test application context. When I call the controller the property that is @Autowired is null. I know that the service is being injected into the test class, but the service seems to not be injected into the controller. I hope this makes sense.

jkrfs