私はここで問題を抱えています。
コンテクスト
JPAエンティティの詳細を表示するap:dialog(primefaces)があります。このダイアログから、ユーザーは情報を変更して送信できます。送信されると、情報はDBに(JPAを介して)保存されます。
p:dialogは、さまざまな状況で使用するためにコンポーネントに「ラップ」されています。
問題:
DBから選択したエンティティでダイアログを表示する場合は、いくつかの情報を変更して、[保存(送信)]ボタンをクリックします。最初は正常に機能します。DBが更新され、p:dialogが非表示になります。
同じエンティティでダイアログを再度表示する場合は、p:dialogのデータを再度変更して、再度送信します。すべてが正常に機能しているように見えますが(確認メッセージとログ)、DBは更新されません。
常に、p:dialogにある情報は正しいです。ただし、BackingBean&DBにあるデータは、最初の送信後にのみ最新になります。
もう1つの手がかり:送信アクションの後でページを更新すると、もう1回送信しても機能します。
デバッグ情報:
送信によって投稿された情報(Firebugの寿命が長い!!!)によると、投稿されたすべてのデータは正しいです(常に最新です)。ただし、バッキングBeanが受け取ったものをログに表示すると、前回の送信と同じ内容になります(新しい情報ではありません)。
データは正しく投稿されていますが、受信/解釈が悪いようです。これは、JSFライフサイクルのRestoreView、ApplyRequestValue、ProcessValidation、またはUpdateModelValueフェーズのいずれかで、送信の投稿の受信時に問題が発生した場合と同じです。
したがって、2番目の保存(送信)が機能しているように見えても機能しない理由は、DBに保存されたデータが後続のすべての送信で同じであるためです.....なぜですか?
Glassfish 3.1.2、Mojarra 2.1.13、JSF、PrimeFaces、CDI、JPA、Hibernateを使用しています...
コードスニペット:
コンポーネントとしてp:dialog(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):
<?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>
管理対象Beanに関しては、プレーンCDI @Named@SessionScopedBeanです。
追加情報:
私はさらにテストを行いました。フェーズリスナーを調べて、そこからアクセスできる興味深い情報を持つオブジェクトがあるかどうかを確認しました...今までここでは運がありませんでした。