Quand devrais-je utiliser RequestFactory vs GWT-RPC?

J’essaie de savoir si je devrais migrer mes appels gwt-rpc vers les nouveaux cals GWT2.1 RequestFactory.

La documentation de 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 faites pas de va-et-vient de l’entité réelle mais seulement du proxy, elle est donc plus légère et plus facile à gérer).

Est-ce le point ou est-ce que je manque quelque chose d’autre dans la grande image?

La grande différence entre GWT RPC et RequestFactory est que le système RPC est “RPC-by-concrete-type” alors que RequestFactory est “RPC by interface”.

RPC est plus pratique pour commencer, car vous écrivez moins de lignes de code et utilisez la même classe à la fois sur le client et sur le serveur. Vous pouvez créer une classe Person avec un groupe de getters et de setters, et peut-être une logique métier simple pour un découpage et un découpage plus poussés des données dans l’object Person . Cela fonctionne assez bien jusqu’à ce que vous souhaitiez avoir un 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 concret à la fois sur le client et sur le serveur, vous pouvez atteindre un mur de complexité en fonction des capacités de votre client GWT.

Pour contourner l’utilisation de code incompatible, de nombreux utilisateurs PersonDTO par créer un pair PersonDTO qui PersonDTO l’object réel Person utilisé sur le serveur. Le PersonDTO juste un sous-ensemble des PersonDTO getters et setters du côté serveur, “domain”, object Person . Vous devez maintenant écrire le code qui regroupe les données entre l’object Person et PersonDTO et tous les autres types d’objects que vous souhaitez transmettre au client.

RequestFactory commence par supposer que vos objects de domaine ne seront pas compatibles avec 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 du serveur RequestFactory veillent à marshaler les données et à appeler vos méthodes de service. Pour les applications qui ont un concept bien défini «Entités» ou «Objets avec identité et version», le type EntityProxy est utilisé pour exposer la sémantique d’identité persistante de vos données au code client. Les objects simples sont mappés en utilisant le type ValueProxy .

Avec RequestFactory, vous payez un coût de démarrage initial pour prendre en charge des systèmes plus complexes que ceux que GWT RPC prend facilement en charge. ServiceLayer de RequestFactory fournit beaucoup plus de hooks pour personnaliser son comportement en ajoutant des instances de ServiceLayerDecorator .

Je suis passé d’une transition de RPC à RF. D’abord, je dois dire que mon expérience est limitée dans ce domaine, j’ai utilisé autant d’entité Proxies que 0.

Avantages de GWT RPC:

  • C’est très facile à configurer, à comprendre et à apprendre!
  • Les mêmes objects de classe sont utilisés sur le client et sur le serveur.
  • Cette approche permet d’économiser des tonnes de code.
  • Idéal lorsque les mêmes objects de modèle (et POJOS) sont utilisés sur le client et le serveur, les POJO == OBJETS DE MODÈLE == DTO
  • Facile à déplacer des choses du serveur au client.
  • Mise en œuvre facile de la logique commune entre le client et le serveur (cela peut s’avérer être 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 devrez peut-être utiliser une autre structure de journalisation sur le client et le serveur, ou une méthode différente.
  • Une implémentation REELLE de BAD qui n’est pas plus extensible: la plupart des fonctionnalités du serveur sont implémentées en tant que méthodes statiques sur une classe RPC. Ça suce vraiment.
  • Par exemple, il est impossible d’append des erreurs côté serveur
  • Certains problèmes de sécurité XSS qui ne peuvent pas être résolus avec élégance, voir docs (je ne suis pas sûr que ce soit plus élégant pour RequestFactory)

Inconvénients de RequestFactory:

  • VRAIMENT DIFFICILE à comprendre du document officiel, quel en est le mérite! Cela commence à un 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 dans Journal. Voilà pour la cartographie.
  • RF ne fera pas beaucoup pour vous en termes de points communs de client et de serveur, car
  • Sur le client, vous devez convertir “PROXIES” en objects de domaine client et inversement. C’est complètement ridicule. Cela pourrait être fait en quelques lignes de code de manière déclarative, mais il n’y a pas de support pour cela! Si seulement nous pouvions mapper nos objects de domaine de manière plus élégante avec des proxys, quelque chose comme la méthode JavaScript JSON.ssortingngify (.. ,,) 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 des objects de votre domaine sur les proxys, et ainsi de suite récursivement.
  • Une mauvaise gestion des erreurs sur le serveur et – Les traces de stack sont omises par défaut sur le serveur et vous obtenez des exceptions inutiles vides sur le client. Même lorsque je définissais un gestionnaire d’erreur personnalisé, je ne pouvais pas accéder aux traces de stack 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 que c’étaient des bugs.
  • DOCUMENTATION SUCKS. Comme je l’ai mentionné, les procurations devraient être mieux expliquées, le terme est MAUVAIS. Pour les problèmes communs de base que je résolvais, DOCS EST INUTILE. Un autre exemple d’incompréhension de la part du DOC est la connexion des annotations JPA à RF. D’après les documents succincts, 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 de fantaisie, 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 remplacement le plus simple des DTO (mais vous devez faire toutes les conversions pas très sophistiquées vous-même).
  • Prise en charge des validations de beans JSR-303.

Considérant d’autres inconvénients de la 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), le SOP pose 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 de selenium (mais ce n’est pas ce que je veux)

  • JSNI est très puissant, mais lors des discussions shinyes qu’ils donnent lors de conférences, ils ne parlent pas beaucoup de ce que l’écriture de codes JSNI comporte également certaines règles. Encore une fois, déterminer comment écrire un simple rappel était une tâche digne d’un vrai chercheur.

En résumé, la transition de GWT RPC à RequestFactory est loin de la situation WIN-WIN, lorsque RPC répond le mieux à vos besoins. Vous finissez par écrire des tonnes de conversions à partir d’objects de domaine client en proxies et vice-versa. Mais vous obtenez 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 des améliorations à votre solution et à votre configuration de développement sans grands compromis.

Je trouve très gênant l’idée de créer des classes de proxy pour toutes mes entités. Mes pojos Hibernate / JPA sont générés automatiquement à partir du modèle de firebase database. Pourquoi dois-je maintenant créer un deuxième miroir de ceux pour RPC? Nous avons un joli cadre “d’estivation” qui consiste à “désengager” les pojos.

En outre, 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émente les méthodes – me semble très J2EE 1.x / 2.x.

Contrairement à RequestFactory qui dispose de faibles capacités de traitement des erreurs et de test (puisqu’il traite la plupart des éléments sous le capot de GWT), RPC vous permet d’utiliser une approche plus orientée service. RequestFactory implémente une approche plus moderne de type dependency injection qui peut fournir une approche utile si vous avez besoin d’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, citée dans la section gwt dev du site Web de Google.

“Déploiement Simple Client / Serveur

La manière la plus simple et la plus simple de penser aux définitions de service est de les traiter comme l’ensemble du back-end de votre application. Dans cette perspective, le code côté client est votre “frontal” et tout code de service exécuté sur le serveur est “back end”. Si vous adoptez cette approche, vos implémentations de services auront tendance à être des API plus générales qui ne sont pas étroitement lié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 du système de fichiers du serveur. Pour de nombreuses applications, cette vue est appropriée et peut être très efficace car elle réduit le nombre de niveaux.

Déploiement à plusieurs niveaux

Dans les architectures multiniveaux plus complexes, vos définitions de service GWT pourraient simplement être des passerelles légères qui appellent des environnements de serveurs principaux tels que des serveurs J2EE. De ce sharepoint vue, vos services peuvent être considérés comme la “moitié serveur” de l’interface utilisateur de votre application. Au lieu d’être polyvalents, les services sont créés pour les besoins spécifiques de votre interface utilisateur. Vos services deviennent le “front-end” des classes “back-end” écrites en assemblant les appels à une couche de services back-end plus polyvalente, implémentée, par exemple, en tant que cluster de serveurs J2EE. Ce type d’architecture est approprié si vous souhaitez que vos services principaux s’exécutent sur un ordinateur physiquement distinct de votre serveur HTTP. ”

Notez également que la configuration d’un service RequestFactory unique nécessite la création d’environ 6 classes java où RPC ne requirejs que 3 classes supplémentaires. Plus de code == plus d’erreurs et de complexité dans mon livre.

RequestFactory a également un peu plus de charge lors du traitement de la requête, car il doit marshaler la sérialisation entre les proxy de données et les modèles Java réels. Cette interface supplémentaire ajoute des cycles de traitement supplémentaires qui peuvent vraiment s’append dans une entreprise ou un environnement de production.

Je ne crois pas non plus que les services RequestFactory soient des services de sérialisation tels que les services RPC.

Dans l’ensemble, après avoir utilisé les deux pendant un certain temps maintenant, je vais toujours avec RPC comme plus léger, plus facile à tester et à déboguer, et plus rapide que d’utiliser un RequestFactory. Bien que RequestFactory puisse être plus élégant et plus extensible que son compteur RPC. La complexité supplémentaire ne le rend 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 du côté serveur de l’application Web client. Le côté serveur du client est simplement un client HTTP pass-to-apache qui utilise un tunnel persistant dans le gestionnaire de requêtes que vous utilisez en tant que servlet unique dans votre application Web de servlet de serveur. L’application Web de servlet doit contenir votre couche d’application de firebase database (hibernate, cayenne, sql, etc.). Cela vous permet de séparer complètement les modèles d’object de firebase database du client réel. Certes, il nécessite un peu de temps de configuration initiale, mais à la fin, vous pouvez créer une fabrique de requêtes dynamic en dehors de GWT. Cela vous permet de tirer parti du meilleur des deux mondes. Sans compter que vous pouvez tester et apporter des modifications à votre serveur sans avoir à comstackr ou à comstackr le client gwt.

Je pense que cela est vraiment utile si vous avez un gros point sur le 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.

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

Cela importe uniquement 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.

Nous avons une très grande implémentation de GWT-RPC dans notre projet. En fait, nous avons 50 interfaces de service avec beaucoup de méthodes chacune, et nous avons des problèmes avec la taille de TypeSerializers générée par le compilateur qui rend notre code JS énorme. Nous nous attendons donc à passer à RequestFactory. J’ai été lu pendant quelques jours en cherchant sur le Web et en essayant de trouver ce que font les autres. L’inconvénient le plus important que j’ai constaté, et peut-être que je pourrais me tromper, est que, avec RequestFactory, vous ne contrôlez plus la communication entre vos objects de domaine de serveur et ceux de vos clients. Nous avons besoin d’appliquer le modèle de chargement / sauvegarde de manière contrôlée. Je veux dire, par exemple, que le client reçoit le graphe d’object entier d’objects appartenant à une transaction spécifique, effectue ses mises à jour et les renvoie au serveur. Le serveur sera responsable de la validation, de la comparaison avec les nouvelles valeurs et de la persistance. Si 2 utilisateurs de sites différents reçoivent la même transaction et effectuent des mises à jour, la transaction qui en résulte ne doit pas être la même. 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

Est-il juste de dire que lorsque l’on considère une application MIS limitée, par exemple avec 10 à 20 objects métier CRUD, et chacun avec environ 1 à 10 propriétés, c’est vraiment à votre préférence personnelle de choisir la route à suivre?

Si c’est le cas, alors peut-être que la projection de votre application à l’échelle pourrait être la clé pour choisir votre itinéraire GWT RPC ou RequestFactory:

  1. Mon application devrait restr avec ce nombre relativement limité d’entités, mais leur nombre augmentera considérablement. 10-20 objects * 100 000 enregistrements.

  2. Mon application va considérablement augmenter dans l’ensemble des entités, mais le nombre relatif de chacun restra faible. 5000 objects * 100 enregistrements.

  3. Mon application devrait restr avec ce nombre relativement restreint d’entités ET restra dans un nombre relativement faible, par exemple de 10 à 20 objects * 100 enregistrements

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