【发布时间】:2011-12-24 08:36:47
【问题描述】:
我遇到了一个非常典型的 CRUD 情况,我正在努力解决,所以我想我一定是误解了一些东西。我整理了一个小演示应用程序来更好地解释我的问题。感兴趣的两个文件如下所示:
PersonView - 支持 JSF 页面的 CDI 托管 Bean
package example
import java.io.Serializable;
import java.util.List;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
@ConversationScoped @Named
public class PersonView implements Serializable {
private Person selectedPerson;
@Inject private PersonService personService;
@Inject private Conversation conversation;
public PersonView() {}
public List<Person> getPeople() { return personService.findAll(); }
public void beginConversation() { if( conversation.isTransient() ) {conversation.begin();} }
public void endConversation() { if( !conversation.isTransient() ) { conversation.end();} }
public void createPerson() {
beginConversation();
setSelectedPerson( new Person() );
}
public void addPerson() {
personService.addPerson( getSelectedPerson() );
endConversation();
}
public void updatePerson() { personService.updatePerson( getSelectedPerson() ); }
public Person getSelectedPerson() { return selectedPerson; }
public void setSelectedPerson(Person selectedPerson) { this.selectedPerson = selectedPerson; }
}
index.xhtml - 用于操纵人的 JSF 页面
<?xml version='1.0' encoding='UTF-8' ?>
<!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:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>CRUD Example</title>
</h:head>
<h:body>
<h:form prependId="false">
<p:dataTable var="p" value="#{personView.people}" id="person_table" rowKey="#{p.id}" selection="#{personView.selectedPerson}">
<p:column selectionMode="single"/>
<p:column><f:facet name="header">ID</f:facet>#{p.id}<p:column>
<p:column><f:facet name="header">Name</f:facet>#{p.name}</p:column>
<f:facet name="footer">
<p:commandButton value="Create Person" onclick="create_dialog.show();" actionListener="#{personView.createPerson}"/>
<p:commandButton value="Edit Person" onclick="edit_dialog.show();" update="edit_panel"/>
</f:facet>
</p:dataTable>
</h:form>
<p:dialog header="Create Person" id="create_dialog" widgetVar="create_dialog" modal="true" width="750" height="300">
<h:form prependId="false">
<p:panel id="create_panel">
<p>Name: <p:inputText value="#{personView.selectedPerson.name}" required="true"/></p>
<p><p:commandButton value="Add" actionListener="#{personView.addPerson}" oncomplete="create_dialog.hide();" update="person_table" /></p>
</p:panel>
</h:form>
</p:dialog>
</h:body>
在索引页面上,用户会看到一个数据表,其中包含系统知道的所有人员。然后他们按下表格底部的 Create Person 按钮。我已经检查过这是否正确调用了 createPerson 方法,并且对话显然开始了。然后会显示 create_dialog,用户可以在其中输入名称。当用户单击“添加”按钮时,问题就出现了。 JSF 尝试存储人员姓名,但 selectedPerson 变量现在为 null,因此它失败并出现 NullPointerException。
我意识到这不是创建对象的常用方法,但在我当前的应用程序中是有意义的,因为我可以猜测新 Person 的一些值。它也非常适合我想要的编辑方式。
所以我的问题是:为什么对话没有传播? PersonView bean 似乎一直在请求范围内。我已经阅读了 JSF2 中的 @ViewScoped,但如果可能的话,我宁愿坚持使用 CDI。根据我的阅读,我认为问题在于未能通过请求传递 CID 名称,但我不知道如何使用 AJAX 做到这一点。
我想出的唯一解决方案是将 PersonView 移到会话中,但这感觉就像一个巨大的杂物。 e
【问题讨论】:
-
我不做 CDI,但这听起来很像 this issue with @ViewScoped。尝试在
update中显式引用另一个<h:form>。例如。<p:commandButton value="Create Person" ... update=":create_form">和<h:form id="create_form">。 -
有趣,我想你已经解释了为什么当我用@ViewScoped 注释bean 时上面的代码不起作用。不过,我希望找到解决该问题的 CDI 解决方案。我发现的最好的是question,它建议使用 MyFaces CODI,这似乎可以满足我的想法。
-
我认为 CDI 也有同样的问题,因为它与 JSF 视图状态有关。您是否尝试过直接更新
<h:form>而不是其子女或父母之一?