UIValidateForm's state saving doesn't work correctly
----------------------------------------------------
Key: SEAMFACES-167
URL:
https://issues.jboss.org/browse/SEAMFACES-167
Project: Seam Faces
Issue Type: Bug
Components: Validation & Conversion
Affects Versions: 3.0.1
Environment: Tomcat 7.0.5, Weld 1.1.0, various versions of Mojarra and MyFaces
tested
Reporter: Christian Kaltepoth
I'm getting the following exception if I use {{s:validateForm}} on a page:
{code}
java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
java.util.HashMap.writeObject(HashMap.java:1001)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
java.util.HashMap.writeObject(HashMap.java:1001)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
com.sun.faces.renderkit.ClientSideStateHelper.doWriteState(ClientSideStateHelper.java:293)
com.sun.faces.renderkit.ClientSideStateHelper.writeState(ClientSideStateHelper.java:167)
com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:123)
com.sun.faces.application.StateManagerImpl.writeState(StateManagerImpl.java:155)
com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:221)
com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:397)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:126)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:273)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:273)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:127)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)
{code}
I'm getting this (or similar) exceptions for the following combinations of JSF
implementation and state saving configuration:
* Mojarra <= 2.0.2 (client side state saving)
* MyFaces (all versions, client & server side state saving)
I'm NOT getting this exception with:
* Mojarra <= 2.0.2 (server side state saving)
* Mojarra >= 2.0.3 (client & server side state saving)
The problem seems to be that {{UIValidateForm}} saves a {{Map<String,UIInput>}} to
the view state. Older Mojarra versions and MyFaces will try to serialize this map which
will fail because {{UIInput}} doesn't implement {{Serializable}}. Newer Mojarra
versions are handling maps by processing keys and values individually and seem to
correctly detect that {{UIInput}} implements {{StateHolder}}.
However I don't think that a JSF implementation is required to support such
situations. I looked at the spec and it only says that the objects written to the state (a
map in this case) have to either implement {{Serializable}} or {{StateHolder}} (see
3.2.4.2).
I'm seeing the following options for this problem:
* Keep the current behavior. But this breaks compatibility with older Mojarra versions and
all MyFaces versions.
* Replace the map with a list. I think this should work because I saw special handling for
lists in both Mojarra and MyFaces. But the spec doesn't enforce this for a JSF
implementation.
* Don't store the map in the state at all. I think this should work because the map is
always populated with the required values by {{FormValidationFieldProducer}} before the
actual validation happens.
What do you think?
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira