Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Composite components displayed at bottom of page after clicking commandLink [SWF-1577] #758

Closed
spring-operator opened this issue Dec 6, 2012 · 2 comments

Comments

@spring-operator
Copy link
Contributor

spring-operator commented Dec 6, 2012

Stijn Lambert opened SWF-1577 and commented

When using Web Flow (2.3.1.RELEASE) in combination with JSF, I have a rendering problem when using a composite component of any kind and e.g. an <h:outputLabel /> component on 1 page after clicking a <h:commandLink />. The contents of the composite component are always displayed at the bottom of the page! When refreshing the page, rendering is fine again...

I can very easily reproduce this using this code:

My facelet:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:test="http://java.sun.com/jsf/composite/components">

	<h:body>
		<h:form id="form">
			<h:commandLink id="link" value="link" /><br/>
			<test:testComponent id="test" />
			<h:outputLabel value="label" id="label" />
		</h:form>
	</h:body>

</html>

testComponent looks like this:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:composite="http://java.sun.com/jsf/composite">

	<composite:interface>
	</composite:interface>

	<composite:implementation>
		<h:outputText value="hello world" />
	</composite:implementation>
</ui:composition>

My suspicion is that the ordering of components is messed up when Web Flow restores the view after resuming the flow. When using the above code in a simple JSF facelet (without using Web Flow), all is working fine.

I've debugged through the internals of Mojarra and Web Flow and can see that the order is being mixed in the buildView(FacesContext ctx, UIViewRoot view) method of FaceletViewHandlingStrategy when using Web Flow and not when using plain JSF.

See the attachments for the output of the example code. Before: ok.png, after clicking link: nok.png.

Thanks in advance for having a look!


Affects: 2.3.1

Attachments:

Sub-tasks:

@spring-operator
Copy link
Contributor Author

Phil Webb commented

It seems like the main cause of this issue is the com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.adjustIndexOfDynamicChildren(). Adding a conditional breakpoint (on parent instanceof UIForm) shows how the child order is changed.

It appears that com.sun.faces.context.StateContext is tracking dynamic changes via a SystemEventListener inner class. The listener is added to the UIViewRoot when startTrackViewModifications is initially called. There seems to be a mismatch between listener used when the 1st postback is received and the one used after the redirect:

  • Postback is received
  • JSF View is restored and startTrackViewModifications starts
  • Event are processed
  • A redirect is issued
  • The redirect GET is received
  • The JSF View is restored but the previous StateContext$AddRemoveListerner appears to already be attached
  • There are now two StateContext in play, a new one that gets added and the previous one referenced via the AddRemoveListerner
  • Calls to startTrackViewModifications now only update the newer StateContext

In order to fix the issue we need to ensure that the StateContext.release() method is called before the redirect. This method will trigger unsubscribeFromViewEvent on the UIViewRoot. It seems that StateContext.release() is only called via StateManagerImpl.saveView. Since Spring Web Flow has its own statemanagement this method is currently not always called.

@spring-operator
Copy link
Contributor Author

Stijn Lambert commented

Thanks for solving!

In the meantime we could solve this by disabling "redirect in same state" as explained in the reference guide http://static.springsource.org/spring-webflow/docs/2.3.x/reference/html/ch13s10.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants