All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dellroad.stuff.vaadin7.SpringVaadinServlet Maven / Gradle / Ivy

The newest version!

/*
 * Copyright (C) 2022 Archie L. Cobbs. All rights reserved.
 */

package org.dellroad.stuff.vaadin7;

import com.vaadin.server.DeploymentConfiguration;
import com.vaadin.server.ServiceException;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.server.VaadinServletService;
import com.vaadin.server.VaadinSession;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.WeakHashMap;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;

/**
 * A {@link VaadinServlet} that associates and manages a Spring
 * {@link org.springframework.web.context.ConfigurableWebApplicationContext} with each
 * {@link com.vaadin.server.VaadinSession} (aka, "Vaadin application" in the old terminology).
 *
 * 
 * 
 * 
 *
 * 

* The {@code configLocation} servlet parameter may be used to specify the Spring XML config * file location(s). For example: * *


 * <servlet>
 *     <servlet-name>My Vaadin App</servlet-name>
 *     <servlet-class>org.dellroad.stuff.vaadin7.SpringVaadinServlet</servlet-class>
 *     <init-param>
 *         <param-name>UI</param-name>
 *         <param-value>com.example.MyApplicationUI</param-value>
 *     </init-param>
 *     <init-param>
 *         <param-name>configLocation</param-name>
 *         <param-value>classpath:com/example/MyApplicationContext.xml</param-value>
 *     </init-param>
 * </servlet>
 * 
* *

* The main function of this servlet is to create and register a {@link SpringVaadinSessionListener} as a listener on the * {@link com.vaadin.server.VaadinService} associated with this servlet. The {@link SpringVaadinSessionListener} in turn detects * the creation and destruction of Vaadin application instances (represented by {@link com.vaadin.server.VaadinSession} * instances) and does the work of managing the associated Spring application contexts. * *

* Use of this servlet in place of the standard Vaadin servlet is required for the {@link VaadinConfigurable @VaadinConfigurable} * annotation to work. * *

* Supported servlet parameters: *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Parameter NameRequired?Description
{@code applicationName}No * Vaadin application name. Used for logging purposes and as the name of the XML application context file * when {@code configLocation} is not specified. If this parameter is not specified, the * name of the servlet is used. *
{@code configLocation}No * Location of Spring application context XML file(s). Multiple locations are separated by whitespace. * If omitted, {@code /WEB-INF/ServletName.xml} is used, where {@code ServletName} is the name of the Vaadin * application (see {@code applicationName}). *
{@code listenerClass}No * Specify the name of a custom class extending {@link SpringVaadinSessionListener} and having the same constructor arguments. * If omitted, {@link SpringVaadinSessionListener} is used. *
{@code sessionTracking}No * Boolean value that configures whether the {@link SpringVaadinSessionListener} should track Vaadin sessions; default * {@code false}. If set to {@code true}, then {@link #getSessions} can be used to access all active sessions. * Session tracking should not be used unless sessions are normally kept in memory; e.g., don't use session tracking * when sessions are being serialized and persisted. See also {@link VaadinSessionContainer}. *
{@code maxSessions}No * Configures a limit on the number of simultaneous Vaadin sessions that may exist at one time. Going over this * limit will result in a {@link com.vaadin.server.ServiceException} being thrown. A zero or negative number * means there is no limit (this is the default). Ignored unless {@value #SESSION_TRACKING_PARAMETER} is set to {@code true}. *
*
* *

* Note: if any beans are declared {@code scope="session"} in your application context, you must register Spring's * {@link org.springframework.web.context.request.RequestContextListener} as a listener in your {@code web.xml} * (normally, Spring's {@link org.springframework.web.servlet.DispatcherServlet} would handle this task). * * @see SpringVaadinSessionListener * @see VaadinConfigurable * @see VaadinApplication */ @SuppressWarnings("serial") public class SpringVaadinServlet extends VaadinServlet { /** * Servlet initialization parameter ({@value #CONFIG_LOCATION_PARAMETER}) used to specify * the location(s) of the Spring application context XML file(s). Multiple XML files may be separated by whitespace. * This parameter is optional. */ public static final String CONFIG_LOCATION_PARAMETER = "configLocation"; /** * Servlet initialization parameter ({@value #LISTENER_CLASS_PARAMETER}) used to specify * the name of an custom subclass of {@link SpringVaadinSessionListener}. * This parameter is optional. */ public static final String LISTENER_CLASS_PARAMETER = "listenerClass"; /** * Servlet initialization parameter ({@value #APPLICATION_NAME_PARAMETER}) used to specify * the name the application. * This parameter is optional. */ public static final String APPLICATION_NAME_PARAMETER = "applicationName"; /** * Servlet initialization parameter ({@value #SESSION_TRACKING_PARAMETER}) that enables * tracking of all Vaadin session. * This parameter is optional, and defaults to false. */ public static final String SESSION_TRACKING_PARAMETER = "sessionTracking"; /** * Servlet initialization parameter ({@value #MAX_SESSIONS_PARAMETER}) that configures the * maximum number of simultaneous Vaadin sessions. Requires {@link #SESSION_TRACKING_PARAMETER} to be set to {@code true}. * This parameter is optional, and defaults to zero, which means no limit. */ public static final String MAX_SESSIONS_PARAMETER = "maxSessions"; // We use weak references to avoid leaks caused by exceptions in SessionInitListeners; see http://dev.vaadin.com/ticket/12915 private final WeakHashMap liveSessions = new WeakHashMap<>(); private String servletName; @Override public void init(ServletConfig config) throws ServletException { this.servletName = config.getServletName(); if (this.servletName == null) throw new IllegalArgumentException("null servlet name"); super.init(config); } @Override protected void servletInitialized() throws ServletException { // Sanity check if (this.servletName == null) throw new IllegalArgumentException("servlet not initialized"); // Defer to superclass super.servletInitialized(); // Get params final VaadinServletService servletService = this.getService(); final Properties params = servletService.getDeploymentConfiguration().getInitParameters(); final String contextLocation = params.getProperty(CONFIG_LOCATION_PARAMETER); final String listenerClassName = params.getProperty(LISTENER_CLASS_PARAMETER); String applicationName = params.getProperty(APPLICATION_NAME_PARAMETER); if (applicationName == null) applicationName = this.servletName; // Detect listener class to use Class listenerClass = SpringVaadinSessionListener.class; if (listenerClassName != null) { try { listenerClass = Class.forName(listenerClassName, false, Thread.currentThread().getContextClassLoader()) .asSubclass(SpringVaadinSessionListener.class); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new ServletException("error finding class " + listenerClassName, e); } } // Create session listener SpringVaadinSessionListener sessionListener; try { sessionListener = listenerClass.getConstructor(String.class, String.class) .newInstance(applicationName, contextLocation); } catch (ReflectiveOperationException e) { throw new ServletException("error instantiating " + listenerClass, e); } // Register session listener servletService.addSessionInitListener(sessionListener); servletService.addSessionDestroyListener(sessionListener); } @Override protected VaadinServletService createServletService(DeploymentConfiguration deploymentConfiguration) throws ServiceException { // Get session tracking parameters final Properties params = deploymentConfiguration.getInitParameters(); final boolean sessionTracking = Boolean.valueOf(params.getProperty(SESSION_TRACKING_PARAMETER)); int maxSessionsParam = 0; try { maxSessionsParam = Integer.parseInt(params.getProperty(MAX_SESSIONS_PARAMETER)); } catch (Exception e) { // ignore } final int maxSessions = maxSessionsParam; // If not tracking sessions, do the normal thing if (!sessionTracking) return super.createServletService(deploymentConfiguration); // Return a VaadinServletService that tracks sessions final VaadinServletService service = new VaadinServletService(this, deploymentConfiguration) { @Override protected VaadinSession createVaadinSession(VaadinRequest request) throws ServiceException { final VaadinSession session; synchronized (SpringVaadinServlet.this.liveSessions) { if (maxSessions > 0 && SpringVaadinServlet.this.liveSessions.size() >= maxSessions) throw new ServiceException("The maximum number of active sessions has been reached"); session = super.createVaadinSession(request); SpringVaadinServlet.this.liveSessions.put(session, null); } return session; } @Override public void fireSessionDestroy(VaadinSession session) { synchronized (SpringVaadinServlet.this.liveSessions) { SpringVaadinServlet.this.liveSessions.remove(session); } super.fireSessionDestroy(session); } }; service.init(); return service; } /** * Get all live {@link VaadinSession}s associated with this instance. * * @return live tracked sessions, or an empty collection if session tracking is not enabled * @see VaadinSessionContainer */ public List getSessions() { synchronized (this.liveSessions) { return new ArrayList<>(this.liveSessions.keySet()); } } /** * Get the {@link SpringVaadinServlet} that is associated with the given {@link VaadinSession}. * * @param session Vaadin session * @return the assocated {@link SpringVaadinServlet} * @throws IllegalStateException if the {@link VaadinServlet} associated with {@code session} is not a * {@link SpringVaadinServlet} */ public static SpringVaadinServlet getServlet(VaadinSession session) { if (session == null) throw new IllegalArgumentException("null session"); if (!(session.getService() instanceof VaadinServletService)) throw new IllegalStateException("the VaadinService associated with the session is not a VaadinServletService instance"); final VaadinServletService service = (VaadinServletService)session.getService(); if (!(service.getServlet() instanceof SpringVaadinServlet)) throw new IllegalStateException("the VaadinServlet associated with the session is not a SpringVaadinServlet instance"); return (SpringVaadinServlet)service.getServlet(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy