Author: ips
Date: 2009-04-20 19:25:07 -0400 (Mon, 20 Apr 2009)
New Revision: 314
Added:
trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupFilter.java
trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupListener.java
Modified:
trunk/core/src/main/webapp/WEB-INF/web.xml
Log:
configure listener/filter that will init Seam lazily (upon first request to the webapp),
rather than than at webapp init (during server startup)
(
https://jira.jboss.org/jira/browse/EMBJOPR-85)
Added: trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupFilter.java
===================================================================
--- trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupFilter.java
(rev 0)
+++ trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupFilter.java 2009-04-20
23:25:07 UTC (rev 314)
@@ -0,0 +1,119 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2008 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.jboss.on.embedded;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A filter which lazily initializes another filter.
+ *
+ * <p>The filter requires an initalization parameter with the name
+ * {@link org.jboss.on.embedded.LazyStartupFilter}
+ *
+ * <p>The value is the name of the filter to lazily load. All other
+ * parameters are passed to the lazily loaded filter.
+ *
+ * <pre><code>
+ * <filter>
+ * <filter-name>Seam Filter</filter-name>
+ * <!-- Lazily start up the Seam Filter -->
+ *
<filter-class>org.jboss.on.embedded.LazyStartupFilter</filter-class>
+ *
+ * <init-param>
+ *
<param-name>org.jboss.on.embedded.LazyStartupFilter</param-name>
+ *
<param-value>org.jboss.seam.servlet.SeamFilter</param-value>
+ * </init-param>
+ * </filter>
+ * <filter-mapping>
+ * <filter-name>Seam Filter</filter-name>
+ * <url-pattern>/*</url-pattern>
+ * </filter-mapping>
+ * </code></pre>
+ *
+ * @author Jason T. Greene
+ */
+public class LazyStartupFilter implements Filter
+{
+ private final Log log = LogFactory.getLog(getClass());
+
+ private volatile Filter filter;
+ private volatile boolean initialized = false;
+ private volatile FilterConfig config;
+
+ public void destroy()
+ {
+ try
+ {
+ init();
+ }
+ catch (ServletException e)
+ {
+ }
+
+ filter.destroy();
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain
chain) throws IOException, ServletException
+ {
+ init();
+
+ filter.doFilter(request, response, chain);
+ }
+
+ private void init() throws ServletException
+ {
+ if (!initialized)
+ {
+ String parameter = getClass().getName();
+ String filterName = config.getInitParameter(parameter);
+ if (filterName == null)
+ throw new IllegalArgumentException("Filter was not specified using the
" + parameter + " parameter");
+
+ log.debug("Loading filter" + filterName);
+ try
+ {
+ filter = (Filter) Class.forName(filterName).newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("Could not instantiated filter:
" + filterName, e);
+ }
+
+ filter.init(config);
+ log.debug("Filter activated: " + filter);
+ initialized = true;
+ }
+ }
+
+ public void init(FilterConfig config) throws ServletException
+ {
+ this.config = config;
+ }
+
+}
Property changes on:
trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupFilter.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Author Id Revision HeadURL
Name: svn:eol-style
+ LF
Added: trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupListener.java
===================================================================
--- trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupListener.java
(rev 0)
+++ trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupListener.java 2009-04-20
23:25:07 UTC (rev 314)
@@ -0,0 +1,413 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2008 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.jboss.on.embedded;
+
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletRequestAttributeEvent;
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * LazyStartupListener is a special listener that can lazily start any number
+ * of hard-coded Servlet listeners.
+ *
+ * <p>This works by delaying instantiation and context initialization events until
+ * any post-init event occurs (session creation, servlet request, etc).
+ *
+ * <p>This filter expects a context parameter with the name:
+ * {@link org.jboss.on.embedded.LazyStartupListener}
+ *
+ * <p>The value is a comma separated list of listeners to lazily load:
+ *
+ * <pre><code>
+ * <!-- Seam (lazy loaded)-->
+ * <context-param>
+ *
<param-name>org.jboss.on.embedded.LazyStartupListener</param-name>
+ *
<param-value>org.jboss.seam.servlet.SeamListener</param-value>
+ * </context-param>
+ * <listener>
+ *
<listener-class>org.jboss.on.embedded.LazyStartupListener</listener-class>
+ * </listener>
+ * </code></pre>
+ *
+ * @author Jason T. Greene
+ *
+ */
+public class LazyStartupListener implements HttpSessionListener, ServletRequestListener,
ServletContextListener, HttpSessionAttributeListener,
+ ServletRequestAttributeListener, ServletContextAttributeListener
+{
+ private final Log log = LogFactory.getLog(getClass());
+ private final ConcurrentLinkedQueue<ContextEvent> contextEvents = new
ConcurrentLinkedQueue<ContextEvent>();
+
+ /*
+ * Technically the array list fields don't need to be volatile, since initialized
+ * is read before they are read and written after they are read.
+ */
+ private volatile ArrayList<HttpSessionListener> sessionListeners;
+ private volatile ArrayList<HttpSessionAttributeListener>
sessionAttributeListeners;
+ private volatile ArrayList<ServletRequestListener> requestListeners;
+ private volatile ArrayList<ServletRequestAttributeListener>
requestAttributeListeners;
+ private volatile ArrayList<ServletContextListener> contextListeners;
+ private volatile ArrayList<ServletContextAttributeListener>
contextAttributeListeners;
+
+ private volatile boolean initialized = false;
+ private volatile ServletContext context;
+ private volatile String[] names;
+
+
+ /**
+ * This lock guards event replay. Any thread which adds to the context event queue
+ * MUST obtain a read lock. The thread which replays the queue MUST obtain a write
+ * lock.
+ */
+ private final ReentrantReadWriteLock replayLock = new ReentrantReadWriteLock();
+
+ private enum ContextEventType
+ {
+ ADD, REMOVE, REPLACE, INIT
+ };
+
+ private final class ContextEvent
+ {
+ final ContextEventType type;
+ final ServletContextEvent event;
+
+ private ContextEvent(ContextEventType type, ServletContextEvent event)
+ {
+ this.type = type;
+ this.event = event;
+ }
+ }
+
+ private void setupListeners()
+ {
+ final ArrayList<HttpSessionListener> sessionListeners = new
ArrayList<HttpSessionListener>();
+ final ArrayList<HttpSessionAttributeListener> sessionAttributeListeners = new
ArrayList<HttpSessionAttributeListener>();
+ final ArrayList<ServletRequestListener> requestListeners = new
ArrayList<ServletRequestListener>();
+ final ArrayList<ServletRequestAttributeListener> requestAttributeListeners =
new ArrayList<ServletRequestAttributeListener>();
+ final ArrayList<ServletContextListener> contextListeners = new
ArrayList<ServletContextListener>();
+ final ArrayList<ServletContextAttributeListener> contextAttributeListeners =
new ArrayList<ServletContextAttributeListener>();
+
+ Object[] objs = new Object[names.length];
+ for (int i = 0; i < names.length; i++)
+ {
+ try
+ {
+ objs[i] = Class.forName(names[i]).newInstance();
+ }
+ catch (InstantiationException e)
+ {
+ }
+ catch (IllegalAccessException e)
+ {
+ }
+ catch (ClassNotFoundException e)
+ {
+ }
+ }
+
+ for (Object obj : objs)
+ {
+ if (obj instanceof HttpSessionListener)
+ sessionListeners.add((HttpSessionListener)obj);
+ if (obj instanceof HttpSessionAttributeListener)
+ sessionAttributeListeners.add((HttpSessionAttributeListener)obj);
+ if (obj instanceof ServletRequestListener)
+ requestListeners.add((ServletRequestListener)obj);
+ if (obj instanceof ServletRequestAttributeListener)
+ requestAttributeListeners.add((ServletRequestAttributeListener)obj);
+ if (obj instanceof ServletContextListener)
+ contextListeners.add((ServletContextListener)obj);
+ if (obj instanceof ServletContextAttributeListener)
+ contextAttributeListeners.add((ServletContextAttributeListener)obj);
+
+ log.debug("Activated listener: "+ obj);
+ }
+
+ this.sessionListeners = sessionListeners;
+ this.sessionAttributeListeners = sessionAttributeListeners;
+ this.requestListeners = requestListeners;
+ this.requestAttributeListeners = requestAttributeListeners;
+ this.contextListeners = contextListeners;
+ this.contextAttributeListeners = contextAttributeListeners;
+ }
+
+ private void initialize()
+ {
+ if (initialized)
+ return;
+
+ log.debug("Activating listeners");
+ setupListeners();
+
+ try
+ {
+ replayLock.writeLock().lock();
+
+ ConcurrentLinkedQueue<ContextEvent> events = contextEvents;
+ ContextEvent event = events.poll();
+ while (event != null)
+ {
+ switch (event.type)
+ {
+ case INIT:
+ for (ServletContextListener listener : contextListeners)
+ listener.contextInitialized(event.event);
+ break;
+ case ADD:
+ for (ServletContextAttributeListener listener :
contextAttributeListeners)
+ listener.attributeAdded((ServletContextAttributeEvent)event.event);
+ break;
+ case REMOVE:
+ for (ServletContextAttributeListener listener :
contextAttributeListeners)
+
listener.attributeRemoved((ServletContextAttributeEvent)event.event);
+ break;
+ case REPLACE:
+ for (ServletContextAttributeListener listener :
contextAttributeListeners)
+
listener.attributeReplaced((ServletContextAttributeEvent)event.event);
+ break;
+ }
+
+ event = events.poll();
+ }
+
+ initialized = true;
+ }
+ finally
+ {
+ replayLock.writeLock().unlock();
+ }
+
+ }
+
+ public void sessionCreated(HttpSessionEvent event)
+ {
+ initialize();
+
+ ArrayList<HttpSessionListener> listeners = sessionListeners;
+ for (HttpSessionListener listener : listeners)
+ listener.sessionCreated(event);
+ }
+
+ public void sessionDestroyed(HttpSessionEvent event)
+ {
+ initialize();
+
+ ArrayList<HttpSessionListener> listeners = sessionListeners;
+ for (HttpSessionListener listener : listeners)
+ listener.sessionDestroyed(event);
+ }
+
+ public void requestDestroyed(ServletRequestEvent event)
+ {
+ initialize();
+
+ ArrayList<ServletRequestListener> listeners = requestListeners;
+ for (ServletRequestListener listener : listeners)
+ listener.requestDestroyed(event);
+
+ }
+
+ public void requestInitialized(ServletRequestEvent event)
+ {
+ initialize();
+
+ ArrayList<ServletRequestListener> listeners = requestListeners;
+ for (ServletRequestListener listener : listeners)
+ listener.requestInitialized(event);
+ }
+
+ public void contextDestroyed(ServletContextEvent event)
+ {
+ initialize();
+
+ ArrayList<ServletContextListener> listeners = contextListeners;
+ for (ServletContextListener listener : listeners)
+ listener.contextDestroyed(event);
+ }
+
+ public void contextInitialized(ServletContextEvent event)
+ {
+ this.context = event.getServletContext();
+
+ // Comma separated list of listeners
+ String param = context.getInitParameter(getClass().getName());
+ log.debug("Listeners configured for lazy loading: " + param);
+ this.names = param == null ? new String[0] : param.split(",");
+
+ try
+ {
+ replayLock.readLock().lock();
+
+ if (!initialized)
+ {
+ contextEvents.add(new ContextEvent(ContextEventType.INIT, event));
+ return;
+ }
+
+ ArrayList<ServletContextListener> listeners = contextListeners;
+ for (ServletContextListener listener : listeners)
+ listener.contextInitialized(event);
+ }
+ finally
+ {
+ replayLock.readLock().unlock();
+ }
+ }
+
+ public void attributeAdded(HttpSessionBindingEvent event)
+ {
+ initialize();
+
+ ArrayList<HttpSessionAttributeListener> listeners =
sessionAttributeListeners;
+ for (HttpSessionAttributeListener listener : listeners)
+ listener.attributeAdded(event);
+ }
+
+ public void attributeRemoved(HttpSessionBindingEvent event)
+ {
+ initialize();
+
+ ArrayList<HttpSessionAttributeListener> listeners =
sessionAttributeListeners;
+ for (HttpSessionAttributeListener listener : listeners)
+ listener.attributeRemoved(event);
+ }
+
+ public void attributeReplaced(HttpSessionBindingEvent event)
+ {
+ initialize();
+
+ ArrayList<HttpSessionAttributeListener> listeners =
sessionAttributeListeners;
+ for (HttpSessionAttributeListener listener : listeners)
+ listener.attributeReplaced(event);
+ }
+
+ public void attributeAdded(ServletRequestAttributeEvent event)
+ {
+ initialize();
+
+ ArrayList<ServletRequestAttributeListener> listeners =
requestAttributeListeners;
+ for (ServletRequestAttributeListener listener : listeners)
+ listener.attributeAdded(event);
+ }
+
+ public void attributeRemoved(ServletRequestAttributeEvent event)
+ {
+ initialize();
+
+ ArrayList<ServletRequestAttributeListener> listeners =
requestAttributeListeners;
+ for (ServletRequestAttributeListener listener : listeners)
+ listener.attributeRemoved(event);
+ }
+
+ public void attributeReplaced(ServletRequestAttributeEvent event)
+ {
+ initialize();
+
+ ArrayList<ServletRequestAttributeListener> listeners =
requestAttributeListeners;
+ for (ServletRequestAttributeListener listener : listeners)
+ listener.attributeReplaced(event);
+
+ }
+
+ public void attributeAdded(ServletContextAttributeEvent event)
+ {
+ try
+ {
+ replayLock.readLock().lock();
+
+ if (!initialized)
+ {
+ contextEvents.add(new ContextEvent(ContextEventType.ADD, event));
+ return;
+ }
+
+ ArrayList<ServletContextAttributeListener> listeners =
contextAttributeListeners;
+ for (ServletContextAttributeListener listener : listeners)
+ listener.attributeAdded(event);
+ }
+ finally
+ {
+ replayLock.readLock().unlock();
+ }
+
+ }
+
+ public void attributeRemoved(ServletContextAttributeEvent event)
+ {
+
+ try
+ {
+ replayLock.readLock().lock();
+
+ if (!initialized)
+ {
+ contextEvents.add(new ContextEvent(ContextEventType.REMOVE, event));
+ return;
+ }
+
+ ArrayList<ServletContextAttributeListener> listeners =
contextAttributeListeners;
+ for (ServletContextAttributeListener listener : listeners)
+ listener.attributeRemoved(event);
+ }
+ finally
+ {
+ replayLock.readLock().unlock();
+ }
+ }
+
+ public void attributeReplaced(ServletContextAttributeEvent event)
+ {
+
+ try
+ {
+ replayLock.readLock().lock();
+
+ if (!initialized)
+ {
+ contextEvents.add(new ContextEvent(ContextEventType.REPLACE, event));
+ return;
+ }
+
+ ArrayList<ServletContextAttributeListener> listeners =
contextAttributeListeners;
+ for (ServletContextAttributeListener listener : listeners)
+ listener.attributeRemoved(event);
+ }
+ finally
+ {
+ replayLock.readLock().unlock();
+ }
+ }
+}
Property changes on:
trunk/core/src/main/java/org/jboss/on/embedded/LazyStartupListener.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Author Id Revision HeadURL
Name: svn:eol-style
+ LF
Modified: trunk/core/src/main/webapp/WEB-INF/web.xml
===================================================================
--- trunk/core/src/main/webapp/WEB-INF/web.xml 2009-04-20 21:50:03 UTC (rev 313)
+++ trunk/core/src/main/webapp/WEB-INF/web.xml 2009-04-20 23:25:07 UTC (rev 314)
@@ -36,40 +36,47 @@
<param-value>jboss-console</param-value>
</context-param>
- <!-- Seam -->
-
+ <!-- Seam (lazy loaded)-->
+ <context-param>
+ <param-name>org.jboss.on.embedded.LazyStartupListener</param-name>
+ <param-value>org.jboss.seam.servlet.SeamListener</param-value>
+ </context-param>
<listener>
- <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
+
<listener-class>org.jboss.on.embedded.LazyStartupListener</listener-class>
</listener>
<!-- From Seam docs: The Seam master filter must be the first filter specified
in web.xml. This ensures it is run first. -->
<filter>
<filter-name>Seam Filter</filter-name>
- <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
+ <!-- Lazily start up the Seam Filter -->
+ <filter-class>org.jboss.on.embedded.LazyStartupFilter</filter-class>
+ <init-param>
+ <param-name>org.jboss.on.embedded.LazyStartupFilter</param-name>
+ <param-value>org.jboss.seam.servlet.SeamFilter</param-value>
+ </init-param>
</filter>
<filter-mapping>
<filter-name>Seam Filter</filter-name>
<url-pattern>/*</url-pattern>
- </filter-mapping>
-
+ </filter-mapping>
+
<!-- JSF -->
-
+
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.seam</url-pattern>
- </servlet-mapping>
+ </servlet-mapping>
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/navigation.xml</param-value>
</context-param>
-
+
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
@@ -81,11 +88,10 @@
</context-param>
<!-- JSF RI -->
-
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
-
+
<!-- Facelets -->
<!-- load our Facelets taglibs (value must be semicolon-delimited) -->