The setup I'm working here is JSF2 in JBoss AS7 with Seam-2.3.
I've a manager bean that get's called via in a big template via an <a4j:commandButton>
like so:
<rich:dataTable value="#{listFactory.getMyList()}" var="ll">
...
</rich:dataTable>
...
<a4j:repeat id="jobs" value="#{person.jobs}" var="job">
<h:outputText value="#{job.name}" />
</a4j:repeat>
<a4j:commandButton value="more" immediate="true"
action="#{personManager.addJob}" render="jobs" limitRender="true" />
The corresponding code from personManager
:
@Name("personManager")
@Scope(ScopeType.CONVERSATION)
public class PersonMgr {
private Person person;
@Begin(flushMode = FlushModeType.MANUAL)
public void selectObjects() {
// grab the person from the request if there's one
}
@End
public void saveChanges() {
em.flush();
}
public void addJob() {
person.getJobs().add(new Job());
}
}
Now what personManager
does is to call person.jobs.add(new Job())
on the private, still transient entity bean person
. Before it can do that, the request dies with the following stacktrace:
javax.el.ELException: /person.xhtml @412,95 value="#{listFactory.getMyList()}": org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Person
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114) [jsf-impl-2.1.7-jbossorg-2.jar:]
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at org.richfaces.component.UISequence.getValue(UISequence.java:175) [richfaces-components-ui.jar:4.3.0.Final]
at org.richfaces.component.UISequence.createExtendedDataModel(UISequence.java:109) [richfaces-components-ui.jar:4.3.0.Final]
at org.richfaces.component.UIDataTableBase.createExtendedDataModel(UIDataTableBase.java:252) [richfaces-components-ui.jar:4.3.0.Final]
at org.richfaces.component.UIDataAdaptor.getExtendedDataModel(UIDataAdaptor.java:459) [richfaces-components-ui.jar:4.3.0.Final]
at org.richfaces.component.UIDataAdaptor.setRowKey(UIDataAdaptor.java:272) [richfaces-components-ui.jar:4.3.0.Final]
at org.richfaces.component.UIDataAdaptor.visitTree(UIDataAdaptor.java:1312) [richfaces-components-ui.jar:4.3.0.Final]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIForm.visitTree(UIForm.java:371) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at org.richfaces.context.ExtendedPartialViewContextImpl.visitActivatorComponent(ExtendedPartialViewContextImpl.java:448) [richfaces-core-impl.jar:4.3.0.Final]
at org.richfaces.context.ExtendedPartialViewContextImpl.visitActivatorAtExecute(ExtendedPartialViewContextImpl.java:309) [richfaces-core-impl.jar:4.3.0.Final]
at org.richfaces.context.ExtendedPartialViewContextImpl.getExecuteIds(ExtendedPartialViewContextImpl.java:98) [richfaces-core-impl.jar:4.3.0.Final]
at org.richfaces.context.ExtendedPartialViewContextImpl.isExecuteAll(ExtendedPartialViewContextImpl.java:148) [richfaces-core-impl.jar:4.3.0.Final]
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.7-jbossorg-2.jar:]
Debugging this, the ExtendedPartialViewContext does indeed "get" that it's supposed to only execute the commandButton component but then appears to proceed to render walk the full JSF tree? I mean, why is that list value even evaluated? It's even in a div that should evaluate to rendered=false
at the time of postback. I must be missing something glaringly obvious here?
What first occured to me is that maybe pages.xml is interfering (calls selectObjects
but the action has the attribute on-postback="false"
set) or I need to add <a4j:keepAlive>
- but since that's gone in Richfaces4 I can't really do this and shouldn't the conversation scope span AJAX requests, too?