1

你们能帮我解释为什么我有这个例外吗?

我将 RequestFactory 代理和上下文接口提取到单独的 jar 中,因此我可以在 GWT 客户端和 Android 客户端中使用它(详细信息在此处

不幸的是,RF 在第一次调用时就在服务器上引发了异常。例外是:

com.google.web.bindery.requestfactory.server.UnexpectedException: No RequestContext for operation LPZEK7DlYkoG1$NQ5MjHlmuRChk=
    at com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.die(ServiceLayerDecorator.java:216)
    at com.google.web.bindery.requestfactory.server.ResolverServiceLayer.resolveRequestContext(ResolverServiceLayer.java:154)

下面是我的工厂界面。正如你所看到的,我不得不替换Service注释,ServiceName因为我不想将所有带有 Guice 注入的自定义定位器编译为将在移动设备上运行的 jar。

public interface AdminRequestFactory extends RequestFactory
{
    // @Service(value = UserServiceDao.class, locator = InjectingServiceLocator.class)
    @ServiceName(value = "com.blah.courierApp.server.dao.UserServiceDao", locator = "com.blah.courierApp.server.inject.InjectingServiceLocator")
    public interface GaeUserServiceContext extends RequestContext
    {
        public Request<String> createLogoutURL(String destinationURL);
        public Request<GaeUser> getCurrentUser();
    }

    // @Service(value = OrderDao.class, locator = InjectingServiceLocator.class)
    @ServiceName(value = "com.blah.courierApp.server.dao.OrderDao", locator = "com.blah.courierApp.server.inject.InjectingServiceLocator")
    public interface OrderRequestContext extends RequestContext
    {
        Request<List<OrderProxy>> listAll();
        Request<Void> delete(Long id);
        Request<Void> createOrder(OrderProxy order);
        Request<OrderProxy> findOrderById(long id);
        Request<Void> updateOrderState(long id, StateType newStateType);
    }

    GaeUserServiceContext contextUserService();
    OrderRequestContext contextOrder();
}

当我编译它时,RF Annotation Tool 给出了以下警告:

Cannot fully validate context since domain type com.blah.courierApp.server.dao.UserServiceDao is not available.
You must run the ValidationTool as part of your server build process.
Add @SuppressWarnings("requestfactory") to dismiss.

So when the exception thrown under the debugger on the server I see that instance of com.google.web.bindery.requestfactory.vm.impl.Deobfuscator has empty operationData field which is being initialized by DeobfuscatorBuilder class that was generated by RequestFactory annotation tool.

So... I decompiled that class and found this:

public final class AdminRequestFactoryDeobfuscatorBuilder extends Deobfuscator.Builder
{
  public AdminRequestFactoryDeobfuscatorBuilder()
  {
    withRawTypeToken("w1Qg$YHpDaNcHrR5HZ$23y518nA=", "com.google.web.bindery.requestfactory.shared.EntityProxy");
    withRawTypeToken("8KVVbwaaAtl6KgQNlOTsLCp9TIU=", "com.google.web.bindery.requestfactory.shared.ValueProxy");
    withRawTypeToken("FXHD5YU0TiUl3uBaepdkYaowx9k=", "com.google.web.bindery.requestfactory.shared.BaseProxy");
    withRawTypeToken("5vjE9LUy$l0uvi4kMYpS3JA1WEE=", "com.blah.shared.model.GaeUser");
    withRawTypeToken("8KVVbwaaAtl6KgQNlOTsLCp9TIU=", "com.google.web.bindery.requestfactory.shared.ValueProxy");
    withRawTypeToken("5a7OV4PSV$1xemsooKLfEQ4g5yY=", "com.blah.shared.proxies.OrderProxy");
    withRawTypeToken("neR_xIhE5oZsc0HbnkAMa8A88yw=", "com.blah.shared.proxies.OrderStateProxy");
    withRawTypeToken("t6gMQWDROJnYvqYhNURV8pd$sn4=", "com.blah.shared.proxies.OrganizationProxy");
    withRawTypeToken("1o45xgS$5bIkBKF4wlR8oMw_FSo=", "com.blah.shared.proxies.PersonProxy");
    withRawTypeToken("FXHD5YU0TiUl3uBaepdkYaowx9k=", "com.google.web.bindery.requestfactory.shared.BaseProxy");
  }
}

It didn't generated tokens for factory. Therefore there are no calls to Deobfuscator.Builder.withOperation because of which my server can't find context when calls comes from the client.

Questions are:

  • Why doesn't RequestFactory Annotation Tool generate tokens for factory (operations) ?
  • How can I fix it ?
4

2 回答 2

1

Well, it was pretty tricky... But debugging in RF Annotation Tool helped :)

Turns out you have to have domain classes that you refer to in @ServiceName in classpath of RF Annotation Processor. It creates chicken-and-egg problem. You have to compile SharedClasses module to compile main module but you have to compile domain classes from main module to compile SharedClasses module.

Here is what I did:

  • Disabled RF annotation processing for SharedClasses module.
  • In RF annotation processor of main module I explicitly specified RF factory that has to be processed using parameter rootOverride = com.blah.shared.factories.AdminRequestFactory

It sucks that I have hardcoded full qualified class name in project settings though.

If you guys know more elegant method please let me know.

于 2012-04-17T09:11:55.763 回答
0

I too hit the same problem. Basically I have 3 GWT modules 1. Main module and in the second module I have the requestFactory, server domain classes and the client side proxy values. I am pretty much sure that your solution is what I need to put in place. However I am confused how to specify the rootOverride in the maven build phase. Any pointers in the structure of pom.xml would be immensely helpful.

于 2013-10-08T21:36:02.830 回答