5

RequestFactory と Editor フレームワークをアプリに実装しようとしています。フォーラム、Google デベロッパー フォーラムなどを調査した後でも、RequestFactory で RequestContext を使用することについて理解できない基本的なことがあることがわかりました。これが私のシナリオです:
CmsObjectType と呼ばれる ID、バージョン、説明の 3 つのフィールドを持つ単純なエンティティがあります。CRUD 操作に対応する EntityProxy と CmsObjectTypeServiceDAO があります。ServiceLocator クラスと ObjectLocator クラスも実装しました。このコードはすべてコンパイルおよび実行されます。

以下を使用して、CRUD 操作をテストするための簡単なテスト ケースも作成しました。

public class RequestFactoryProvider {

public static CmsRequestFactory get() {
    SimpleEventBus eventBus = new SimpleEventBus();
    CmsRequestFactory requestFactory = RequestFactoryMagic.create(CmsRequestFactory.class);
    ServiceLayer serviceLayer = ServiceLayer.create();

    SimpleRequestProcessor processor = new SimpleRequestProcessor(
            serviceLayer);
    requestFactory.initialize(eventBus, new InProcessRequestTransport(
            processor));
    return requestFactory;
}

}

テスト:

public class TestCmsObjectTypeRequest extends Assert {

private static CmsRequestFactory requestFactory;
private static CmsObjectTypeRequestContext objectTypeRequest;
private Long newId;

@Before
public void setUp() {
    requestFactory = RequestFactoryProvider.get();
    objectTypeRequest = requestFactory.objectTypeRequest();
}

    @Test
public void testEdit() {
    final CmsObjectTypeProxy newType = objectTypeRequest
            .create(CmsObjectTypeProxy.class);
    newType.setDescription("NEW TYPE");
    objectTypeRequest.persist(newType).to(new Receiver<Long>() {

        @Override
        public void onSuccess(Long response) {
            if (response != null) {
                newId = response;
                assertTrue(true);
            } else {
                fail();
            }
        }

        @Override
        public void onFailure(ServerFailure error) {
            fail();
        }
    });

    // Edit the newly created object
    newType.setDescription("EDITED NEW TYPE");

        objectTypeRequest.update(newType).to(new Receiver<Boolean>() {

            @Override
            public void onSuccess(Boolean response) {
                assertTrue(response);
            }

            @Override
            public void onFailure(ServerFailure error) {
                fail();
            }
        });

        //Remove it when we're done..
        objectTypeRequest.delete(newType).to(new Receiver<Boolean>() {

        @Override
        public void onSuccess(Boolean response) {
            System.out.println("onSuccess from delete.");
            assertTrue(response);
        }

        @Override
        public void onFailure(ServerFailure error) {
            fail();
        }
    });
    objectTypeRequest.fire();
}
}

新しいリクエスト コンテキストを作成し、作成、更新、削除のメソッド呼び出しをチェーンしてから fire() を呼び出すと、上記のテストでは問題なく動作します。ただし、メソッドを呼び出してから fire() を呼び出してこれらの呼び出しを個別に実行しようとすると、問題が発生します。新しく作成されたエンティティの ID を返すレシーバーで create() を呼び出し、その ID を使用して find(id) を呼び出すと、新しく作成されたエンティティが返されます。この時点まで、すべて正常に動作します。ただし、これは私が混乱しているところです.. find(id) から受信者の onSuccess() メソッド内で現在の RequestContext を使用して edit を呼び出そうとすると、コンテキストが既に進行中であるというエラーが表示されます。foundProxy のローカル変数を作成し、RequestContext の新しいインスタンスを使用して requestContext を呼び出そうとするとします。新しく見つかったエンティティで edit(foundProxy) を実行し、update() を呼び出します。最も一般的なサーバー エラーが発生します。 サーバー エラー: 要求されたエンティティはサーバーで利用できません。リクエスト コンテキストの新しいインスタンスを作成しないと、リクエストが既に進行中であることを示す IllegalStateException が発生します。これをより明確にするためのサンプル テストを次に示します。

@Test
public void testEditWOChaining() {
    final CmsObjectTypeProxy newType = objectTypeRequest
            .create(CmsObjectTypeProxy.class);
    newType.setDescription("NEW TYPE");
    objectTypeRequest.persist(newType).to(new Receiver<Long>() {

        @Override
        public void onSuccess(Long response) {
            if (response != null) {
                setNewId(response);
                assertTrue(true);
            } else {
                fail();
            }
        }

        @Override
        public void onFailure(ServerFailure error) {
            fail();
        }
    }).fire();

    if (newId != null) {
        objectTypeRequest = requestFactory.objectTypeRequest();
        objectTypeRequest.find(newId)
                .to(new Receiver<CmsObjectTypeProxy>() {

                    @Override
                    public void onSuccess(CmsObjectTypeProxy response) {
                        if (response != null) {
                            foundProxy = response;
                        }
                    }

                    @Override
                    public void onFailure(ServerFailure error) {
                        fail();
                    }
                }).fire();
    }

    if (foundProxy != null) {
        // Edit the newly created object
        objectTypeRequest = requestFactory.objectTypeRequest();
        CmsObjectTypeProxy editableProxy = objectTypeRequest
                .edit(foundProxy);
        editableProxy.setDescription("EDITED NEW TYPE");

        objectTypeRequest.update(editableProxy).to(new Receiver<Boolean>() {

            @Override
            public void onSuccess(Boolean response) {
                assertTrue(response);
            }

            @Override
            public void onFailure(ServerFailure error) {
                fail();
            }
        }).fire();
    }

    // Remove it when we're done..
    objectTypeRequest.delete(foundProxy).to(new Receiver<Boolean>() {

        @Override
        public void onSuccess(Boolean response) {
            System.out.println("onSuccess from delete.");
            assertTrue(response);
        }

        @Override
        public void onFailure(ServerFailure error) {
            fail();
        }
    });
    objectTypeRequest.fire();
}

これが私の質問です..編集がcreate()ではなくfind()に関連付けられている場合、編集を処理する最良の方法は何ですか? 検索を更新で連鎖させようとすると、foundProxy が null になり、更新されません。プロキシは、更新を実行できるようにするために、作成されたコンテキストにバインドされたままにする必要がありますか? 誰かがこれがどのように機能するかを説明したり、私が欠けているものを指摘するドキュメントを教えてくれたりしたら、私は感謝します. これは、テスト フレームワークがリクエストを処理する方法に関係している可能性はありますか? 私は以下を読んだので、何か見落としがあれば教えてください: tbroyer による素晴らしい説明

Google docs どんな助けでも大歓迎です。ありがとうございました!

4

1 に答える 1

18

RequestFactoryTest例については、GWTソースコードのをご覧ください。方法はあなた testChangedEdit()が書き込もうとしているものと似ています。メソッドを呼び出してから、find()メソッドで返されたプロキシを操作しonSuccess()ます。

ARequestContextは長寿命のオブジェクトではありません。呼び出されてから呼び出したときまでのみ有効ですfire()onFailure()またはonViolation()メソッドがで呼び出された場合にのみ再利用できますReceiver

EntityProxyまたはValueProxy返されるviaはReceiver.onSuccess()、サーバーデータのスナップショットを表します。RequestContextしたがって、プロキシは、を呼び出すことによってに関連付けられていない限り、不変edit()です。によって返されるプロキシRequestContext.create()は変更可能です。可変プロキシは常に正確に1つに関連付けられており、「ストリームを横断RequestContextする」ことはエラーです。可変プロキシのエラーではありません。re-edit()

このように機能する理由は、RequestFactoryクライアントがサーバーにデルタのみを送信できるようにするためです。find()デルタは、ドメインオブジェクトのメソッドを呼び出す(またはを使用する)ことにより、サーバー上の存続期間の長いエンティティに適用されますLocator。RequestContextは、基本的に、proxy.setFoo()呼び出しと1つ以上のRequest/InstanceRequest呼び出しのアキュムレータです。

一般的なガイドライン:

  • fire()メソッド呼び出しの存続期間を超える存続期間を持つオブジェクトのフィールドにRequestContextインスタンスを格納しないでください。
  • 同様に、編集可能EntityProxyまたはValueProxyインスタンスは、への呼び出しを超えて保持されるべきではありませんfire()
  • EntityProxyIdから返されたものは、新しく作成されたプロキシからでも無期限に保持EntityProxy.stableId() できます。このstableIdオブジェクトは、オブジェクトのキーとしての使用に適してMapおり、安定したオブジェクトIDセマンティクスを備えています(つまり、バージョンが異なる同じサーバードメインオブジェクトの2つのスナップショットは、同じ `EntityProxyId'を返します)。
  • のインスタンスはRequestFactory一度構築し、モジュールの存続期間中保持する必要があります。これは、構築コストが重要であるためです。
于 2011-04-12T22:31:30.350 に答える