You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shale.apache.org by gv...@apache.org on 2006/11/20 05:17:41 UTC
svn commit: r477032 - in /shale/framework/trunk:
shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/
shale-apps/shale-test-view/src/main/webapp/
shale-apps/shale-test-view/src/main/webapp/WEB-INF/
shale-view/src/main/java/org/...
Author: gvanmatre
Date: Sun Nov 19 20:17:39 2006
New Revision: 477032
URL: http://svn.apache.org/viewvc?view=rev&rev=477032
Log:
This patch is an attempt to catch exceptions raised in JSF phases allowing the shale view controller to handle them (SHALE-336). The key extension point is subclassing the UIViewRoot and overriding the methods invoked by the lifecycle. The overrides catch unchecked exceptions and queue them up to be processed by a global error page.
I've extended the shale-test-view to demonstrate the added exception traps.
Added:
shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/Error.java (with props)
shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/RaiseException.java (with props)
shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/error.jsp (with props)
shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/raiseException.jsp (with props)
shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ShaleViewRoot.java
Modified:
shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/faces-config.xml
shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/web.xml
shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/menu.jsp
shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ViewPhaseListener.java
shale/framework/trunk/shale-view/src/main/resources/META-INF/faces-config.xml
Added: shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/Error.java
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/Error.java?view=auto&rev=477032
==============================================================================
--- shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/Error.java (added)
+++ shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/Error.java Sun Nov 19 20:17:39 2006
@@ -0,0 +1,140 @@
+/*
+ * 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.shale.examples.test.view;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+
+import org.apache.shale.view.AbstractViewController;
+import org.apache.shale.view.faces.FacesConstants;
+
+public class Error extends AbstractViewController {
+
+ private String httpErrorCode = null;
+
+ private String exceptionType = null;
+
+ private String message = null;
+
+ private String requestUri = null;
+
+ private String servletName = null;
+
+ private Recorder recorder = null;
+
+ public void prerender() {
+ System.out.println("Error - Removing exceptions stack");
+
+ Map requestMap = getRequestMap();
+
+ Exception exception = (Exception) requestMap
+ .get("javax.servlet.error.exception");
+
+ FacesContext facesContext = getFacesContext();
+ if (facesContext == null) return;
+
+ UIViewRoot root = facesContext.getViewRoot();
+ if (root == null) return;
+
+ List exceptions = (List) requestMap.get(FacesConstants.EXCEPTIONS_LIST);
+ if (exception != null && exceptions != null) {
+ // save on the view root
+ getFacesContext().getViewRoot().getAttributes().put("errors", exceptions);
+ requestMap.remove(FacesConstants.EXCEPTIONS_LIST);
+
+
+ Integer errorCode = (Integer) requestMap.get("javax.servlet.error.status_code");
+ if (errorCode != null) {
+ setHttpErrorCode(errorCode.toString());
+ }
+
+ Object clazz = requestMap.get("javax.servlet.error.exception_type");
+ if (clazz != null) {
+ setExceptionType(clazz.toString());
+ }
+ setMessage((String) requestMap.get("javax.servlet.error.message"));
+ setRequestUri((String) requestMap
+ .get("javax.servlet.error.request_uri"));
+ setServletName((String) requestMap
+ .get("javax.servlet.error.servlet_name"));
+
+ setRecorder((Recorder) getBean("recorder"));
+ }
+
+ }
+
+ public String getExceptionType() {
+ return exceptionType;
+ }
+
+ public void setExceptionType(String exceptionType) {
+ this.exceptionType = exceptionType;
+ }
+
+ public String getHttpErrorCode() {
+ return httpErrorCode;
+ }
+
+ public void setHttpErrorCode(String httpErrorCode) {
+ this.httpErrorCode = httpErrorCode;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getRequestUri() {
+ return requestUri;
+ }
+
+ public void setRequestUri(String requestUri) {
+ this.requestUri = requestUri;
+ }
+
+ public String getServletName() {
+ return servletName;
+ }
+
+ public void setServletName(String servletName) {
+ this.servletName = servletName;
+ }
+
+ public Recorder getRecorder() {
+ return recorder;
+ }
+
+ public void setRecorder(Recorder recorder) {
+ this.recorder = recorder;
+ }
+
+ public String getStackTrace() {
+ StringBuffer buff = new StringBuffer();
+ Exception e = (Exception) getBean("e");
+ for (int i = 0; i < e.getStackTrace().length; i++) {
+ buff.append(e.getStackTrace()[i].toString())
+ .append("\n");
+ }
+ return buff.toString();
+ }
+}
Propchange: shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/Error.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/Error.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added: shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/RaiseException.java
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/RaiseException.java?view=auto&rev=477032
==============================================================================
--- shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/RaiseException.java (added)
+++ shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/RaiseException.java Sun Nov 19 20:17:39 2006
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+package org.apache.shale.examples.test.view;
+
+import javax.faces.event.ActionEvent;
+import javax.faces.event.ValueChangeEvent;
+
+import org.apache.shale.view.AbstractViewController;
+
+/**
+ * <p>Tests for handling exceptions.</p>
+ */
+public class RaiseException extends AbstractViewController {
+
+
+ // -------------------------------------------------------------- Properties
+
+
+ // The "Recorder" object for this request
+ private Recorder recorder = null;
+ public Recorder getRecorder() {
+ return this.recorder;
+ }
+ public void setRecorder(Recorder recorder) {
+ this.recorder = recorder;
+ }
+
+
+ // ------------------------------------------------------- Lifecycle Methods
+
+
+ /**
+ * <p>Record an init event.</p>
+ */
+ public void init() {
+ getRecorder().record("init");
+ System.out.println("RaiseException.init()");
+ }
+
+
+ /**
+ * <p>Record a preprocess event.</p>
+ */
+ public void preprocess() {
+ getRecorder().record("preprocess");
+ System.out.println("RaiseException.preprocess()");
+ }
+
+
+ /**
+ * <p>Record a prerender event.</p>
+ */
+ public void prerender() {
+ getRecorder().record("prerender");
+ System.out.println("RaiseException.prerender()");
+ }
+
+
+ /**
+ * <p>Record a destroy event.</p>
+ */
+ public void destroy() {
+ getRecorder().record("destroy");
+ System.out.println("RaiseException.destroy()");
+ }
+
+ /**
+ * <p>Raises an unchecked exception from an action callback.</p>
+ *
+ * @return null
+ */
+ public String throwActionException() {
+ getRecorder().record("throwActionException");
+ System.out.println("RaiseException.throwActionException()");
+ throw new NullPointerException("throwActionException");
+ }
+
+ /**
+ * <p>Raises an unchecked exception from an action listener
+ * binding event.</p>
+ *
+ * @param event action event
+ */
+ public void throwActionListenerException(ActionEvent event) {
+ getRecorder().record("throwActionListenerException");
+ System.out.println("RaiseException.throwActionListenerException(ActionEvent)");
+ throw new NullPointerException("throwActionListenerException");
+ }
+
+ /**
+ * <p>Raises an unchecked exception from a value change listener
+ * callback.</p>
+ *
+ * @param event value change listener event
+ */
+ public void throwValueChangeListenerException(ValueChangeEvent event) {
+ getRecorder().record("throwValueChangeListenerException");
+ System.out.println("RaiseException.throwValueChangeListenerException(ValueChangeEvent)");
+ throw new NullPointerException("throwValueChangeListenerException");
+
+ }
+
+}
Propchange: shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/RaiseException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: shale/framework/trunk/shale-apps/shale-test-view/src/main/java/org/apache/shale/examples/test/view/RaiseException.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/faces-config.xml?view=diff&rev=477032&r1=477031&r2=477032
==============================================================================
--- shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/faces-config.xml (original)
+++ shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/faces-config.xml Sun Nov 19 20:17:39 2006
@@ -47,6 +47,11 @@
<from-outcome>status</from-outcome>
<to-view-id>/status.jsp</to-view-id>
</navigation-case>
+ <navigation-case>
+ <from-outcome>raiseException</from-outcome>
+ <to-view-id>/raiseException.jsp</to-view-id>
+ </navigation-case>
+
</navigation-rule>
<!-- ========== View Controller Beans ========== -->
@@ -81,6 +86,27 @@
org.apache.shale.examples.test.view.Standard
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
+ </managed-bean>
+
+ <managed-bean>
+ <managed-bean-name>error</managed-bean-name>
+ <managed-bean-class>
+ org.apache.shale.examples.test.view.Error
+ </managed-bean-class>
+ <managed-bean-scope>request</managed-bean-scope>
+ </managed-bean>
+
+ <managed-bean>
+ <managed-bean-name>raiseException</managed-bean-name>
+ <managed-bean-class>
+ org.apache.shale.examples.test.view.RaiseException
+ </managed-bean-class>
+ <managed-bean-scope>request</managed-bean-scope>
+ <managed-property>
+ <property-name>recorder</property-name>
+ <value>#{recorder}</value>
+ </managed-property>
+
</managed-bean>
<managed-bean>
Modified: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/web.xml?view=diff&rev=477032&r1=477031&r2=477032
==============================================================================
--- shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/web.xml (original)
+++ shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/WEB-INF/web.xml Sun Nov 19 20:17:39 2006
@@ -40,6 +40,11 @@
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
+ <context-param>
+ <param-name>org.apache.shale.view.EXCEPTION_DISPATCH_PATH</param-name>
+ <param-value>/error.faces</param-value>
+ </context-param>
+
<!-- JavaServer Faces Servlet Configuration -->
<servlet>
<servlet-name>faces</servlet-name>
Added: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/error.jsp
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/error.jsp?view=auto&rev=477032
==============================================================================
--- shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/error.jsp (added)
+++ shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/error.jsp Sun Nov 19 20:17:39 2006
@@ -0,0 +1,92 @@
+<%--
+
+ 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.
+
+ $Id$
+
+--%>
+
+<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
+<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
+
+<f:view>
+<html>
+<head>
+ <title>Exception Occurred</title>
+</head>
+<body>
+
+<h:form id="error">
+ <table border="0">
+ <tr>
+ <td>Test Record Events:</td>
+ <td>
+ <h:outputText value="#{error.recorder.events}"/>
+ </td>
+ </tr>
+ <tr>
+ <td>HTTP Error Error Status Code:</td>
+ <td>
+ <h:outputText value="#{error.httpErrorCode}"/>
+ <h:inputHidden value="#{error.httpErrorCode}"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Exception Type:</td>
+ <td>
+ <h:outputText value="#{error.exceptionType}"/>
+ <h:inputHidden value="#{error.exceptionType}"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Message:</td>
+ <td>
+ <h:outputText value="#{error.message}" />
+ <h:inputHidden value="#{error.message}"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Request URI:</td>
+ <td>
+ <h:outputText value="#{error.requestUri}"/>
+ <h:inputHidden value="#{error.requestUri}"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Servlet Name:</td>
+ <td>
+ <h:outputText value="#{error.servletName}" />
+ <h:inputHidden value="#{error.servletName}"/>
+ </td>
+ </tr>
+ </table>
+
+ <h:dataTable var="e" value="#{facesContext.viewRoot.attributes.errors}">
+ <h:column>
+ <f:verbatim><dl><dt></f:verbatim>
+ <h:outputText value="#{e.message}"/>
+ <f:verbatim></dt><dd></f:verbatim>
+ <h:outputText value="#{error.stackTrace}"/>
+ <f:verbatim></dd></dl></f:verbatim>
+ </h:column>
+ </h:dataTable>
+
+ <p><h:commandLink action="raiseException" value="Back"/> to raise exception.</p>
+
+</h:form>
+</body>
+</html>
+</f:view>
Propchange: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/error.jsp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/error.jsp
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/menu.jsp
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/menu.jsp?view=diff&rev=477032&r1=477031&r2=477032
==============================================================================
--- shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/menu.jsp (original)
+++ shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/menu.jsp Sun Nov 19 20:17:39 2006
@@ -46,6 +46,20 @@
navigation links are included so that the pages may be executed by hand
as well.</p>
+
+ <h3>Test View Controller Exception Handling Strategy</h3>
+
+ <p>The raise exception page has several links to invoke backing logic that
+ will raise an unchecked exception. The view controller exception handler
+ catches these exceptions and forwards on to a error page. The error page
+ is configured in the web.xml using the "org.apache.shale.view.EXCEPTION_DISPATCH_PATH"
+ context parameter. The error page will also show a record of the view controller
+ lifecycle callback events in addition to the other events where the exception is raised.
+ <br/><br/>
+ <h:form id="f1">
+ <h:commandLink action="raiseException" value="Raise Unchecked Exception"/>
+ </h:form>
+ </p>
</body>
</html>
</f:view>
Added: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/raiseException.jsp
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/raiseException.jsp?view=auto&rev=477032
==============================================================================
--- shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/raiseException.jsp (added)
+++ shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/raiseException.jsp Sun Nov 19 20:17:39 2006
@@ -0,0 +1,73 @@
+<%--
+
+ 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.
+
+ $Id$
+
+--%>
+
+<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
+<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
+
+<f:view>
+<html>
+<head>
+ <title>Test View Controller Exception handling Strategy</title>
+</head>
+<body>
+
+ <h3>Immediate Action, Action Listeners and Value Change Listeners</h3>
+
+ <h:form id="form1">
+ <ol>
+ <li><h:commandLink immediate="true" id="throwActionException" value="Action Binding" action="#{raiseException.throwActionException}"/></li>
+ <li><h:commandLink immediate="true" id="throwActionListenerException" value="Action Listener Attribute Binding" actionListener="#{raiseException.throwActionListenerException}"/></li>
+ <li>
+ <h:outputLabel for="testvc" value="Value Change Listener Attribute Binding"/>
+ <h:selectOneListbox id="testvc" immediate="true" valueChangeListener="#{raiseException.throwValueChangeListenerException}">
+ <f:selectItem itemLabel="one" itemValue="1"/>
+ <f:selectItem itemLabel="two" itemValue="2"/>
+ <f:selectItem itemLabel="three" itemValue="3"/>
+ </h:selectOneListbox>
+ <h:commandLink id="testvcCmd" immediate="true" action="raiseException" value="Apply"/>
+ </li>
+ </ol>
+ </h:form>
+
+
+ <h3>Action, Action Listeners and Value Change Listeners</h3>
+
+ <h:form id="form2">
+ <ol>
+ <li><h:commandLink id="throwActionException" value="Action Binding" action="#{raiseException.throwActionException}"/></li>
+ <li><h:commandLink id="throwActionListenerException" value="Action Listener Attribute Binding" actionListener="#{raiseException.throwActionListenerException}"/></li>
+ <li>
+ <h:outputLabel for="testvc" value="Value Change Listener Attribute Binding"/>
+ <h:selectOneListbox id="testvc" valueChangeListener="#{raiseException.throwValueChangeListenerException}">
+ <f:selectItem itemLabel="one" itemValue="1"/>
+ <f:selectItem itemLabel="two" itemValue="2"/>
+ <f:selectItem itemLabel="three" itemValue="3"/>
+ </h:selectOneListbox>
+ <h:commandLink id="testvcCmd" action="raiseException" value="Apply"/>
+ </li>
+ </ol>
+ </h:form>
+
+ <p><a href="menu.faces">Back</a> to main menu</p>
+
+</body>
+</html>
+</f:view>
Propchange: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/raiseException.jsp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: shale/framework/trunk/shale-apps/shale-test-view/src/main/webapp/raiseException.jsp
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added: shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ShaleViewRoot.java
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ShaleViewRoot.java?view=auto&rev=477032
==============================================================================
--- shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ShaleViewRoot.java (added)
+++ shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ShaleViewRoot.java Sun Nov 19 20:17:39 2006
@@ -0,0 +1,113 @@
+/*
+ * 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.shale.view.faces;
+
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+
+import org.apache.shale.view.Constants;
+import org.apache.shale.view.ExceptionHandler;
+
+/**
+ * <p>Extending the UIViewRoot to provide specialized exception
+ * handling needed for the Shale view controller to enforce the contracts
+ * of the callbacks.</p>
+ */
+public class ShaleViewRoot extends UIViewRoot {
+
+ /**
+ * <p>Override to catch exceptions raised by the action listeners
+ * in the invoke application phase.</p>
+ *
+ * @param context faces context
+ */
+ public void processApplication(FacesContext context) {
+ try {
+ super.processApplication(context);
+ } catch (Exception e) {
+ handleException(context, e);
+ context.responseComplete();
+ }
+ }
+
+ /**
+ * <p>Override to catch and handle exceptions with immediate commands
+ * and value change listeners in the apply request values phase.</p>
+ *
+ * @param context faces context
+ */
+ public void processDecodes(FacesContext context) {
+ try {
+ super.processDecodes(context);
+ } catch (Exception e) {
+ handleException(context, e);
+ context.responseComplete();
+ }
+ }
+
+ /**
+ * <p>Override to catch and handle exceptions raised in the
+ * update model phase.</p>
+ *
+ * @param context faces context
+ */
+ public void processUpdates(FacesContext context) {
+ try {
+ super.processUpdates(context);
+ } catch (Exception e) {
+ handleException(context, e);
+ context.responseComplete();
+ }
+ }
+
+ /**
+ * <p>Override to catch and handle exceptions in value change
+ * listeners that might have occured in the process validations
+ * phase.</p>
+ *
+ * @param context faces context
+ */
+ public void processValidators(FacesContext context) {
+ try {
+ super.processValidators(context);
+ } catch (Exception e) {
+ handleException(context, e);
+ context.responseComplete();
+ }
+ }
+
+
+ /**
+ * <p>Handle the specified exception according to the strategy
+ * defined by our current {@link ExceptionHandler}.</p>
+ *
+ * @param context FacesContext for the current request
+ * @param exception Exception to be handled
+ */
+ private void handleException(FacesContext context, Exception exception) {
+
+ if (context == null) {
+ exception.printStackTrace(System.out);
+ return;
+ }
+ ExceptionHandler handler = (ExceptionHandler)
+ context.getApplication().getVariableResolver().resolveVariable
+ (context, Constants.EXCEPTION_HANDLER);
+ handler.handleException(exception);
+
+ }
+}
Modified: shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ViewPhaseListener.java
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ViewPhaseListener.java?view=diff&rev=477032&r1=477031&r2=477032
==============================================================================
--- shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ViewPhaseListener.java (original)
+++ shale/framework/trunk/shale-view/src/main/java/org/apache/shale/view/faces/ViewPhaseListener.java Sun Nov 19 20:17:39 2006
@@ -90,11 +90,15 @@
log.trace("afterPhase(" + event.getFacesContext()
+ "," + event.getPhaseId() + ")");
}
+
+ if (afterPhaseExceptionCheck(event)) {
+ // dispatched to the target error page, stop further processing
+ return;
+ }
+
PhaseId phaseId = event.getPhaseId();
if (PhaseId.RESTORE_VIEW.equals(phaseId)) {
afterRestoreView(event);
- } else if (PhaseId.INVOKE_APPLICATION.equals(phaseId)) {
- afterInvokeApplication(event);
} else if (PhaseId.RENDER_RESPONSE.equals(phaseId)
|| event.getFacesContext().getResponseComplete()) {
afterRenderResponse(event);
@@ -145,23 +149,27 @@
* to proceed.</p>
*
* @param event <code>PhaseEvent</code> for the current event
+ * @return <code>true</code> if exceptions have been handled
+ * and dispatched to the specified path
*/
- private void afterInvokeApplication(PhaseEvent event) {
+ private boolean afterPhaseExceptionCheck(PhaseEvent event) {
// Have we accumulated any exceptions during the current request?
+ // Have we already logged the exception?
FacesContext context = event.getFacesContext();
ExternalContext econtext = context.getExternalContext();
List list = (List)
econtext.getRequestMap().get(FacesConstants.EXCEPTIONS_LIST);
- if (list == null) {
- return;
+ if (list == null
+ || econtext.getRequestMap().get("javax.servlet.error.exception") != null) {
+ return false;
}
// Has the user specified a forwarding URL for handling exceptions?
String path =
econtext.getInitParameter(Constants.EXCEPTION_DISPATCH_PATH);
if (path == null) {
- return;
+ return false;
}
// Forward control to the specified path instead of allowing
@@ -187,11 +195,15 @@
map.put("javax.servlet.error.servlet_name", "javax.faces.webapp.FacesServlet"); // Best we can do ...
// Dispatch to the specified error handler
context.responseComplete();
+ // force a destroy before dispatching to the error page
+ econtext.getRequestMap().remove(FacesConstants.VIEWS_INITIALIZED);
econtext.dispatch(path);
+
} catch (IOException e) {
handleException(context, e);
}
+ return true;
}
@@ -208,11 +220,12 @@
if (list == null) {
return;
}
- Iterator vcs = list.iterator();
- while (vcs.hasNext()) {
- Object vc = vcs.next();
-// viewControllerCallbacks(event.getFacesContext()).destroy(vc);
- }
+ //Iterator vcs = list.iterator();
+ //while (vcs.hasNext()) {
+ // Object vc = vcs.next();
+ // viewControllerCallbacks(event.getFacesContext()).destroy(vc);
+ //}
+
map.remove(FacesConstants.VIEWS_INITIALIZED);
}
Modified: shale/framework/trunk/shale-view/src/main/resources/META-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-view/src/main/resources/META-INF/faces-config.xml?view=diff&rev=477032&r1=477031&r2=477032
==============================================================================
--- shale/framework/trunk/shale-view/src/main/resources/META-INF/faces-config.xml (original)
+++ shale/framework/trunk/shale-view/src/main/resources/META-INF/faces-config.xml Sun Nov 19 20:17:39 2006
@@ -48,6 +48,16 @@
<phase-listener>org.apache.shale.view.faces.ViewPhaseListener</phase-listener>
</lifecycle>
+ <component>
+ <description>
+ Extending the UIViewRoot to provide specialized exception
+ handling needed for the Shale view controller to enforce the contracts
+ of the callbacks.
+ </description>
+ <component-type>javax.faces.ViewRoot</component-type>
+ <component-class>org.apache.shale.view.faces.ShaleViewRoot</component-class>
+ </component>
+
<!-- Custom JSF Components -->
<component>
<description>