Когда я должен использовать RequestFactory против GWT-RPC?
Я пытаюсь выяснить, нужно ли перенести мои вызовы gwt-rpc на новые клиентские лицензии GWT2.1.
В документации Google смутно упоминается, что RequestFactory - лучший способ взаимодействия клиент-сервер для "сервисов, ориентированных на данные".
Что я могу извлечь из документации, так это то, что есть новый класс Proxy, который упрощает взаимодействие (вы не передаете реальную сущность туда-сюда, а просто прокси, так что она легче и легче управляется)
В этом весь смысл или я что-то упускаю из общей картины?
8 ответов
Большая разница между GWT RPC и RequestFactory заключается в том, что система RPC является "RPC-by-concrete-type", а RequestFactory является "RPC-by-interface".
С RPC удобнее начинать, потому что вы пишете меньше строк кода и используете один и тот же класс как на клиенте, так и на сервере. Вы можете создать Person
класс с кучей геттеров и сеттеров и, возможно, некоторой простой бизнес-логики для дальнейшей нарезки и нарезки данных в Person
объект. Это работает довольно хорошо, пока вы не захотите иметь в своем классе специфичный для сервера, не GWT-совместимый код. Поскольку система RPC основана на наличии одного и того же конкретного типа как на клиенте, так и на сервере, вы можете столкнуться со сложностью, основанной на возможностях вашего клиента GWT.
Чтобы обойти использование несовместимого кода, многие пользователи создают одноранговый PersonDTO
это затмевает реальное Person
объект, используемый на сервере. PersonDTO
просто имеет подмножество геттеров и сеттеров на стороне сервера, "домен", Person
объект. Теперь вам нужно написать код, который собирает данные между Person
а также PersonDTO
объект и все другие типы объектов, которые вы хотите передать клиенту.
RequestFactory начинается с предположения, что ваши доменные объекты не будут GWT-совместимыми. Вы просто объявляете свойства, которые должны быть прочитаны и записаны клиентским кодом в интерфейсе Proxy, а компоненты сервера RequestFactory позаботятся о маршалинге данных и вызове ваших методов обслуживания. Для приложений, которые имеют четко определенную концепцию "сущностей" или "объектов с идентичностью и версией", EntityProxy
Тип используется для предоставления клиенту кода постоянной семантики идентификаторов ваших данных. Простые объекты отображаются с помощью ValueProxy
тип.
С RequestFactory вы оплачиваете первоначальную стоимость запуска для размещения более сложных систем, которые GWT RPC легко поддерживает. RequestFactory-х ServiceLayer
предоставляет значительно больше хуков для настройки его поведения, добавляя ServiceLayerDecorator
экземпляров.
Я прошел переход от RPC к RF. Сначала я должен сказать, что мой опыт ограничен в этом, я использовал столько EntityProxies, сколько 0.
Преимущества GWT RPC:
- Это очень легко настроить, понять и узнать!
- Одинаковые объекты на основе классов используются на клиенте и на сервере.
- Такой подход экономит тонны кода.
- Идеально, когда одни и те же объекты модели (и POJOS) используются на клиенте и сервере, POJOs == МОДЕЛЬНЫЕ ОБЪЕКТЫ == DTO
- Легко перемещать вещи с сервера на клиент.
- Легко делиться реализацией общей логики между клиентом и сервером (это может стать критическим недостатком, когда вам нужна другая логика).
Недостатки GWT RPC:
- Невозможно по-разному реализовать некоторые методы для сервера и клиента, например, вам может потребоваться использовать разные рамки ведения журналов на клиенте и сервере или другой метод equals.
- Реально плохая реализация, которая не может быть расширена в дальнейшем: большая часть функциональности сервера реализована в виде статических методов в классе RPC. ЭТО ДЕЙСТВИТЕЛЬНО ОТСУТСТВУЕТ.
- Например, невозможно добавить обфускацию ошибок на стороне сервера.
- Некоторые проблемы безопасности XSS, которые не совсем элегантно разрешимы, см. В документации (я не уверен, что это более элегантно для RequestFactory)
Недостатки RequestFactory:
- ДЕЙСТВИТЕЛЬНО ТРУДНО понять из официального документа, в чем его заслуга! Он начинается прямо с вводящего в заблуждение термина ПРОКСИ - на самом деле это DTO РФ, которые создаются РФ автоматически. Прокси определяются интерфейсами, например, @ProxyFor(Journal.class). IDE проверяет, существуют ли соответствующие методы в журнале. Так много для картирования.
- RF не будет делать много для вас с точки зрения общности клиента и сервера, потому что
- На клиенте вам необходимо преобразовать "ПРОКСИ" в объекты вашего клиентского домена и наоборот. Это совершенно нелепо. Это можно сделать в несколько строк кода декларативно, но НИКАКОЙ ПОДДЕРЖКИ ДЛЯ ЭТОГО! Если бы мы только могли более элегантно отобразить наши доменные объекты на прокси-серверы, что-то вроде JavaScript-метода JSON.stringify(..,,) - это ПРОПУСК в панели инструментов RF.
- Не забывайте, что вы также несете ответственность за установку передаваемых свойств ваших доменных объектов для прокси и т. Д. Рекурсивно.
- ОБРАЩЕНИЕ С ОШИБКАМИ НА ПЛОЩАДКЕ на сервере и - Трассировки стека по умолчанию на сервере опущены, и вы получаете пустые бесполезные исключения на клиенте. Даже когда я установил собственный обработчик ошибок, я не смог получить низкоуровневые трассировки стека! Грозный.
- Некоторые незначительные ошибки в поддержке IDE и в других местах. Я подал два запроса на ошибку, которые были приняты. Не Эйнштейн был нужен, чтобы понять, что это на самом деле ошибки.
- ДОКУМЕНТАЦИЯ ОТСЕКАЕТ. Как я уже упоминал, прокси лучше объяснить, этот термин - НЕПРАВИЛЬНЫЙ. Для основных общих проблем, которые я решал, DOCS IS бесполезен. Другим примером недоразумения со стороны DOC является подключение аннотаций JPA к RF. Из кратких документов видно, что они вроде играют вместе, и да, есть соответствующий вопрос по Stackru. Я рекомендую забыть любое JPA-соединение перед пониманием RF.
Преимущества RequestFactory
- Отличная поддержка форума.
- Поддержка IDE довольно хорошая (но не является преимуществом по сравнению с RPC)
- Гибкость реализации вашего клиента и сервера (слабая связь)
- Необычные вещи, связанные с EntityProxies, помимо простых DTO - кэширование, частичные обновления, очень полезные для мобильных устройств.
- Вы можете использовать ValueProxies как простейшую замену DTO (но вы должны делать все не так уж и необычно).
- Поддержка проверки бина JSR-303.
Учитывая другие недостатки GWT в целом:
Невозможно выполнить интеграционные тесты (клиентский код GWT + удаленный сервер) с предоставленной поддержкой JUnit <= все JSNI должны быть проверены (например, localStorage), SOP является проблемой.
Нет поддержки для настройки тестирования - безголовый браузер + удаленный сервер <= нет простого безголового тестирования GWT, SOP.
Да, можно запускать интеграционные тесты селена (но это не то, что я хочу)
JSNI очень мощен, но на тех блестящих выступлениях, которые они проводят на конференциях, они не много говорят о том, что написание кодов JSNI имеет некоторые правила. Опять же, выяснить, как написать простой обратный вызов, было задачей настоящего исследователя.
Таким образом, переход от GWT RPC к RequestFactory далек от ситуации WIN-WIN, когда RPC в основном соответствует вашим потребностям. Вы заканчиваете тем, что пишете тонны преобразований из объектов клиентского домена в прокси и наоборот. Но вы получаете некоторую гибкость и надежность вашего решения. И поддержка на форуме отличная, в субботу тоже!
Принимая во внимание все преимущества и недостатки, которые я только что упомянул, стоит заранее подумать, действительно ли какой-либо из этих подходов приведет к улучшению вашего решения и вашей разработки без значительных компромиссов.
Я нахожу идею создания прокси-классов для всех моих сущностей довольно раздражающей. Мои pojos Hibernate/JPA автоматически генерируются из модели базы данных. Зачем мне сейчас создавать второе зеркало из них для RPC? У нас есть приятная структура "эстимации", которая заботится о "де-гибернации" pojos.
Кроме того, идея определения интерфейсов служб, которые не совсем реализуют службу на стороне сервера в качестве java-контракта, но реализуют методы, звучит для меня очень J2EE 1.x/2.x.
В отличие от RequestFactory, который имеет плохие возможности обработки ошибок и тестирования (поскольку он обрабатывает большую часть содержимого GWT), RPC позволяет использовать более ориентированный на сервис подход. RequestFactory реализует более современный подход в стиле внедрения зависимостей, который может предоставить полезный подход, если вам нужно вызывать сложные полиморфные структуры данных. При использовании RPC ваши структуры данных должны быть более плоскими, поскольку это позволит вашим утилитам маршалинга переводить между вашими моделями json/xml и java. Использование RPC также позволяет реализовать более надежную архитектуру, как указано в разделе gwt dev на веб-сайте Google.
"Простое развертывание клиента / сервера
Первый и самый простой способ думать об определениях сервисов - это рассматривать их как весь бэкэнд вашего приложения. С этой точки зрения клиентский код - это ваш "передний конец", а весь служебный код, выполняемый на сервере, является "задним числом". Если вы воспользуетесь этим подходом, ваши реализации служб будут иметь тенденцию быть более универсальными API, которые не тесно связаны с одним конкретным приложением. Ваши определения служб, скорее всего, будут напрямую обращаться к базам данных через JDBC или Hibernate или даже файлы в файловой системе сервера. Для многих приложений это представление подходит, и оно может быть очень эффективным, поскольку оно уменьшает количество уровней.
Многоуровневое развертывание
В более сложных многоуровневых архитектурах ваши определения служб GWT могут быть просто облегченными шлюзами, которые обращаются к средам фоновых серверов, таким как серверы J2EE. С этой точки зрения ваши сервисы могут рассматриваться как "серверная половина" пользовательского интерфейса вашего приложения. Вместо того, чтобы быть универсальными, сервисы создаются для конкретных потребностей вашего пользовательского интерфейса. Ваши сервисы становятся "интерфейсными" для "серверных" классов, которые пишутся путем соединения вызовов к более общему фоновому уровню сервисов, реализованному, например, в виде кластера серверов J2EE. Этот тип архитектуры подходит, если вы хотите, чтобы ваши серверные службы работали на физически отдельном компьютере от вашего HTTP-сервера ".
Также обратите внимание, что для настройки одного сервиса RequestFactory требуется создать около 6 или около того классов Java, в то время как для RPC требуется только 3. Больше кода == больше ошибок и сложности в моей книге.
RequestFactory также имеет немного больше накладных расходов во время обработки запроса, поскольку он должен упорядочить сериализацию между прокси-серверами данных и фактическими моделями Java. Этот добавленный интерфейс добавляет дополнительные циклы обработки, которые действительно могут накапливаться в корпоративной или производственной среде.
Я также не верю, что сервисы RequestFactory являются сериализацией, как сервисы RPC.
В общем, после того, как я использую оба в течение некоторого времени, я всегда использую RPC как более легкий, более легкий для тестирования и отладки и более быстрый, чем с помощью RequestFactory. Хотя RequestFactory может быть более элегантным и расширяемым, чем его контрпрограмма RPC. Добавленная сложность не делает его лучшим необходимым инструментом.
Мое мнение таково, что лучшей архитектурой является использование двух веб-приложений, одного клиента и одного сервера. Сервер представляет собой простое облегченное универсальное Java-приложение, использующее библиотеку servlet.jar. Клиент GWT. Вы делаете RESTful-запрос через GWT-RPC на стороне сервера клиентского веб-приложения. Серверная часть клиента - это всего лишь проход по клиенту apache http, который использует постоянный туннель в обработчик запросов, который вы используете как отдельный сервлет в веб-приложении сервлета сервера. Веб-приложение сервлета должно содержать уровень приложения базы данных (hibernate, cayenne, sql и т. Д.). Это позволяет полностью отделить объектные модели базы данных от реального клиента, предоставляя гораздо более расширяемый и надежный способ разработки и модульного тестирования вашего приложения. Конечно, это требует немного начального времени установки, но, в конце концов, позволяет вам создать фабрику динамических запросов вне GWT. Это позволяет вам использовать лучшее из обоих миров. Не говоря уже о возможности тестирования и внесения изменений на стороне сервера без необходимости компиляции или сборки клиента gwt.
Единственное предостережение, которое я хотел бы добавить, заключается в том, что RequestFactory использует передачу двоичных данных (может быть, deRPC?), А не обычный GWT-RPC.
Это имеет значение, только если вы проводите интенсивное тестирование с SyncProxy, Jmeter, Fiddler или любым подобным инструментом, который может считывать / оценивать содержимое HTTP-запроса / ответа (например, GWT-RPC), но будет более сложным с deRPC или RequestFactory.
Я думаю, что это действительно полезно, если у вас много приложений на стороне клиента, например, если вы используете объекты Hibernate или JPA. Мы приняли другое решение, используя постоянную среду стиля Django с очень легкими объектами.
У нас очень большая реализация GWT-RPC в нашем проекте. На самом деле у нас есть 50 сервисных интерфейсов с множеством методов каждый, и у нас есть проблемы с размером TypeSerializer, сгенерированным компилятором, который превращает наш JS-код в огромный. Поэтому мы анализируем движение к RequestFactory. Я был прочитан в течение нескольких дней, копаясь в Интернете и пытаясь найти то, что делают другие люди. Самый важный недостаток, который я увидел, и, возможно, я мог ошибаться, заключается в том, что с RequestFactory вы больше не управляете связью между объектами вашего домена сервера и объектами вашего клиента. Нам нужно применить шаблон загрузки / сохранения контролируемым образом. Я имею в виду, например, что клиент получает целый граф объектов, относящихся к конкретной транзакции, выполняет его обновления и отправляет все обратно на сервер. Сервер будет отвечать за проверку, сравнивать старые с новыми значениями и делать упорство. Если 2 пользователя с разных сайтов получают одну и ту же транзакцию и выполняют некоторые обновления, итоговая транзакция не должна быть слитой. В моем сценарии должно произойти сбой одного из обновлений. Я не вижу, чтобы RequestFactory помогал поддерживать такую обработку.
С уважением, Даниэль
Справедливо ли сказать, что при рассмотрении ограниченного MIS-приложения, скажем, с 10-20 CRUD-совместимыми бизнес-объектами и каждым с ~1-10 свойствами, что на самом деле все зависит от личных предпочтений, какой путь выбрать?
Если это так, то, возможно, проектирование того, как ваше приложение будет масштабироваться, может стать ключом при выборе маршрута GWT RPC или RequestFactory:
Ожидается, что мое заявление останется с этим относительно ограниченным числом объектов, но значительно увеличится с точки зрения их количества. 10-20 объектов * 100 000 записей.
Мое приложение будет значительно увеличиваться в широте сущностей, но относительные числа участвующих будут оставаться низкими. 5000 объектов * 100 записей.
Ожидается, что мое приложение останется с этим относительно ограниченным числом объектов И останется в относительно небольшом количестве, например, 10-20 объектов * 100 записей
В моем случае я нахожусь в самом начале попытки принять это решение. Еще более усложняется изменением архитектуры клиентского интерфейса пользовательского интерфейса, а также выбором транспорта. В моем предыдущем (значительно) крупномасштабном пользовательском интерфейсе GWT использовалась библиотека Hmvc4Gwt, которая была заменена средствами GWT MVP.