[seam-commits] Seam SVN: r9818 - in trunk/src: wicket/org/jboss/seam/wicket and 1 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Mon Dec 22 11:49:56 EST 2008


Author: cpopetz
Date: 2008-12-22 11:49:56 -0500 (Mon, 22 Dec 2008)
New Revision: 9818

Modified:
   trunk/src/main/org/jboss/seam/web/WicketFilter.java
   trunk/src/wicket/org/jboss/seam/wicket/SeamWebApplication.java
   trunk/src/wicket/org/jboss/seam/wicket/web/WicketFilterInstantiator.java
Log:
JBSEAM-3670: Wicket filter shouldn't unconditionally set up scopes.


Modified: trunk/src/main/org/jboss/seam/web/WicketFilter.java
===================================================================
--- trunk/src/main/org/jboss/seam/web/WicketFilter.java	2008-12-22 16:20:30 UTC (rev 9817)
+++ trunk/src/main/org/jboss/seam/web/WicketFilter.java	2008-12-22 16:49:56 UTC (rev 9818)
@@ -13,19 +13,19 @@
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
 
 import org.jboss.seam.Component;
 import org.jboss.seam.ScopeType;
+import org.jboss.seam.Seam;
 import org.jboss.seam.annotations.Install;
 import org.jboss.seam.annotations.Name;
 import org.jboss.seam.annotations.Observer;
 import org.jboss.seam.annotations.Scope;
 import org.jboss.seam.annotations.intercept.BypassInterceptors;
 import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.contexts.ServletLifecycle;
 import org.jboss.seam.core.Init;
 import org.jboss.seam.deployment.HotDeploymentStrategy;
-import org.jboss.seam.servlet.ContextualHttpServletRequest;
 
 @Scope(APPLICATION)
 @Name("org.jboss.seam.web.wicketFilter")
@@ -49,6 +49,9 @@
    
    private ClassLoader hotDeployClassLoader;
    
+   /*
+    * Upon initialization and re-initialization, lookup the hot deployment strategy and grab its classloader, if it exists.
+    */
    @Observer(value= { "org.jboss.seam.postInitialization","org.jboss.seam.postReInitialization"} )
    public void postReInitialization() 
    { 
@@ -65,23 +68,20 @@
    
    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain chain) throws IOException, ServletException
    {
+      /* If there is no delegate, we are a no-op filter */
       if (delegate==null)
       {
          chain.doFilter(servletRequest, servletResponse);
       }
       else
       {
-         new ContextualHttpServletRequest((HttpServletRequest) servletRequest)
-         {
-            @Override
-            public void process() throws Exception 
-            {
+           Init init = (Init) ServletLifecycle.getServletContext().getAttribute( Seam.getComponentName(Init.class) );
                /*
                 * We initialize the delegate on the first actual request and any time the
                 * init timestamp changes, so that the WicketFilter gets reinitialized whenever the
                 * hot deployment classloader detects changes, enabling wicket components to be hot deployed.
                 */
-               if (lastInitTime != Init.instance().getTimestamp())
+           if (init != null && lastInitTime != init.getTimestamp())
                {
                   delegate.destroy();
       
@@ -98,6 +98,10 @@
                  {
                     parameters.put("filterMappingUrlPattern", "/*");
                  }
+                  
+                  /* Let the seam debug flag control the wicket configuration flag (deployment vs. development) */
+                  parameters.put("configuration",init.isDebug() ? "development" : "deployment");
+                  
                  if (getApplicationFactoryClass() != null)
                  {
                     parameters.put("applicationFactoryClassName", getApplicationFactoryClass());
@@ -123,22 +127,24 @@
 			            if (hotDeployClassLoader != null)
 			               Thread.currentThread().setContextClassLoader(previousClassLoader);
 			         }
-                  lastInitTime = Init.instance().getTimestamp();
+              lastInitTime = init.getTimestamp();
                }
                delegate.doFilter(servletRequest, servletResponse, chain);
             }
-            
-         }.run();
       }
-   }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {  
       super.init(filterConfig);
-      
-      delegate = (javax.servlet.Filter) Component.getInstance("org.jboss.seam.wicket.web.wicketFilterInstantiator", ScopeType.STATELESS);
-      savedConfig = filterConfig;
+      /* Save the configuration so that we can use it to re-initialize the wicket filter at request time, as 
+       * we may need to do it again if changes are hot deployed.  Also, look up the delegate now, as the presence
+       * of the delegate component implies the presence of the wicket classes themselves.
+       */
+      if (delegate == null) {
+         delegate = (javax.servlet.Filter) Component.getInstance("org.jboss.seam.wicket.web.wicketFilterInstantiator", ScopeType.STATELESS);
+         savedConfig = filterConfig;
+      }
    }
    
    public String getApplicationClass()

Modified: trunk/src/wicket/org/jboss/seam/wicket/SeamWebApplication.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/SeamWebApplication.java	2008-12-22 16:20:30 UTC (rev 9817)
+++ trunk/src/wicket/org/jboss/seam/wicket/SeamWebApplication.java	2008-12-22 16:49:56 UTC (rev 9818)
@@ -1,5 +1,7 @@
 package org.jboss.seam.wicket;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.wicket.IRedirectListener;
 import org.apache.wicket.Request;
 import org.apache.wicket.RequestCycle;
@@ -10,15 +12,27 @@
 import org.apache.wicket.markup.html.form.IOnChangeListener;
 import org.apache.wicket.markup.html.link.ILinkListener;
 import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.protocol.http.WebRequest;
+import org.apache.wicket.protocol.http.WebRequestCycle;
 import org.apache.wicket.protocol.http.WebRequestCycleProcessor;
+import org.apache.wicket.protocol.http.WebResponse;
 import org.apache.wicket.protocol.http.WebSession;
 import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy;
 import org.apache.wicket.request.IRequestCodingStrategy;
 import org.apache.wicket.request.IRequestCycleProcessor;
 import org.apache.wicket.request.target.component.IBookmarkablePageRequestTarget;
 import org.apache.wicket.request.target.component.listener.IListenerInterfaceRequestTarget;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.contexts.Lifecycle;
+import org.jboss.seam.contexts.ServletLifecycle;
 import org.jboss.seam.core.Conversation;
+import org.jboss.seam.core.ConversationPropagation;
+import org.jboss.seam.core.Events;
 import org.jboss.seam.core.Manager;
+import org.jboss.seam.log.LogProvider;
+import org.jboss.seam.log.Logging;
+import org.jboss.seam.servlet.ServletRequestSessionMap;
+import org.jboss.seam.web.ServletContexts;
 import org.jboss.seam.wicket.international.SeamStatusMessagesListener;
 
 /**
@@ -30,7 +44,26 @@
 public abstract class SeamWebApplication extends WebApplication
 {
    
+   private static final LogProvider log = Logging.getLogProvider(SeamWebApplication.class);
+
    /**
+    * When operating in tests, it is sometimes useful to leave the contexts extant
+    * after a request, and destroy them upon the next request, so that models that use injections
+    * can be queried post-request to determine their values. 
+    */
+   protected boolean destroyContextsLazily = false;
+
+   public boolean isDestroyContextsLazily()
+   {
+      return destroyContextsLazily;
+   }
+
+   public void setDestroyContextsLazily(boolean destroyContextsLazily)
+   {
+      this.destroyContextsLazily = destroyContextsLazily;
+   }
+
+   /**
     * Custom session with invalidation override. We can't just let Wicket
     * invalidate the session as Seam might have to do some cleaning up to do.
     */
@@ -136,4 +169,91 @@
 
    protected abstract Class getLoginPage();
 
+   /*
+    * Override to provide a seam-specific RequestCycle, which sets up seam contexts.  
+    */
+   @Override
+   public RequestCycle newRequestCycle(final Request request, final Response response)
+   {
+      return new SeamWebRequestCycle(this, (WebRequest)request, (WebResponse)response);
+   }
+   
+   
+   /**
+    * A WebRequestCycle that sets up seam requests.  Essentially this
+    * is similiar to the work of ContextualHttpServletRequest, but using the wicket API
+    * @author cpopetz
+    *
+    */
+   protected static class SeamWebRequestCycle extends WebRequestCycle { 
+      
+      public SeamWebRequestCycle(WebApplication application, WebRequest request, Response response)
+      {
+         super(application, request, response);
+      }
+
+      @Override
+      protected void onBeginRequest() 
+      {
+         HttpServletRequest httpRequest = ((WebRequest)request).getHttpServletRequest();
+
+         if (Contexts.getEventContext() != null && ((SeamWebApplication)getApplication()).isDestroyContextsLazily() && ServletContexts.instance().getRequest() != httpRequest)
+         { 
+            destroyContexts();
+         }
+
+         if (Contexts.getEventContext() == null)
+         {
+            ServletLifecycle.beginRequest(httpRequest);
+            ServletContexts.instance().setRequest(httpRequest);
+            ConversationPropagation.instance().restoreConversationId( request.getParameterMap() );
+            Manager.instance().restoreConversation();
+            ServletLifecycle.resumeConversation(httpRequest);
+            Manager.instance().handleConversationPropagation( request.getParameterMap() );
+
+            // Force creation of the session
+            if (httpRequest.getSession(false) == null)
+            {
+               httpRequest.getSession(true);
+            }
+         }
+         super.onBeginRequest();
+         Events.instance().raiseEvent("org.jboss.seam.wicket.beforeRequest");
+      }  
+
+      @Override
+      protected void onEndRequest() 
+      {
+         // TODO Auto-generated method stub
+         try 
+         { 
+            super.onEndRequest();
+            Events.instance().raiseEvent("org.jboss.seam.wicket.afterRequest");
+         }
+         finally 
+         {
+            if (Contexts.getEventContext() != null && !((SeamWebApplication)getApplication()).isDestroyContextsLazily())
+            {
+               destroyContexts();
+            }
+         }
+      }
+
+      private void destroyContexts() 
+      {
+         try { 
+            HttpServletRequest httpRequest = ((WebRequest)request).getHttpServletRequest();
+            Manager.instance().endRequest( new ServletRequestSessionMap(httpRequest)  );
+            ServletLifecycle.endRequest(httpRequest);
+         }
+	      catch (Exception e)
+	      {
+	         /* Make sure we always clear out the thread locals */
+	         Lifecycle.endRequest();
+	         log.warn("ended request due to exception", e);
+	         throw new RuntimeException(e);
+	      }
+      }
+   }
+
 }

Modified: trunk/src/wicket/org/jboss/seam/wicket/web/WicketFilterInstantiator.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/web/WicketFilterInstantiator.java	2008-12-22 16:20:30 UTC (rev 9817)
+++ trunk/src/wicket/org/jboss/seam/wicket/web/WicketFilterInstantiator.java	2008-12-22 16:49:56 UTC (rev 9818)
@@ -1,6 +1,3 @@
-/**
- * 
- */
 package org.jboss.seam.wicket.web;
 
 import static org.jboss.seam.annotations.Install.BUILT_IN;
@@ -25,12 +22,20 @@
 import org.jboss.seam.annotations.Scope;
 import org.jboss.seam.annotations.Unwrap;
 import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.contexts.Lifecycle;
 import org.jboss.seam.log.LogProvider;
 import org.jboss.seam.log.Logging;
 import org.jboss.seam.web.FilterConfigWrapper;
 import org.jboss.seam.wicket.WebApplication;
 import org.jboss.seam.wicket.ioc.WicketClassLoader;
 
+/**
+ * This component wraps the WicketFilter, encapsulates the class dependencies 
+ * upon the wicket library, and propogates the configuration from seam's own
+ * WicketFilter, specified with web:wicket-wilter.  It also sets up the WicketClassLoader
+ * to instrument wicket components on the fly, if necessary.
+ *
+ */
 @Name("org.jboss.seam.wicket.web.wicketFilterInstantiator")
 @Install(precedence = BUILT_IN, classDependencies={"org.apache.wicket.Application"})
 @BypassInterceptors
@@ -46,55 +51,70 @@
    {
       return new WicketFilter()
       {
-         
          private ClassLoader classLoader;
          
          @Override
          public void init(FilterConfig filterConfig) throws ServletException
          {
-            Map<String, String> parameters = new HashMap<String, String>();
-            try
-            {
-
-               ClassLoader parent = Thread.currentThread().getContextClassLoader();
-               File dir = getRealFile(filterConfig.getServletContext(), DEFAULT_WICKET_COMPONENT_DIRECTORY_PATH);
-               if (dir == null)
+            try 
+            { 
+               // We need the Application context active in order to lookup the WebApplication component
+               Lifecycle.setupApplication();
+               Map<String, String> parameters = new HashMap<String, String>();
+               try
                {
-                  log.warn("No wicket components directory specified to give Seam super powers to");
-                  this.classLoader = parent;
+                  ClassLoader parent = Thread.currentThread().getContextClassLoader();
+                  
+                  /* if there is a directory specified for which we should instrument wicket components,
+                   * create a WicketClassLoader to do that.  Otherwise, just use the contextClassLoader
+                   */
+                  File dir = getRealFile(filterConfig.getServletContext(), DEFAULT_WICKET_COMPONENT_DIRECTORY_PATH);
+                  if (dir == null)
+                  {
+                     log.warn("No wicket components directory specified to give Seam super powers to");
+                     this.classLoader = parent;
+                  }
+                  else
+                  {
+                     this.classLoader = new WicketClassLoader(Thread.currentThread().getContextClassLoader(), new ClassPool(), dir).instrument();
+                  }
                }
-               else
+               catch (NotFoundException e)
                {
-                  this.classLoader = new WicketClassLoader(Thread.currentThread().getContextClassLoader(), new ClassPool(), dir).instrument();
+                  throw new ServletException(e);
                }
-            }
-            catch (NotFoundException e)
-            {
-               throw new ServletException(e);
-            }
-            catch (CannotCompileException e)
-            {
-               throw new ServletException(e);
-            }
-            catch (ClassNotFoundException e)
-            {
-               throw new ServletException(e);
-            }
-            if (filterConfig.getInitParameter("applicationClassName") == null)
-            {
-               String applicationClass = WebApplication.instance().getApplicationClass();
-               if (applicationClass != null)
+               catch (CannotCompileException e)
                {
-                  parameters.put("applicationClassName", applicationClass); 
+                  throw new ServletException(e);
                }
-               else
+               catch (ClassNotFoundException e)
                {
-                  throw new IllegalStateException("Must set application-class using <wicket:web-application /> in components.xml");
+                  throw new ServletException(e);
                }
+               /*
+                * If no applicationClassName has been specified on the filter, use the name specified with 
+                * <wicket:web-application/> in components.xml
+                */
+               if (filterConfig.getInitParameter("applicationClassName") == null)
+               {
+                  String applicationClass = WebApplication.instance().getApplicationClass();
+                  if (applicationClass != null)
+                  {
+                     parameters.put("applicationClassName", applicationClass); 
+                  }
+                  else
+                  {
+                     throw new IllegalStateException("Must set application-class using <wicket:web-application /> in components.xml");
+                  }
+               }
+               super.init(new FilterConfigWrapper(filterConfig, parameters));
             }
-            super.init(new FilterConfigWrapper(filterConfig, parameters));
+            finally 
+            { 
+               Lifecycle.cleanupApplication();
+            }
          }
-         
+
          @Override
          protected ClassLoader getClassLoader()
          {




More information about the seam-commits mailing list