Giter Site home page Giter Site logo

Comments (13)

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

from mojarra.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@javaserverfaces Commented
Reported by rogerk

from mojarra.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@javaserverfaces Commented
rogerk said:
Created an attachment (id=7)
Patch For Issue 12

from mojarra.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@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.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@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

{@inheritdoc}

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.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@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]"...

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();
  • 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.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@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.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@javaserverfaces Commented
rogerk said:
Went with Option 2.

from mojarra.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@javaserverfaces Commented
@manfredriem said:
Closing issue out

from mojarra.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@javaserverfaces Commented
File: patch.tar.gz
Attached By: rogerk

from mojarra.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@javaserverfaces Commented
Was assigned to rogerk

from mojarra.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@javaserverfaces Commented
This issue was imported from java.net JIRA JAVASERVERFACES-12

from mojarra.

ren-zhijun-oracle avatar ren-zhijun-oracle commented on July 16, 2024

@javaserverfaces Commented
Marked as fixed on Wednesday, April 19th 2006, 5:44:32 am

from mojarra.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.