Search code examples
springspring-mvcdependency-injectionspring-annotations

Unable to autowire attributes in package


For some reason, in my config package, I can not autowire fields while in my controller package, there does not seem to be any problem.

For instance:

servlet-context.xml

<context:component-scan base-package="service, controller, config" />

root-context.xml (tried adding service here as well)

<context:component-scan base-package="security" />

This does not work: Setup class inside the config package. I receive a null pointer error.

@Component
public class Setup { //inside the config package
    @Autowired
    private UserService userService; //null pointer error
    /*..other stuff */
}

This does work: A controller inside the controller package:

@Controller
@RequestMapping(value="/contact")
public class ContactController { //inside the controller package
    @Autowired
    private UserService userService; //this works
    /*..other stuff..*/
}

Why does it work for the controller package but not config package?


Solution

  • This happens because probably the @Service class UserService is not visible in any of the two packages "config" or "controller" I assume you would also need a component scan for the packages containing the services:

    <context:component-scan base-package="service" />
    

    Edit:

    Usually you should remember that if a Bean/Component is not within the scanned context it will always be null on injection (autowiring).

    EDIT 2:

    So as you've probably seen Spring has two type of contexts, the ApplicationContext and the ServletContext. If you scan a bean in the ServletContext it will be accessible only from Controllers (or as the name states from the servlets), but beans scanned by the ApplicationContext are also accessible from Services or other Components and any servlet can access beans scanned here without having to scan them in the servlet context.

    In your case you should have the following setup:

    In servlet-context.xml:

    <context:component-scan base-package="controller" />
    

    In applicationContext.xml or root-context.xml (I assume you've referenced it as so in the web.xml)

    <context:component-scan base-package="config, security, services" />
    

    The image bellow illustrates the context hierarchy from Spring:

    enter image description here