J'essaie de savoir si je dois 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 de proxy qui simplifie la communication (vous ne passez pas dans les deux sens l'entité réelle mais juste le proxy, il est donc plus léger et plus facile à gérer)
Est-ce que c'est tout 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" tandis 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 sur le client et 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 le découpage et le découpage des données dans l'objet Person
. Cela fonctionne très bien jusqu'à ce que vous souhaitiez avoir du code spécifique au serveur, non compatible GWT, dans votre classe. Parce que le système RPC est basé sur le fait d'avoir le même type concret sur le client et le serveur, vous pouvez frapper un mur de complexité en fonction des capacités de votre client GWT.
Pour contourner l'utilisation de code incompatible, de nombreux utilisateurs finissent par créer un homologue PersonDTO
qui masque le véritable objet Person
utilisé sur le serveur. PersonDTO
a juste un sous-ensemble des getters et setters de l'objet "domaine", Person
côté serveur. Vous devez maintenant écrire du code qui rassemble les données entre l'objet Person
et PersonDTO
et tous les autres types d'objet que vous souhaitez transmettre au client.
RequestFactory commence en supposant que vos objets de 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 du 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 "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 objets simples sont mappés à l'aide du type ValueProxy
.
Avec RequestFactory, vous payez un coût de démarrage initial pour s'adapter à des systèmes plus compliqués que GWT RPC ne prend facilement en charge. ServiceLayer
de RequestFactory fournit beaucoup plus de hooks pour personnaliser son comportement en ajoutant des instances ServiceLayerDecorator
.
Je suis passé par une transition de RPC à RF. Je dois d'abord dire que mon expérience est limitée en ce sens que j'ai utilisé autant d'entités proxies que 0.
Avantages de GWT RPC:
Inconvénients de GWT RPC:
Inconvénients de RequestFactory:
Avantages de RequestFactory
Compte tenu des autres inconvénients du 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 moqué (par exemple localStorage), SOP est un problème.
Pas de prise en charge pour la configuration des tests - navigateur sans tête + serveur distant <= pas de test sans tête simple pour GWT, SOP.
Oui, il est possible d'exécuter des tests d'intégration Selenium (mais ce n'est pas ce que je veux)
JSNI est très puissant, mais lors de ces discussions brillantes 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 à RequestFactory est loin d'être une situation WIN-WIN, lorsque RPC correspond principalement à vos besoins. Vous finissez par écrire des tonnes de conversions d'objets de domaine client vers des proxys 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 vaut vraiment la peine 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.
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'estimation" 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 comme un contrat Java mais implémentent les méthodes) me semble très J2EE 1.x/2.x.
Contrairement à RequestFactory qui a de faibles 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épendance plus moderne qui peut fournir une approche utile si vous devez invoquer 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 , tel que cité dans la section gwt dev du site Web de Google.
"Déploiement simple client/serveur
La première et la plus simple façon de penser aux définitions de service est de les traiter comme le back-end de votre application. De ce point de vue, le code côté client est votre "front-end" 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 auraient tendance à être des API plus générales qui ne sont pas étroitement couplées à une application spécifique. Vos définitions de service accéderaient probablement directement à des 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 à plusieurs niveaux plus complexes, vos définitions de service GWT pourraient simplement être des passerelles légères qui appellent des environnements de serveur 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 "front end" des classes "back end" qui sont écrites en assemblant les appels à une couche de services back-end plus générale, implémentée, par exemple, comme un cluster de serveurs J2EE. Ce type d'architecture est approprié si vous avez besoin que vos services principaux s'exécutent sur un ordinateur physiquement distinct de votre serveur HTTP. "
Notez également que la mise en place d'un seul service RequestFactory nécessite la création d'environ 6 Java classes où RPC en nécessite seulement 3. Plus de code == plus d'erreurs et de complexité dans mon livre.
RequestFactory a également un peu plus de temps lors du traitement des demandes, car il doit organiser la sérialisation entre les proxys de données et les modèles réels Java. Cette interface ajoutée ajoute des cycles de traitement supplémentaires qui peuvent vraiment s'additionner dans un environnement d'entreprise ou de production.
Je ne pense pas non plus que les services RequestFactory soient de la sérialisation comme les services RPC.
Dans l'ensemble, après avoir utilisé les deux pendant un certain temps maintenant, j'utilise toujours RPC comme son plus léger, plus facile à tester et à déboguer, et plus rapide que l'utilisation d'un 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, la meilleure architecture consiste à utiliser deux applications Web, un client et un serveur. Le serveur est un simple générique léger Java webapp qui utilise la bibliothèque servlet.jar. Le client est GWT. Vous effectuez une demande RESTful via GWT-RPC dans le côté serveur de l'application Web client. 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 demandes que vous exécutez 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 base de données (mise en veille prolongée, 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 unitaire votre application. Certes, cela nécessite un peu de temps de configuration initiale, mais dans la fin vous permet de créer une fabrique de requêtes dynamique en dehors de GWT. Cela vous permet de tirer le meilleur parti des deux mondes. Sans oublier de pouvoir tester et apporter des modifications à votre serveur sans avoir à avoir le client gwt comp iled ou construire.
Je pense que c'est vraiment utile si vous avez un gros pojo côté client, par exemple si vous utilisez des entités Hibernate ou JPA. Nous avons adopté une autre solution, en utilisant un framework de persistance de style Django avec des entités très légères).
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 transforme notre code JS en énorme. Nous sommes donc en train d'analyser pour évoluer vers RequestFactory. J'ai été lu pendant quelques jours en fouillant sur le Web et en essayant de trouver ce que font les autres. L'inconvénient le plus important que j'ai vu, et peut-être que je peux me tromper, c'est qu'avec RequestFactory, vous ne contrôlez plus la communication entre vos objets de domaine de serveur et ceux de votre client. Ce dont nous avons besoin, c'est d'appliquer le modèle de chargement/sauvegarde de manière contrôlée. Je veux dire, par exemple, le client reçoit le graphe d'objet entier des objets appartenant à une transaction spécifique, fait ses mises à jour et les renvoie 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 doit pas être la fusionnée. L'une des mises à jour devrait échouer dans mon scénario. Je ne vois pas que RequestFactory aide à prendre en charge ce type de traitement.
Cordialement Daniel
Est-il juste de dire que lorsque l'on considère une application SIG limitée, disons avec 10-20 objets métier CRUD'ables, et chacun avec ~ 1-10 propriétés, que c'est vraiment à la préférence personnelle quelle route suivre?
Si oui, alors peut-être que la projection de la façon dont votre application va évoluer pourrait être la clé dans le choix de votre itinéraire GWT RPC ou RequestFactory:
On s'attend à ce que ma candidature reste avec ce nombre relativement limité d'entités, mais augmentera massivement en termes de nombre. 10-20 objets * 100 000 enregistrements.
Ma candidature va augmenter de manière significative dans l'étendue des entités mais le nombre relatif impliqué de chacune restera faible. 5000 objets * 100 enregistrements.
On s'attend à ce que ma demande reste avec ce nombre relativement limité d'entités ET restera en nombre relativement faible, par ex. 10-20 objets * 100 enregistrements
Dans mon cas, je suis sur le point de commencer à essayer de prendre cette décision. Encore plus compliqué en devant changer l'architecture côté client de l'interface utilisateur ainsi qu'en faisant le choix de transport. Mon interface utilisateur GWT à grande échelle précédente (de manière significative) utilisait la bibliothèque Hmvc4Gwt, qui a été remplacée par les installations GWT MVP.
La seule mise en garde que je voudrais apporter 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 demande/réponse HTTP (comme GWT-RPC), mais serait plus difficile avec deRPC ou RequestFactory.