Search code examples
javaspringejbjaasvaadin7

Vaadin 7 + Spring + VaadinSpringIntegration Add-on - Autowired bean is null


So I have a Vaadin 7 Application that I have been working on but now there is a requirement to integrate JAAS and eventually OpenAM for authentication and authorization. I noticed that alot of folks were using Spring to get it to work, so I went that route. I used the VaadinSpringIntegration addon and I think it is setup correctly, but when I launch my app, my autowired bean is null. I have never used Spring before so its very possible I'm overlooking something.

So here is a part of my web.xml

<web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Hoplite Tool</display-name>

 <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>

<servlet>
    <servlet-name>Hoplite</servlet-name>
    <servlet-class>org.hoplite.servlet.HopliteServlet</servlet-class>
    <init-param>
        <param-name>UI</param-name>
        <param-value>org.hoplite.dashboard.DashboardUI</param-value>
    </init-param>
    <init-param>
        <param-name>widgetset</param-name>
        <param-value>org.hoplite.dashboard.DashboardWidgetSet</param-value>
    </init-param>
    <init-param>
        <param-name>UIProvider</param-name>
        <param-value>org.hoplite.dashboard.DashboardUIProvider</param-value>
    </init-param>

    <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>BAT3</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

Here is my applicationContext.xml

<?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:lang="http://www.springframework.org/schema/lang"
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/lang
 http://www.springframework.org/schema/lang/spring-lang.xsd
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context.xsd">

<context:annotation-config />
<context:component-scan base-package="org.hoplite.dashboard" />       

</beans>

I had to include some javascript for the webapp so I extended SpringVaadinServlet

public class HopliteServlet extends SpringVaadinServlet {

/**
 * Attempt to load extra javascript
 * 
 * @throws ServletException
 */
@Override
protected void servletInitialized() throws ServletException {
    super.servletInitialized();
    getService().addSessionInitListener(new SessionInitListener() {

        @Override
        public void sessionInit(SessionInitEvent event) throws ServiceException {
            event.getSession().addBootstrapListener(new BootstrapListener() {

                @Override
                public void modifyBootstrapPage(BootstrapPageResponse response) {

                    response.getDocument().head().appendElement("script").attr("type", "text/javascript").attr("src", "https://www.google.com/jsapi");

                }

                @Override
                public void modifyBootstrapFragment(BootstrapFragmentResponse response) {
                }
            });
        }
    });
}

}

And finally I have my UI class that has an Autowired bean (sorry that class is long so I can only provide a snippet)

@Push(PushMode.MANUAL)
@Theme("dashboard")
@Title("Hoplite Tool")
@Component
@Scope("prototype")
public class DashboardUI extends UI {

      @Autowired
      private LoginBean loginBean; 

      ...

      //add listener to button
      signin.addClickListener(new ClickListener() {

        @Override
        public void buttonClick(ClickEvent event) {
           String name = loginBean.performLogin(username.getValue().toString(), password.getValue().toString());
           buildMainView();
        }
}

Here is the loginBean class

@Component
@Scope("prototype")
public class LoginBean {

    @Autowired
    private HttpServletRequest request;

    /**
     * Logs the user in with given username and password.
     * 
     * @param username
     * @param password
     * @return principal name if login is successful
     * @throws ServletException if login fails
     */
    public String performLogin(String username, String password) throws ServletException {

        // If login fails, we throw exception. Otherwise return the principal
        // name of logged in user.
        request.login(username, password);
        return request.getUserPrincipal().getName();
    }

    /**
     * Logs out the current user.
     * 
     * @throws ServletException if logout fails
     */
    public void performLogout() throws ServletException {
        request.logout();
    }
}

My bean class and the UI class are in org.hoplite.dashboard

However every time I get the main UI then the loginBean is null...can anyone help me out here?


Solution

  • I'll take them 1 at a time:

    1) Unless otherwise specified, the SpringVaadinServlet will use a SpringUIProvider to retrieve the beans from the context. If you absolutely need to overwrite the default one, make sure the DashboardUIProvider is retrieving the UI instance from the spring application context so that the "auto-magic" can happen:

    <init-param>
        <param-name>UIProvider</param-name>
        <param-value>org.hoplite.dashboard.DashboardUIProvider</param-value>
    </init-param>
    

    2) If you discard your DashboardUIProvider, please note that the default SpringUIProvider expects a beanName param instead of UI so change:

    <init-param>
        <param-name>UI</param-name>
        <param-value>org.hoplite.dashboard.DashboardUI</param-value>
    </init-param>
    

    to

    <init-param>
        <param-name>beanName</param-name>
        <param-value>dashboardUI</param-value>
    </init-param>
    

    where dashboardUI is the implicit name spring will use for your UI. If you change it, make sure to update your web.xml with the new one