Quand dois-je utiliser RequestFactory vs GWT-RPC?

87

J'essaie de déterminer si je dois migrer mes appels gwt-rpc vers les nouveaux cals GWT2.1 RequestFactory.

La documentation Google mentionne vaguement que RequestFactory est une meilleure méthode de communication client-serveur pour les "services orientés données"

Ce que je peux distiller de la documentation, c'est qu'il existe une nouvelle classe Proxy qui simplifie la communication (vous ne passez pas dans les deux sens l'entité réelle mais juste le proxy, donc c'est plus léger et plus facile à gérer)

Est-ce là tout l'intérêt ou est-ce que je rate quelque chose d'autre dans le tableau d'ensemble?

Daghan ---
la source
8
yay, cette question est liée à partir du devguide officiel de gwt !
törzsmókus

Réponses:

73

La grande différence entre GWT RPC et RequestFactory est que le système RPC est "RPC-by-concret-type" tandis que RequestFactory est "RPC-by-interface".

RPC est plus pratique pour démarrer, car vous écrivez moins de lignes de code et utilisez la même classe sur le client et le serveur. Vous pouvez créer une Personclasse avec un tas de getters et de setters et peut-être une logique métier simple pour un découpage plus approfondi des données dans lePerson objet. Cela fonctionne assez bien jusqu'à ce que vous finissiez par vouloir avoir du code spécifique au serveur, non compatible avec GWT, dans votre classe. Étant donné que le système RPC est basé sur le même type de béton sur le client et le serveur, vous pouvez atteindre un mur de complexité basé sur les capacités de votre client GWT.

Pour contourner l'utilisation de code incompatible, de nombreux utilisateurs finissent par créer un pair PersonDTOqui fait de l'ombre à l' Personobjet réel utilisé sur le serveur. Le PersonDTOjust a un sous-ensemble des getters et des setters de l'objet côté serveur, "domain" Person. Maintenant , vous devez écrire du code que les données de Marshalls entre le Personet PersonDTOobjet et tous les autres types d'objets que vous souhaitez passer au client.

RequestFactory commence par supposer que les objets de votre domaine ne seront pas compatibles GWT. Vous déclarez simplement les propriétés qui doivent être lues et écrites par le code client dans une interface Proxy, et les composants serveur RequestFactory se chargent de marshaler les données et d'appeler vos méthodes de service. Pour les applications qui ont un concept bien défini d '"Entités" ou "Objets avec identité et version", le EntityProxytype est utilisé pour exposer la sémantique d'identité persistante de vos données au code client. Les objets simples sont mappés à l'aide du ValueProxytype.

Avec RequestFactory, vous payez un coût de démarrage initial pour accueillir des systèmes plus compliqués que ce que GWT RPC prend facilement en charge. RequestFactory ServiceLayerfournit beaucoup plus de hooks pour personnaliser son comportement en ajoutant des ServiceLayerDecoratorinstances.

BobV
la source
C'est une bonne raison pour soutenir ma décision de passer à RequestFactory. Merci, Bob! Cela a du sens et je ne comprends pas pourquoi certaines personnes disent "utilisez RPC dans certains cas et RF dans d'autres en fonction de vos besoins", car il semble qu'avec RPC, vous devez écrire beaucoup de code de colle et cette couche DTO
Dan Leahu
5
Un autre avantage de RequestFactory est qu'il peut être utilisé avec Android et GWT avec exactement le même code.
Patrick
28

J'ai traversé une transition de RPC à RF. Tout d'abord, je dois dire que mon expérience est limitée en cela, j'ai utilisé autant d'EntityProxies que 0.

Avantages de GWT RPC:

  • C'est très facile à configurer, à comprendre et à APPRENDRE!
  • Les mêmes objets basés sur les classes sont utilisés sur le client et sur le serveur.
  • Cette approche économise des tonnes de code.
  • Idéal, lorsque les mêmes objets de modèle (et POJOS) sont utilisés sur le client et le serveur, POJO == MODEL OBJECTs == DTO
  • Facile à déplacer des éléments du serveur au client.
  • Implémentation facile à partager de la logique commune entre le client et le serveur (cela peut s'avérer un inconvénient critique lorsque vous avez besoin d'une logique différente).

Inconvénients de GWT RPC:

  • Impossible d'avoir une implémentation différente de certaines méthodes pour le serveur et le client, par exemple, vous pourriez avoir besoin d'utiliser un cadre de journalisation différent sur le client et le serveur, ou une méthode d'égalité différente.
  • Implémentation VRAIMENT MAUVAISE qui n'est pas plus extensible: la plupart des fonctionnalités du serveur sont implémentées sous forme de méthodes statiques sur une classe RPC. CELA SUCE VRAIMENT.
  • Par exemple, il est impossible d'ajouter un masquage des erreurs côté serveur
  • Certains problèmes de sécurité XSS qui ne sont pas assez élégamment résolus, voir la documentation (je ne suis pas sûr que ce soit plus élégant pour RequestFactory)

Inconvénients de RequestFactory:

  • VRAIMENT DIFFICILE à comprendre de la doc officielle, quel en est le mérite! Cela commence juste au terme complètement trompeur PROXIES - ce sont en fait des DTO de RF qui sont créés automatiquement par RF. Les proxies sont définis par des interfaces, par exemple @ProxyFor (Journal.class). IDE vérifie s'il existe des méthodes correspondantes sur Journal. Voilà pour la cartographie.
  • RF ne fera pas grand-chose pour vous en termes de points communs entre le client et le serveur car
  • Sur le client, vous devez convertir "PROXIES" en objets de votre domaine client et vice-versa. C'est complètement ridicule. Cela pourrait être fait en quelques lignes de code de manière déclarative, mais il n'y a AUCUN SUPPORT POUR CELA! Si seulement nous pouvions mapper nos objets de domaine avec des proxys plus élégamment, quelque chose comme la méthode JavaScript JSON.stringify (.. ,,) est MANQUANT dans la boîte à outils RF.
  • N'oubliez pas que vous êtes également responsable de la définition des propriétés transférables de vos objets de domaine aux proxys, et ainsi de suite de manière récursive.
  • MAUVAISE GESTION DES ERREURS sur le serveur et - Les traces de pile sont omises par défaut sur le serveur et vous obtenez des exceptions vides et inutiles sur le client. Même lorsque j'ai défini un gestionnaire d'erreur personnalisé, je n'ai pas pu accéder aux traces de pile de bas niveau! Terrible.
  • Quelques bugs mineurs dans le support IDE et ailleurs. J'ai déposé deux demandes de bogues qui ont été acceptées. Pas un Einstein n'était nécessaire pour comprendre qu'il s'agissait en fait de bugs.
  • LA DOCUMENTATION SUCE. Comme je l'ai mentionné, les procurations devraient être mieux expliquées, le terme est trompeur. Pour les problèmes communs de base, que je résolvais, DOCS EST INUTILE. Un autre exemple de malentendu de la part du DOC est la connexion des annotations JPA à RF. Il semble d'après la documentation succincte qu'ils jouent un peu ensemble, et oui, il y a une question correspondante sur StackOverflow. Je recommande d'oublier toute «connexion» JPA avant de comprendre RF.

Avantages de RequestFactory

  • Excellent support du forum.
  • Le support IDE est plutôt bon (mais ce n'est pas un avantage par rapport à RPC)
  • Flexibilité de votre implémentation client et serveur (couplage lâche)
  • Des trucs fantaisistes, connectés à EntityProxies, au-delà des simples DTO - mise en cache, mises à jour partielles, très utiles pour les mobiles.
  • Vous pouvez utiliser ValueProxies comme le remplacement le plus simple des DTO (mais vous devez faire toutes les conversions pas si sophistiquées vous-même).
  • Prise en charge des validations de Bean JSR-303.

Compte tenu des autres inconvénients de GWT en général:

  • Impossible d'exécuter des tests d'intégration (code client GWT + serveur distant) avec le support JUnit fourni <= tout JSNI doit être simulé (par exemple localStorage), SOP est un problème.

  • Pas de support pour la configuration des tests - navigateur sans tête + serveur distant <= pas de test simple sans tête pour GWT, SOP.

  • Oui, il est possible d'exécuter des tests d'intégration au sélénium (mais ce n'est pas ce que je souhaite)

  • JSNI est très puissant, mais lors de ces brillantes discussions qu'ils donnent lors de conférences, ils ne parlent pas beaucoup du fait que l'écriture de codes JSNI a également des règles. Encore une fois, trouver comment écrire un simple rappel était une tâche digne d'un vrai chercheur.

En résumé, la transition de GWT RPC vers RequestFactory est loin d'être une situation WIN-WIN, lorsque RPC répond principalement à vos besoins. Vous finissez par écrire des tonnes de conversions d'objets du domaine client vers des proxys et vice-versa. Mais vous bénéficiez d'une certaine flexibilité et robustesse de votre solution. Et le support sur le forum est excellent, samedi aussi!

Compte tenu de tous les avantages et inconvénients que je viens de mentionner, il est très utile de penser à l'avance si l'une de ces approches apporte réellement une amélioration à votre solution et à votre configuration de développement sans grands compromis.

honzajde
la source
Découvrez JBoss Erai. J'adore leur approche du RPC.
Καrτhικ
6

Je trouve l'idée de créer des classes Proxy pour toutes mes entités assez ennuyeuse. Mes pojos Hibernate / JPA sont générés automatiquement à partir du modèle de base de données. Pourquoi dois-je maintenant créer un deuxième miroir de ceux pour RPC? Nous avons un joli cadre "d'estivation" qui s'occupe de "déshiberner" les pojos.

De plus, l'idée de définir des interfaces de service qui n'implémentent pas tout à fait le service côté serveur en tant que contrat Java mais implémentent les méthodes - me semble très J2EE 1.x / 2.x.

Καrτhικ
la source
5
C'est ennuyeux, mais si vous devez tout de même créer des proxies, vous préférez avoir l'aide supplémentaire que RF vous donne pour gérer ces proxies. Tout le monde ne veut pas envoyer le pojo entier au client - par exemple, considérez un jeu de poker - votre objet Player peut contenir des informations que tout le monde devrait voir (nombre de cartes en main, cartes visibles, nombre total de jetons) et d'autres informations qui un joueur devrait voir (cartes face cachée).
Peter Recore
Votre exemple de poker est valide - nous contournons cela en ayant des annotations (@WireTransient) que notre cadre "d'estivation" utilise pour supprimer les valeurs.
Καrτhικ
4

Contrairement à RequestFactory qui a de mauvaises capacités de gestion des erreurs et de test (car il traite la plupart des choses sous le capot de GWT), RPC vous permet d'utiliser une approche plus orientée service. RequestFactory implémente une approche de style d'injection de dépendances plus moderne qui peut fournir une approche utile si vous devez appeler des structures de données polymorphes complexes. Lorsque vous utilisez RPC, vos structures de données devront être plus plates, car cela permettra à vos utilitaires de marshaling de traduire entre vos modèles json / xml et java. L'utilisation de RPC vous permet également de mettre en œuvre une architecture plus robuste, comme indiqué dans la section gwt dev sur le site Web de Google.

"Déploiement client / serveur simple

La première et la plus simple façon de penser aux définitions de service est de les traiter comme l'ensemble du back-end de votre application. De ce point de vue, le code côté client est votre "frontal" et tout le code de service qui s'exécute sur le serveur est "back-end". Si vous adoptez cette approche, vos implémentations de service auront tendance à être des API plus générales qui ne sont pas étroitement associées à une application spécifique. Vos définitions de service accèderaient probablement directement aux bases de données via JDBC ou Hibernate ou même à des fichiers dans le système de fichiers du serveur. Pour de nombreuses applications, cette vue est appropriée et elle peut être très efficace car elle réduit le nombre de niveaux.

Déploiement à plusieurs niveaux

Dans des architectures plus complexes et à plusieurs niveaux, vos définitions de service GWT peuvent simplement être des passerelles légères qui font appel à des environnements de serveurs principaux tels que des serveurs J2EE. De ce point de vue, vos services peuvent être considérés comme la «moitié serveur» de l'interface utilisateur de votre application. Au lieu d'être à usage général, les services sont créés pour les besoins spécifiques de votre interface utilisateur. Vos services deviennent le "frontal" des classes "back-end" qui sont écrites en assemblant des appels à une couche de services back-end plus générale, implémentée, par exemple, sous la forme d'un cluster de serveurs J2EE. Ce type d'architecture est approprié si vous avez besoin que vos services back-end s'exécutent sur un ordinateur physiquement séparé de votre serveur HTTP. "

Notez également que la mise en place d'un seul service RequestFactory nécessite de créer environ 6 classes java alors que RPC ne nécessite que 3. Plus de code == plus d'erreurs et de complexité dans mon livre.

RequestFactory a également un peu plus de temps système pendant le traitement de la demande, car il doit rassembler la sérialisation entre les proxys de données et les modèles Java réels. Cette interface ajoutée ajoute des cycles de traitement supplémentaires qui peuvent vraiment s'additionner dans une entreprise ou un environnement de production.

Je ne crois pas non plus que les services RequestFactory soient une sérialisation comme les services RPC.

Dans l'ensemble, après avoir utilisé les deux pendant un certain temps maintenant, j'utilise toujours RPC car il est plus léger, plus facile à tester et à déboguer, et plus rapide que l'utilisation d'une RequestFactory. Bien que RequestFactory puisse être plus élégant et extensible que son homologue RPC. La complexité supplémentaire n'en fait pas un meilleur outil nécessaire.

Mon avis est que la meilleure architecture consiste à utiliser deux applications Web, un client et un serveur. Le serveur est une simple application web java générique légère qui utilise la bibliothèque servlet.jar. Le client est GWT. Vous effectuez une requête RESTful via GWT-RPC dans le côté serveur de l'application Web cliente. Le côté serveur du client n'est qu'un passage vers le client Apache http qui utilise un tunnel persistant dans le gestionnaire de requêtes que vous exécutez en tant que servlet unique dans votre application Web de servlet serveur. L'application Web servlet doit contenir la couche d'application de votre base de données (hibernate, cayenne, sql, etc.). Cela vous permet de séparer complètement les modèles d'objet de base de données du client réel, offrant un moyen beaucoup plus extensible et robuste de développer et de tester l'unité de votre application. Certes, cela nécessite un peu de temps de configuration initiale, mais à la fin vous permet de créer une usine de requêtes dynamiques en dehors de GWT. Cela vous permet de tirer parti du meilleur des deux mondes. Sans oublier de pouvoir tester et apporter des modifications à votre serveur sans avoir à faire compiler ou construire le client gwt.

1-14x0r
la source
0

Je pense que c'est vraiment utile si vous avez un gros problème côté client, par exemple si vous utilisez des entités Hibernate ou JPA. Nous avons adopté une autre solution, utilisant un framework de persistance de style Django avec des entités très légères.

Uberto
la source
0

La seule mise en garde que je ferais est que RequestFactory utilise le transport de données binaires (deRPC peut-être?) Et non le GWT-RPC normal.

Cela n'a d'importance que si vous effectuez des tests intensifs avec SyncProxy, Jmeter, Fiddler ou tout autre outil similaire capable de lire / évaluer le contenu de la requête / réponse HTTP (comme GWT-RPC), mais serait plus difficile avec deRPC ou RequestFactory.

Dhartford
la source
1
Sauf qu'en réalité, RequestFactory fournit une implémentation "pure Java" prête à l'emploi, sans avoir besoin d'outils tiers comme SyncProxy. Voir stackoverflow.com/questions/4853188/…
Thomas Broyer
0

Nous avons une très grande implémentation de GWT-RPC dans notre projet. En fait, nous avons 50 interfaces de service avec de nombreuses méthodes chacune, et nous avons des problèmes avec la taille des TypeSerializers générés par le compilateur qui rend notre code JS énorme. Nous sommes donc en train de passer à RequestFactory. On me lit depuis quelques jours en train de fouiller sur le Web et d'essayer de trouver ce que font les autres. L'inconvénient le plus important que j'ai vu, et peut-être que je pourrais me tromper, est qu'avec RequestFactory, vous ne contrôlez plus la communication entre vos objets de domaine serveur et ceux de vos clients. Ce dont nous avons besoin, c'est d'appliquer le modèle de chargement / enregistrement de manière contrôlée. Je veux dire, par exemple, le client reçoit le graphe d'objets entier des objets appartenant à une transaction spécifique, effectue ses mises à jour et les renvoie le tout au serveur. Le serveur sera responsable de la validation, de la comparaison des anciennes avec les nouvelles valeurs et de la persistance. Si 2 utilisateurs de sites différents obtiennent la même transaction et effectuent des mises à jour, la transaction résultante ne devrait pas être celle fusionnée. L'une des mises à jour devrait échouer dans mon scénario. Je ne vois pas que RequestFactory aide à supporter ce type de traitement.

Cordialement Daniel

Daniel Ardison
la source
Je partage ces préoccupations ... avez-vous fini par utiliser RF?
HDave
0

Est-il juste de dire que lorsqu'on considère une application MIS limitée, par exemple avec 10 à 20 objets métier CRUD'able, et chacun avec ~ 1-10 propriétés, cela dépend vraiment de la préférence personnelle de l'itinéraire à suivre?

Si tel est le cas, alors peut-être que la projection de la façon dont votre application va évoluer pourrait être la clé du choix de votre itinéraire GWT RPC ou RequestFactory:

  1. On s'attend à ce que ma candidature reste avec ce nombre relativement limité d'entités, mais elle augmentera massivement en termes de nombre. 10-20 objets * 100 000 enregistrements.

  2. Ma candidature va augmenter considérablement dans la largeur des entités, mais le nombre relatif de chacune d'entre elles restera faible. 5000 objets * 100 enregistrements.

  3. On s'attend à ce que mon application reste avec ce nombre relativement limité d'entités ET restera dans un nombre relativement faible, par exemple 10 à 20 objets * 100 enregistrements

Dans mon cas, je suis au tout début d'essayer de prendre cette décision. Plus compliqué par la nécessité de changer l'architecture côté client de l'interface utilisateur et de faire le choix du transport. Mon ancienne interface utilisateur GWT à grande échelle (significativement) utilisait la bibliothèque Hmvc4Gwt, qui a été remplacée par les installations MVP de GWT.

cuillère à soupe
la source