阐明GWT RequestFactory和RequestContext的工作原理

mcf*_*far 5 gwt requestcontext requestfactory

我正在尝试将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;
}
Run Code Online (Sandbox Code Playgroud)

}

考试:

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();
}
}
Run Code Online (Sandbox Code Playgroud)

当我创建一个新的请求上下文并链接我的方法调用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();
}
Run Code Online (Sandbox Code Playgroud)

以下是我的问题..如果编辑没有与create()相关但是使用find(),那么处理编辑的最佳方法是什么?如果我尝试使用更新链接查找,我的foundProxy为null,并且事情不会更新.代理必须保持绑定到创建它们的上下文,以便能够对它们执行更新吗?如果有人可以解释这是如何工作的,或者指出一些文件,指出我错过了什么,我将不胜感激.这是否可能与测试框架处理请求的方式有关?我已阅读以下内容,如果我遗漏了其中的内容,请告诉我: tbroyer的精彩描述

Google文档 任何帮助将不胜感激.谢谢!

Bob*_*obV 18

请查看RequestFactoryTestGWT源代码中的示例.该 testChangedEdit()方法类似于您尝试编写的方法.它调用一个find()方法,然后对onSuccess()方法中返回的代理进行操作.

A RequestContext不是一个长期存在的对象.它仅在您呼叫fire()它时被呼叫时才有效.只有在您的调用中调用onFailure()or onViolation()方法时才可以重复使用它Receiver.

一个EntityProxyValueProxy经由返回Receiver.onSuccess()表示服务器数据的快照.因此,代理是不可变的,除非它与RequestContext通过调用相关联edit().返回的代理RequestContext.create()是可变的.可变代理总是与一个相关联,RequestContext并且" 跨流 " 是错误.这对re-edit()可变代理来说不是错误.

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

一般准则:

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