Index: core/src/com/icesoft/faces/async/render/GroupAsyncRenderer.java =================================================================== --- core/src/com/icesoft/faces/async/render/GroupAsyncRenderer.java (revision 17152) +++ core/src/com/icesoft/faces/async/render/GroupAsyncRenderer.java (working copy) @@ -48,6 +48,7 @@ import javax.faces.context.FacesContext; import javax.portlet.PortletSession; import javax.servlet.http.HttpSession; +import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -79,9 +80,11 @@ protected String name; protected boolean stopRequested = false; + private ServletContext context; public GroupAsyncRenderer() { - // do nothing. + HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true); + context = session.getServletContext(); } /** @@ -346,7 +349,7 @@ Iterator i = ((MainSessionBoundServlet) SessionDispatcher. - getSingletonSessionServlet(sessionId)). + getSingletonSessionServlet(sessionId, context)). getViews().values().iterator(); i.hasNext(); ) { Index: core/src/com/icesoft/faces/webapp/http/servlet/MainServlet.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/servlet/MainServlet.java (revision 17152) +++ core/src/com/icesoft/faces/webapp/http/servlet/MainServlet.java (working copy) @@ -66,11 +66,11 @@ } }; monitorRunner = new MonitorRunner(configuration.getAttributeAsLong("monitorRunnerInterval", 10000)); - setUpMessageServiceClient(); + //setUpMessageServiceClient(); RenderManager.setServletConfig(servletConfig); PseudoServlet resourceServer = new BasicAdaptingServlet(new ResourceServer(configuration, mimeTypeMatcher, localFileLocator)); - //don't create new sessions for XMLHTTPRequests identified by the path prefix "block/*" - PseudoServlet sessionDispatcher = new SessionDispatcher() { + //don't create new sessions for XMLHTTPRequests identified by "block/*" prefixed paths + PseudoServlet sessionDispatcher = new SessionDispatcher(context) { protected PseudoServlet newServlet(HttpSession session, Monitor sessionMonitor) { return new MainSessionBoundServlet(session, sessionMonitor, idGenerator, mimeTypeMatcher, monitorRunner, configuration); } @@ -99,7 +99,7 @@ } public void destroy() { - tearDownMessageServiceClient(); + //tearDownMessageServiceClient(); monitorRunner.stop(); DisposeBeans.in(context); dispatcher.shutdown(); Index: core/src/com/icesoft/faces/webapp/http/servlet/SessionDispatcher.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/servlet/SessionDispatcher.java (revision 17152) +++ core/src/com/icesoft/faces/webapp/http/servlet/SessionDispatcher.java (working copy) @@ -4,6 +4,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpServletRequest; @@ -14,38 +15,57 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; -import java.util.List; import java.util.Map; +import java.util.Set; public abstract class SessionDispatcher implements PseudoServlet { - //having a static field here is ok because web applications are started in separate classloaders private final static Log Log = LogFactory.getLog(SessionDispatcher.class); - private final static List SessionDispatchers = new ArrayList(); //ICE-3073 - manage sessions with this structure private final static Map SessionMonitors = new HashMap(); private Map sessionBoundServers = new HashMap(); + private ServletContext context; - public SessionDispatcher() { - SessionDispatchers.add(this); + public SessionDispatcher(ServletContext context) { + //avoid instance collision -- Glassfish shares EAR module classloaders + associateSessionDispatcher(context); + this.context = context; } protected abstract PseudoServlet newServlet(HttpSession session, Monitor sessionMonitor) throws Exception; public void service(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession(true); - notifyIfNew(session); + checkSession(session); lookupServlet(session).service(request, response); } - //synchronize access in case there are multiple SessionDispatcher instances created - protected static void notifyIfNew(HttpSession session) { + protected void checkSession(HttpSession session) { + try { + final String id = session.getId(); + + final Monitor monitor; synchronized (SessionMonitors) { - if (!SessionMonitors.containsKey(session.getId())) { - notifySessionInitialized(session); + if (!SessionMonitors.containsKey(id)) { + monitor = new Monitor(session); + SessionMonitors.put(id, monitor); + } else { + monitor = (Monitor) SessionMonitors.get(id); } + //it is possible to have multiple web-app contexts associated to the same HttpSession instance + monitor.addInSessionContext(context); } + + synchronized (sessionBoundServers) { + if (!sessionBoundServers.containsKey(id)) { + sessionBoundServers.put(id, this.newServlet(session, monitor)); } + } + } catch (Exception e) { + Log.error(e); + } + } protected PseudoServlet lookupServlet(final HttpSession session) { return lookupServlet(session.getId()); @@ -63,18 +83,6 @@ } } - private void sessionCreated(HttpSession session, Monitor monitor) { - try { - sessionBoundServers.put(session.getId(), this.newServlet(session, monitor)); - } catch (Exception e) { - Log.warn(e); - throw new RuntimeException(e); - } catch (Throwable t) { - Log.warn(t); - throw new RuntimeException(t); - } - } - private void sessionShutdown(HttpSession session) { PseudoServlet servlet = (PseudoServlet) sessionBoundServers.get(session.getId()); servlet.shutdown(); @@ -85,24 +93,6 @@ } /** - * Create new session bound servers. - */ - private static void notifySessionInitialized(HttpSession session) { - Monitor monitor = new Monitor(session); - SessionMonitors.put(session.getId(), monitor); - - Iterator i = SessionDispatchers.iterator(); - while (i.hasNext()) { - try { - SessionDispatcher sessionDispatcher = (SessionDispatcher) i.next(); - sessionDispatcher.sessionCreated(session, monitor); - } catch (Exception e) { - Log.error(e); - } - } - } - - /** * Perform the session shutdown tasks for a session that has either been invalidated via * the ICEfaces Session wrapper (internal) or via a sessionDestroyed event from a container * (external). #3164 If the Session has been externally invalidated this method doesn't need @@ -110,7 +100,7 @@ * * @param session Session to invalidate */ - private static void notifySessionShutdown(final HttpSession session) { + private static void notifySessionShutdown(final HttpSession session, final ServletContext context) { Log.debug("Shutting down session: " + session.getId()); String sessionID = session.getId(); // avoid executing this method twice @@ -119,40 +109,32 @@ return; } - //shutdown session bound servers - Iterator i = SessionDispatchers.iterator(); - while (i.hasNext()) { + SessionDispatcher sessionDispatcher = lookupSessionDispatcher(context); + //shutdown session bound server try { - SessionDispatcher sessionDispatcher = (SessionDispatcher) i.next(); sessionDispatcher.sessionShutdown(session); } catch (Exception e) { Log.error(e); } - } synchronized (SessionMonitors) { - //invalidate session and discard session ID - i = SessionDispatchers.iterator(); - while (i.hasNext()) { try { - SessionDispatcher sessionDispatcher = (SessionDispatcher) i.next(); sessionDispatcher.sessionDestroy(session); } catch (Exception e) { Log.error(e); } - } //ICE-3189 - do this before invalidating the session SessionMonitors.remove(sessionID); } } //Exposing MainSessionBoundServlet for Tomcat 6 Ajax Push - public static PseudoServlet getSingletonSessionServlet(final HttpSession session) { - return getSingletonSessionServlet(session.getId()); + public static PseudoServlet getSingletonSessionServlet(final HttpSession session, ServletContext context) { + return lookupSessionDispatcher(context).lookupServlet(session); } - public static PseudoServlet getSingletonSessionServlet(final String sessionId) { - return ((SessionDispatcher) SessionDispatchers.get(0)).lookupServlet(sessionId); + public static PseudoServlet getSingletonSessionServlet(final String sessionId, ServletContext context) { + return lookupSessionDispatcher(context).lookupServlet(sessionId); } public static class Listener implements ServletContextListener, HttpSessionListener { @@ -193,12 +175,21 @@ } public void sessionDestroyed(HttpSessionEvent event) { - notifySessionShutdown(event.getSession()); + HttpSession session = event.getSession(); + notifySessionShutdown(session, session.getServletContext()); } } + private void associateSessionDispatcher(ServletContext context) { + context.setAttribute(SessionDispatcher.class.getName(), this); + } + private static SessionDispatcher lookupSessionDispatcher(ServletContext context) { + return (SessionDispatcher) context.getAttribute(SessionDispatcher.class.getName()); + } + public static class Monitor { + private Set contexts = new HashSet(); private HttpSession session; private long lastAccess; @@ -223,7 +214,12 @@ } public void shutdown() { - notifySessionShutdown(session); + //notify all the contexts associated to this monitored session + Iterator i = contexts.iterator(); + while (i.hasNext()) { + ServletContext context = (ServletContext) i.next(); + notifySessionShutdown(session, context); + } try { session.invalidate(); } catch (IllegalStateException e) { @@ -236,5 +232,9 @@ shutdown(); } } + + public void addInSessionContext(ServletContext context) { + contexts.add(context); } + } } Index: core/src/com/icesoft/faces/webapp/http/servlet/TomcatPushServlet.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/servlet/TomcatPushServlet.java (revision 17152) +++ core/src/com/icesoft/faces/webapp/http/servlet/TomcatPushServlet.java (working copy) @@ -128,7 +128,7 @@ if (!eventResponderMap.containsKey(session)) { MainSessionBoundServlet servlet = (MainSessionBoundServlet) - SessionDispatcher.getSingletonSessionServlet(session); + SessionDispatcher.getSingletonSessionServlet(session, getServletContext()); eventResponderMap.put( session, new EventResponder( Index: core/src/com/icesoft/faces/webapp/xmlhttp/PersistentFacesServlet.java =================================================================== --- core/src/com/icesoft/faces/webapp/xmlhttp/PersistentFacesServlet.java (revision 17152) +++ core/src/com/icesoft/faces/webapp/xmlhttp/PersistentFacesServlet.java (working copy) @@ -35,13 +35,14 @@ import com.icesoft.faces.webapp.http.servlet.MainServlet; -import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; //todo: deprecate this class public class PersistentFacesServlet extends MainServlet { - protected static Servlet Instance; - - public PersistentFacesServlet() { - Instance = this; + + public void init(ServletConfig servletConfig) throws ServletException { + super.init(servletConfig); + servletConfig.getServletContext().setAttribute(PersistentFacesServlet.class.getName(), this); } } Index: core/src/com/icesoft/faces/webapp/xmlhttp/BlockingServlet.java =================================================================== --- core/src/com/icesoft/faces/webapp/xmlhttp/BlockingServlet.java (revision 17152) +++ core/src/com/icesoft/faces/webapp/xmlhttp/BlockingServlet.java (working copy) @@ -36,13 +36,23 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.ServletConfig; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; import java.io.IOException; //todo: deprecate this class public class BlockingServlet extends HttpServlet { + private ServletContext context; + public void init(ServletConfig servletConfig) throws ServletException { + super.init(servletConfig); + context = servletConfig.getServletContext(); + } + public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { - PersistentFacesServlet.Instance.service(servletRequest, servletResponse); + Servlet servlet = (PersistentFacesServlet) context.getAttribute(PersistentFacesServlet.class.getName()); + servlet.service(servletRequest, servletResponse); } } Index: ahs/src/com/icesoft/faces/async/servlet/AsyncHttpServlet.java =================================================================== --- ahs/src/com/icesoft/faces/async/servlet/AsyncHttpServlet.java (revision 17152) +++ ahs/src/com/icesoft/faces/async/servlet/AsyncHttpServlet.java (working copy) @@ -112,14 +112,14 @@ "in servlet-mode..."); } final ExecuteQueue _executeQueue = new ExecuteQueue(); - SessionDispatcher _sessionDispatcher = new SessionDispatcher() { + SessionDispatcher _sessionDispatcher = new SessionDispatcher(getServletContext()) { public void service( final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) throws Exception { HttpSession _httpSession = httpServletRequest.getSession(true); - notifyIfNew(_httpSession); + checkSession(_httpSession); lookupServlet(_httpSession). service(httpServletRequest, httpServletResponse); }