Journée 2
Deuxième journée de formation du training « JBoss for Advanced J2EE developers ».
Tout d’abord je tiens à présenter les 3 personnes de JBoss qui nous ont fait cette formation (et compléter ce que je disais hier). L’orateur principal est Kabir Khan, venu de Norvège. Après un temps passé en Angleterre et en Espagne, il a rejoint JBoss Europe en septembre 2004. Il est l’un des développeurs de JBoss AOP avec Bill Burke.
Pour l’assister, Thomas Diesler qui vient d’Allemagne, était aussi présent. Il a solide background sur J2EE, les EJB, l’architecture CMP 2.0. Il travaille maintenant sur JBoss Web Services, c’est le monsieur Jboss-WS. C’est un gars très sympa et qui explique simplement des choses complexes.
Enfin Mladen Turk était aussi présent. Venu de Croatie, Mladen nous a présenté un article qu’il écrit actuellement sur l’intégration entre Apache, Tomcat et mod_jk. C’est un des contributeurs d’Apache, il est l’auteur de mod_jk le module qui permet de brancher Tomcat avec Apache. Au sein de JBoss il travaille sur JBossWeb et l’intégration native de serveurs Webs comme Apache ou IIS avec Tomcat.
La deuxième journée a commencé par le système des proxy dynamiques côté client (Dynamic Proxies et Client Interceptors). La génération de proxy côté client repose sur la class java.lang.reflect.Proxy introduite à partir de la version 1.3 du JDK. Cela permet au client au niveau du code d’utiliser un object comme si celui-ci était présent dans la même JVM, et de transferer à la volée les appels locaux vers une JVM distante. D’autre part, cela permet à JBoss d’avoir ce qu’ils appellent des DETYPED CHAIN que je ne me risquerai pas à traduire. Dans le monde de RMI, vous implémentez une interface locale du côté du client. Votre client va donc appeler la méthode userTest.getUserName()
. JBoss propose de détyper ces appels pour que l’implémentation change sans que le client soit obligé de réécrire le code. On a alors une méthode invoke(…) qui est appelée et qui sera executée avec getUserName
en argument.
La deuxième notion qui nous a été présenté est le principe des Interceptors. Il s’agit de class qui ajoutent des comportements à la volée sur un appel de méthode. Utilisant le pattern Chain of Responsability ce principe permet côté client d’ajouter à la volée des fonctionnalités telles que le logging, la gestion des transactions, la sécurité, etc. Nous avons vu cela en détail. Enfin ce pattern de Client Proxy est poussé jusqu`au bout au niveau des EJB. Les EJBHome et les EJBObjects sont des instances de proxy qui implémente la partie EJB du côté client. Par client, il faut comprendre aussi qu’il peut s’agir d’un client distant via RMI mais aussi un autre MBean dans le conteneur JBoss ! Et aussi un SessionStateful bean ! Il faut se souvenir que EJB sont des Remotes Interfaces. Cela permet d’accélerer le fonctionnement du conteneur de manière transparente.
La suite nous a présenté les Invokers qui sont des MBeans fonctionnnant dans le micro-kernel de JBoss. Les Invokers permettent de fournir une interface de transport pour recevoir des appels distants de client qui ne peuvent pas être connecté directement avec des MBean. Ainsi si vous avez un Mbean qui envoie un email, il est facile d’ajouter un Invoker pour recevoir des commandes via JMS, puis d’ajouter un autre Invoker utilisant RMI/JRMP pour un client Java distant, le tout utilisant le même MBean. Et ce, parce que le micro-kernel de JBoss est un Mediator
(Pattern) qui centralise les appels. Cerise sur le gâteau, j’ai compris qu’il était facile d’avoir un Invoker de type Web Services pour pouvoir ajouter une interface SOAP à une application J2EE existante.
Ensuite nous avons abordé la partie serveur. Comment sont gérer les connexions vers les MBean dans JBoss ? Comment s’effectue l’invocation d’une méthode ? Nous avons eu aussi la présentation des Interceptors mais côté serveur qui permettent de fournir les services suivants: sécurité, transaction, locking, instance et synchronization. Nous avons vu comment écrire nos propres Interceptors si nécessaire. Après avoir parlé du JRMP Proxy, l’invoker principal de JBoss pour les MBeans, nous avons vu comment le serveur d’application J2EE est implémenté avec l’architecture qui nous a été présenté. Un container EJB c’est des Interceptors, un plugin par conteneur et des MBeans sur le serveur. Lorsqu’un fichier .EAR est placé dans le répertoire deploy de JBoss, le deployer EAR charge l’archive, retrouve l’interface Home et l’enregistre sur JNDI. Les Interceptors permettent de fournir les fonctions suivantes: logging, security, transaction (géré par le conteneur), le locking d’instance lorsque 2 threads accèdent au même objet, l’acquisition d’instance (ou comment retrouver l’objet XXX qui correspond à l’appel) et donc la gestion du cache. Les EJB entity disposent d’un cache dans JBoss dont la gestion (policy) est déterminée dans la configuration. Il existe 4 types de « Commit » pour le cache:
- Commit option A: le cache est toujours vrai par rapport à la DB. Cas où JBoss est le seul client de la DB
- Commit option B: le cache n’est jamais vrai, il faut tout le temps recharger les données à partir de la DB.
- Commit option C: pareil que B mais en plus le contexte utilisé dans les entity n’est jamais valide (encore + lent)
- Commit option D (JBoss only) pareil que commit option A mais avec un rechargement toutes les n secondes du cache. Cette option permet de décider que les données du cache peuvent être désynchronisée de la DB pendant n secondes par exemple.
En conclusion, nous avons appris lors de cette session le fonctionnement de JBoss et du conteneur EJB. Nous avons aussi vu comment écrire nos propres Interceptors.
Changement de sujet l’après-midi: Aspect-Oriented Middleware/AOP par Kabir. Qu’est-ce que AOM/AOP? présentation de l’outil JBoss AOP et exemples de programmation par Aspects. J’avais entendu parler de AOP et j’avais quelques à-priori négatifs. Pour moi, encore une couche de « je mets des tags dans mon fichier Java et ça fait telle fonction » comme le fait XDoclet. Et bien ça n’a rien n’à voir…
Aspect Oriented Programming (AOP) est une technologie Java qui part du constat suivant: lorsque l’on écrit du code Java, le code est pollué par du code pour effectuer des fonctions métiers comme le logging, la sécurité ou l’authentification. D’autre part ces fonctionalités ne sont pas particulières au code que l’on écrit. C’est pour cela qu’il est recommandé d’utiliser des API comme Log4J pour tout ce qui est logging, JXTA pour les transactions ou JAAS pour l’authentification et la sécurité. Cependant on reste obligé d’ajouter dans le code des appels vers ces outils et cela rajoute du code inutile. Il n’est pas possible ensuite de retirer ce code sans réécrire une partie. Et ce, parce que l’assemblage de ces fonctions se fait à la compilation.
AOP propose une autre approche. Il définit la notion d’Aspect. Un aspect est une class Java qui définit des Advices. Un advice est un event-handler appelé par le framework AOP lorsqu’un certain évenement est rencontré. Les types d’évenement sont: les accès à une instance, à une class, à un champ (Field), l’entrée dans une méthode et la sortie, etc. D’autre part, AOP étant ajouté à la compilation, il est possible de voir les accès aux membres private d’une classe. Pour mettre en place cela, AOP définit une autre notion: les Pointcuts. C’est un langage de requête qui permet de dire au moteur: si une méthode du package org.jboss est appelée alors appelle tel advice ou « Si le constructeur est appelé avec en argument une instance de la class XXX alors execute tel advice« . La syntaxe du langage Pointcuts est assez souple pour permettre des opérations booléennes et utiliser des jokers.
Comment AOP s’intègre dans du code ? Si le code existe déjà, les Pointcuts qui sont définit dans un fichier XML sont compilés avec un outil livré avec AOP. Sinon il est aussi possible d’utiliser des mots clés dans le code Java, comme Java 5.0 le permet. Cela ressemble à XDoclet à la différence que ces marqueurs ne sont pas mis dans la javadoc mais directement dans le code. L’inconvénient est qu’il faut alors utiliser Java 5.0 et que tous les éditeurs java ne le supportent pas encore (Intellij IDEA le fait très bien cependant).
Nous avons demandé quel est le coût en terme de vitesse d’execution d’AOP ? Cela dépend de la quantité d’appels délégués à AOP. Mais il est assez minime puisque le code est compilé et le framework travaille sur la JVM directement. Il intercepte les appels en examinant la pile d’execution et le bytecode. Cela peut paraître assez étrange mais c’est le moyen trouvé pour permettre d’ajouter des appels AOP sur du code existant. Quels sont les use-cases d’AOP ? Pour effectuer des mesures de performances par exemple. Il est possible ainsi d’ajouter des Metrics le temps de faire des benchmarks. Puis une fois les tests terminés, de retirer cela sans devoir modifier l’application… Je crois que les tests de performances sur P.D.S. (notre produit) seront fait avec AOP et très bientôt…
Nous avons terminé cette deuxième journée par un labs sur AOP.
Fin de la journée 2