我在一个项目中,我将编写很多这样的页面,所以我想使用最有效(写入)的编码模式。
背景:过去我使用CODI的@ViewAccessScoped来保持请求之间的状态,最近我开始使用闪存范围对象来保存状态。我不能使用JSF @ViewScoped,因为我使用CDI并且它们不能很好地协同工作。所以我想看看我是否只能使用@RequestScoped支持bean来实现这一点。
页面设计如下(p名称空间为Primefaces):
<f:metadata>
<f:viewParam name="ID" value="#{backing.id}" />
</f:metadata>
....
<h1>Edit Object Page</h1>
<h:form id="formObj" rendered="#{backing.accessOK}">
<p:panelGrid columns="2">
<h:outputLabel value="Field #1:"/>
<p:inputText value="#{backing.record.field1}" />
(more input fields)
<h:outputLabel value="Action:" />
<h:panelGroup>
<p:commandButton value="Save"
action="#{backing.save}"
/>
<p:commandButton value="Cancel" action="backing.cancel" />
</h:panelGroup>
</p:panelGrid>
<p:messages showDetail="true" showSummary="true" />
</h:form>
如果请求页面, accessOK()方法可以保持 h:form 的呈现。相反, p:消息会显示 FaceOKMessage , accessOK()方法需要设置。
bean 支持的模式如下所示:
@Named
@RequestScoped
public class Backing {
private long id;
private SomeJPAEntity record;
private Boolean accessOK;
public long getId() { return id; }
public void setId(long value) { id = value; }
public boolean accessOK() {
if (accessOK != null) return accessOK;
if (getRecord() == null) {
// add a FacesMessage that explains the record
// does not exist
return accessOK = false; // note single =
}
// do any other access checks, such as write permissions
return accessOK = true;
}
public SomeJPAEntity getRecord() {
if (record != null) return record;
if (getId() > 0) record = // get the record from DB
else record = new SomeJPAEntity();
return record;
}
public String execute() {
if (!accessOK()) return null; // bad edit
// do other integrity checks here. If fail, set FacesMessages
// and return null;
if (getId() > 0) // merge the record back into the data base
else // persist the record
}
}
这个模型出了什么问题。单击“保存”按钮后,将构建一个新的 Backing 实例,然后在之前有很多对 getRecord() getter 的调用>调用 setID() setter。因此 getRecord()中的逻辑会中断,因为它在调用时无法依赖 id 属性。
如果这是 @ViewAccessScoped (或 ViewScoped )支持bean,那么 id 和记录使用 commandButton 处理表单时已设置属性。或者,您可以将这些属性保存在闪存存储中,但这有我想避免的问题。
那么有没有办法让这个编程模型在规范中工作?
的更新: 的
我有一个解决方案,根据经验允许它无需使用flash或视图范围的变体即可工作。如上所述,处理表单时,在第一次调用 setId()之前,会有一些对 getRecord() 的调用。然后最后调用 save()方法。
我所做的是修改 setId(),如下所示:
public void setId(long value) {
id = value;
record = null;
}
这会强制 getRecord()重新计算(即获取/构建)属性记录,然后进行后续调用。具体而言,输入 save()方法,并正确初始化对象,包括记录实体的内容。我不知道先前对 getRecord()的所有调用是针对什么的。
此时我还不知道我可以依赖的是是否所有写入记录实体的值都将从 UIinput 组件设置 getId()之后。如果是这样,那么我可以使用这种模式。这是由规范控制还是运气好吗?
有任何意见或建议吗?
答案 0 :(得分:2)
我认为你可以用CODI(或者更确切地说是DeltaSpike)感到安全。我已经很好地使用了Tomcat。他们几乎都支持所有人。
Deltaspike现在正在研究JSF模块,并且有很多活动,当这个酿造完成后,我相信你会对它感到满意。即使项目仍处于孵化阶段,deltaspike的每个模块都是单独生产的。
现在针对您的实际问题,我无法提出您尚未提出的任何建议。
但是我想知道,这个案例中有一个人可能会关心对f:viewParam
的约束吗?我不确定因为我几乎从未使用绑定。
答案 1 :(得分:1)
CODI和DeltaSpike为CDI启用@ViewScoped。 JSF中的Flash-Scope&lt; 2.2完全打破了多个窗口。我看到退出CODI的唯一原因是迁移到DeltaSpike,直到它准备就绪,你可以并行使用它们。