1

私には問題があり、それがどうなるかわかりません... GWT の初心者で、個人的なプロジェクトに取り組んでいます。

環境:

  • 2 つのモジュールを含むMavenプロジェクト

    • 1 つのモジュールは「モデル」であり、HibernateHSQLDBSpring の依存関係があります。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 アノテーションが適用されていない可能性があります...

4

2 に答える 2

2

なぜこれがエラー/例外としてクライアントに送信されないのですか?

です。は"S": [false]、最初の(そして唯一の)メソッド呼び出し(aRequestContextはバッチであることを忘れないでください!)が失敗したことを示します。呼び出しのonFailureメソッドがReceiver呼び出されます。

のthenは致命的なエラーであると言っているので、のデフォルトの実装は"F": true。をスローします。ただし、をまったく使用しないため、何も起こらず、エラーは黙って無視されます。ServerFailureReceiver#onFailureRuntimeExceptionReceiver

バッチリクエスト自体が成功したため、グローバルReceiver(渡すものRequestContext#fire)のonSuccessメソッドが呼び出されることに注意してください。また、これは(引数なしで)続くの省略形である
ことに注意してください。Request#fire(Receiver)Request#to(Receiver)RequestContext#fire()

なぜこれはHibernateによってログに記録されないのですか?

これはわかりません、ごめんなさい。

Spring Rooで生成されたコード(私が言ったように、基本として使用される)が、この問題を明示せずに機能するのはなぜですか?

OK、例外の根本的な理由を調べてみましょう。エンティティはユーザーLocator(またはエンティティクラスのfindXxx静的メソッド)によって読み込まれpersist、インスタンスでメソッドが呼び出されます。とメソッドで同じJPA EntityManager/Hibernateセッションを使用しない場合は、問題が発生します。Request Factoryは、これを克服するために、ビューパターンで開いているセッション を使用することを期待しています。残念ながら、SpringRooがどのようなコードを生成するのかわかりません。findpersist

于 2012-07-27T14:49:25.983 に答える
2

Thomas が言及したopen session in viewパターンに関してはweb.xml、Spring アプリケーションでパターンを有効にするために、このフィルター定義を に追加するだけです。

<filter>
    <filter-name>
        Spring OpenEntityManagerInViewFilter
    </filter-name>
    <filter-class>
         org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
于 2012-07-30T08:45:19.283 に答える