0

我在这里工作的设置是 JBoss AS7 中的 JSF2 和 Seam-2.3。

我有一个管理器 bean,它在一个大模板中通过<a4j:commandButton>如下方式调用:

<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" />

对应的代码来自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());
  }
}

现在要做personManager的是调用person.jobs.add(new Job())私有的、仍然是瞬态的实体 bean person。在它执行此操作之前,请求会因以下堆栈跟踪而终止:

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:]

对此进行调试,ExtendedPartialViewContext 确实“得到”它应该只执行 commandButton 组件但随后似乎继续渲染遍历完整的 JSF 树?我的意思是,为什么还要评估该列表值?它甚至在一个应该在回发时评估的 div 中rendered=false。我一定在这里遗漏了一些明显的东西吗?

我首先想到的是可能 pages.xml 正在干扰(调用selectObjects,但操作具有属性on-postback="false"集)或者我需要添加<a4j:keepAlive>- 但由于 Richfaces4 中已经消失了,我不能真正做到这一点,不应该对话范围跨越AJAX 请求也是?

4

1 回答 1

0

RichFaces 中存在一个错误,即扩展 UIDataAdaptor 的组件的 value 属性在“树访问”时进行评估,即使 render=false: https ://issues.jboss.org/browse/RF-11382

尝试更新到修复 bug 的 RichFaces 4.3.0.Final,或应用解决方法(应对每个扩展 UIDataAdaptor 的组件重复解决方法):

public class UIDataTableWorkaround extends UIDataTable {
  @Override
  public void setRowKey(FacesContext facesContext, Object rowKey) {
    if (rowKey == null && getRowKey() == null) {
      return;
    }
    super.setRowKey(facesContext, rowKey);
  }
}

在 faces-config 中:

  <component>
    <component-type>org.richfaces.DataTable</component-type>
    <component-class>com.example.UIDataTableWorkaround</component-class>
  </component>
于 2013-02-28T19:45:16.743 回答