Когда следует использовать RequestFactory vs GWT-RPC?

Я пытаюсь выяснить, должен ли я переносить свои вызовы gwt-rpc на новые запросы GWT2.1 RequestFactory.

Документация Google смутно упоминает, что RequestFactory - лучший способ связи между клиентом и сервером для "ориентированных на данные сервисов"

Что я могу отделить от документации, так это то, что есть новый класс Proxy, который упрощает связь (вы не проходите назад и вперед по фактическому объекту, а просто через прокси-сервер, поэтому он легче и проще в управлении)

Является ли это целым или не хватает чего-то другого в общей картине?

Ответ 1

Большая разница между GWT RPC и RequestFactory заключается в том, что система RPC является "RPC-by-specific-type", а RequestFactory - "RPC-by-interface".

RPC удобнее начинать с того, что вы пишете меньше строк кода и используете тот же класс как на клиенте, так и на сервере. Вы можете создать класс Person с кучей геттеров и сеттеров и, возможно, простую бизнес-логику для дальнейшего нарезки и обработки данных в объекте Person. Это работает очень хорошо, пока вы не захотите иметь код, специфичный для сервера, а не GWT-совместимый код внутри вашего класса. Поскольку система RPC основана на том же конкретном типе как на клиенте, так и на сервере, вы можете столкнуться со стеной сложности, основанной на возможностях вашего клиента GWT.

Чтобы обойти использование несовместимого кода, многие пользователи завершают создание peer PersonDTO, который затеняет реальный объект Person, используемый на сервере. PersonDTO просто имеет подмножество геттеров и сеттеров на стороне сервера, "домен", Person объект. Теперь вам нужно написать код, который объединяет данные между объектами Person и PersonDTO и всеми другими типами объектов, которые вы хотите передать клиенту.

RequestFactory начинается с предположения, что ваши объекты домена не будут совместимы с GWT. Вы просто объявляете свойства, которые должны считываться и записываться кодом клиента в интерфейсе Proxy, а серверные компоненты RequestFactory заботятся о маршалировании данных и использовании ваших методов обслуживания. Для приложений, которые имеют четко определенную концепцию "Объекты" или "Объекты с идентификатором и версией", тип EntityProxy используется для отображения постоянной семантики данных ваших данных на клиентский код. Простые объекты отображаются с использованием типа ValueProxy.

С помощью RequestFactory вы оплачиваете авансовые затраты на запуск для более сложных систем, чем GWT RPC легко поддерживает. RequestFactory ServiceLayer предоставляет значительно больше крючков для настройки своего поведения, добавляя ServiceLayerDecorator экземпляры.

Ответ 2

Я прошел переход от RPC к RF. Сначала я должен сказать, что мой опыт ограничен в этом, я использовал столько EntityProxies, сколько 0.

Преимущества GWT RPC:

  • Очень легко настроить, понять и научиться!
  • Те же объекты на основе классов используются на клиенте и на сервере.
  • Этот подход экономит массу кода.
  • Идеально, когда одни и те же объекты модели (и POJOS) используются как на клиенте, так и на сервере, POJO == МОДЕЛЬ OBJECTs == DTOs
  • Легко перемещать файлы с сервера на клиент.
  • Легко разделить реализацию общей логики между клиентом и сервером (это может оказаться критическим недостатком, когда вам нужна другая логика).

Недостатки GWT RPC:

  • Невозможно реализовать другую реализацию некоторых методов для сервера и клиента, например. вам может потребоваться использовать разные рамки ведения журнала на клиенте и сервере или другой метод equals.
  • Реализация REALY BAD, которая не является расширяемой: большинство функциональных возможностей сервера реализовано как статические методы в классе RPC. ЧТО ДЕЙСТВИТЕЛЬНО ПРОСИТ.
  • например. Невозможно включить обфускацию ошибок на стороне сервера.
  • Некоторые проблемы безопасности XSS, которые не совсем элегантно разрешимы, см. в документах (я не уверен, является ли это более элегантным для RequestFactory)

Недостатки RequestFactory:

  • ДЕЙСТВИТЕЛЬНО ТРУДНО, чтобы понять из официального документа, какова его заслуга! Он начинается прямо на полностью вводящем в заблуждение терминах PROXIES - это фактически DTOs РФ, которые создаются RF автоматически. Прокси определяются интерфейсами, например. @ProxyFor (Journal.class). IDE проверяет, существуют ли соответствующие методы в журнале. Так много для отображения.
  • RF не будет делать для вас много общего с клиентом и сервером, потому что
  • На клиенте вам нужно преобразовать "PROXIES" в объекты вашего домена клиента и наоборот. Это совершенно смешно. Это можно сделать в нескольких строках кода декларативно, но там НЕ ПОДДЕРЖИВАЙТЕ ЭТО! Если бы только мы могли более элегантно сопоставлять наши объекты домена с прокси-серверами, что-то вроде JavaScript-метода JSON.stringify(..,) является MISSING в RF toolbox.
  • Не забывайте, что вы также несете ответственность за установку передаваемых свойств объектов домена на прокси и т.д. Рекурсивно.
  • ПРАВИЛЬНОЕ ОБОРОТНОЕ ОБРАЩЕНИЕ на сервере и - Трассировки стека по умолчанию опущены на сервере, и вы получаете пустые бесполезные исключения на клиенте. Даже когда я устанавливаю пользовательский обработчик ошибок, мне не удалось добраться до трасс низкого уровня! Грозный.
  • Некоторые незначительные ошибки в поддержке IDE и в других местах. Я подал два запроса на ошибку, которые были приняты. Для Эйнштейна не нужно было выяснять, что на самом деле это были ошибки.
  • ДОКУМЕНТАЦИЯ. Как я уже говорил, прокси должны быть лучше объяснены, этот термин относится к MISLEADING. Для основных распространенных проблем, которые я решал, DOCS НЕОБХОДИМО. Другим примером недопонимания от DOC является подключение аннотаций JPA к РФ. Из кратких документов видно, что они любят играть вместе, и да, есть соответствующий вопрос в StackOverflow. Я рекомендую забыть любое соединение "JPA", прежде чем понимать RF.

Преимущества RequestFactory

  • Отличная поддержка форума.
  • Поддержка IDE довольно хороша (но не является преимуществом в отличие от RPC)
  • Гибкость реализации вашего клиента и сервера (свободная связь)
  • Необычные вещи, связанные с EntityProxies, помимо простых DTO - кэширование, частичные обновления, очень полезные для мобильных устройств.
  • Вы можете использовать ValueProxies в качестве простейшей замены для DTO (но вы должны сами делать все не очень фантастические преобразования).
  • Поддержка Bean Проверки JSR-303.

Учитывая другие недостатки GWT в целом:

  • Невозможно выполнить интеграционные тесты (код клиента GWT + удаленный сервер) с предоставленной поддержкой JUnit <= all JSNI необходимо издеваться (например, localStorage), проблема SOP.

  • Нет поддержки для настройки тестирования - безгласный браузер + удаленный сервер <= нет простого тестирования без головок для GWT, SOP.

  • Да, можно запускать тесты интеграции селена (но это не то, что я хочу)

  • JSNI очень силен, но на тех блестящих переговорах, которые они дают на конференциях, они мало говорят о том, что в написании кодексов JSNI есть некоторые правила. Опять же, выяснение того, как написать простой обратный вызов, было задачей истинного исследователя.

Таким образом, переход от GWT RPC к RequestFactory далек от ситуации WIN-WIN,  когда RPC в основном соответствует вашим потребностям. Вы в конечном итоге пишете тонны конверсий с объектов домена клиента на прокси и наоборот. Но вы получаете некоторую гибкость и надежность своего решения. И поддержка на форуме отлично, в субботу тоже!

Учитывая все преимущества и недостатки, о которых я только что упомянул, очень важно заранее подумать, действительно ли какой-либо из этих подходов улучшает ваше решение и вашу разработку без больших компромиссов.

Ответ 3

Я нахожу идею создания классов прокси для всех моих сущностей, довольно раздражающих. Мои Hibernate/JPA pojos автоматически генерируются из модели базы данных. Почему теперь мне нужно создать второе зеркало для RPC? У нас есть хорошая "эстинационная" структура, которая заботится о "де-гибернации" pojos.

Кроме того, идея определения интерфейсов служб, которые не совсем реализуют серверную службу в качестве java-контракта, но реализуют методы, - мне очень нравится J2EE 1.x/2.x.

Ответ 4

В отличие от RequestFactory, которая имеет плохую работу по обработке ошибок и тестированию (поскольку она обрабатывает большинство материалов под капотом GWT), RPC позволяет использовать более ориентированный на обслуживание подход. RequestFactory реализует более современный подход, основанный на использовании инъекций, который может обеспечить полезный подход, если вам нужно вызвать сложные полиморфные структуры данных. При использовании RPC ваши структуры данных должны быть более плоскими, так как это позволит вашим утилитам маршалинга переводить между вашими json/xml и java-моделями. Использование RPC также позволяет реализовать более надежную архитектуру, как указано в разделе gwt dev на веб-сайте Google.

"Простое развертывание клиента/сервера

Первый и самый простой способ думать о определениях сервисов - рассматривать их как ваше приложение целиком. С этой точки зрения клиентский код является вашим "интерфейсом", и все служебные коды, которые выполняются на сервере, являются "обратными". Если вы примете такой подход, ваши сервисные реализации будут иметь тенденцию быть более универсальными API-интерфейсами, которые не тесно связаны с одним конкретным приложением. Определения служб, скорее всего, будут напрямую обращаться к базам данных через JDBC или Hibernate или даже файлы в файловой системе сервера. Для многих приложений это представление подходит, и оно может быть очень эффективным, поскольку оно уменьшает количество уровней.

Развертывание многоуровневого уровня

В более сложных многоуровневых архитектурах ваши определения службы GWT могут быть просто легкими шлюзами, которые обращаются к серверным средам сервера, таким как серверы J2EE. С этой точки зрения ваши сервисы можно рассматривать как "половину сервера" вашего пользовательского интерфейса приложения. Вместо того, чтобы быть универсальным, службы создаются для конкретных потребностей вашего пользовательского интерфейса. Ваши услуги становятся "интерфейсом" к классам "back end", которые записываются путем сшивания вызовов на более общий серверный уровень служб, реализованный, например, как кластер серверов J2EE. Такая архитектура подходит, если вам требуется, чтобы ваши серверные службы запускались на физически отдельном компьютере с вашего HTTP-сервера.

Также обратите внимание, что для настройки единственной службы RequestFactory требуется создание примерно 6 классов Java, где для RPC требуется только 3. Больше кода == больше ошибок и сложности в моей книге.

RequestFactory также имеет немного больше служебных данных во время обработки запроса, так как он должен сортировать сериализацию между прокси данными и фактическими java-моделями. Этот добавленный интерфейс добавляет дополнительные циклы обработки, которые могут реально складываться в корпоративной или производственной среде.

Я также не считаю, что службы RequestFactory сериализуются как службы RPC.

В целом после использования обоих в течение некоторого времени я всегда обращаюсь к RPC как к более легким, легче тестировать и отлаживать, а затем быстрее использовать RequestFactory. Хотя RequestFactory может быть более элегантным и расширяемым, то его часть счетчика RPC. Добавленная сложность не делает его лучшим инструментом.

Я считаю, что лучшей архитектурой является использование двух веб-приложений, одного клиента и одного сервера. Сервер представляет собой простой легкий универсальный java webapp, который использует библиотеку servlet.jar. Клиент - GWT. Вы делаете запрос RESTful через GWT-RPC на серверную веб-приложение клиента. Серверная сторона клиента - это всего лишь пропуск, хотя клиент http-apache, который использует постоянный туннель в обработчике запросов, который вы используете как один сервлет в веб-приложении сервлетов сервера. Веб-приложение сервлета должно содержать ваш прикладной уровень базы данных (hibernate, cayenne, sql и т.д.). Это позволяет полностью развести модели объектов базы данных с фактическим клиентом, предоставляя гораздо более расширяемый и надежный способ разработки и unit test ваше приложение, Конечно, для этого требуется бит бит начального времени установки, но в конце вы можете создать динамический запрос factory, сидящий за пределами GWT. Это позволяет использовать лучшее из обоих миров. Не говоря уже о возможности тестирования и внесения изменений на серверную сторону без необходимости компиляции или сборки клиента gwt.

Ответ 5

Я думаю, что это действительно полезно, если у вас тяжелое pojo на стороне клиента, например, если вы используете объекты Hibernate или JPA. Мы приняли другое решение, используя структуру сохранения в стиле Django с очень легкими объектами.

Ответ 6

Единственное предостережение, которое я бы поставил, заключается в том, что RequestFactory использует двоичную передачу данных (например, deRPC?), а не обычный GWT-RPC.

Это имеет значение только в том случае, если вы проводите тяжелые испытания с помощью SyncProxy, Jmeter, Fiddler или любого подобного инструмента, который может читать/оценивать содержимое HTTP-запроса/ответа (например, GWT-RPC), но будет более сложным с deRPC или RequestFactory.

Ответ 7

У нас есть очень большая реализация GWT-RPC в нашем проекте. На самом деле у нас есть 50 сервисных интерфейсов со многими методами каждый, и у нас есть проблемы с размером TypeSerializers, сгенерированным компилятором, что делает наш JS-код огромным. Поэтому мы анализируем движение в направлении RequestFactory. Я читал пару дней, копаясь в Интернете и пытаясь найти то, что делают другие люди. Самый важный недостаток, который я видел, и, может быть, я ошибаюсь, заключается в том, что с помощью RequestFactory вы больше не контролируете связь между объектами сервера домена и вашими клиентскими. Нам нужно применять шаблон загрузки/сохранения контролируемым образом. Я имею в виду, например, клиент получает весь объектный граф объектов, принадлежащих к определенной транзакции, делает свои обновления, и они отправляют всю информацию обратно на сервер. Сервер будет отвечать за проверку, сравнить старые с новыми значениями и сделать упорство. Если 2 пользователя с разных сайтов получают одну и ту же транзакцию и выполняют некоторые обновления, результирующая транзакция не должна быть объединенной. В моем сценарии одно из обновлений должно завершиться неудачно. Я не вижу, что RequestFactory помогает поддерживать этот вид обработки.

Отношения Даниэль

Ответ 8

Справедливости ради стоит сказать, что при рассмотрении ограниченного приложения MIS, скажем, с 10-20 CRUD'able бизнес-объектами и каждый с ~ 1-10 свойствами, это действительно к личным предпочтениям, с каким маршрутом идти?

Если да, то, возможно, проецирование того, как ваше приложение будет масштабироваться, может стать ключом к выбору вашего маршрута GWT RPC или RequestFactory:

  • Ожидается, что мое приложение останется с этим относительно ограниченным числом объектов, но будет увеличиваться в увеличении их количества. 10-20 объектов * 100 000 записей.

  • Мое приложение будет значительно увеличиваться в широте сущностей, но относительные числа, связанные с каждым из них, будут оставаться низкими. 5000 объектов * 100 записей.

  • Ожидается, что мое приложение останется с этим относительно ограниченным числом объектов И останется в относительно низком числе, например. 10-20 объектов * 100 записей

В моем случае я нахожусь в самой начальной точке, пытаясь принять это решение. Дальше осложняется необходимость изменения архитектуры клиентской стороны клиентского интерфейса, а также выбор транспорта. Мой предыдущий (значительно) широкомасштабный пользовательский интерфейс GWT использовал библиотеку Hmvc4Gwt, которая была заменена средствами GWT MVP.