阐明GWT RequestFactory和RequestContext的工作原理

时间:2011-04-12 21:31:13

标签: gwt requestfactory requestcontext

我正在尝试将RequestFactory和Editor框架实现到我的应用程序中。我甚至在研究了论坛,谷歌开发者论坛以及其他人之后发现,有些基本的东西我不理解将RequestContext与RequestFactory一起使用。这是我的情景:
我有一个简单的实体,它有三个字段,id,version,描述名为CmsObjectType。我有一个对应的EntityProxy和一个CmsObjectTypeServiceDAO与我的CRUD操作。我还实现了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();
}
}

当我创建一个新的请求上下文并链接我的方法调用create,update和delete然后调用fire()时,它在上面的测试中没有问题。但是,如果我尝试通过调用方法单独执行这些调用然后fire()我会遇到问题。我可以调用create(),Receiver返回新创建的实体的id,然后我使用该id调用find(id),然后我返回新创建的实体。到目前为止一切正常。但是,这是我感到困惑的地方..如果我尝试使用查找(id)中Receiver的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,并且事情不会更新。代理必须保持绑定到创建它们的上下文,以便能够对它们执行更新吗?如果有人可以解释这是如何工作的,或者指出一些文件,指出我错过了什么,我将不胜感激。这是否可能与测试框架处理请求的方式有关? 我已阅读以下内容,如果我遗漏了其中的内容,请告诉我: Great description by tbroyer

Google docs 任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:18)

请查看GWT源代码中的RequestFactoryTest以获取示例。 testChangedEdit()方法类似于您尝试编写的方法。它调用find()方法,然后在onSuccess()方法中对返回的代理进行操作。

RequestContext不是长期存在的对象。只有当您在其上调用fire()时,它才会被调用。只有在onFailure()中调用onViolation()Receiver方法时,才能重复使用它。

通过EntityProxy返回的ValueProxyReceiver.onSuccess()表示服务器数据的快照。因此,代理是不可变的,除非它通过调用RequestContextedit()相关联。 RequestContext.create()返回的代理是可变的。可变代理始终只与一个RequestContext相关联,而“cross the streams”则出错。 re-edit()可变代理不是错误。

它以这种方式工作的原因是允许RequestFactory客户端仅向服务器发送增量。通过调用域对象的find()方法(或使用Locator),将增量应用于服务器上的长期实体。 RequestContext本质上是proxy.setFoo()个调用和一个或多个Request / InstanceRequest个调用的累加器。

一般准则:

  • 不要将RequestContext实例存储在生命周期超过fire()方法调用的对象的字段中。
  • 同样,除了EntityProxy的调用之外,不应保留可编辑的ValueProxyfire()个实例。
  • EntityProxyId 返回的EntityProxy.stableId()可以无限期保留,即使是来自新创建的代理也是如此。 stableId对象适合用作Map对象中的键,并具有稳定的对象标识语义(即具有不同版本的同一服务器域对象的两个快照将返回相同的`EntityProxyId')。
  • RequestFactory的实例应该构建一次,并在模块的生命周期内保留,因为它们具有非常重要的构建成本。