¿Cuándo debería usar RequestFactory vs GWT-RPC?

87

Estoy tratando de averiguar si debo migrar mis llamadas gwt-rpc a las nuevas llamadas RequestFactory de GWT2.1.

La documentación de Google menciona vagamente que RequestFactory es un mejor método de comunicación cliente-servidor para "servicios orientados a datos".

Lo que puedo extraer de la documentación es que hay una nueva clase de Proxy que simplifica la comunicación (no pasa de un lado a otro la entidad real, sino solo el proxy, por lo que es más liviano y más fácil de administrar)

¿Es ese el punto o me estoy perdiendo algo más en el panorama general?

Daghan ---
fuente
8
¡Sí, esta pregunta está vinculada desde la guía de desarrollo oficial de gwt !
törzsmókus

Respuestas:

73

La gran diferencia entre GWT RPC y RequestFactory es que el sistema RPC es "RPC-by-concrete-type" mientras que RequestFactory es "RPC-by-interface".

RPC es más conveniente para comenzar, porque escribe menos líneas de código y usa la misma clase tanto en el cliente como en el servidor. Puede crear una Personclase con un grupo de captadores y definidores y tal vez alguna lógica comercial simple para seguir dividiendo y dividiendo los datos en el Personobjeto. Esto funciona bastante bien hasta que termina queriendo tener código específico del servidor, no compatible con GWT, dentro de su clase. Debido a que el sistema RPC se basa en tener el mismo tipo concreto tanto en el cliente como en el servidor, puede encontrar un muro de complejidad en función de las capacidades de su cliente GWT.

Para evitar el uso de código incompatible, muchos usuarios terminan creando un par PersonDTOque eclipsa el Personobjeto real utilizado en el servidor. El PersonDTOsólo tiene un subconjunto de los captadores y definidores del lado del servidor, "dominio", Personobjeto. Ahora usted tiene que escribir código que Marshalls datos entre el Persony el PersonDTOobjeto y todos los otros tipos de objetos que desea transmitir al cliente.

RequestFactory comienza asumiendo que los objetos de su dominio no serán compatibles con GWT. Simplemente declara las propiedades que debe leer y escribir el código del cliente en una interfaz de proxy, y los componentes del servidor RequestFactory se encargan de ordenar los datos e invocar sus métodos de servicio. Para las aplicaciones que tienen un concepto bien definido de "Entidades" u "Objetos con identidad y versión", el EntityProxytipo se utiliza para exponer la semántica de identidad persistente de sus datos al código del cliente. Los objetos simples se mapean usando el ValueProxytipo.

Con RequestFactory, usted paga un costo inicial inicial para adaptarse a sistemas más complicados que los que GWT RPC admite fácilmente. RequestFactory ServiceLayerproporciona significativamente más ganchos para personalizar su comportamiento agregando ServiceLayerDecoratorinstancias.

BobV
fuente
Esta es una buena razón para respaldar mi decisión de cambiar a RequestFactory. ¡Gracias Bob! Tiene sentido y no entiendo por qué algunas personas dicen "usa RPC en algunos casos y RF en otros dependiendo de tus necesidades" porque parece que con RPC tienes que escribir mucho código de pegamento y esa capa DTO
Dan L.
5
Otra ventaja de RequestFactory es que se puede usar con Android y GWT con exactamente el mismo código.
Patrick
28

Pasé por una transición de RPC a RF. Primero tengo que decir que mi experiencia es limitada en eso, usé tantos EntityProxies como 0.

Ventajas de GWT RPC:

  • ¡Es muy fácil de configurar, entender y APRENDER!
  • Los mismos objetos basados ​​en clases se utilizan en el cliente y en el servidor.
  • Este enfoque ahorra toneladas de código.
  • Ideal, cuando se utilizan los mismos objetos de modelo (y POJOS) en el cliente y en el servidor, POJOs == MODEL OBJECTs == DTOs
  • Fácil de mover cosas del servidor al cliente.
  • Implementación fácil de compartir de la lógica común entre el cliente y el servidor (esto puede convertirse en una desventaja crítica cuando se necesita una lógica diferente).

Desventajas de GWT RPC:

  • Imposible tener una implementación diferente de algunos métodos para el servidor y el cliente, por ejemplo, es posible que deba utilizar un marco de registro diferente en el cliente y el servidor, o un método igual diferente.
  • REALMENTE MALA implementación que no es más extensible: la mayor parte de la funcionalidad del servidor se implementa como métodos estáticos en una clase RPC. Eso realmente apesta.
  • por ejemplo, es imposible agregar ofuscación de errores del lado del servidor
  • Algunas preocupaciones de seguridad XSS que no se pueden resolver con elegancia, consulte los documentos (no estoy seguro de si esto es más elegante para RequestFactory)

Desventajas de RequestFactory:

  • REALMENTE DIFÍCIL de entender del documento oficial, ¿cuál es el mérito de esto? Comienza con el término PROXIES completamente engañoso: en realidad, estos son DTO de RF que se crean automáticamente mediante RF. Los proxies se definen mediante interfaces, por ejemplo, @ProxyFor (Journal.class). IDE comprueba si existen métodos correspondientes en Journal. Hasta aquí el mapeo.
  • RF no hará mucho por usted en términos de características comunes de cliente y servidor porque
  • En el cliente, debe convertir "PROXIES" en los objetos de dominio de su cliente y viceversa. Esto es completamente ridículo. Se podría hacer en pocas líneas de código de forma declarativa, ¡pero NO HAY SOPORTE PARA ESO! Si tan solo pudiéramos mapear nuestros objetos de dominio a proxies de manera más elegante, algo como el método JavaScript JSON.stringify (.. ,,) FALTA en la caja de herramientas de RF.
  • No olvide que también es responsable de configurar las propiedades transferibles de los objetos de su dominio a los proxies, y así sucesivamente de forma recursiva.
  • DEFICIENTE MANEJO DE ERRORES en el servidor y - Los seguimientos de pila se omiten de forma predeterminada en el servidor y se obtienen excepciones inútiles vacías en el cliente. Incluso cuando configuré un controlador de errores personalizado, ¡no pude acceder a los seguimientos de pila de bajo nivel! Terrible.
  • Algunos errores menores en el soporte de IDE y en otros lugares. Presenté dos solicitudes de error que fueron aceptadas. No se necesitaba un Einstein para darse cuenta de que en realidad eran errores.
  • LA DOCUMENTACIÓN apesta. Como mencioné, los proxies deberían explicarse mejor, el término es ENGAÑOSO. Para los problemas comunes básicos que estaba resolviendo, DOCS ES INÚTIL. Otro ejemplo de malentendido del DOC es la conexión de las anotaciones JPA a RF. A partir de los documentos breves, parece que juegan un poco juntos, y sí, hay una pregunta correspondiente en StackOverflow. Recomiendo olvidar cualquier "conexión" JPA antes de entender RF.

Ventajas de RequestFactory

  • Excelente soporte de foro.
  • El soporte IDE es bastante bueno (pero no es una ventaja en contraste con RPC)
  • Flexibilidad de la implementación de su cliente y servidor (acoplamiento flexible)
  • Cosas elegantes, conectadas a EntityProxies, más allá de simples DTO: almacenamiento en caché, actualizaciones parciales, muy útil para dispositivos móviles.
  • Puede usar ValueProxies como el reemplazo más simple para los DTO (pero debe hacer todas las conversiones no tan sofisticadas usted mismo).
  • Soporte para validaciones de Bean JSR-303.

Considerando otras desventajas de GWT en general:

  • Imposible ejecutar pruebas de integración (código de cliente GWT + servidor remoto) con soporte JUnit proporcionado <= todo JSNI tiene que ser burlado (por ejemplo, localStorage), SOP es un problema.

  • Sin soporte para la configuración de prueba: navegador sin cabeza + servidor remoto <= sin pruebas simples sin cabeza para GWT, SOP.

  • Sí, es posible ejecutar pruebas de integración de selenio (pero eso no es lo que quiero)

  • JSNI es muy poderoso, pero en esas brillantes charlas que dan en las conferencias no se habla mucho de que escribir códigos JSNI también tiene algunas reglas. Nuevamente, descubrir cómo escribir una simple devolución de llamada fue una tarea digna de un verdadero investigador.

En resumen, la transición de GWT RPC a RequestFactory está lejos de la situación WIN-WIN, cuando RPC se adapta principalmente a sus necesidades. Terminas escribiendo toneladas de conversiones de objetos de dominio de cliente a proxies y viceversa. Pero obtiene cierta flexibilidad y solidez de su solución. Y el apoyo en el foro es excelente, ¡también el sábado!

Teniendo en cuenta todas las ventajas y desventajas que acabo de mencionar, vale la pena pensar de antemano si alguno de estos enfoques realmente aporta mejoras a su solución y a su configuración de desarrollo sin grandes compensaciones.

honzajde
fuente
Echa un vistazo a JBoss Erai. Me encanta su enfoque de RPC.
Καrτhικ
6

Me parece bastante molesta la idea de crear clases Proxy para todas mis entidades. Mis pojos de Hibernate / JPA se generan automáticamente a partir del modelo de base de datos. ¿Por qué ahora necesito crear un segundo espejo de los de RPC? Tenemos un bonito marco de "estivación" que se encarga de "deshibernar" a los pojos.

Además, la idea de definir interfaces de servicio que no implementen el servicio del lado del servidor como un contrato de Java, pero sí implementan los métodos, me suena muy J2EE 1.x / 2.x.

Καrτhικ
fuente
5
Es molesto, pero si tiene que crear proxies de todos modos, entonces prefiere tener la ayuda adicional que le brinda RF para administrar esos proxies. No todo el mundo quiere enviar el pojo completo al cliente, por ejemplo, considere un juego de póquer, su objeto Player puede tener información que todos deberían ver (número de cartas en la mano, cartas que aparecen boca arriba, fichas totales) y otra información que solo un jugador debería ver (cartas boca abajo).
Peter Recore
Su ejemplo de Poker es válido - solucionamos eso al tener anotaciones (@WireTransient) que nuestro marco de "estivación" usa para suprimir valores.
Καrτhικ
4

A diferencia de RequestFactory, que tiene pocas capacidades de prueba y manejo de errores (ya que procesa la mayoría de las cosas bajo el capó de GWT), RPC le permite utilizar un enfoque más orientado a servicios. RequestFactory implementa un enfoque de estilo de inyección de dependencia más moderno que puede proporcionar un enfoque útil si necesita invocar estructuras de datos polimórficas complejas. Cuando use RPC, sus estructuras de datos deberán ser más planas, ya que esto permitirá que sus utilidades de clasificación se traduzcan entre sus modelos json / xml y java. El uso de RPC también le permite implementar una arquitectura más robusta, como se cita en la sección gwt dev del sitio web de Google.

"Implementación simple de cliente / servidor

La primera y más sencilla forma de pensar en las definiciones de servicio es tratarlas como el back-end completo de su aplicación. Desde esta perspectiva, el código del lado del cliente es su "interfaz" y todo el código de servicio que se ejecuta en el servidor es "back-end". Si adopta este enfoque, las implementaciones de sus servicios tenderán a ser API de uso más general que no están estrechamente acopladas a una aplicación específica. Es probable que sus definiciones de servicio accedan directamente a las bases de datos a través de JDBC o Hibernate o incluso archivos en el sistema de archivos del servidor. Para muchas aplicaciones, esta vista es apropiada y puede ser muy eficiente porque reduce el número de niveles.

Implementación de varios niveles

En arquitecturas más complejas y de varios niveles, sus definiciones de servicio GWT podrían ser simplemente pasarelas ligeras que llaman a entornos de servidor back-end como servidores J2EE. Desde esta perspectiva, sus servicios pueden verse como la "mitad del servidor" de la interfaz de usuario de su aplicación. En lugar de ser de uso general, los servicios se crean para las necesidades específicas de su interfaz de usuario. Sus servicios se convierten en el "front-end" de las clases "back-end" que se escriben uniendo llamadas a una capa de servicios de back-end de uso más general, implementada, por ejemplo, como un clúster de servidores J2EE. Este tipo de arquitectura es apropiado si necesita que sus servicios de back-end se ejecuten en una computadora físicamente separada de su servidor HTTP ".

También tenga en cuenta que la configuración de un único servicio RequestFactory requiere la creación de alrededor de 6 o más clases de Java, mientras que RPC solo requiere 3. Más código == más errores y complejidad en mi libro.

RequestFactory también tiene un poco más de sobrecarga durante el procesamiento de la solicitud, ya que tiene que ordenar la serialización entre los proxies de datos y los modelos Java reales. Esta interfaz adicional agrega ciclos de procesamiento adicionales que realmente pueden sumarse en un entorno empresarial o de producción.

Tampoco creo que los servicios RequestFactory sean serialización como los servicios RPC.

En general, después de usar ambos durante algún tiempo, siempre opto por RPC porque es más liviano, más fácil de probar y depurar, y más rápido que usar RequestFactory. Aunque RequestFactory podría ser más elegante y extensible que su contraparte RPC. La complejidad añadida no la convierte en una herramienta mejor necesaria.

Mi opinión es que la mejor arquitectura es utilizar dos aplicaciones web, un cliente y un servidor. El servidor es una aplicación web java genérica y ligera que utiliza la biblioteca servlet.jar. El cliente es GWT. Realiza una solicitud RESTful a través de GWT-RPC en el lado del servidor de la aplicación web del cliente. El lado del servidor del cliente es solo un paso al cliente http de apache que usa un túnel persistente en el controlador de solicitudes que tiene ejecutándose como un solo servlet en su aplicación web de servlet del servidor. La aplicación web del servlet debe contener la capa de aplicación de la base de datos (hibernate, cayenne, sql, etc.). Esto le permite divorciar completamente los modelos de objetos de la base de datos del cliente real, lo que proporciona una forma mucho más extensible y robusta de desarrollar y realizar pruebas unitarias de su aplicación. De acuerdo, requiere un poco de tiempo de configuración inicial, pero al final le permite crear una fábrica de solicitudes dinámicas fuera de GWT. Esto le permite aprovechar lo mejor de ambos mundos. Sin mencionar la posibilidad de probar y realizar cambios en el lado del servidor sin tener que compilar o compilar el cliente gwt.

1-14x0r
fuente
0

Creo que es realmente útil si tiene un pojo pesado en el lado del cliente, por ejemplo, si usa entidades Hibernate o JPA. Adoptamos otra solución, usando un marco de persistencia estilo Django con entidades muy ligeras.

Uberto
fuente
0

La única advertencia que haría es que RequestFactory usa el transporte de datos binarios (¿quizás deRPC?) Y no el GWT-RPC normal.

Esto solo importa si está realizando pruebas intensas con SyncProxy, Jmeter, Fiddler o cualquier herramienta similar que pueda leer / evaluar el contenido de la solicitud / respuesta HTTP (como GWT-RPC), pero sería más desafiante con deRPC o RequestFactory.

Dhartford
fuente
1
Excepto que RequestFactory proporciona una implementación de "Java puro" lista para usar, sin la necesidad de herramientas de terceros como SyncProxy. Ver stackoverflow.com/questions/4853188/…
Thomas Broyer
0

Tenemos una implementación muy grande de GWT-RPC en nuestro proyecto. En realidad, tenemos 50 interfaces de servicio con muchos métodos cada una, y tenemos problemas con el tamaño de TypeSerializers generados por el compilador que hace que nuestro código JS sea enorme. Así que estamos analizando avanzar hacia RequestFactory. Me han leído durante un par de días buscando en la web y tratando de encontrar lo que hacen otras personas. El inconveniente más importante que vi, y tal vez podría estar equivocado, es que con RequestFactory ya no tienes el control de la comunicación entre los objetos de tu dominio de servidor y los de tu cliente. Lo que necesitamos es aplicar el patrón de carga / guardado de forma controlada. Quiero decir, por ejemplo, el cliente recibe el gráfico de objetos completo de los objetos que pertenecen a una transacción específica, realiza sus actualizaciones y envían todo de vuelta al servidor. El servidor será responsable de hacer la validación, comparar los valores antiguos con los nuevos y hacer la persistencia. Si 2 usuarios de diferentes sitios obtienen la misma transacción y realizan algunas actualizaciones, la transacción resultante no debería ser la fusionada. Una de las actualizaciones debería fallar en mi escenario. No veo que RequestFactory ayude a respaldar este tipo de procesamiento.

Saludos Daniel

Daniel Ardison
fuente
Comparto estas preocupaciones ... ¿terminaste yendo con RF?
HDave el
0

¿Es justo decir que cuando se considera una aplicación de MIS limitada, digamos con 10-20 objetos comerciales compatibles con CRUD, y cada uno con ~ 1-10 propiedades, realmente depende de la preferencia personal qué ruta seguir?

Si es así, entonces tal vez proyectar cómo se escalará su aplicación podría ser la clave para elegir su ruta GWT RPC o RequestFactory:

  1. Se espera que mi aplicación se quede con ese número relativamente limitado de entidades, pero aumentará enormemente en términos de su número. 10-20 objetos * 100.000 registros.

  2. Mi aplicación aumentará significativamente en la amplitud de entidades, pero el número relativo de cada una seguirá siendo bajo. 5000 objetos * 100 registros.

  3. Se espera que mi aplicación permanezca con ese número relativamente limitado de entidades Y permanecerá en un número relativamente bajo de, por ejemplo, 10-20 objetos * 100 registros

En mi caso, estoy en el punto de partida de intentar tomar esta decisión. Se complica aún más al tener que cambiar la arquitectura del lado del cliente de la interfaz de usuario y al elegir el transporte. Mi interfaz de usuario de GWT anterior (significativamente) a gran escala usaba la biblioteca Hmvc4Gwt, que ha sido reemplazada por las instalaciones de GWT MVP.

cuchara fría
fuente