You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gp...@apache.org on 2011/05/15 01:36:40 UTC

svn commit: r1103252 - in /myfaces/extensions/cdi/trunk/jee-modules: jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/

Author: gpetracek
Date: Sat May 14 23:36:40 2011
New Revision: 1103252

URL: http://svn.apache.org/viewvc?rev=1103252&view=rev
Log:
EXTCDI-180 and EXTCDI-181 exception-handler enhancements

Added:
    myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/DefaultErrorViewExceptionHandler.java
Modified:
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ConversationUtils.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/CodiFacesContextWrapper.java

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ConversationUtils.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ConversationUtils.java?rev=1103252&r1=1103251&r2=1103252&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ConversationUtils.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ConversationUtils.java Sat May 14 23:36:40 2011
@@ -25,6 +25,7 @@ import org.apache.myfaces.extensions.cdi
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.WindowScoped;
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.config.WindowContextConfig;
 import org.apache.myfaces.extensions.cdi.core.api.provider.BeanManagerProvider;
+import org.apache.myfaces.extensions.cdi.core.impl.projectstage.ProjectStageProducer;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.WindowContextManager;
 
 import org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils;
@@ -37,6 +38,7 @@ import org.apache.myfaces.extensions.cdi
 import org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.spi.EditableWindowContext;
 import org.apache.myfaces.extensions.cdi.message.api.Message;
 
+import javax.enterprise.context.ContextNotActiveException;
 import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.Typed;
@@ -617,33 +619,45 @@ public abstract class ConversationUtils
     //don't move it to an observer due to an unpredictable invocation order
     public static void postRenderCleanup(FacesContext facesContext)
     {
-        BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
+        try
+        {
+            BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
 
-        EditableWindowContextManager windowContextManager =
-                CodiUtils.getContextualReferenceByClass(beanManager, EditableWindowContextManager.class);
+            EditableWindowContextManager windowContextManager =
+                    CodiUtils.getContextualReferenceByClass(beanManager, EditableWindowContextManager.class);
 
-        WindowContextConfig windowContextConfig =
-                CodiUtils.getContextualReferenceByClass(beanManager, WindowContextConfig.class);
+            WindowContextConfig windowContextConfig =
+                    CodiUtils.getContextualReferenceByClass(beanManager, WindowContextConfig.class);
 
-        ViewAccessConversationExpirationEvaluatorRegistry registry =
-                CodiUtils.getContextualReferenceByClass(
-                        beanManager, ViewAccessConversationExpirationEvaluatorRegistry.class);
+            ViewAccessConversationExpirationEvaluatorRegistry registry =
+                    CodiUtils.getContextualReferenceByClass(
+                            beanManager, ViewAccessConversationExpirationEvaluatorRegistry.class);
 
-        UIViewRoot uiViewRoot = facesContext.getViewRoot();
+            UIViewRoot uiViewRoot = facesContext.getViewRoot();
 
-        //e.g. in case of a ViewExpiredException (e.g. in case of an expired session)
-        if(uiViewRoot == null)
-        {
-            return;
-        }
+            //e.g. in case of a ViewExpiredException (e.g. in case of an expired session)
+            if(uiViewRoot == null)
+            {
+                return;
+            }
 
-        registry.broadcastRenderedViewId(uiViewRoot.getViewId());
+            registry.broadcastRenderedViewId(uiViewRoot.getViewId());
 
-        storeCurrentViewIdAsOldViewId(facesContext);
+            storeCurrentViewIdAsOldViewId(facesContext);
 
-        if(windowContextConfig.isCloseEmptyWindowContextsEnabled())
+            if(windowContextConfig.isCloseEmptyWindowContextsEnabled())
+            {
+                cleanupInactiveWindowContexts(windowContextManager);
+            }
+        }
+        catch (ContextNotActiveException e)
         {
-            cleanupInactiveWindowContexts(windowContextManager);
+            if(ProjectStageProducer.getInstance().getProjectStage() ==
+                                org.apache.myfaces.extensions.cdi.core.api.projectstage.ProjectStage.Development)
+            {
+                e.printStackTrace();
+            }
+            //we can ignore the exception because it's just an optional (immediate) cleanup
         }
 
         //if the cache would get resetted by an observer or a phase-listener

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/CodiFacesContextWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/CodiFacesContextWrapper.java?rev=1103252&r1=1103251&r2=1103252&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/CodiFacesContextWrapper.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/CodiFacesContextWrapper.java Sat May 14 23:36:40 2011
@@ -21,6 +21,7 @@ package org.apache.myfaces.extensions.cd
 import org.apache.myfaces.extensions.cdi.core.api.config.CodiCoreConfig;
 import org.apache.myfaces.extensions.cdi.core.impl.util.ClassDeactivation;
 import org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils;
+import org.apache.myfaces.extensions.cdi.jsf.impl.config.view.ViewConfigCache;
 import org.apache.myfaces.extensions.cdi.jsf.impl.listener.request.BeforeAfterFacesRequestBroadcaster;
 import org.apache.myfaces.extensions.cdi.jsf.impl.listener.request.FacesMessageEntry;
 import org.apache.myfaces.extensions.cdi.jsf2.impl.scope.conversation.RedirectedConversationAwareExternalContext;
@@ -28,10 +29,12 @@ import org.apache.myfaces.extensions.cdi
 import org.apache.myfaces.extensions.cdi.message.api.Message;
 
 import javax.faces.application.FacesMessage;
+import javax.faces.application.Application;
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerWrapper;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 import javax.faces.context.FacesContextWrapper;
-import javax.faces.application.Application;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -51,6 +54,8 @@ class CodiFacesContextWrapper extends Fa
 
     private boolean temporaryViewRootAwareApplicationWrapperActivated;
 
+    private boolean defaultErrorViewExceptionHandlerActivated;
+
     CodiFacesContextWrapper(FacesContext wrappedFacesContext)
     {
         this.wrappedFacesContext = wrappedFacesContext;
@@ -62,6 +67,24 @@ class CodiFacesContextWrapper extends Fa
     }
 
     /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ExceptionHandler getExceptionHandler()
+    {
+        lazyInit();
+
+        ExceptionHandler exceptionHandler = this.wrappedFacesContext.getExceptionHandler();
+
+        if(this.defaultErrorViewExceptionHandlerActivated)
+        {
+            exceptionHandler = new DefaultErrorViewExceptionHandler(exceptionHandler);
+        }
+        tryToInjectFields(exceptionHandler);
+        return exceptionHandler;
+    }
+
+    /**
      * Performs dependency injection manually (if permitted)
      * {@inheritDoc}
      */
@@ -122,6 +145,22 @@ class CodiFacesContextWrapper extends Fa
             this.temporaryViewRootAwareApplicationWrapperActivated =
                     ClassDeactivation.isClassActivated(SecurityAwareViewHandler.class) &&
                     ClassDeactivation.isClassActivated(TemporaryViewRootAwareApplicationWrapper.class);
+
+            //deactivate it, if there is no default-error-view available
+            //ExceptionHandler used as marker because it's part of the jsf2 api and won't change
+            this.defaultErrorViewExceptionHandlerActivated =
+                    ViewConfigCache.getDefaultErrorViewConfigDescriptor() != null &&
+                            ClassDeactivation.isClassActivated(ExceptionHandler.class);
+        }
+    }
+
+    private void tryToInjectFields(ExceptionHandler exceptionHandler)
+    {
+        CodiUtils.injectFields(exceptionHandler, this.advancedQualifierRequiredForDependencyInjection);
+
+        if(exceptionHandler instanceof ExceptionHandlerWrapper)
+        {
+            tryToInjectFields(((ExceptionHandlerWrapper) exceptionHandler).getWrapped());
         }
     }
 

Added: myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/DefaultErrorViewExceptionHandler.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/DefaultErrorViewExceptionHandler.java?rev=1103252&view=auto
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/DefaultErrorViewExceptionHandler.java (added)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf20-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf2/impl/listener/request/DefaultErrorViewExceptionHandler.java Sat May 14 23:36:40 2011
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.cdi.jsf2.impl.listener.request;
+
+import org.apache.myfaces.extensions.cdi.core.api.Advanced;
+import org.apache.myfaces.extensions.cdi.core.api.config.view.DefaultErrorView;
+import org.apache.myfaces.extensions.cdi.core.api.navigation.ViewNavigationHandler;
+import org.apache.myfaces.extensions.cdi.core.impl.projectstage.ProjectStageProducer;
+
+import javax.enterprise.context.ContextNotActiveException;
+import javax.faces.FacesException;
+import javax.faces.application.ProjectStage;
+import javax.faces.application.ViewExpiredException;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerWrapper;
+import javax.faces.context.FacesContext;
+import javax.faces.context.Flash;
+import javax.faces.event.ExceptionQueuedEvent;
+import javax.faces.event.ExceptionQueuedEventContext;
+import javax.inject.Inject;
+import java.util.Iterator;
+
+/**
+ * @author Gerhard Petracek
+ */
+@Advanced
+class DefaultErrorViewExceptionHandler extends ExceptionHandlerWrapper
+{
+    private ExceptionHandler wrapped;
+
+    @Inject
+    private ViewNavigationHandler viewNavigationHandler;
+
+    DefaultErrorViewExceptionHandler(ExceptionHandler wrapped)
+    {
+        this.wrapped = wrapped;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void handle() throws FacesException
+    {
+        Iterator<ExceptionQueuedEvent> exceptionQueuedEventIterator = getUnhandledExceptionQueuedEvents().iterator();
+
+        while (exceptionQueuedEventIterator.hasNext())
+        {
+            ExceptionQueuedEventContext exceptionQueuedEventContext =
+                    (ExceptionQueuedEventContext) exceptionQueuedEventIterator.next().getSource();
+
+            @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"})
+            Throwable throwable = exceptionQueuedEventContext.getException();
+
+            String viewId = null;
+
+            if (throwable instanceof ViewExpiredException)
+            {
+                viewId = ((ViewExpiredException) throwable).getViewId();
+            }
+            else if(throwable instanceof ContextNotActiveException)
+            {
+                FacesContext facesContext = exceptionQueuedEventContext.getContext();
+                Flash flash =  facesContext.getExternalContext().getFlash();
+
+                //the error page uses a cdi scope which isn't active as well
+                if(flash.containsKey(ContextNotActiveException.class.getName()))
+                {
+                    break;
+                }
+
+                if(facesContext.getViewRoot() != null)
+                {
+                    viewId = facesContext.getViewRoot().getViewId();
+                }
+            }
+
+            if(viewId != null)
+            {
+                FacesContext facesContext = exceptionQueuedEventContext.getContext();
+                UIViewRoot uiViewRoot = facesContext.getApplication().getViewHandler().createView(facesContext, viewId);
+
+                if (uiViewRoot == null)
+                {
+                    continue;
+                }
+
+                if(facesContext.isProjectStage(ProjectStage.Development) ||
+                        ProjectStageProducer.getInstance().getProjectStage() ==
+                                org.apache.myfaces.extensions.cdi.core.api.projectstage.ProjectStage.Development)
+                {
+                    throwable.printStackTrace();
+                }
+
+                facesContext.setViewRoot(uiViewRoot);
+                exceptionQueuedEventIterator.remove();
+
+                Flash flash =  facesContext.getExternalContext().getFlash();
+                flash.put(throwable.getClass().getName(), throwable);
+                flash.keep(throwable.getClass().getName());
+
+                this.viewNavigationHandler.navigateTo(DefaultErrorView.class);
+
+                break;
+            }
+        }
+
+        this.wrapped.handle();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ExceptionHandler getWrapped()
+    {
+        return wrapped;
+    }
+}