3

I'm trying to simply try out Spring, yet I seem to be missing something. It seems to load Spring and the beans just fine, however when it comes to injecting those beans with autowired, it doesn't work. Does anybody have a clue?

The part for of web.xml for Spring and the mainServlet:

    <welcome-file-list>
        <welcome-file>/login.jsp</welcome-file>
    </welcome-file-list>

    <!-- Spring Dependency Injection -->

     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

  <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
    </listener-class>

<!-- Login Filter -->
<filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>com.nortal.pirs.presentation.web.LoginFilter</filter-class>
    <init-param>
        <param-name>secretParameter</param-name>
        <param-value>8392</param-value>
    </init-param>
</filter>

<filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/MainServlet</url-pattern>
        <servlet-name>MainServlet</servlet-name>
</filter-mapping>

<!-- Main Servlet -->
<servlet>
<servlet-name>MainServlet</servlet-name>
<servlet-class>com.nortal.pirs.presentation.web.MainServlet</servlet-class>

<servlet-mapping>
    <servlet-name>MainServlet</servlet-name>
    <url-pattern>/main/*</url-pattern>
</servlet-mapping>

Spring application context file (Though I think I also loaded it with too much unnecessary crap, but it was out of desperation because it wasn't working):

    <?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />

    <!-- Turn on AspectJ @Configurable support -->
    <context:spring-configured />

    <context:component-scan base-package="com.nortal.pirs.test.independent" />
    <context:component-scan base-package="com.nortal.pirs.businesslogic.logic" />
    <context:component-scan base-package="com.nortal.pirs.presentation.vaadin" />
    <context:component-scan base-package="com.nortal.pirs.presentation.vaadin.views" />
    <context:component-scan base-package="com.nortal.pirs.presentation.web" />

    <!-- Turn on @Autowired, @PostConstruct etc support -->
    <bean
        class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
    <bean
        class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

</beans>

UserManagerLogic (The bean that has to be injected in MainServlet with @autowired later):

@Component("UserManager")
public class UserManagerLogic implements UserManagerInterface {

MainServlet:

 @Service
public class MainServlet extends HttpServlet {

    @Autowired
    @Qualifier("UserManager")
    private UserManagerInterface userManager;
    Logger log;

    public MainServlet() {
        log = Logger.getLogger(getClass());
    }

    public boolean userLoggedIn(String username, String password) {     
        return SecurityManager.getInstance().credentialsValid(username, password);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        processRequest(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        processRequest(req, resp);
    }

    public void processRequest(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {

        HttpSession session = ((HttpServletRequest) request).getSession();

        String username = (String) session.getAttribute("username");
        boolean authenticated = (boolean) session.getAttribute("authenticated");

        User user = userManager.getUserByEmail(username);

        WelcomeGenerator welcomeGenerator = new WelcomeGenerator();

        if (authenticated) {
            generateResponse(response, welcomeGenerator.WelcomeMessage(user), "The secret code is " + session.getAttribute("secretParameter"));
        } else {
            generateResponse(response, welcomeGenerator.wrongCredentialsMessage(username), "Secret code is hidden, because authentication failed");
        }
    }

    public void generateResponse(HttpServletResponse response, String welcomeMessage, String additionalData) throws IOException {       
        HtmlGenerator generator = new HtmlGenerator("PIRS");
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        out.write(generator.printHeader());
        out.write(generator.printCenter(welcomeMessage));
        out.write(generator.printCenter(additionalData));
        out.write(generator.printFooter());
    }

    public UserManagerInterface getUserManager() {
        return userManager;
    }

    public void setUserManager(UserManagerInterface userManager) {
        this.userManager = userManager;
    }               
}

And the outcome is a null pointer exception on the call for userManager of course, which was supposed to be injected by Spring?

java.lang.NullPointerException
    at com.nortal.pirs.presentation.web.MainServlet.processRequest(MainServlet.java:58)
    at com.nortal.pirs.presentation.web.MainServlet.doPost(MainServlet.java:47)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)

However Spring does load the beans it only doesn't inject them and doesn't throw any error, why is that?

2013-03-08 03:48:42,834 [localhost-startStop-1] INFO  org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6a4ac9fb: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.config.internalBeanConfigurerAspect,mainController,SecurityManager,**UserManager**,VisitManager,**mainServlet**,org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#0,org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy
Arturas M
  • 4,120
  • 18
  • 50
  • 80
  • why don't you use a controller instead of servlet – Arun P Johny Mar 08 '13 at 03:02
  • `@service` annotation is not meant for a servlet.Check this out.Should be same issue as yours .http://stackoverflow.com/questions/14283750/instantiationexception-using-spring-injection – SRy Mar 08 '13 at 06:37

2 Answers2

1

Your servlet isn't @Configurable. Since its lifecycle isn't controlled by Spring, that's the only way you're going to get it to be autowired.

Oh, and your servlet definitely isn't a @Service.

Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • It's more than that. Your servlet isn't managed by spring and so it can't inject other beans into it. – Sotirios Delimanolis Mar 08 '13 at 02:07
  • @Sotirios: That's not true. See ["Using AspectJ to dependency inject domain objects with Spring"](http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-atconfigurable). It's targeted at domain objects but works for anything. – Ryan Stewart Mar 08 '13 at 02:10
  • Within the context of this question, the servlet container will instantiate his `MainServlet`, so how do Spring know to autowire anything into it? – Sotirios Delimanolis Mar 08 '13 at 03:40
  • @Sotirios: Using AspectJ build-time or load-time bytecode weaving, you can let Spring gain control of the construction of any object, not just beans it manages. The link in my previous comment is to the section of the reference guide that describes how it works. – Ryan Stewart Mar 08 '13 at 04:40
  • Well I also tried it with Configurable, nothing had changed, what else needs to be done apart from changing Service to Configurable? Also how could I make all those servlets Spring manageable? – Arturas M Mar 08 '13 at 06:38
  • If you're just beginning with Spring, you might not want to use @Configurable yet, as it's a pretty advanced concept. Without that, as has been mentioned, the only objects you can manage with Spring are those that are created by Spring itself--that is, beans that you've set up using XML or annotations or something. – Ryan Stewart Mar 09 '13 at 01:58
0

Thats because Servlets are managed by Spring Container. Servlets are managed by the Servlet Container.

But fortunately Spring provides an utility method to get hold of SpringApplicationContext to get beans from the Servlet. This is accomplished using WebApplicationContextUtils

Sample Code

ApplicationContext ctx = 
                    WebApplicationContextUtils.
                          getWebApplicationContext(session.getServletContext());
UserManagerInterface userManager = (UserManagerInterface )ctx.getBean("UserManager");
Sudhakar
  • 4,823
  • 2
  • 35
  • 42