Configuring Vaadin with Spring Session Scoped Beans

Hi vaadin guys,

I’ve tried to configure spring in order it use vaadin component as session scoped components.
i followed various posts such as
here
but wasn’t able to configure it properly.

I’m facing this message and don’t understand how why…

Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread?
 If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet:
 In this case, use RequestContextListener or RequestContextFilter to expose the current request.

In web.xml my spring configuration is like this :

	<!-- Listener IOC -->
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	<listener>
		<!-- To allow session-scoped beans -->
		<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
	</listener>
	<!-- Le listener lié à Quartz Scheduler -->
	<listener>

And alos tried to use dispatcher Servlet like this

	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/app/*</url-pattern>
	</servlet-mapping>

My Vaadin Servlet is a custom Servlet configured by mixing Navigator7 Servlet and icepush Servlet and is available in /app/* url pattern.

As anybody encountered this kind of problem ?

Thanks,

Hi,
We’re using session scoped beans (not for vaadin components, but that’s by-the-by): this is the relevant section of our web.xml :


  <!-- When the servlet context starts, configure spring -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- The Spring config files to load; used by the ContextLoaderListener -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring-*.xml</param-value>
  </context-param>

  <!-- This listener allows us to define session scoped beans -->
  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>

We are not using the Dispatcher servlet, just the plain-old Vaadin ApplicationServlet; my limited understanding of Spring suggest that if you are using the Dispatcher servlet, you don’t need the RequestContextListener, and vice versa.

Cheers,

Charles

Thanks, for your answer,

Yup the first time I used only your kind of configuration and I have tried to use dispatcher servlet as the stacktrace I had suggested it.

An other element which maybe can help.

My application is not bounded by spring, only the component I initialize are bound.
Can the problem come from that ?

here is the piece of code instanciating the factory bean

	
<bean id="IUIFactory"
		class="com.compagny.ui.factory.UIOrderFactory"
		factory-method="getInstance" scope="singleton">
<property name="InterventionDialog">
			<bean
				class="com.compagny.ui.dialogs.InterventionDialog"
				scope="session">
			</bean>
 </property>

Hi Anthony,
i’m also using session-scoped beans. I don’t use the spring dispatcher servlet, only the Vaadin servlet, which i extend to initialize the Spring context, and to get the “Application” bean with Spring.
See
http://dev.vaadin.com/browser/incubator/SpringApplication/src/main/java/com/vaadin/incubator/spring/servlet/SpringApplicationServlet.java
for an example.

My web.xml:


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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_2_5.xsd">
    <display-name>P2P Web Application</display-name>
    <context-param>
        <description>Vaadin production mode</description>
        <param-name>productionMode</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/applicationContext-p2p-ioc.xml classpath:/applicationContext-p2p-security.xml</param-value>
    </context-param>
    <!-- Listeners for Spring framework-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <!-- To allow session-scoped beans -->
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>SpringVaadinServlet</servlet-name>
        <servlet-class>com.itesoft.p2p.common.servlet.SpringApplicationServlet</servlet-class>
        <init-param>
            <description>Vaadin application class to start</description>
            <param-name>applicationBean</param-name>
            <param-value>application</param-value>
        </init-param>
        <init-param>
            <description>Vaadin application class to start</description>
            <param-name>application</param-name>
            <param-value>com.itesoft.p2p.P2pApplication</param-value>
        </init-param>
        <init-param>
            <description>Application widgetset</description>
            <param-name>widgetset</param-name>
            <param-value>com.itesoft.p2p.gwt.WidgetSet</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringVaadinServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <resource-ref>
        <description>oracle jndi datasource</description>
        <res-ref-name>jdbc/ItesoftWSOra</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</web-app>

Hope this helps,

Richard

Thanks all for your quicks answer.

i noticed that i’m not using LocalResolver in my Servlet.

Maybe Spring complains about that.

I will try to add it to my custom servlet.

Ok

Configuration is quiet complicated.
As I’m using Navigator7 Addon Servlet this example can’t fit for my need.

Here is My full servlet code

package com.logic.silogisme.core.ui;

import java.io.IOException;
import java.util.Locale;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.icepush.servlet.MainServlet;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.vaadin.artur.icepush.ICEPush;
import org.vaadin.artur.icepush.JavascriptProvider;
import org.vaadin.navigator7.WebApplication;

import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;

/** Extends Vaadin Servlet to instantiate the WebApplication class (or descendant) 
 * and attach it to the ServletContext. 
 * 
 * @author John Rizzo - BlackBeltFactory.com
 * 
 * */
public class NavigatorIcePushServlet extends AbstractApplicationServlet {

	private static final long serialVersionUID = 8507549113847241656L;
	private MainServlet NavigatorIcePushServlet;

	private Logger log = Logger.getLogger(NavigatorIcePushServlet.class);

	private JavascriptProvider javascriptProvider;
	private LocaleResolver localeResolver;
	private String applicationBean;
	private Class<? extends Application> applicationClass;
	private WebApplicationContext applicationContext;
	/**
	 * Called by the servlet container to indicate to a servlet that the servlet
	 * is being placed into service.
	 * 
	 * @param servletConfig
	 *            the object containing the servlet's configuration and
	 *            initialization parameters
	 * @throws javax.servlet.ServletException
	 *             if an exception has occurred that interferes with the
	 *             servlet's normal operation.
	 */
	@Override
	public void init(javax.servlet.ServletConfig servletConfig)
	throws javax.servlet.ServletException {

		if (log.isDebugEnabled()) {
			log.debug("init()");
		}
		super.init(servletConfig);
		applicationBean = servletConfig.getInitParameter("applicationBean");
		if (applicationBean == null) {
			throw new ServletException("ApplicationBean not specified in servlet parameters");
		}
		applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletConfig.getServletContext());
		applicationClass = (Class<? extends Application>) applicationContext.getType(applicationBean);
		initLocaleResolver(applicationContext);

		WebApplication.init(servletConfig, getServletContext(), getClassLoader());

		//NavigatorIcePushServlet = new MainServlet(servletConfig.getServletContext());

		try {
			javascriptProvider = new JavascriptProvider(getServletContext()
					.getContextPath());

			ICEPush.setCodeJavascriptLocation(javascriptProvider
					.getCodeLocation());
		} catch (IOException e) {
			throw new ServletException("Error initializing JavascriptProvider",
					e);
		}
	}

	/** I'd prefer to do that in a Filter, but it would be against the Vaadin current architecture 
	 * Note that Vaadin TransactionListeners have no access to the ServletContext => we cannot use TransactionListeners. */
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		WebApplication.beforeService(request, response, getServletContext());
		final Locale locale = localeResolver.resolveLocale(request);
		LocaleContextHolder.setLocale(locale);
		ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
		RequestContextHolder.setRequestAttributes(requestAttributes);
		try {
			super.service(new HttpServletRequestWrapper(request) {
				@Override
				public Locale getLocale() {
					return locale;
				}
			}, response);
		} finally {
			if(!locale.equals(LocaleContextHolder.getLocale())) {
				if(log.isDebugEnabled()) {
					log.debug("locale changed, updating locale resolver");
				}
				localeResolver.setLocale(request, response, LocaleContextHolder.getLocale());
			}
			LocaleContextHolder.resetLocaleContext();
			RequestContextHolder.resetRequestAttributes();
		}
		try{
			//Insertion du code spécifique à IcePush
			String pathInfo = request.getPathInfo();
			if (pathInfo != null
					&& pathInfo.equals("/" + javascriptProvider.getCodeName())) {
				// Serve icepush.js
				serveIcePushCode(request, response);
				return;
			}
			if (request.getRequestURI().endsWith(".icepush")) {
				// Push request
				try {
					NavigatorIcePushServlet.service(request, response);
				} catch (ServletException e) {
					throw e;
				} catch (IOException e) {
					throw e;
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			} else {
				//  Vaadin request
				super.service(request, response);
			}
		}
		finally{
			//Fin d'insertion code spécifique à icePush
			WebApplication.afterService(request, response, getServletContext());
		}
	}

	private void serveIcePushCode(HttpServletRequest request,
			HttpServletResponse response) throws IOException {

		String icepushJavscript = javascriptProvider.getJavaScript();

		response.setHeader("Content-Type", "text/javascript");
		response.getOutputStream().write(icepushJavscript.getBytes());
	}

	@Override
	public void destroy() {
		super.destroy();
		NavigatorIcePushServlet.shutdown();
	}

	private void initLocaleResolver(ApplicationContext context) {
		try {
			this.localeResolver = (LocaleResolver) context.getBean(DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME,
					LocaleResolver.class);
			if (log.isDebugEnabled()) {
				log.debug("Using LocaleResolver [" + this.localeResolver + "]
");
			}
		} catch (NoSuchBeanDefinitionException ex) {
			this.localeResolver = new SessionLocaleResolver();
			if (log.isDebugEnabled()) {
				log.debug("Unable to locate LocaleResolver with name '"
						+ DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME + "' using default [" + localeResolver + "]
");
			}
		}
	}

	@Override
	protected Application getNewApplication(HttpServletRequest request)
	throws ServletException {
		if (log.isTraceEnabled()) {
			log.trace("getNewApplication()");
		}
		return (Application) applicationContext.getBean(applicationBean);
	}

	@Override
	protected Class<? extends Application> getApplicationClass()
	throws ClassNotFoundException {
		if (log.isTraceEnabled()) {
			log.trace("getApplicationClass()");
		}
		return applicationClass;
	}

}

As you can see I’m using icepush, Navigator and Spring together and it’s quite hard to manage all theses stuff working.

It seems that icepush and spring are working right know but not Navigator as it try to add twice a window with the same name

GRAVE: Servlet.service() for servlet luminem threw exception
java.lang.IllegalArgumentException: Window with name 'AppLevelWindow' is already present in the application
	at com.vaadin.Application.addWindow(Application.java:336)
	at com.vaadin.Application.setMainWindow(Application.java:673)
	at org.vaadin.navigator7.NavigableApplication.init(NavigableApplication.java:53)
	at com.vaadin.Application.start(Application.java:554)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.startApplication(AbstractApplicationServlet.java:1182)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:466)
	at com.logic.silogisme.core.ui.NavigatorIcePushServlet.service(NavigatorIcePushServlet.java:101)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:662)
25 févr. 2011 11:25:18 org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() for servlet luminem threw exception
java.lang.IllegalStateException: Cannot create a session after the response has been committed
	at org.apache.catalina.connector.Request.doGetSession(Request.java:2301)
	at org.apache.catalina.connector.Request.getSession(Request.java:2075)
	at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:833)
	at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:844)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.handleServiceSessionExpired(AbstractApplicationServlet.java:1101)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:526)
	at com.logic.silogisme.core.ui.NavigatorIcePushServlet.service(NavigatorIcePushServlet.java:139)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:662)

If a Servlet Specialist can help me into integrating all theses components, I would be grateful :wink:

Thanks,