Сбой RequestFactory с "UnexpectedException: нет RequestContext для операции LPZEK7DlYkoG1$NQ5MjHlmuRChk="

Не могли бы вы, ребята, помочь мне, почему у меня это исключение?

Я извлек прокси-запросы 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.

Поэтому, когда исключение выдается под отладчиком на сервере, я вижу этот экземпляр com.google.web.bindery.requestfactory.vm.impl.Deobfuscator имеет пустой operationData поле, которое инициализируется DeobfuscatorBuilder класс, сгенерированный инструментом аннотации RequestFactory.

Итак... Я декомпилировал этот класс и нашел это:

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");
  }
}

Он не генерировал токены для фабрики. Поэтому нет звонков Deobfuscator.Builder.withOperation из-за чего мой сервер не может найти контекст, когда звонки приходят от клиента.

Вопросы:

  • Почему RequestFactory Annotation Tool не генерирует токены для фабрики (операций)?
  • Как я могу это исправить?

2 ответа

Решение

Ну, это было довольно сложно... Но отладка в RF Annotation Tool помогла:)

Оказывается, у вас должны быть доменные классы, на которые вы ссылаетесь в @ServiceName в classpath обработчика аннотаций RF. Это создает проблему курицы и яйца. Вы должны скомпилировать SharedClasses модуль для компиляции основного модуля, но вы должны компилировать доменные классы из основного модуля для компиляции SharedClasses модуль.

Вот что я сделал:

  • Отключена обработка аннотаций RF для модуля SharedClasses.
  • В обработчике RF-аннотаций основного модуля я явно указал RF-фабрику, которая должна обрабатываться с использованием параметра rootOverride = com.blah.shared.factories.AdminRequestFactory

Это отстой, что я жестко закодировал полное имя класса в настройках проекта.

Если вы, ребята, знаете более элегантный метод, пожалуйста, дайте мне знать.

Я тоже столкнулся с той же проблемой. В основном у меня есть 3 модуля GWT 1. Основной модуль, а во втором модуле у меня есть requestFactory, классы домена сервера и значения прокси на стороне клиента. Я почти уверен, что ваше решение - это то, что мне нужно применить. Однако я запутался, как указать rootOverride на этапе сборки maven. Любые указатели в структуре pom.xml были бы чрезвычайно полезны.

Другие вопросы по тегам