Jsf 未在第二次提交时使用最新信息更新托管
我在这里遇到了一个似乎比我更好的问题 上下文 我有一个p:对话框(primefaces),显示JPA实体的详细信息。通过此对话框,用户可以修改信息并提交。提交后,信息保存在DB中(通过JPA) 对话框被“包装”在一个组件中,用于不同的情况 问题: 如果我显示一个从DB中选择的实体的对话框,修改一些信息并单击save(submit)按钮:它第一次工作正常。数据库被更新,p:对话框被隐藏。Jsf 未在第二次提交时使用最新信息更新托管,jsf,jakarta-ee,jsf-2,primefaces,cdi,Jsf,Jakarta Ee,Jsf 2,Primefaces,Cdi,我在这里遇到了一个似乎比我更好的问题 上下文 我有一个p:对话框(primefaces),显示JPA实体的详细信息。通过此对话框,用户可以修改信息并提交。提交后,信息保存在DB中(通过JPA) 对话框被“包装”在一个组件中,用于不同的情况 问题: 如果我显示一个从DB中选择的实体的对话框,修改一些信息并单击save(submit)按钮:它第一次工作正常。数据库被更新,p:对话框被隐藏。 如果我再次显示具有相同实体的对话框,请再次修改p:对话框中的数据,然后再次提交:一切正常(确认消息和日志),但
如果我再次显示具有相同实体的对话框,请再次修改p:对话框中的数据,然后再次提交:一切正常(确认消息和日志),但数据库未更新 在任何时候,p:对话框中的信息都是正确的。但是,BackingBean&DB中的数据只有在第一次提交之后才是最新的 另一个提示:如果在提交操作之后我刷新了页面,那么它将再次提交 调试信息: 根据提交人发布的信息(Firebug长寿!!!)所有发布的数据都是正确的(总是最新的)。但是,如果我在日志中显示支持bean接收到的内容,它与上一次提交的内容相同(而不是新信息) 数据发布正确,但似乎接收/解释不好。这就像问题发生在JSF生命周期的RestoreView、ApplyRequestValue、ProcessValidation或UpdateModelValue阶段的submit帖子接收时一样 因此,第二次保存(提交)似乎有效,但无效的原因是,保存在数据库中的数据对于后续的每次提交都是相同的为什么? 我使用Glassfish 3.1.2、Mojarra 2.1.13、JSF、PrimeFaces、CDI、JPA、Hibernate 代码: 包含p:对话框(cmpnt:dataEntryDialog)作为组件的页面:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:cmpnt="http://java.sun.com/jsf/composite/component"
>
<h:head>
<title>
Test!!!
</title>
</h:head>
<h:body>
<h:commandButton type="button" onclick="PVDlg.show();" value="show dlg"/>
<cmpnt:dataEntryDialog id="PVDataEntry" video="#{processStatus.testedVideo}" fieldGroupId="2"
header="This is a test"
widgetVar="PVDlg" render="@this"/>
</h:body>
</html>
测验
p:dialog的组件实现(cmpnt:dataEntryDialog):
[…其他属性]
函数handleDataEntrySaveTest(xhr、状态、参数){
如果(args.validationFailed | | |!args.saved){
jQuery('#'+#{cc.clientId}+':cmpntDataEntryDialog').effect(“shake”,{times:3},100);
}否则{
${cc.attrs.widgetVar}.hide();
}
返回true;
}
[…针对不同数据类型的一些其他可选呈现字段]
关于托管bean,它们是普通的CDI@Named@SessionScoped bean
其他信息:
我做了进一步的测试:通过phase listener查看是否有任何对象可以从那个里访问到有趣的信息。。。到现在为止这里运气都不好。我找到了!问题不在表示层上(真令人惊讶!)。这与我的逻辑有关。不久前,我通过将实体实例(不再由entityManager管理)更改为实体管理器的合并方法返回的托管实例,修复了JPA乐观锁异常。我的设计并没有像预期的那样支持任何地方的改变。。。我被帖子内容所吸引,这是正确的,但不是我所期望的实体实例。我想更多的网络开发经验不会有什么坏处 我说不出是什么问题。然而,经常帮助我追踪使用Primefaces构建的组件中的错误的是在我的
中添加ajax=“false”
。您可能知道,默认情况下,Primefaces
使用AJAX发布。奇怪的是,在一些情况下禁用AJAX会从JSF中得到有用的错误消息,而启用AJAX后,我会得到似乎什么都没发生的行为。尝试一下,看看它是否有助于跟踪问题,然后在修复后恢复。尝试了你的建议,但没有改变任何东西(我的意思是没有其他有用的错误消息)。我还不能说明问题是什么,但它似乎与我用来避免javax.persistence.OptimisticLockException的方式有关。。。更多的细节很快!
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:c="http://java.sun.com/jsp/jstl/core"
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">
<composite:interface componentType="dataEntryComponent">
<composite:attribute name="video" required="true"/>
<composite:attribute name="widgetVar" required="true"/>
<composite:attribute name="render" required="false"/>
<composite:attribute name="closeActionListener" method-signature="void listener(org.primefaces.event.CloseEvent)" required="false" />
[... other attributes]
</composite:interface>
<composite:implementation>
<h:outputStylesheet library="css" name="dataEntryDialog.css" target="head" />
<div id="#{cc.clientId}">
<script type="text/javascript">
function handleDataEntrySaveAttempt(xhr, status, args) {
if( args.validationFailed || !args.saved ) {
jQuery('#' + #{cc.clientId} + ':cmpntDataEntryDialog').effect("shake", {times:3}, 100);
} else {
${cc.attrs.widgetVar}.hide();
}
return true;
}
</script>
<p:dialog
id="cmpntDataEntryDialog"
header="#{cc.attrs.header}"
widgetVar="#{cc.attrs.widgetVar}"
resizable="false"
showEffect="fade"
hideEffect="fade"
dynamic="true"
minimizable="true"
maximizable="false"
width="550"
height="500"
>
<h:form id="cmpntDataEntryForm" style="position:relative;">
<div style="height:460px;">
<div style="width:100%;height:100%;margin-bottom:5px;overflow:auto;">
<ui:repeat value="#{dataEntryDialog.loadDataEntryFields( cc.attrs.video, cc.attrs.fieldGroupId )}" var="field" varStatus="fieldRankInfo">
<div style="position:relative;width:100%;height:24px;margin:4px 0px;">
<h:outputText value="#{field.fieldName}:" style="vertical-align:middle;" styleClass="margin"/>
<p:calendar id="cmpntInputDate" value="#{field.value}" rendered="#{'java.util.Date' eq field.type}" styleClass="input margin" effect="drop" />
<p:selectOneMenu id="cmpntInputComboBox" value="#{field.value}" rendered="#{'ComboBox' eq field.type}" styleClass="input margin">
<f:selectItem itemLabel="SelectAValue"/>
<f:selectItems value="#{field.possibleValues}"/>
<f:converter converterId="com.ctec.world.ConvertInteger" />
</p:selectOneMenu>
[... some other optionally rendered fields for different data types]
</div>
</ui:repeat>
</div>
</div>
<div style="position:relative;bottom:0;">
<div style="float:right;margin-top:5px;">
<p:commandButton id="cmpntSubmit" action="#{dataEntryDialog.save( cc.attrs.video.video )}"
value="${cc.resourceBundleMap.dataEntryDialog_Save}"
process="@form" update="${cc.attrs.render} @form"
styleClass="margin" oncomplete="handleDataEntrySaveAttempt( xhr, status, args )"/>
<p:commandButton id="cmpntCancel"
value="${cc.resourceBundleMap.dataEntryDialog_Cancel}"
onclick="${cc.attrs.widgetVar}.hide();" styleClass="margin"/>
</div>
</div>
</h:form>
</p:dialog>
</div>
</composite:implementation>
</html>