私には問題があり、それがどうなるかわかりません... GWT の初心者で、個人的なプロジェクトに取り組んでいます。
環境:
2 つのモジュールを含むMavenプロジェクト
1 つのモジュールは「モデル」であり、Hibernate、HSQLDB、Spring の依存関係があります。HSQLDB は、Spring applicationContext.xml から構成されたメモリ内に埋め込まれて実行されます
もう 1 つのモジュールは「web」であり、すべてのGWT 依存関係があります
アプリケーションは、Spring Roo で生成されたコードをベースとして構築され、後で変更および拡張されます。
問題は、一部のエンティティ フィールドを編集して保存を押しても、何も起こらないことです。新しいエンティティ インスタンスを作成するときは問題ありません。編集時に一部のフィールドを変更して「保存」を押すと、基本的に新しい値が上書きされます。そこで、クライアントコードを徹底的にデバッグし始め、休止状態とSpringの詳細なログを有効にしましたが、それでも...何もありません。
すると、(私にとっては)驚くべき発見がありました。GWT 応答ペイロードを調べると、次のことがわかりました。
{"S":[false],"O": [{"T":"663_uruC_g7F5h5IXBGvTP3BBKM=","V":"MS4w","S":"IjMi","O":"UPDATE"}],"I":[{"F":true,"M":"Server Error: org.hibernate.PersistentObjectException: detached entity passed to persist: com.myvdm.server.domain.Document; nested exception is javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.myvdm.server.domain.Document"}]}
ああ、切り離されたエンティティが持続するために渡されました!!! gwt クライアント コードは、このスニペットを使用してサービスを呼び出すことに注意してください。
requestContext.persist().using(プロキシ);
おそらく、これにより例外がトリガーされ、merge() を呼び出すことで問題を解決できる可能性がありますが、質問 3 を読み進めてください...
ここで 3 つの疑問が生じます。
- これがエラー/例外としてクライアントに送信されないのはなぜですか?
- これが Hibernate によってログに記録されないのはなぜですか?
- Spring Roo で生成されたコード (前述のように、ベースとして使用される) がこの問題を明らかにせずに機能するのはなぜでしょうか?
どうもありがとう、
いくつかの意見/提案を待っています。
T. BROYERの応答後に編集::
こんにちは、トーマスさん、返信ありがとうございます。
RequestTransport を実装し、send() を実装するカスタム クラスがあります。これが、応答ペイロードを収集した方法です。実装は次のとおりです::
public void send(String payload, final TransportReceiver receiver) {
TransportReceiver myReceiver = new TransportReceiver() {
@Override
public void onTransportSuccess(String payload) {
try {
receiver.onTransportSuccess(payload);
} finally {
eventBus.fireEvent(new RequestEvent(RequestEvent.State.RECEIVED));
}
}
@Override
public void onTransportFailure(ServerFailure failure) {
try {
receiver.onTransportFailure(failure);
} finally {
eventBus.fireEvent(new RequestEvent(RequestEvent.State.RECEIVED));
}
}
};
try {
wrapped.send(payload, myReceiver);
} finally {
eventBus.fireEvent(new RequestEvent(RequestEvent.State.SENT));
}
}
編集モードで「保存」ボタンがクリックされたときに実行されるコードは次のとおりです。
RequestContext requestContext = editorDriver.flush();
if (editorDriver.hasErrors()) {
return;
}
requestContext.fire(new Receiver<Void>() {
@Override
public void onFailure(ServerFailure error) {
if (editorDriver != null) {
setWaiting(false);
super.onFailure(error);
}
}
@Override
public void onSuccess(Void ignore) {
if (editorDriver != null) {
editorDriver = null;
exit(true);
}
}
@Override
public void onConstraintViolation(Set<ConstraintViolation<?>> errors) {
if (editorDriver != null) {
setWaiting(false);
editorDriver.setConstraintViolations(errors);
}
}
});
あなたが言ったことに基づいて、 onSuccess() を呼び出す必要があり、呼び出されます
では、問題を引き起こしているコードを正確に切り分けるにはどうすればよいでしょうか。オブジェクトを永続化するために新しいリクエストコンテキストを作成するこのメソッドがあります
@Override
protected RequestContext createSaveRequestContextFor(DocumentProxy proxy) {
DocumentRequestContext request = requests.documentRequestContext();
request.persist().using(proxy);
return request;
}
そして、これはそれが呼ばれる方法です::
editorDriver.edit(getProxy(), createSaveRequestContextFor(getProxy()));
Spring の問題に関しては、find() と persist() という 2 つの後続のリクエストの間で、JPA entityManager を閉じてはいけないと言っています。これについてはまだ調査中ですが、編集ボタンを押した後に「org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager」というメッセージが表示され、それは正しくありません。@Transactional アノテーションが適用されていない可能性があります...