dev@javaserverfaces.java.net

Jim, Ryan: Seeking Review: 248-UIInput.updateModel()

From: Ed Burns <Ed.Burns_at_Sun.COM>
Date: Wed, 14 Jan 2009 14:44:11 -0800

>>>>> On Fri, 12 Dec 2008 08:13:24 -0800, Ed Burns <Ed.Burns_at_Sun.COM> said:

>>>>> On Fri, 12 Dec 2008 12:38:12 +0100, Martin Marinschek <mmarinschek_at_APACHE.ORG> said:
MM> I have (while preparing for Devoxx) read through the spec once
MM> more. I think we are on a good track, however:

MM> - exception handling states 3 exceptions for the exception handler
MM> _not_ to be called:

MM> - convert --> ok
MM> - validate --> ok

MM> - model update --> IMHO, not ok

MM> why?

EB> I assert that this it is consistent with current behavior.

Therefore, I have come up with the following changebundle.

https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=248

Issue: 248-UIInput.updateModel

- Modify the contract for UIInput.updateModel to not queue a message if
  the updateModel causes an exception to be thrown. Rather, use the
  ExceptionHandler. The exception is if the ExceptionHandlerFactory is
  the PreJsf2ExceptionHandlerFactory.

All automated tests still run successfully.

SECTION: Modified Files
----------------------------
M jsf-api/src/javax/faces/component/UIInput.java

- take the above action

M jsf-api/build.xml
M jsf-ri/build-tests.xml

- Leverage the PreJsf2ExceptionHandlerFactory, because these tests
  assume the old behavior.

SECTION: Diffs
----------------------------
Index: jsf-api/src/javax/faces/component/UIInput.java
===================================================================
--- jsf-api/src/javax/faces/component/UIInput.java (revision 6211)
+++ jsf-api/src/javax/faces/component/UIInput.java (working copy)
@@ -43,23 +43,31 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.el.ELException;
 import javax.el.ValueExpression;
 import javax.faces.FacesException;
+import javax.faces.FactoryFinder;
 import javax.faces.application.Application;
 import javax.faces.application.FacesMessage;
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerFactory;
 import javax.faces.context.FacesContext;
 import javax.faces.convert.Converter;
 import javax.faces.convert.ConverterException;
 import javax.faces.el.MethodBinding;
+import javax.faces.event.ExceptionEvent;
+import javax.faces.event.ExceptionEventContext;
+import javax.faces.event.PhaseId;
 import javax.faces.event.ValueChangeEvent;
 import javax.faces.event.ValueChangeListener;
 import javax.faces.render.Renderer;
 import javax.faces.validator.Validator;
 import javax.faces.validator.ValidatorException;
+import javax.faces.webapp.PreJsf2ExceptionHandlerFactory;
 
 /**
  * <p><span class="changed_modified_2_0"><strong>UIInput</strong></span>
@@ -767,11 +775,14 @@
         }
         ValueExpression ve = getValueExpression("value");
         if (ve != null) {
+ Throwable caught = null;
+ FacesMessage message = null;
             try {
                 ve.setValue(context.getELContext(), getLocalValue());
                 setValue(null);
                 setLocalValueSet(false);
             } catch (ELException e) {
+ caught = e;
                 String messageStr = e.getMessage();
                 Throwable result = e.getCause();
                 while (null != result &&
@@ -779,7 +790,6 @@
                     messageStr = result.getMessage();
                     result = result.getCause();
                 }
- FacesMessage message;
                 if (null == messageStr) {
                     message =
                          MessageFactory.getMessage(context, UPDATE_MESSAGE_ID,
@@ -790,28 +800,54 @@
                                                messageStr,
                                                messageStr);
                 }
- LOGGER.log(Level.SEVERE, message.getSummary(), result);
- context.addMessage(getClientId(context), message);
                 setValid(false);
             } catch (IllegalArgumentException e) {
- FacesMessage message =
+ caught = e;
+ message =
                      MessageFactory.getMessage(context, UPDATE_MESSAGE_ID,
                           MessageFactory.getLabel(
                                context, this));
- LOGGER.log(Level.SEVERE, message.getSummary(), e);
- context.addMessage(getClientId(context), message);
                 setValid(false);
             } catch (Exception e) {
- FacesMessage message =
+ caught = e;
+ message =
                      MessageFactory.getMessage(context, UPDATE_MESSAGE_ID,
                           MessageFactory.getLabel(
                                context, this));
- LOGGER.log(Level.SEVERE, message.getSummary(), e);
- context.addMessage(getClientId(context), message);
                 setValid(false);
             }
+ if (null != caught) {
+ assert(null != message);
+ if (isPreJsf2ExceptionHandler(context)) {
+ LOGGER.log(Level.SEVERE, message.getSummary(), caught);
+ context.addMessage(getClientId(context), message);
+ } else {
+ ExceptionHandler exHandler = context.getExceptionHandler();
+ ExceptionEventContext eventContext = new ExceptionEventContext(context, caught, this,
+ PhaseId.UPDATE_MODEL_VALUES);
+ exHandler.processEvent(new ExceptionEvent(eventContext));
+ }
+ }
+
         }
     }
+
+ private static final String PRE_JSF2_EXCEPTION_HANDLER_ATTR_NAME =
+ "javax.faces.component.PRE_JSF2_EXCEPTION_HANDLER";
+
+ private boolean isPreJsf2ExceptionHandler(FacesContext context) {
+ boolean result = false;
+ Map<String, Object> appMap = context.getExternalContext().getApplicationMap();
+ if (appMap.containsKey(PRE_JSF2_EXCEPTION_HANDLER_ATTR_NAME)) {
+ result = (Boolean) appMap.get(PRE_JSF2_EXCEPTION_HANDLER_ATTR_NAME);
+ } else {
+ ExceptionHandlerFactory exHandlerFactory = (ExceptionHandlerFactory)
+ FactoryFinder.getFactory(FactoryFinder.EXCEPTION_HANDLER_FACTORY);
+ result = exHandlerFactory.getClass().isAssignableFrom(PreJsf2ExceptionHandlerFactory.class);
+ appMap.put(PRE_JSF2_EXCEPTION_HANDLER_ATTR_NAME, (Boolean)result);
+ }
+ return result;
+ }
 
     // ------------------------------------------------------ Validation Methods
 
Index: jsf-api/build.xml
===================================================================
--- jsf-api/build.xml (revision 6211)
+++ jsf-api/build.xml (working copy)
@@ -396,6 +396,12 @@
             </fileset>
         </copy>
 
+ <delete dir="${build.test.dir}/META-INF/services" />
+ <mkdir dir="${build.test.dir}/META-INF/services"/>
+ <echo
+ file="${build.test.dir}/META-INF/services/javax.faces.context.ExceptionHandlerFactory">javax.faces.webapp.PreJsf2ExceptionHandlerFactory</echo>
+
+
     </target>
 
 
Index: jsf-ri/build-tests.xml
===================================================================
--- jsf-ri/build-tests.xml (revision 6211)
+++ jsf-ri/build-tests.xml (working copy)
@@ -193,6 +193,12 @@
         <filter token="test.root.dir" value="${out.test.dir}"/>
         <copy file="${conf.test.dir}/web.xml" todir="${out.test.dir}"
               filtering="on"/>
+
+ <delete dir="${out.test.dir}/classes/META-INF/services" />
+ <mkdir dir="${out.test.dir}/classes/META-INF/services"/>
+ <echo
+ file="${out.test.dir}/classes/META-INF/services/javax.faces.context.ExceptionHandlerFactory">javax.faces.webapp.PreJsf2ExceptionHandlerFactory</echo>
+
         <jsf.war basedir="${basedir}/build"
                  archive-name="test"
                  webxml="${out.test.dir}/web.xml">






-- 
| ed.burns_at_sun.com  | office: 408 884 9519 OR x31640
| homepage:         | http://ridingthecrest.com/
-- 
| ed.burns_at_sun.com  | office: 408 884 9519 OR x31640
| homepage:         | http://ridingthecrest.com/