Comments (13)
- Issue Imported From: https://github.com/javaserverfaces/mojarra/issues/16
- Original Issue Raised By:@javaserverfaces
- Original Issue Assigned To: @glassfishrobot
- Original Issue Closed By:@javaserverfaces
from mojarra.
@javaserverfaces Commented
Reported by rogerk
from mojarra.
@javaserverfaces Commented
rogerk said:
Created an attachment (id=7)
Patch For Issue 12
from mojarra.
@javaserverfaces Commented
rogerk said:
The bug only surfaces in "client side" state saving.
M src/javax/faces/component/UIComponentBase.java
- ony store a child's state if state is not null
M systest/src/com/sun/faces/systest/NavigationTestCase.java
- new test case with verbatim tag
A systest/web/jsp/verbatim-one-test.jsp
Index: UIComponentBase.java
RCS file:
/cvs/javaserverfaces-sources/jsf-api/src/javax/faces/component/UIComponentBase.java,v
retrieving revision 1.101
diff -u -r1.101 UIComponentBase.java
— UIComponentBase.java 16 Jun 2004 00:06:55 -0000 1.101
+++ UIComponentBase.java 19 Jul 2004 16:05:38 -0000
@@ -943,7 +943,6 @@
-
@exception NullPointerException {@inheritdoc}
*/
public Object processSaveState(FacesContext context) { -
if (context == null)
{ throw new NullPointerException(); }
@@ -964,7 +963,10 @@
Iterator kids = getChildren().iterator();
while (kids.hasNext()) {
UIComponent kid = (UIComponent) kids.next(); -
childState[i++] = kid.processSaveState(context);
- Object savedState = kid.processSaveState(context);
- if (savedState != null) { + childState[i++] = savedState; + }
}
Iterator myFacets = getFacets().keySet().iterator();
Index: NavigationTestCase.java
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/systest/src/com/sun/faces/systest/NavigationTestCase.java,v
retrieving revision 1.5
diff -u -r1.5 NavigationTestCase.java
— NavigationTestCase.java 1 May 2004 00:48:43 -0000 1.5
+++ NavigationTestCase.java 19 Jul 2004 16:06:19 -0000
@@ -120,4 +120,28 @@
assertTrue(false);
}
}
+
- public void testNavigateWithVerbatim_One() throws Exception {
- HtmlForm form;
from mojarra.
@javaserverfaces Commented
@edburns said:
On Mon, 19 Jul 2004 12:40:51 -0400, Roger Kitain [email protected] said:
I appreciate your thorough testing. Something this core has to be
thoroughly tested.
I don't understand how this change fixes the bug however. Can you
please explain it?
RK> Index: UIComponentBase.java
RK> ===================================================================
RK> RCS file:
/cvs/javaserverfaces-sources/jsf-api/src/javax/faces/component/UIComponentBase.java,v
RK> retrieving revision 1.101
RK> diff -u -r1.101 UIComponentBase.java
RK> — UIComponentBase.java 16 Jun 2004 00:06:55 -0000 1.101
RK> +++ UIComponentBase.java 19 Jul 2004 16:05:38 -0000
RK> @@ -943,7 +943,6 @@
RK> * @exception NullPointerException
RK> */
RK> public Object processSaveState(FacesContext context) {
RK> -
RK> if (context == null)
{ RK> throw new NullPointerException(); RK> }
RK> @@ -964,7 +963,10 @@
RK> Iterator kids = getChildren().iterator();
RK> while (kids.hasNext()) {
RK> UIComponent kid = (UIComponent) kids.next();
RK> - childState[i++] = kid.processSaveState(context);
RK> + Object savedState = kid.processSaveState(context);
RK> + if (savedState != null)
{ RK> + childState[i++] = savedState; RK> + }
RK> }
I would think that you'd want to increment "i" each time around the
while loop, regardless of savedState being null. Otherwise, the
restoreState may not synch up, right? Perhaps I'm missing something.
Also, you're going to have a null in that slot anyway, even if you skip
filling it in with the null return from processSaveState(). We
initialize childState to be new Object[len].
Can you please explain why this works?
Thanks,
Ed
from mojarra.
@javaserverfaces Commented
rogerk said:
Additional Background:
The current client side state saving processing is broken in some cases
(primarily when "verbatim" components are used). A cause of this is
a "misallignment" when processing state save/restore. Consider the
following example:
JSP
—
<f:view>
<h:form id="form">
<h:panelGrid id="panel" columns="2">
<f:facet name="header" >
<h:outputText id="outputheader" value="this is the header" />
</f:facet>
<h:commandLink id="commandLink">
<h:outputText id="redisplay" value="redisplay"/>
</h:commandLink>
<f:verbatim>
verbatim text
</f:verbatim>
</h:panelGrid>
</h:form>
</f:view>
Let's focus on the verbatim tag and the components surrounding the
verbatim tag. At the completion of save state processing, we end up
with the following:
In state saving terms, the panel component ends up with the following
structure:
The "Panel" Component has 3 children:
childState[0] Component:commandLink State:[Ljava.lang.Object;@1e090ee
childState[1] Component:_id0 (This is verbatim tag) State: null
childState[2] Component:outputHeader State:[Ljava.lang.Object;@1123eb0
When the restore state process kicks in, we end up with the following:
Component:commandLink is restored with state from "childState[0]" (correct)
Component:outputHeader is restored with state from "childState[1]
-
- which is null ** hence, this component will not appear on postback.
this component should have been restored with "childState[2]"...
- which is null ** hence, this component will not appear on postback.
As explained in the issue comments, there are two possible fixes
for this state saving bug:
- Option 1: api code change (deal with ignoring transient children
and facets during state saving process in UIComponentBase).
The tree state that will be saved will not include
"verbatim" component slots. - Option 2: ri code change (remove transient/facets from the physical tree
in StateManagerImpl for client side state saving. This is
already done for server side state saving). This would be
done before the API (UIComponentBase.processSaveState) is
executed, hence, end result would be the same as
Option 1 - the tree state that will be saved will not
include "verbatim" components slots.
Keep in mind the following:
The spec (javadoc comments in the api - UIComponent.processSaveState)
mention that as each component is examined, the "transient" property should
be consulted, and if true, return "null";
The spec (javadoc comments in the api - StateManager) say:
"Components may opt out of being included in the serialized view
by setting their transient
property to true
.
This must cause the component itself, as well as all of that component's
children and facets, to be omitted from the saved tree structure
and component state information."
To me, this implies that we can also handle transient components in
the StateManager implementation.
Note: If Option 2 is used (the RI approach), then I can't think of a reason,
that there would be transient components in the tree during
API (UIComponentBase.processSaveState) processing - I kept the
checks in because the spec mentions it...
**Option 1 Change Bundle **
M src/javax/faces/component/UIComponentBase.java
M systest/src/com/sun/faces/systest/NavigationTestCase.java
A systest/web/jsp/verbatim-one-test.jsp
A systest/web/jsp/verbatim-two-test.jsp
Index: UIComponentBase.java
RCS file:
/cvs/javaserverfaces-sources/jsf-api/src/javax/faces/component/UIComponentBase.java,v
retrieving revision 1.101
diff -u -r1.101 UIComponentBase.java
— UIComponentBase.java 16 Jun 2004 00:06:55 -0000 1.101
+++ UIComponentBase.java 22 Jul 2004 15:35:27 -0000
@@ -951,20 +951,20 @@
return null;
}
Object [] stateStruct = new Object[2];
- Object [] childState = null;
// Process this component itself
stateStruct[MY_STATE] = saveState(context);
// Process all the children of this component
-
int i = 0, len = getChildren().size() + getFacets().keySet().size();
-
childState = new Object[len];
-
stateStruct[CHILD_STATE] = childState;
- List nonTransientState = new ArrayList();
Iterator kids = getChildren().iterator();
while (kids.hasNext()) {
UIComponent kid = (UIComponent) kids.next();
- List nonTransientState = new ArrayList();
-
childState[i++] = kid.processSaveState(context);
-
if (kid.isTransient()) { + continue; + }
-
nonTransientState.add(kid.processSaveState(context));
}
-
Iterator myFacets = getFacets().keySet().iterator();
@@ -975,18 +975,16 @@
while (myFacets.hasNext()) {
facetName = (String) myFacets.next();
facet = (UIComponent) getFacets().get(facetName);
-
if (!facet.isTransient()) { - facetState = facet.processSaveState(context); - facetSaveState = new Object[1][2]; - facetSaveState[0][0] = facetName; - facetSaveState[0][1] = facetState; - childState[i] = facetSaveState; - }
-
else {
-
childState[i] = null;
- if (facet.isTransient()) { + continue; }
-
i++;
- facetState = facet.processSaveState(context);
- facetSaveState = new Object[1][2];
- facetSaveState[0][0] = facetName;
- facetSaveState[0][1] = facetState;
- nonTransientState.add(facetSaveState);
} - stateStruct[CHILD_STATE] = nonTransientState.toArray();
return stateStruct;
}
-
- Option 2 Change Bundle **
M src/com/sun/faces/application/StateManagerImpl.java
M systest/src/com/sun/faces/systest/NavigationTestCase.java
A systest/web/jsp/verbatim-one-test.jsp
A systest/web/jsp/verbatim-two-test.jsp
Index: StateManagerImpl.java
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/StateManagerImpl.java,v
retrieving revision 1.22
diff -u -r1.22 StateManagerImpl.java
— StateManagerImpl.java 1 Jun 2004 17:06:26 -0000 1.22
+++ StateManagerImpl.java 22 Jul 2004 15:37:16 -0000
@@ -101,6 +101,7 @@
sessionMap.put(FACES_VIEW_LIST, viewList);
}
} else {
- removeTransientChildrenAndFacets(context, viewRoot, new HashSet());
if (log.isDebugEnabled())
{ log.debug("Begin creating serialized view for " + viewRoot.getViewId()); Test Case Modifications/Additions Common To Both Options: Index: NavigationTestCase.java =================================================================== RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/src/com/sun/faces/systest/NavigationTestCase.java,v retrieving revision 1.5 diff -u -r1.5 NavigationTestCase.java --- NavigationTestCase.java 1 May 2004 00:48:43 -0000 1.5 +++ NavigationTestCase.java 22 Jul 2004 15:40:46 -0000 @@ -120,4 +120,58 @@ assertTrue(false); }
}
+
- public void testNavigateWithVerbatim_One() throws Exception {
- HtmlForm form;
- HtmlSubmitInput submit;
- HtmlPage page, page1;
- page = getPage("/faces/jsp/verbatim-one-test.jsp");
- form = getFormById(page, "form");
- assertNotNull("form exists", form);
- submit = (HtmlSubmitInput)
- form.getInputByName("form" + NamingContainer.SEPARATOR_CHAR +
- "submit");
- // press the link, return to the same page, and check that
- // output text (header) is still present...
- try
{ + page1 = (HtmlPage) submit.click(); + assertTrue(-1 != page1.asText().indexOf("this is the header")); + }
catch (Exception e)
{ + e.printStackTrace(); + assertTrue(false); + }
-
}
-
public void testNavigateWithVerbatim_Two() throws Exception {
-
HtmlForm form;
-
HtmlSubmitInput submit;
-
HtmlPage page, page1;
-
page = getPage("/faces/jsp/verbatim-two-test.jsp");
-
form = getFormById(page, "form");
-
assertNotNull("form exists", form);
-
submit = (HtmlSubmitInput)
-
form.getInputByName("form" + NamingContainer.SEPARATOR_CHAR +
-
"submit");
-
// submit the form, return to the same page, and check that
-
// output text (header) is still present...
-
// and verbatim text is still present...
-
try { + page1 = (HtmlPage) submit.click(); + assertTrue(-1 != page1.asText().indexOf("verbatim one text here")); + assertTrue(-1 != page1.asText().indexOf("this is the header")); + assertTrue(-1 != page1.asText().indexOf("verbatim two text here")); + } catch (Exception e) { + e.printStackTrace(); + assertTrue(false); + }
-
}
verbatim-one-test.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %><f:view>
<title></title><f:facet name="header" >
<h:panelGrid id="panel2" columns="1" >
<h:outputText id="outputheader" value="this is the header" />
<f:verbatim>
</f:verbatim>
</h:panelGrid>
</f:facet>
<h:commandButton id="submit" value="submit"/>
<f:verbatim >
verbatim text here
</f:verbatim>
</h:panelGrid>
</h:form>
verbatim-two-test.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %><f:view>
<title></title><f:verbatim >
verbatim one text here
</f:verbatim>
<h:panelGrid id="panel2" columns="1" >
<h:outputText id="outputheader" value="this is the header" />
<f:verbatim>
</f:verbatim>
</h:panelGrid>
<h:commandButton id="submit" value="submit"/>
<f:verbatim >
verbatim two text here
</f:verbatim>
</h:panelGrid>
</h:form>
Comments are welcome at this point....
from mojarra.
@javaserverfaces Commented
@edburns said:
Option 2 is certainly simpler, but couldn't you move the
removeTransientChildrenAndFacets() call above the if()else{} block, since in
your new world it would execute in either case?
If you assert that option 2 works, and I can indeed see how it would at a top
level, you can go with option 2.
r=edburns
from mojarra.
@javaserverfaces Commented
rogerk said:
Went with Option 2.
from mojarra.
@javaserverfaces Commented
@manfredriem said:
Closing issue out
from mojarra.
@javaserverfaces Commented
File: patch.tar.gz
Attached By: rogerk
from mojarra.
@javaserverfaces Commented
Was assigned to rogerk
from mojarra.
@javaserverfaces Commented
This issue was imported from java.net JIRA JAVASERVERFACES-12
from mojarra.
@javaserverfaces Commented
Marked as fixed on Wednesday, April 19th 2006, 5:44:32 am
from mojarra.
Related Issues (20)
- Dynamic actions not correctly processed HOT 12
- FaceletViewHandlingStrategy handleRenderException log exception before rethrow
- class-level bean validation: Array data not copied after bean cloning HOT 2
- Remove dependencies on SOAP web servcies HOT 5
- Programmatic View with UIOutput HOT 2
- Duplicate `<changes>` entry in PrimeFaces PartialResponseWriter HOT 7
- Revert #5157 HOT 13
- Revert or fix #5417 and release a new 4.0.x version HOT 1
- Static variables in ELUtils cause memory leaks and leaks of resolver cache between applications HOT 1
- U+FFFE and U+FFFF characters can block JSF applications by rendered as ajax response HOT 1
- HtmlUtils#writeAttribute must follow same rules as HtmlUtils#writeUnescapedTextForXML when writing for partial response
- SearchExpressionResolver: `@id` always uses visitTree ?
- 5.0: Unify NavigationHandler and ConfigurableNavigationHandler
- 5.0 Utilize ability to pass VisitHints to UIViewRoot#resetValues()
- 5.0: FacesMessage.Severity will be migrated to enum HOT 1
- 5.0: PhaseId will be migrated to enum HOT 1
- Support new resolvers from Expression Language 6 HOT 1
- cc:attribute elements that have a "default" attribute can not be accessed in FacesComponent HOT 3
- Webapp fails to start with jakarta.faces.AUTOMATIC_EXTENSIONLESS_MAPPING set to true HOT 3
- Bug: API References Implementation Class
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mojarra.