<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:media="http://search.yahoo.com/mrss/"
> <channel><title>Blog Xebia France &#187; Benoit Moussaud</title> <atom:link href="http://blog.xebia.fr/author/bmoussaud/feed/" rel="self" type="application/rss+xml" /><link>http://blog.xebia.fr</link> <description>J2EE, Agilité et SOA</description> <lastBuildDate>Wed, 08 Feb 2012 09:23:16 +0000</lastBuildDate> <language>fr</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=</generator> <copyright>CC BY-NC-ND 2.0 http://creativecommons.org/licenses/by-nc-nd/2.0/fr/</copyright> <managingEditor>blog-france@xebia.com (Xebia France)</managingEditor> <webMaster>blog-france@xebia.com (Xebia France)</webMaster> <ttl>1440</ttl> <image> <url>http://blog.xebia.fr/videos/xebia-podcast.png</url><title>Blog Xebia France</title><link>http://blog.xebia.fr</link> <width>144</width> <height>144</height> </image> <itunes:new-feed-url>http://blog.xebia.fr/feed/podcast/</itunes:new-feed-url> <itunes:subtitle>Les podcasts de Xebia France vous permettent de suivre l&#039;actualité autour de Java, de l&#039;agilité, des technologies Web et bien d&#039;autres. Xebia France est une entreprise spécialisée dans les technologies Java et JEE en environnement agi[...]</itunes:subtitle> <itunes:summary>Les podcasts de Xebia France vous permettent de suivre l&#039;actualité autour de Java, de l&#039;agilité, des technologies Web et bien d&#039;autres. Xebia France est une entreprise spécialisée dans les technologies Java et JEE en environnement agile.</itunes:summary> <itunes:keywords>Xebia, Java, JEE, SOA, Agile, Méthodes, Agiles</itunes:keywords> <itunes:category text="Technology" /> <itunes:category text="Technology"> <itunes:category text="Software How-To" /> </itunes:category> <itunes:category text="Technology"> <itunes:category text="Tech News" /> </itunes:category> <itunes:author>Xebia France</itunes:author> <itunes:owner> <itunes:name>Xebia France</itunes:name> <itunes:email>blog-france@xebia.com</itunes:email> </itunes:owner> <itunes:block>no</itunes:block> <itunes:explicit>no</itunes:explicit> <itunes:image href="http://blog.xebia.fr/videos/xebia-podcast.png" /> <item><title>Séminaire Deployit: Karavel automatise ses déploiements Tomcat</title><link>http://blog.xebia.fr/2011/04/27/seminaire-deployit-karavel-automatise-ses-deploiements-tomcat/</link> <comments>http://blog.xebia.fr/2011/04/27/seminaire-deployit-karavel-automatise-ses-deploiements-tomcat/#comments</comments> <pubDate>Wed, 27 Apr 2011 14:06:51 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Exploitation]]></category> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Déploiement]]></category> <category><![CDATA[DeployIt]]></category> <category><![CDATA[Séminaire]]></category> <category><![CDATA[Tomcat]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=7555</guid> <description><![CDATA[De nombreuses sociétés font aujourd&#8217;hui confiance aux technologies Java EE pour leurs applications critiques d&#8217;entreprise, leurs sites web et / ou leur intranet. Pourtant, nombre d&#8217;entre elles se retrouvent aujourd&#8217;hui confrontées à un obstacle de taille : comment déployer plus rapidement et de manière plus industrielle des applications toujours complexes, livrées de plus en plus [...]]]></description> <content:encoded><![CDATA[<p>De nombreuses sociétés font aujourd&#8217;hui confiance aux technologies Java EE pour leurs applications critiques d&#8217;entreprise, leurs sites web et / ou leur intranet. Pourtant, nombre d&#8217;entre elles se retrouvent aujourd&#8217;hui confrontées à un obstacle de taille : comment déployer plus rapidement et de manière plus industrielle des applications toujours complexes, livrées de plus en plus fréquemment sur des socles middlewares différents et/ou sur des environnements de plus en plus nombreux ?</p><p>Les tâches de déploiement et de configuration des applications deviennent ainsi bien souvent un goulet d&#8217;étranglement quand elles ne sont pas un frein à l&#8217;activité.<br
/> <strong>Deployit</strong>, de la société <strong>XebiaLabs</strong>, a été conçu en collaboration avec KLM/Air France pour adresser cette problématique. Il est aujourd&#8217;hui mis en oeuvre avec succès par de nombreuses sociétés dans des secteurs très variés.</p><p>Les bénéfices de Deployit</p><ul><li>Réduire jusqu’à 95% des erreurs de déploiement et jusqu&#8217;à 50% de vos coûts de déploiement classique</li><li>Réduire les temps d&#8217;attente des équipes via des déploiements en self-service et continus</li><li>Standardiser les procédures de déploiement entre différents environnements</li><li>Fluidifier les relations entre départements études, intégration/recette et production</li><li>Augmenter contrôle et visibilité sur votre processus de déploiement applicatif</li><li>Accélérer votre time-to-market</ul><p>Programme du séminaire : le<strong> 29 avril de 9h45 à 11h45, 156 bd Haussmann 75008 Paris</strong></p><ul><li>9h45 : accueil</li><li>10h : présentation des enjeux du déploiement applicatif et de la solution Deployit</li><li>10h30 : démonstration produit</li><li>11h : retour d&#8217;expérience client Karavel/Promovacances</li></ul><p><strong>Public cible</strong> : Directeur Informatique, Responsable des Développements / Etudes, Responsable Intégration / QA / Tests, Responsable Production / Exploitation, Responsable Qualité, Architecte, Chef de projet</p><p><strong>Inscription</strong>: <a
href="http://www.xebialabs.com/seminaire-deploiement-automatique">http://www.xebialabs.com/seminaire-deploiement-automatique</a></p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2011/04/27/seminaire-deployit-karavel-automatise-ses-deploiements-tomcat/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Les fournisseurs de serveurs d&#8217;application ont-ils vraiment compris le déploiement ?</title><link>http://blog.xebia.fr/2009/11/16/les-fournisseurs-de-serveurs-dapplication-ont-ils-vraiment-compris-le-deploiement/</link> <comments>http://blog.xebia.fr/2009/11/16/les-fournisseurs-de-serveurs-dapplication-ont-ils-vraiment-compris-le-deploiement/#comments</comments> <pubDate>Mon, 16 Nov 2009 11:09:35 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Exploitation]]></category> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Déploiement]]></category> <category><![CDATA[DeployIt]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=3130</guid> <description><![CDATA[Chez XebiaLabs, nous nous y connaissons en déploiement automatique d&#8217;applications Java EE. L&#8217;une des choses les plus surprenantes réside dans le fait que «les fournisseurs de serveurs d&#8217;application ne semblent pas faire partie des personnes qui maitrisent le mieux le déploiement d&#8217;applications». Dans un article précédent, nous avons décrit ce que nous considérons comme le [...]]]></description> <content:encoded><![CDATA[<p><img
src="http://www.xebialabs.com/sites/all/themes/xebialabs/images/block-sidebar-green-not-front.png" alt="DeployIt" style="margin: 1em 1em 1em 1em; float: right;" /></p><p>Chez <a
href="http://www.xebialabs.com/" title="XebiaLabs" >XebiaLabs</a>, nous nous y connaissons en déploiement automatique d&#8217;applications Java EE. L&#8217;une des choses les plus surprenantes réside dans le fait que «les fournisseurs de serveurs d&#8217;application ne semblent pas faire partie des personnes qui maitrisent le mieux le déploiement d&#8217;applications».</p><p>Dans un article précédent, nous avons décrit ce que nous considérons comme le <a
href="http://blog.xebia.fr/2009/10/20/le-deploiement-cas-decole/" title="dploiement dapplication J2EE global" >déploiement d&#8217;application J2EE global</a>. Et force est de constater que:</p><ul><li>Déployer va bien au delà d&#8217;un simple déploiement d&#8217;un EAR ou d&#8217;un WAR.</li><li>La plupart des applications ont également besoin d&#8217;autres artéfacts comme par exemple du contenu statique pour le serveur web ou encore des fichiers de configuration, utilisés par le code java, au démarrage.</li><li>Il faut également configurer des ressources JEE comme des Datasources JDBC ou des composants JMS (Queues, Topics, Servers).</li><li>A ceci s&#8217;ajoute, bien entendu, la configuration du middleware lui-même: création et configuration de clusters de serveurs d&#8217;application ou de virtual hosts d&#8217;un serveur Apache.</li><li>L&#8217;ordre d&#8217;exécution des tâches est important afin de réduire (voire de prévenir) la coupure de service de l&#8217;application pendant le déploiement et d&#8217;en augmenter la vitesse.</li></ul><p>Alors posons nous la question. Que nous proposent les fournisseurs de serveurs d&#8217;application dans ce domaine ?</p><h3><a
name="OracleWebLogicServer"></a>Oracle WebLogic Server</h3><p>Oracle WebLogic Server propose un concept de &#8216;Deployment&#8217;: c&#8217;est la <a
href="http://download.oracle.com/docs/cd/E15051_01/wls/docs103/ConsoleHelp/taskhelp/applications/DeployEnterpriseApplications.html" title="chose que vous créez" >chose que vous créez</a> quand vous déployez un EAR, un WAR ou un EJB Jar. Sic ! Vous pouvez l&#8217;adapter à l&#8217;environnement en fournissant un <a
href="http://blog.xebia.fr/2008/04/17/les-plans-de-deploiement-weblogic/" title="plan de dploiement" >plan de déploiement</a>. Cependant, rien n&#8217;est proposé pour regrouper plusieurs artéfacts JEE dans un seul déploiement ou inclure la création de ressources JEE telle qu&#8217;une Datasource.</p><p>Dans WebLogic, il y a le concept de &#8216;<a
href="http://download.oracle.com/docs/cd/E15051_01/wls/docs103/jms_admin/basic_config.html#wp1170473" title="SubDeployement'" >SubDeployement&#8217;</a> mais étrangement il n&#8217;est pas corrélé à un déploiement. C&#8217;est un mécanisme utilisé pour cibler des parties d&#8217;un <a
href="http://download.oracle.com/docs/cd/E15051_01/wls/docs103/jms_admin/basic_config.html#wp1170355" title="module JMS" >module JMS</a> vers des serveurs JMS ou des serveurs WebLogic. L&#8217;artifice proposé par les modules JMS semble destiné seulement à regrouper des ressources JMS. Sans doute qu&#8217;un jour un développeur l&#8217;a initialement appelé Déploiement sans se souvenir que le concept existait déjà dans WebLogic et il l&#8217;a alors renommé SubDeployement. Bien sûr, tout ceci n&#8217;est que supputation!</p><p>WebLogic propose un grand nombre d&#8217;API pour le déploiement: l&#8217;historique <a
href="http://download.oracle.com/docs/cd/E15051_01/wls/docs103/deployment/deploy.html" title="weblogic.Deployer" >weblogic.Deployer</a> en ligne de commande, la tâche ANT <a
href="http://download.oracle.com/docs/cd/E12840_01/wls/docs103/programming/wldeploy.html" title="wldeploy" >wldeploy</a> et le <a
href="http://download.oracle.com/docs/cd/E15051_01/wls/docs103/config_scripting/index.html" title="WebLogic Scripting Tools" >WebLogic Scripting Tools</a>, WLST pour les intimes, basé sur Python. Ce dernier est, je pense, le plus complet. Grâce à sa représentation sous forme de système de fichier de la hiérarchie des MBeans, il fournit un moyen très intuitif d&#8217;accéder à l&#8217;information.</p><h3><a
name="JBossApplicationServer"></a>JBoss Application Server</h3><p>Le déploiement dans JBoss est géré par le <a
href="http://www.jboss.org/file-access/default/members/jbossas/freezone/docs/Administration_And_Configuration_Guide/5/html/virtual_deployment_framework.html" title="Virtual Deployment Framework" >Virtual Deployment Framework</a>. C&#8217;est un framework basé sur des MBeans qui permet à différents artéfacts (EARs, WARs, EJB JARs, RARs, SARs &#8230;) et à différentes ressources (sources de données, paramètres JMS &#8230;) d&#8217;être déployés sur JBoss. Tout ceci est géré par leurs <a
href="http://www.jboss.org/file-access/default/members/jbossas/freezone/docs/Administration_And_Configuration_Guide/5/html/ch06s04.html" title="deployers" >deployers</a>.</p><p>Cependant, la plupart des gens n&#8217;invoque pas ces <code>deployers</code>, ni même &#8216;<a
href="http://www.jboss.org/community/wiki/Twiddle" title="twiddle" >twiddle</a>&#8216;. Ils préfèrent simplement déposer leurs artéfacts dans le répertoire <code>deploy/</code> de leur serveur d&#8217;application Jboss, puis attendre que le <a
href="http://www.jboss.org/community/wiki/ConfiguringTheDeploymentScannerInConfjbossSystemxml" title="Deployment Scanner" >Deployment Scanner</a> le détecte. Ils vérifient ensuite dans le fichier de log que le déploiement est terminé.</p><p>Le souci avec cette méthode : le déploiement n&#8217;est pas une opération atomique. Quand on automatise un déploiement, on ne veut redémarrer le serveur web qu&#8217;après un déploiement réussi du nouveau WAR. Mais écrire un bout de code qui analyse les logs du serveur à la recherche d&#8217;un mot clé est tout simplement moche. Une alternative serait de positionner la propriété <code>ScanEnabled</code> du <code>DeploymentScanner</code> à <code>false</code> d&#8217;invoquer manuellement le <code>deployer</code>. Non seulement cela complexifie le code, mais il faut également prévoir la copie des fichiers dans le répertoire <code>deploy</code> du serveur JBoss.</p><p>Ainsi, il s&#8217;avère qu&#8217;avec JBoss Application Server, il est difficile d&#8217;intégrer des déploiements vers ses serveurs dans un scénario de déploiement plus global. RedHat doit corriger ce problème au plus vite pour que JBoss soit réellement prêt pour les entreprises.</p><h3><a
name="IBMWebSphereApplicationServer"></a>IBM WebSphere Application Server</h3><p>Et pour le gros monstre JEE de chez &#8216;Big Blue&#8217; ? Il offre une façon polyvalente et transactionnelle pour déployer des applications et des ressources. Globalement, le langage de script <a
href="http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/txml_launchscript.html" title="wsadmin" >wsadmin</a> permet de contrôler tous les aspects de WebSphere. Par exemple, vous pouvez synchroniser des nœuds explicitement et l&#8217;invocation de la méthode (par Jython ou JACL) pour déployer l&#8217;application ne rendra la main que lorsque l&#8217;opération sera réalisée. Le côté négatif est qu&#8217;il est beaucoup plus lent que l&#8217;outil similaire WLST proposé par WebLogic (les nombreuses copies de documents XML à travers SOAP doivent y être pour quelque chose) et les API proposées sont plutôt complexes à manipuler (qui peut donner la différences entre un <code>containment path</code>, un <code>configuration id</code> et un <code>object name</code>?)</p><p>Bien que WAS ne propose pas de mécanismes pour regrouper les différents artéfacts et ressources liés à un même déploiement, sa nature transactionnelle permet de commiter les différents changements de configuration en une fois. Il peut même gérer la configuration des instances des serveurs <a
href="http://www-01.ibm.com/software/webservers/httpservers/" title="IBM HTTP Server" >IBM HTTP Server</a> ou <a
href="http://httpd.apache.org/" title="Apache HTTP Server" >Apache HTTP Server</a> .</p><p>Malgré une vitesse de déploiement lente, rien ne vaut la fiabilité des déploiements de WebSphere !</p><h3><a
name="Conclusion"></a>Conclusion</h3><p>Les serveurs d&#8217;application fournissent chacun un niveau de support différent pour prendre en charge les déploiements des applications d&#8217;entreprise. Bien sûr, ils offrent tous le déploiement basique des artéfacts Java EE mais aucun d&#8217;entre eux ne propose de regrouper différents artéfacts en un seul déploiement ou de lier des ressources Java EE à ces artéfacts. WebLogic Server est le seul qui essaye de regrouper des ressources (JMS Modules et SubDeployment). Mais ces abstractions ne couvrent qu&#8217;une petite partie de toute l&#8217;étendue du déploiement Java EE.</p><p>La répétition et la prédiction sont très importantes pour une stratégie de déploiement réussie, ce qui peut expliquer la prévisibilité de WebSphere sur le marché. Et finalement, une bonne API est nécessaire pour automatiser votre processus de déploiement: WebLogic et WebSphere l&#8217;offrent, JBoss a un sérieux manque dans ce domaine (même avec <code>twiddle</code> !)</p><p>Les consultants de <a
href="http://www.xebia.fr/" title="Xebia" >Xebia</a> et l&#8217;ensemble des développeurs chez <a
href="http://www.xebialabs.com/" title="XebiaLabs" >XebiaLabs</a> ont quasiment tous écrit dans leurs expériences passées des tonnes de scripts pour automatiser des déploiements et ont dû batailler sur ces questions encore et encore. Nous avons développé <a
href="http://www.xebialabs.com/deployit-automated-deployment-java-applications" title="Deployit" >Deployit</a> afin de prendre en charge ces différences entre serveurs d&#8217;applications et parce que nous croyons que l&#8217;automatisation des déploiements est de la plus haute importance du fait du nombre croissant de déploiements dans les entreprises.</p><p>&#8211;<br
/> Traduction libre du billet «<a
href="http://blog.xebia.com/2009/11/13/do-application-server-vendors-really-understand-deployment/" title="Do application server vendors really understand deployment? " >Do application server vendors really understand deployment? </a>» publié par Vincent Partington.</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2009/11/16/les-fournisseurs-de-serveurs-dapplication-ont-ils-vraiment-compris-le-deploiement/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Booster vos recherches avec Oracle Coherence</title><link>http://blog.xebia.fr/2009/10/14/booster-vos-recherches-avec-oracle-coherence/</link> <comments>http://blog.xebia.fr/2009/10/14/booster-vos-recherches-avec-oracle-coherence/#comments</comments> <pubDate>Wed, 14 Oct 2009 08:36:24 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[Coherence]]></category> <category><![CDATA[Oracle]]></category> <category><![CDATA[Performances]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=2996</guid> <description><![CDATA[Oracle Coherence est une solution de Data Grid. Elle permet de constituer des grilles de données à l&#8217;aide de 4 types de caches: Cache distribué: l&#8217;ensemble des données est réparti sur les différents nœuds qui composent le cluster Coherence. Afin de garantir une bonne tolérance aux pannes, les données peuvent être sauvegardées sur un ou [...]]]></description> <content:encoded><![CDATA[<p>Oracle Coherence est une solution de <a
href="http://blog.xebia.fr/2009/05/06/paris-jug-soiree-grid-computing-le-12-mai/" title="Data Grid" >Data Grid</a>. Elle permet de constituer des grilles de données à l&#8217;aide de 4 types de caches:</p><ul><li>Cache distribué: l&#8217;ensemble des données est réparti sur les différents nœuds qui composent le cluster Coherence. Afin de garantir une bonne tolérance aux pannes, les données peuvent être sauvegardées sur un ou plusieurs nœuds du cluster. Cette typologie est extrêmement extensible : il suffit d&#8217;ajouter des nouveaux nœuds pour augmenter la capacité globale du cache.</li><li>Cache répliqué: l&#8217;ensemble des données est répliqué sur l&#8217;ensemble des nœuds du cluster. La modification d&#8217;une entrée sera propagée à l&#8217;ensemble des nœuds. Cette typologie permet d&#8217;offrir un accès très rapide en lecture car un seul nœud est sollicité dans l&#8217;opération. La contre-partie est que les opérations d&#8217;écriture sont lentes et que la taille du cache est indépendante du nombre de nœuds qui composent le cluster.</li><li>Cache local: les données sont conservées exclusivement sur la JVM.</li><li>Near Cache: il permet d&#8217;offrir le meilleur des caches de type &#8216;Répliqué&#8217; (Performance) et de type &#8216;Distribué&#8217; (Extensibilité) en fournissant un accès rapide aux données accédées le plus fréquemment et le plus récemment. Il est composé de 2 parties:</li><ul><li>le &#8216;front-cache&#8217; pour les accès locaux, de petite taille, typiquement un cache Local (Local Cache),</li><li>le &#8216;back-cache&#8217; un cache de plus grande envergure, typiquement un cache distribué (Distributed Cache), qui contient l&#8217;ensemble des données avec leurs éventuelles sauvegardes.</li></ul></ul><p>Le point fort d&#8217;Oracle Coherence est de proposer la même API quelque soit le type de cache. Il est donc possible, par simple configuration, de modifier le type de cache et de l&#8217;adapter en fonction des besoins ou de l&#8217;environnement: cache local en &laquo;&nbsp;Développement&nbsp;&raquo;, cache distribué en &laquo;&nbsp;Intégration&nbsp;&raquo;, &laquo;&nbsp;Near&nbsp;&raquo; cache en &laquo;&nbsp;Production&nbsp;&raquo;.</p><p>En première approche, l&#8217;API d&#8217;Oracle Coherence est extrêmement simple : elle se résume à obtenir une <a
href="http://java.sun.com/javase/6/docs/api/java/util/Map.html" title="Map" ><code>Map</code></a> et à la manipuler par les opérations habituelles: put(), get(), keySet(), entrySet()&#8230;.</p><pre class="brush: java; title: ; notranslate">
import com.tangosol.net.CacheFactory;
Map cache = CacheFactory.getCache(&quot;moncache&quot;);        //1. Récupération d'une instance de cache,
cache.put(&quot;benoit&quot;,&quot;moussaud&quot;);                       //2. Ajout d'un élément dans le cache
String name = (String)cache.get(&quot;benoit&quot;);            //3. Recherche par sa clé d'un élément dans le cache
assert name.equals(&quot;moussaud&quot;);
</pre><p>Le type de cache est déduit du nom du cache. Il est configuré dans le fichier <code>coherence-cache-config.xml</code> inclus dans <code>coherence.jar</code>. Par défaut, les règles suivantes sont appliquées:</p><table
cellspacing="0" cellpadding="5" style="border: 1px solid black"><tr><td
bgcolor="#663366" style="color: #ffffff; border: 1px solid black"> Nom du cache</td><td
bgcolor="#663366" style="color: #ffffff; border: 1px solid black"> Type</td></tr><tr><td
style="border: 1px solid black"> <code>dist-*</code></td><td
style="border: 1px solid black"> distribué</td></tr><tr><td
style="border: 1px solid black"> <code>near-*</code></td><td
style="border: 1px solid black"> near cache</td></tr><tr><td
style="border: 1px solid black"> <code>repl-*</code></td><td
style="border: 1px solid black"> repliqué</td></tr><tr><td
style="border: 1px solid black"> <code>local-*</code></td><td
style="border: 1px solid black"> local</td></tr><tr><td
style="border: 1px solid black"> sinon</td><td
style="border: 1px solid black"> distribué</td></tr></table><p>Si l&#8217;on veut appliquer ses propres règles, il faut définir son propre fichier de configuration et indiquer son emplacement au lancement de Coherence avec la propriété système <code>tangosol.coherence.cacheconfig</code>.</p><p>La suite de l&#8217;article va montrer comment interroger un cache Coherence autrement que par une clé dans une Map.</p><h4><a
name="Unservicederecherchedecommunes"></a>Un service de recherche de communes&#8230;</h4><p>Prenons un service qui permet de rechercher l&#8217;ensemble des communes françaises en précisant le début de leur nom.</p><pre class="brush: java; title: ; notranslate">
public interface CatalogService {
	public List&lt;Commune&gt; getCommuneByName(String name);
}
</pre><p>Une implémentation classique est de créer une table &#8216;COMMUNE&#8217; dans une base de données, d&#8217;y insérer les ensembles des communes de France (38206 dans mon exemple) avec leur libellé, un code postal et un code Insee, et d&#8217;effectuer la requête SQL <code>SELECT ID, DEP_CODE, CODE_INSEE, LIBELLE FROM COMMUNE where LIBELLE like #name#</code>.</p><p>Voici le résultat d&#8217;un benchmark du service avec pour paramètre la première lettre de la commune (de A à Z)</p><div
id="attachment_3003" class="wp-caption aligncenter" style="width: 643px"><img
src="http://blog.xebia.fr/wp-content/uploads/2009/10/bdd.png" alt="Résultat du benchmark Base de données" title="Résultat du benchmark Base de données" width="633" height="426" class="size-full wp-image-3003" /><p
class="wp-caption-text">Benchmark Base de données</p></div><p>Le temps de réponse du service est mauvais et proportionnel au nombre de communes retournées</p><h4><a
name="Coherencelarescousse"></a>&#8230;Coherence à la rescousse&#8230;</h4><p>La première idée est de placer le résultat de la recherche dans un cache avec pour clé le paramètre de recherche. Ce type de conception est efficace seulement si le nombre de filtres est fini, par exemple s&#8217;il résulte d&#8217;une sélection d&#8217;une combo-box dans une page web. Si la valeur du filtre est moins contrainte, le service sera appelé par un grand nombre de filtres différents et donc le cache risque d&#8217;être peu efficace (à moins de disposer d&#8217;une mémoire infinie de manière à conserver toutes les requêtes !).</p><p>La seconde idée est de charger dans un cache l&#8217;ensemble des communes et d&#8217;effectuer une recherche directement dans le cache. L&#8217;API Coherence offre la notion de <code>Filter</code></p><pre class="brush: java; title: ; notranslate">
public class CatalogServiceWithCoherence implements CatalogService,
     private final NamedCache cacheCommunes = CacheFactory.getCache(&quot;Commune&quot;);
     public List&lt;Commune&gt; getCommuneByName(String name) {
         Filter filter = new LikeFilter(&quot;getName&quot;, name + &quot;%&quot;, false);
         return performSearch(filter);
     }
     @SuppressWarnings(&quot;unchecked&quot;)
     private List&lt;Commune&gt; performSearch(Filter filter) {
         Set&lt;Map.Entry&lt;Object, Commune&gt;&gt; entrySet=cacheCommunes
                 .entrySet(filter);
         List&lt;Commune&gt; result = new ArrayList&lt;Commune&gt;(entrySet.size());
         for (Map.Entry&lt;Object, Commune&gt; e : entrySet) {
             result.add(e.getValue());
         }
         return result;
     }
}
</pre><p>Appliquons le même benchmark.</p><div
id="attachment_3005" class="wp-caption aligncenter" style="width: 613px"><img
src="http://blog.xebia.fr/wp-content/uploads/2009/10/coherence-filter.png" alt="Résultat du benchmark Coherence avec Filtre" title="Résultat du benchmark Coherence avec Filtre" width="603" height="428" class="size-full wp-image-3005" /><p
class="wp-caption-text">Résultat du benchmark Coherence avec Filtre</p></div><p>Le temps de réponse du service est meilleur (autour de 500 ms) mais constant. Il y a donc un gain par rapport aux requêtes qui retournent beaucoup d&#8217;éléments (A,B,C,L,S,..) mais une perte sur les requêtes qui retournent peu d&#8217;éléments. Donc plus le filtre sera sélectif, moins la recherche dans le cache sera efficace.</p><p>Ceci se comprend mieux si on affine l&#8217;étude de l&#8217;API Coherence. L&#8217;interface <a
href="http://download.oracle.com/otn_hosted_doc/coherence/350/com/tangosol/util/Filter.html" title="Filter" >Filter</a> définit une seule méthode: <code>evaluate</code></p><pre class="brush: java; title: ; notranslate">
package com.tangosol.util;
public abstract interface Filter
{
  public abstract boolean evaluate(Object paramObject);
}
</pre><p>Donc une recherche dans le cache par filtre se résume à parcourir l&#8217;ensemble des entrées de la <code>Map</code> et à appliquer le filtre passé en paramètre.</p><h4><a
name="Encoreplusrapideavecunindex"></a>&#8230;Encore plus rapide avec un index</h4><p>Si on examine de plus près le filtre utilisé <a
href="http://download.oracle.com/otn_hosted_doc/coherence/350/com/tangosol/util/filter/LikeFilter.html" title="<code>LikeFilter</code>" ><code>LikeFilter</code></a>, on peut noter qu'il implémente l'interface <a
href="http://download.oracle.com/otn_hosted_doc/coherence/350/com/tangosol/util/filter/IndexAwareFilter.html" title="IndexAwareFilter" ><code>IndexAwareFilter</code></a>. Il est donc possible d'indexer le contenu d'un cache Coherence. Le code ci-dessous ajoute un index au cache "IndexedCommune": pour chaque entrée ajoutée au cache, il va extraire et indexer la valeur de la propriété "Name" (getName()).</p><pre class="brush: java; title: ; notranslate">
NamedCache cache = CacheFactory.getCache(&quot;IndexedCommune&quot;);
cache.addIndex(new ReflectionExtractor(&quot;getName&quot;), true, null);
</pre><p>Appliquons le benchmark.</p><div
id="attachment_3006" class="wp-caption aligncenter" style="width: 632px"><img
src="http://blog.xebia.fr/wp-content/uploads/2009/10/coherence-indexed-filter.png" alt="Benchmark Coherence avec filtre indexé" title="Benchmark Coherence avec filtre indexé" width="622" height="427" class="size-full wp-image-3006" /><p
class="wp-caption-text">Benchmark Coherence avec filtre indexé</p></div><p>Avec l'ajout de l'index, le temps de réponse du service a encore nettement chuté et reste proportionnel au nombre de communes retourné. Donc si le filtre est sélectif, le temps de réponse sera très bon.</p><p>En moyenne, la première solution a divisé le temps de réponse par 5, la seconde par 80. Cependant il faut garder à l'esprit qu'un accès à une valeur par son index (<code>cache.get(key)</code>) reste beaucoup plus performant que l'utilisation des <code>Filters</code>. Leurs utilisations doivent rester des exceptions.</p><h4><a
name="Conclusion"></a>Conclusion</h4><p>Les solutions de "Data Grid" modernes comme Oracle Coherence offrent maintenant des services de haut niveau, semblables à ceux offerts par des SGBD, comme la gestion de la concurrence, des transactions, des indexs, du partitionnement, qui permettent d'améliorer nettement les performances d'une application J2EE.</p><h4><a
name="Sources"></a>Sources</h4><p>Vous retrouverez l'ensemble des sources présentées dans ce billet dans le <a
href="http://code.google.com/p/xebia-france/source/browse/trunk/grid/coherence-filter/" title="repository SVN de Xebia France" >repository SVN de Xebia France</a>.</p><h4><a
name="Rfrences"></a>Références</h4><ul><li><a
href="http://www.oracle.com/technology/products/coherence/index.html " title="Oracle Coherence" >Oracle Coherence</a> (Site Officiel)</li><li><a
href=" http://blog.xebia.fr/2009/08/26/les-caches-ces-armes-a-manipuler-avec-precaution/" title="Les caches ces armes  manipuler avec prcaution" >Les caches, ces armes à manipuler avec précaution</a></li><li><a
href=" http://blog.xebia.fr/2009/05/06/paris-jug-soiree-grid-computing-le-12-mai/ " title="Paris JUG  Soire Data Grid le 12 mai" >Paris JUG : Soirée Data Grid le 12 mai</a></li><li><a
href=" http://wiki.tangosol.com/display/COH/Oracle+Coherence+Knowledge+Base+Home " title="Oracle Coherence Knowledge Base Home " >Oracle Coherence Knowledge Base Home </a></li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2009/10/14/booster-vos-recherches-avec-oracle-coherence/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Stateful Aspects</title><link>http://blog.xebia.fr/2009/08/04/stateful-aspects/</link> <comments>http://blog.xebia.fr/2009/08/04/stateful-aspects/#comments</comments> <pubDate>Tue, 04 Aug 2009 09:30:49 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[AOP]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=2609</guid> <description><![CDATA[L&#8217;AOP (Programmation Orientée Aspect) permet au sein d&#8217;un programme d&#8217;implémenter facilement des problématiques transversales, comme la gestion de transaction, les mécanismes de cache ou la sécurité. Généralement, le traitement de ces opérations est soit local à une méthode, soit sans état. Je vous propose dans cet article de vous montrer comment déclarer des aspects dont [...]]]></description> <content:encoded><![CDATA[<p>L&#8217;AOP (Programmation Orientée Aspect) permet au sein d&#8217;un programme d&#8217;implémenter facilement des problématiques transversales, comme la gestion de transaction, les mécanismes de cache ou la sécurité. Généralement, le traitement de ces opérations est soit local à une méthode, soit sans état. Je vous propose dans cet article de vous montrer comment déclarer des aspects dont le cycle de vie n&#8217;est plus celui de la JVM (static) mais fonction d&#8217;un pointcut.</p><h3><a
name="Lapplicationtmoin"></a>L&#8217;application témoin</h3><p>Voici une magnifique application ayant la structure suivante : Application -> Manager -> DAO avec un modèle simple : Caddy -> * Item. Chaque run de l&#8217;application ajoute 10 items au Caddy et effectue un paiement. Le test case effectue 5 run().</p><pre class="brush: java; title: ; notranslate">
package fr.xebia.aop.app;
import java.util.Random;
public class Application implements Runnable{
	static Random r = new Random();
	private CaddyManager  manager = new CaddyManager();
	public void run() {
		for (int i =0 ; i &lt; 10; i++) {
			manager.addItem(new Item(i,&quot;Item#&quot;+i,r.nextInt(100)));
		}
		manager.purchase();
		manager.clearCaddy();
	}
}
</pre><p>Dans la suite de l&#8217;article nous allons écrire 2 aspects qui vont nous permettre de :</p><ul><li>Connaître le nombre d&#8217;appels au DAO lors de l&#8217;appel à la méthode &#8216;purchase&#8217;.</li><li>Calculer la moyenne du prix des Item du Caddy.</li></ul><h3><a
name="NombredappelsauDAO"></a>Nombre d&#8217;appels au DAO</h3><h4><a
name="Utilisationdunaspectclassique"></a>Utilisation d&#8217;un aspect &#8216;classique&#8217;</h4><p>Le premier exemple va permettre de connaître le nombre d&#8217;appels au DAO lors de l&#8217;appel à la méthode &#8216;purchase&#8217;. Voici le code de la classe <code>CaddyManager</code>.</p><pre class="brush: java; title: ; notranslate">
package fr.xebia.aop.app;
public class CaddyManager {
	private CaddyDAO dao = new CaddyDAO();
	private Caddy caddy = new Caddy();
	public void addItem(Item i) {
		caddy.add(i);
	}
	void purchase() {
		for (Item item : caddy.getItems()) {
			 dao.persist(item);
		}
	}
	public void clearCaddy() {
		caddy.clear();
	}
}
</pre><p>Dans une vision sans état, l&#8217;aspect peut être écrit comme ceci :</p><pre class="brush: java; title: ; notranslate">
package fr.xebia.aop.aspects;
public aspect MonitorManager {
	pointcut onManager() : execution(&lt;/strong&gt; fr.xebia.aop.app.CaddyManager.purchase(..));
	pointcut onDao() : execution(* fr.xebia.aop.app.CaddyDAO.persist(..));
	int managerCalls = 0;
	int daoCalls = 0;
	Object around() : onManager() {
		managerCalls++;
		try {
			return proceed();
		} finally {
			System.out
					.println(thisJoinPointStaticPart.getSignature()
							+ &quot; managerCalls/daoCalls &quot; + managerCalls + &quot;/&quot;
							+ daoCalls);
		}
	}
	before() : onDao() {
		daoCalls++;
	}
}
</pre><p>Lors de l&#8217;exécution du test, on obtient le nombre total des appels à <code>purchase</code> et à <code>persist</code>: l&#8217;effet &#8216;Aspect Sans Etat&#8217;</p><pre class="brush: java; title: ; notranslate">
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 2/20
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 3/30
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 4/40
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 5/50
</pre><p>Cet aspect ne répond donc pas à notre problématique : obtenir un nombre d&#8217;appels &#8216;hiérarchisé&#8217; par appel à la méthode de plus haut niveau.</p><h4><a
name="Lasolutionpercflow"></a>La solution : percflow</h4><p>Il suffit de modifier légèrement l&#8217;aspect avec <code>percflow</code> pour modifier ses conditions de création:</p><pre class="brush: java; title: ; notranslate">
public aspect MonitorManager percflow(onManager()) {
// code identique
}
</pre><p>Si un aspect A est défini avec l&#8217;instruction <code>percflow(pointcut)</code>, alors une nouvelle instance de l&#8217;aspect est créée dès que le déroulement du code correspond au pointcut passé en paramètre. Dans notre exemple, avec l&#8217;ajout de <code> percflow(onManager()) </code>, la JVM va instancier l&#8217;aspect à chaque fois que le code exécutera <code>CaddyManager.purchase()</code></p><p>L&#8217;exécution du test donne maintenant 10 appels au DAO par appel de la méthode <code>purchase</code></p><pre class="brush: java; title: ; notranslate">
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
</pre><p>L&#8217;exemple est ici trivial mais ce type d&#8217;aspect placé sur une application J2EE qui aurait mal vieillie peut permettre d&#8217;en extraire les principaux chemins d&#8217;exécution.</p><h3><a
name="PrixMoyendesarticles"></a>Prix Moyen des articles</h3><h4><a
name="Utilisationdunaspectclassique"></a>Utilisation d&#8217;un aspect &#8216;classique&#8217;</h4><p>Le second exemple va permettre de calculer la moyenne du prix des Item du Caddy. Voici le code de l&#8217;aspect sans état: à chaque appel à la méthode <code> Cadd.add()</code>, le prix total et le nombre d&#8217;articles est incrémenté. L&#8217;exécution de la méthode <code>Caddy.clear()</code> affiche le résultat et remet à zéro les variables.</p><pre class="brush: java; title: ; notranslate">
public aspect MonitorItems  {
	private int total = 0;
	private int nb = 0;
	after(Item i) returning() : execution(* Caddy.add(Item)) &amp;&amp; args(i) {
		total +=i.getPrice();
		nb ++;
	}
	before(): execution(* Caddy.clear()) {
		System.out.println(&quot; Caddy items(&quot;+nb+&quot;), average price (&quot;+total/nb+&quot;)&quot;);
		total = 0;
		nb = 0;
	}
}
</pre><p>L&#8217;exécution de l&#8217;application donne un résultat correct dans sa version mono-threadée. Dans une version multi-threadée (qui se rappoche d&#8217;un serveur d&#8217;application J2EE), l&#8217;application échoue avec un message erroné (50 items au lieu de 10) suivie d&#8217;une exception:</p><pre class="brush: java; title: ; notranslate">
Caddy items(50), average price (47)
Caused by: java.lang.ArithmeticException: / by zero
	at fr.xebia.aop.aspects.MonitorItems.ajc$before$fr_xebia_aop_aspects_MonitorItems$2$6dfa1e74(MonitorItems.aj:17)
	at fr.xebia.aop.app.Caddy.clear(Caddy.java:20)
	at fr.xebia.aop.app.CaddyManager.clearCaddy(CaddyManager.java:21)
	at fr.xebia.aop.app.Application.run(Application.java:16)
</pre><p>L&#8217;ensemble des threads partagent le même aspect, et donc les mêmes attributs. Un des thread effectue la mise à zéro l&#8217;attribut de <code>nb</code> pendant l&#8217;exécution du pointcut <code>before()</code> et lorsqu&#8217;un second thread veut effectuer la moyenne, une division par zéro arrive et provoque l&#8217;exception.</p><h4><a
name="Lasolutionperthis"></a>La solution : perthis</h4><p>La solution est d&#8217;indiquer qu&#8217;il faut créer un nouvelle instance de l&#8217;aspect à chaque nouvelle instance de la classe <code>Caddy</code>. Si un aspect A est défini avec <code>perthis(pointcut)</code>, alors une nouvelle instance de l&#8217;aspect est créée pour chaque objet qui exécute (<code>this</code>), le pointcut passé en paramètre. L&#8217;instruction <code>pertarget(pointcut)</code> existe également.</p><pre class="brush: java; title: ; notranslate">
public aspect MonitorItems perthis (execution(Caddy.new(..))) {
// code identique
}
</pre><p>L&#8217;exécution du test donne maintenant un résultat correct (le prix moyen des 10 objets) en mode mono-thread <em>et</em> multi-thread.</p><pre class="brush: java; title: ; notranslate">
ApplicationTest.testSameInstanceMT()
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
 Caddy items(10), average price (66)
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
 Caddy items(10), average price (50)
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
 Caddy items(10), average price (49)
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
 Caddy items(10), average price (51)
void fr.xebia.aop.app.CaddyManager.purchase() managerCalls/daoCalls 1/10
 Caddy items(10), average price (51)
</pre><p>Vous retrouverez l&#8217;ensemble des sources présentées dans ce billet dans le repository <a
href="http://code.google.com/p/xebia-france/source/browse/trunk/aop/persomething/" title="SVN de Xebia France" >SVN de Xebia France</a>.</p><p><strong>Référence :</strong></p><ul><li><a
href="http://www.eclipse.org/aspectj/doc/released/progguide/semantics-aspects.html#aspect-instantiation" title="Aspects Appendix B Language Semantics" >Aspects, Appendix B. Language Semantics</a></li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2009/08/04/stateful-aspects/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Prenez le contrôle de Confluence avec Swizzle</title><link>http://blog.xebia.fr/2008/12/16/prenez-le-controle-de-confluence-avec-swizzle/</link> <comments>http://blog.xebia.fr/2008/12/16/prenez-le-controle-de-confluence-avec-swizzle/#comments</comments> <pubDate>Tue, 16 Dec 2008 10:22:58 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[confluence]]></category> <category><![CDATA[Revue de presse]]></category> <category><![CDATA[swizzle]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=1129</guid> <description><![CDATA[Je vais vous révéler un secret à propos de notre célèbre Revue de Presse ! Elle est élaborée collectivement par l&#8217;ensemble des consultants de Xebia sous Confluence avant d&#8217;être publiée sur notre blog. L&#8217;utilisation d&#8217;un wiki permet de suivre facilement les différentes modifications (contribution, corrections, commentaires). Une fois celle-ci terminée, la page est archivée et [...]]]></description> <content:encoded><![CDATA[<p>Je vais vous révéler un secret à propos de notre <em>célèbre</em> <a
href="http://blog.xebia.fr/category/revue-de-presse/" title="Revue de Presse" >Revue de Presse</a> ! Elle est élaborée collectivement par l&#8217;ensemble des consultants de Xebia sous <a
href="http://www.atlassian.com/software/confluence/" title="Confluence" >Confluence</a> avant d&#8217;être publiée sur notre blog. L&#8217;utilisation d&#8217;un wiki permet de suivre facilement les différentes modifications (contribution, corrections, commentaires). Une fois celle-ci terminée, la page est archivée et une autre est créée, vide, afin de recevoir la prochaine version. La fin de l&#8217;année arrive, c&#8217;est l&#8217;heure de faire les statistiques 2008. L&#8217;une des questions que je me pose est &laquo;&nbsp;Quelle est la proportion des entrées de la revue de presse entre les différentes catégories (Actualité éditeurs / SSII, Agilité, RIA, SOA, &#8230;) ?&nbsp;&raquo;</p><p>Solution N°1 : Ouvrir dans le navigateur toutes les pages &#8216;Revue de Presse&#8217; une par une et compter les entrées. Une revue de presses par semaine, 52 semaines &#8230; non</p><p>Solution N°2 : Utiliser une API. En effet Confluence expose ses <a
href="http://confluence.atlassian.com/display/DOC/Remote+API+Specification" title="principales fonctions" >principales fonctions</a> par web services. Voici le <a
href="http://confluence.atlassian.com/rpc/soap-axis/confluenceservice-v1?wsdl" title="wsdl" >wsdl</a>. Plus de 7300 lignes, 238 opérations, 50 types. À ce moment-là, j&#8217;étais presque prêt à repasser à la solution N°1 quand je suis tombé au détour d&#8217;une recherche Google (<em>Google est notre ami à tous !</em>), sur le projet Swizzle&#8230;</p><p><a
href="http://docs.codehaus.org/display/SWIZZLE/Home" title="Swizzle" >Swizzle</a> est un wrapper Java autour de l&#8217;api XML-RPC proposée par Confluence.</p><h4><a
name="Installation"></a>Installation</h4><p>Rapide ! Swizzle est disponible dans le repository Maven</p><pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
    &lt;groupId&gt;org.codehaus.swizzle&lt;/groupId&gt;
    &lt;artifactId&gt;swizzle-confluence&lt;/artifactId&gt;
    &lt;version&gt;1.1&lt;/version&gt;
&lt;/dependency&gt;
</pre><h4><a
name="Principe"></a>Principe</h4><ul><li>Une seule classe, <code>org.codehaus.swizzle.confluence.Confluence</code>, permet d&#8217;accéder aux différents services.</li><li>Un ensemble de POJO qui servent de paramètres d&#8217;entrée et de retour. Exemple : <code>org.codehaus.swizzle.confluence.PageSummary</code>.</li></ul><h4><a
name="Seconnecter"></a>Se connecter</h4><pre class="brush: java; title: ; notranslate">
String endpoint = &quot;https://the.confluence.of.xebia.com/confluence/rpc/xmlrpc&quot;;
confluence = new Confluence(endpoint);
System.out.println(&quot;Connected to &quot; + endpoint);
String username = &quot;bmoussaud&quot;;
String password = &quot;tiger&quot;;
confluence.login(username, password);
</pre><p>Si vous êtes dérrière un proxy, initialiser les variables d&#8217;environnement suivantes:</p><pre class="brush: java; title: ; notranslate">
System.getProperties().put(&quot;proxySet&quot;,  &quot;true&quot;);
System.getProperties().put(&quot;proxyHost&quot;, &quot;17.240.34.194&quot;);
System.getProperties().put(&quot;proxyPort&quot;, &quot;3128&quot;);
</pre><h4>Retrouver une page</h4><p>Les <a
href="http://blog.xebia.fr/category/revue-de-presse/" title="Revues de Presse" >Revues de Presse</a> sont archivées, comme l&#8217;ensemble du blog, par trimestre. Il faut donc :</p><ol><li>Retrouver la page correspondant à ce trimestre.</li><li>Récupérer les pages filles.</li><li>Filtrer pour ne garder que les articles &laquo;&nbsp;Revue de Presse&nbsp;&raquo;.</li></ol><pre class="brush: java; title: ; notranslate">
public List&lt;PageSummary&gt; getRevuesDePresse(String quarter) throws Exception {
	List&lt;PageSummary&gt; results = new ArrayList&lt;PageSummary&gt;();
	Page page = confluence.getPage(&quot;Espace Xebia France&quot;, quarter); 	//#1
	List&lt;PageSummary&gt; children = confluence.getChildren(page.getId());	//#2
	for (PageSummary pageSummary : children) {
		if (pageSummary.getTitle().contains(REVUE_DE_PRESSE)) {		//#3
			results.add(pageSummary);
		}
	}
	return results;
}
</pre><ul><li>Une page est identifiée par son Id représenté par un type <code>java.lang.String</code>.</li><li>La classe <code><a
href="http://confluence.atlassian.com/display/DOC/Remote+API+Specification#RemoteAPISpecification-PageSummary" title="PageSummary" >PageSummary</a></code> contient les informations minimales d&#8217;une page : <code>Id</code>, <code>ParentId</code>, <code>Title</code>, <code>URL</code>.</li><li>La classe <code><a
href="http://confluence.atlassian.com/display/DOC/Remote+API+Specification#RemoteAPISpecification-Page" title="Page" >Page</a></code> contient toutes les informations de la page, y compris son contenu.</li></ul><h4><a
name="Analyserlecontenudunepage"></a>Analyser le contenu d&#8217;une page</h4><p>La <a
href="http://blog.xebia.fr/category/revue-de-presse/" title="Revue de Presse" >Revue de Presse</a> contient 6 catégories principales (Actualité éditeurs / SSII, Agilité, RIA, SOA, &#8230;). Elles sont hiérarchisées en niveau 3 (syntaxe wiki <code>h3.</code>). Les différentes entrées de la revue de presse sont de niveau 4 (syntaxe wiki <code>h4.</code>). Il faut donc :</p><ol><li>Récupérer le contenu de la page.</li><li>Filtrer les titres de niveau 3 et 4.</li><li>Effectuer le comptage.</li></ol><pre class="brush: java; title: ; notranslate">
public Map&lt;String, Integer&gt; countArticleByCategory(String pageId)
		throws Exception {
	String content = confluence.getPage(pageId).getContent();	// #1
	String currentCategory = null;
	String currentEntry = null;
	Pattern h3h4 = Pattern.compile(&quot;(^h3|^h4)
.(.*)&quot;,
					 Pattern.MULTILINE);		// #2
	Matcher matcher = h3h4.matcher(content);
	Map&lt;String, Integer&gt; categories = newMap();
	while (matcher.find()) {
		//entrées vides
		if (matcher.group().contains(&quot;...&quot;)
				|| matcher.group().contains(&quot;..&quot;))
			continue;
		// niveau 3
		if (&quot;h3&quot;.equals(matcher.group(1))) {			// #2
			currentCategory = matcher.group(2).trim();
			categories.put(currentCategory, 0);
			continue;
		}
		// niveau 4
		if (&quot;h4&quot;.equals(matcher.group(1))) {			// #2
			currentEntry = matcher.group(2);
			if (currentCategory != null
					&amp;&amp; categories.containsKey(currentCategory)) {
				int c = categories.get(currentCategory);
				categories.put(currentCategory, ++c);	// #3
			}
		}
	}
	return categories;
}
</pre><h4><a
name="Conclusion"></a>Conclusion</h4><p>Il suffit maintenant :</p><ul><li>D&#8217;assembler les deux méthodes.</li><li>De dumper les informations au format CSV.</li><li>D&#8217;ouvrir Excel.</li><li>De construire un tableau croisé dynamique.</li></ul><p>et vous n&#8217;aurez pas les résultats !!</p><p>Pour en revenir à Swizzle / Confluence : l&#8217;encapsulation proposée est correcte et performante. Le seul point négatif : toutes les méthodes de la classe <code>Confluence</code> lancent des <code>java.lang.Exceptions</code>, non typées. Elles sont dans l&#8217;ensemble le résultat d&#8217;un comportement de type <code>Runtime</code>. J&#8217;aurais donc préféré une signature finissant par <code>throws RuntimeException</code>.</p><p>L&#8217;api permet également :</p><ul><li>D&#8217;obtenir des informations sur l&#8217;historique des pages et des contributeurs, les commentaires, l&#8217;état de la page (nombre de verrous, supprimées, &#8230;).</li><li>De créer, déplacer et détruire des pages et des espaces.</li></ul><p>Exemple : archivage des revues de presse :</p><pre class="brush: java; title: ; notranslate">
void run(String newParent) throws Exception {
	System.out.println(&quot;Archivage des Revues de Presse dans &quot;+newParent);
	myConfluence = new MyConfluence();
	List&lt;PageSummary&gt; draftedRevuesDePresse = myConfluence.getDraftedRevuesDePresse();
	int count = 0;
	for (PageSummary pageSummary : draftedRevuesDePresse) {
		if (pageSummary.getTitle().startsWith(&quot;DRAFT&quot;))
			continue;
		myConfluence.moveTo(pageSummary,newParent);
	}
	System.out.println(&quot;Total &quot;+count);
}
//....
public void moveTo(PageSummary pageSummary, String newParent)
		throws Exception {
	Page targetPage = confluence.getPage(&quot;XF&quot;, newParent);
	Page page = confluence.getPage(pageSummary.getId());
	System.out.println(&quot;Change Parent from '&quot;
			+ confluence.getPage(page.getParentId()).getTitle() + &quot;' to '&quot;
			+ targetPage.getTitle() + &quot;'&quot;);
	page.setParentId(targetPage.getId());		//Changement de Parent
	confluence.storePage(page);			//Applique les modifications
}
</pre><p>Swizzle propose également un wrapper sur les API exposées par <a
href="http://www.atlassian.com/software/jira/" title="Jira" >Jira</a>.<br
/> Note: Swizzle ne fonctionne que si l&#8217;option &laquo;&nbsp;API à distance (XML-RPC &#038; SOAP)&nbsp;&raquo; est activée.</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/12/16/prenez-le-controle-de-confluence-avec-swizzle/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Analyse mémoire d&#8217;une JVM</title><link>http://blog.xebia.fr/2008/11/27/analyse-memoire-dune-jvm/</link> <comments>http://blog.xebia.fr/2008/11/27/analyse-memoire-dune-jvm/#comments</comments> <pubDate>Thu, 27 Nov 2008 13:04:40 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Exploitation]]></category> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Eclipse Memory Analyzer]]></category> <category><![CDATA[jhat]]></category> <category><![CDATA[jmat]]></category> <category><![CDATA[JVM]]></category> <category><![CDATA[MAT]]></category> <category><![CDATA[OutOfMemorry]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=1063</guid> <description><![CDATA[Mardi, 10 heures - La production &#171;&#160;Allo, le projet, depuis 10 minutes on voit passer des messages &#8216;OutOfMemoryError&#8217;. Que fait-on ? &#171;&#160; - Le projet &#171;&#160;Augmentez la mémoire de la JVM, doublez-la valeur de l&#8217;option -Xmx &#171;&#160; Mardi, 13 heures - La production &#171;&#160;Allo, le projet, depuis 5 minutes on voit encore passer des messages [...]]]></description> <content:encoded><![CDATA[<p><em>Mardi, 10 heures</em><br
/> - <em>La production &laquo;&nbsp;Allo, le projet, depuis 10 minutes on voit passer des messages &#8216;OutOfMemoryError&#8217;. Que fait-on ? &laquo;&nbsp;</em><br
/> - <em>Le projet &laquo;&nbsp;Augmentez la mémoire de la JVM, doublez-la valeur de l&#8217;option -Xmx &laquo;&nbsp;</em></p><p><em>Mardi, 13 heures</em><br
/> - <em>La production &laquo;&nbsp;Allo, le projet, depuis 5 minutes on voit</em> <strong>encore</strong> <em>passer  des messages &#8216;OutOfMemoryError&#8217;. Que fait-on ? &laquo;&nbsp;</em><br
/> - <em>Le projet &laquo;&nbsp;Augmentez la mémoire de la JVM, doublez</em> <strong>encore</strong> <em>la valeur de l&#8217;option -Xmx &laquo;&nbsp;</em></p><p><em>Mardi 18 heures</em><br
/> - <em>La production &laquo;&nbsp;Allo, le projet, depuis 2 minutes on voit passer</em> <strong>encore</strong> <em>des messages &#8216;OutOfMemoryError&#8217;. Que fait-on ? &laquo;&nbsp;</em><br
/> - <em>Le projet &laquo;&nbsp;Tut, tut, tut,&#8230;..&nbsp;&raquo;</em><br
/> - <em>La production &laquo;&nbsp;Plus d&#8217;équipe projet, la nuit va être longue&#8230;&nbsp;&raquo;</em></p><p>Cette petite scène est un classique, un air de <em>déjà-vu</em> mais que faire ?  Si votre application a déjà subi une batterie de tests techniques, augmenter la mémoire est rarement la bonne solution. La scène décrite ci-dessus laisse penser à ce que l&#8217;on appelle classiquement une <em>Fuite Mémoire</em> (Memory Leak). En réalité, avec les JVM récentes, la fuite mémoire n&#8217;existe pas, je préfère parler <em>d&#8217;accumulation d&#8217;objets non désirés</em>. Cet article va vous montrer comment débusquer cette accumulation avec les outils <a
href="http://java.sun.com/javase/6/docs/technotes/tools/share/jmap.html" title="jmap" >jmap</a>, <a
href="http://java.sun.com/javase/6/docs/technotes/tools/share/jhat.html" title="jhat" >jhat</a> et <a
href="http://www.eclipse.org/mat/" title="Eclipse Memory Analyser" >Eclipse Memory Analyser</a></p><h3><a
name="jmap"></a>jmap</h3><p>jmap est <strong>l&#8217;outil</strong> qui permet d&#8217;effectuer des photographies de la mémoire d&#8217;une JVM. Deux options sont particulièrement intéressantes : l&#8217;histogramme et le dump.</p><p><br
/> <strong>L&#8217;histogramme</strong></p><p>L&#8217;option <code>-histo</code> permet d&#8217;obtenir un histogramme de la mémoire de la JVM. Les informations suivantes sont affichées pour chacune des classes Java :</p><ul><li>son nom complet</li><li>le nombre d&#8217;objets et</li><li>la taille de la mémoire occupée en octets</li></ul><p>L&#8217;ensemble est trié par taille mémoire <em>décroissante</em>. Attention, la demande d&#8217;un histogramme implique <em>automatiquement</em> un <strong>Full GC</strong> de la mémoire de la JVM.</p><p>Exemple :</p><pre class="brush: java; title: ; notranslate">
jmap -histo &lt;pid&gt;
 num     #instances         #bytes  class name
----------------------------------------------
   1:         41202       27502288  [C
   2:          2304        1332520  [I
   3:         37934         910416  java.lang.String
   4:          5130         503632  &lt;constMethodKlass&gt;
   5:          5130         412968  &lt;methodKlass&gt;
   6:         12348         395136  fr.xebia.memory.bean.Person
   7:         12846         308304  java.util.concurrent.ConcurrentHashMap$HashEntry
   8:          7650         285656  &lt;symbolKlass&gt;
   9:         12518         200288  java.lang.Long
  10:           349         189184  &lt;constantPoolKlass&gt;
  11:           349         138704  &lt;instanceKlassKlass&gt;
  12:           327         132144  &lt;constantPoolCacheKlass&gt;
  13:            38         115456  [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;
  14:           414          76392  [B
  15:           422          40512  java.lang.Class
  16:           556          32656  [[I
  17:           518          32056  [S
  18:            44          14080  &lt;objArrayKlassKlass&gt;
  19:           315          13480  [Ljava.lang.Object;
  20:           576           9216  java.lang.StringBuffer
.....
 184:             1              8  java.lang.System$2
 185:             1              8  java.io.File$1
 186:             1              8  java.lang.Terminator$1
Total        142211       32693376
</pre><p>Que peut-on en déduire ?</p><ul><li>Les premières places sont souvent trustées par les objets de base ( java.lang.String, java.lang.Object, java.lang.class) et leur déclinaison en collections (java.util.* et les tableaux, symbolisé par des '['). Si vous retrouvez des classes de votre application dans le top 20, elles deviennent <em>suspectes</em>. Dans notre exemple, l'histogramme montre que la classe 'fr.xebia.memory.bean.Person' est instanciée 12348 fois pour une occupation mémoire de 308304 octets. Elle est suivie de près par des entrées d'une ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap$HashEntry)</li><li>L'obtention de cet histogramme est extrêmement rapide <strike> et perturbe peu la JVM (au Full GC près ;</strike>) ). Il est donc possible d'en faire régulièrement (exemple toutes les 'n' secondes) et d'en déduire ainsi des tendances : nombre d'instances d'une classe qui augmente, taille des instances d'une classe qui diminue, ...</li></ul><p>Note : avec les JVM en version 1.4.2, il est possible d'obtenir également un histogramme à chaque thread dump en ajoutant l'option <strong>-XX:+PrintClassHistogram</strong> au démarrage de la JVM. Comme pour jstat <code>-histo</code>, cette option implique <em>automatiquement</em> un Full GC de la mémoire de la JVM.</p><p>L'histogramme permet de connaître les classes qui occupent le plus de mémoire, il n'indique pas qui les a allouées.</p><p><strong>Le dump</strong></p><p>L'histogramme c'est bien, mais ce n'est pas suffisant : il est parfois nécessaire d'obtenir un dump complet de la mémoire afin de déterminer précisément la chaîne de référencement.</p><p>L'outil jmap permet également d'effectuer un dump complet et binaire de la mémoire d'une JVM. Deux remarques importantes :</p><ul><li>pendant la durée du dump, plus rien ne s'exécute dans la JVM, tous les threads sont stoppés, qu'ils soient applicatifs ou systèmes.</li><li>la durée du dump est proportionnelle à la taille de la mémoire occupée et fonction de la taille de la mémoire restante (il faut un peu de mémoire libre pour exécuter le traitement du dump !). Exemple: la durée d'un dump d'une JVM avec un heap de 1 Go à la limite de la saturation mémoire se compte en minute !</li></ul><p>Exemple : création d'un dump</p><pre class="brush: java; title: ; notranslate">
jmap -dump:format=b,file=c:tempheap.bin &lt;pid&gt;
Dumping heap to c:tempheap.bin ...
Heap dump file created
</pre><p>Note : L'option <code>-XX:+HeapDumpOnOutOfMemoryError</code> indique à la JVM d'effectuer un heap dump en cas d'OutOfMemoryError. Le fichier est généré dans le répertoire de lancement de la JVM.</p><p>Vous voilà l'heureux propriétaire d'un fichier binaire de plusieurs centaines de méga-octets. Comment en extraire des informations ? C'est là que le compagnon de jmap rentre en jeu : jhat.</p><h3><a
name="jhat"></a>jhat</h3><p><a
href="http://java.sun.com/javase/6/docs/technotes/tools/share/jhat.html" title="jhat" >jhat</a> est un analyseur de dump mémoire. C'est en réalité un serveur web, comme le montre l'exemple ci-dessous.</p><pre class="brush: java; title: ; notranslate">
D:ProjetsMesProjetsMemoryLeakjmap5968&gt;jhat heap5968.bin
Reading from heap5968.bin...
Dump file created Mon Nov 24 13:03:54 CET 2008
Snapshot read, resolving...
Resolving 118955 objects...
Chasing references, expect 23 dots.......................
Eliminating duplicate references.......................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
</pre><p>L'application jhat lancée, il suffit de lancer un navigateur web pour commencer l'exploration du dump.</p><div
align="center"> <object
classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"             codebase="https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" data="http://blog.xebia.fr/wp-content/uploads/2008/11/jhat.swf" height="407" width="700" type="application/x-shockwave-flash" ><param
name="data" value="http://blog.xebia.fr/wp-content/uploads/2008/11/jhat.swf" /><param
name="loop" value="false" /><param
name="menu" value="false" /><param
name="movie" value="http://blog.xebia.fr/wp-content/uploads/2008/11/jhat.swf" /><param
name="quality" value="high" /><param
name="scale" value="exactfit" /><param
name="src" value="http://blog.xebia.fr/wp-content/uploads/2008/11/jhat.swf" /><param
name="type" value="application/x-shockwave-flash" /><embed
height="407" width="700" quality="high"             pluginspage="https://www.macromedia.com/shockwave/download/index.cgi?p1_prod_version=shockwaveflash" src="http://blog.xebia.fr/wp-content/uploads/2008/11/jhat.swf" type="application/x-shockwave-flash" /><br
/> </object><br
/> [ <a
href="http://blog.xebia.fr/wp-content/uploads/2008/11/jhat.swf">MODE PLEIN ECRAN</a> ]</div><p>Grâce à jhat, on a pu voir que les instances de type fr.xebia.memory.bean.Person étaient majoritairement référencées par un champ statique de type fr.xebia.memory.dao.MySuperSmartCache qui fait office de cache. Sans rentrer dans le code, on peut commencer à avoir des doutes sur l'efficacité de ce cache !</p><p>jhat a l'avantage d'être disponible dans tous les JDK récents. Cependant, l'interface proposée permet certes de naviguer facilement de classe en classe, d'instance en instance, mais il manque de fonctions d'analyse. Un outil est venu combler ce manque...</p><h3><a
name="EclipseMemoryAnalyzer"></a>Eclipse Memory Analyzer</h3><p><a
href="http://www.eclipse.org/mat/" title="Eclipse Memory Analyzer" >Eclipse Memory Analyzer</a> (MAT) est un sous projet de la fondation Eclipse, initié par la société SAP. Son but est non seulement d'offrir une interface graphique permettant de naviguer dans un dump mémoire, mais également de proposer des rapports d'analyses précablés (Leak Suspects, Heap Dump Overview, Top Consumers,...).</p><p>Ouvrons le dump avec MAT. Après analyse, MAT ouvre une fenêtre avec une vue d'ensemble de la mémoire. Il est clair que l'ensemble de la mémoire est retenu par une seule instance de type fr.xebia.memory.dao.Loader.</p><div
align="center"><a
href="http://blog.xebia.fr/wp-content/uploads/2008/11/mat1.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/11/mat1-300x263.png" alt="" title="Eclipse Memory Analyser - Overview" width="300" height="263" class="aligncenter size-medium wp-image-1065" /></a></div><p>La vue histogramme ressemble à celle fournie par jmap ou jhat mais avec des libellés un peu plus clairs.</p><div
align="center"><a
href="http://blog.xebia.fr/wp-content/uploads/2008/11/mat2.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/11/mat2-300x263.png" alt="" title="Eclipse Memory Analyser - histogramme" width="300" height="263" class="aligncenter size-medium wp-image-1066" /></a></div><p>Une fonction très intéressante, le <em>'Dominator Tree'</em> donne la liste des plus gros objets, consolidée avec l'ensemble de leurs références.</p><div
align="center"><a
href="http://blog.xebia.fr/wp-content/uploads/2008/11/mat3.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/11/mat3-300x263.png" alt="" title="Eclipse Memory Analyser - Dominator Tree" width="300" height="263" class="aligncenter size-medium wp-image-1067" /></a></div><p>Pour terminer, jetons un coup d'œil sur le <em>rapport 'Leak Suspect'</em>, et là il n'y a plus de doute, nous avons trouvé le coupable.</p><div
align="center"><a
href="http://blog.xebia.fr/wp-content/uploads/2008/11/mat4.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/11/mat4-300x263.png" alt="" title="Eclipse Memory Analyser - Leak Suspect" width="300" height="263" class="aligncenter size-medium wp-image-1068" /></a></div><h3><a
name="Conclusion"></a>Conclusion</h3><p>Avec ces outils de capture et d'analyse de la mémoire, il est maintenant facile de débusquer les consommations mémoires excessives, même dans un environnement de production. N'hésitez pas à user et à abuser de ces outils afin de déterminer au plus tôt les tailles des JVM et les éventuelles accumulations d'objets non désirés !</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/11/27/analyse-memoire-dune-jvm/feed/</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>Diagnostic d&#8217;une JVM à distance</title><link>http://blog.xebia.fr/2008/10/22/diagnostic-dune-jvm-a-distance/</link> <comments>http://blog.xebia.fr/2008/10/22/diagnostic-dune-jvm-a-distance/#comments</comments> <pubDate>Wed, 22 Oct 2008 08:28:07 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Exploitation]]></category> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[JVM]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=878</guid> <description><![CDATA[Développer une application Java, c&#8217;est bien. La rendre performante, c&#8217;est mieux. Cependant, qui dit &#171;&#160;performance&#160;&#187;, dit &#171;&#160;mesure&#160;&#187;. En effet, il est nécessaire de pouvoir : connaître les paramètres de lancement de la JVM, mesurer l&#8217;empreinte mémoire et le comportement du Garbage Collector, Cet article va décrire dans une première partie les différents outils permettant de [...]]]></description> <content:encoded><![CDATA[<p><em>Développer une application Java, c&#8217;est bien. La rendre performante, c&#8217;est mieux.</em></p><p>Cependant, qui dit &laquo;&nbsp;performance&nbsp;&raquo;, dit &laquo;&nbsp;mesure&nbsp;&raquo;. En effet, il est nécessaire de pouvoir :</p><ul><li>connaître  les paramètres de lancement de la JVM,</li><li>mesurer l&#8217;empreinte mémoire et le comportement du Garbage Collector,</li></ul><p>Cet article va décrire dans une première partie les différents outils permettant de collecter ces informations en local. La seconde partie se concentre sur les moyens pour obtenir ces <strong>mêmes</strong> informations à distance.</p><h3><a
name="Enlocal"></a>En local&#8230;</h3><p>Au fur et à mesure des différentes versions et afin d&#8217;obtenir les meilleures performances, la machine virtuelle Java (JVM) s&#8217;est dotée d&#8217;outils de diagnostic. Les principaux sont:</p><ul><li><a
href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jps.html" title="jps" >jps</a> liste l&#8217;ensemble des JVM qui s&#8217;exécutent sur un système.</li></ul><pre class="brush: bash; title: ; notranslate">
#jps -l
22791 weblogic.Server
18602 sun.tools.jps.Jps
5697 weblogic.Server
16937 activity.jar
6324 weblogic.Server
</pre><ul><li><a
href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html" title="jstat" >jstat</a> affiche les statistiques d&#8217;une JVM sur sa gestion mémoire et le compilateur JIT.</li></ul><pre class="brush: bash; title: ; notranslate">
#jstat -gcutil 16937 1s
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  0.00  99.96   0.00  89.53  33.10   1274   71.231   194   69.937  141.167
 83.53   0.00  65.48  77.26  33.10   1275   71.285   194   70.610  141.895
 83.53   0.00  75.30  77.26  33.10   1275   71.285   194   70.610  141.895
 83.53   0.00  84.44  77.26  33.10   1275   71.285   194   70.610  141.895
 83.53   0.00  96.26  77.26  33.10   1275   71.285   194   70.610  141.895
  0.00  99.77   0.00  90.35  33.10   1276   71.391   195   70.610  142.001
  0.00   0.00   4.87   0.73  33.11   1276   71.391   195   70.749  142.140
  0.00   0.00  10.18   0.73  33.11   1276   71.391   195   70.749  142.140
  0.00   0.00  29.65   0.73  33.11   1276   71.391   195   70.749  142.140
</pre><ul><li><a
href="http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html" title="jconsole" >jconsole</a> est une application graphique Swing qui affiche des informations sur la mémoire, les threads, les classes et les MBeans.</li></ul><div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/jconsole.jpg"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/jconsole-300x251.jpg" alt="" title="jconsole" width="300" height="251" class="aligncenter size-medium wp-image-881" /></a></div><ul><li><a
href="https://visualvm.dev.java.net/" title="visualvm" >visualvm</a> est également une application graphique qui reprend les informations affichées par JConsole mais en allant plus loin (ex: Détection de Contentions Thread). Livré avec le JDK de sun depuis la version JDK 6 update 7, VisualVM pourrait avec le temps  remplacer complètement JConsole</li></ul><div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm.jpg"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-300x213.jpg" alt="" title="visualvm" width="300" height="213" class="aligncenter size-medium wp-image-883" /></a></div><ul><li><strong><a
href=" http://java.sun.com/performance/jvmstat/visualgc.html" title="visualgc" ><strong>visualgc</strong> </a></strong> affiche sous forme graphique les informations que l&#8217;on peut obtenir sur le garbage collector avec jstat. cette application n&#8217;est pas packagée avec la jvm, elle est disponible séparément avec les outils <a
href="http://java.sun.com/performance/jvmstat/" title="jvmstat" >jvmstat</a>. de plus, elle fonctionne avec les jvm 1.4.<div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/visualgc.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/visualgc-300x266.png" alt="" title="visualgc" width="300" height="266" class="aligncenter size-medium wp-image-882" /></a></div></li></ul><h3><a
name="Etdistance"></a>Et à distance &#8230; ?</h3><p>Par défaut, tous ces outils doivent être lancés sur la système d&#8217;exploitation où s&#8217;exécute la JVM à diagnostiquer. Cependant les contraintes de sécurité des entreprises interdisent parfois d&#8217;accéder physiquement à la machine. Dans le meilleur des cas, il est possible d&#8217;obtenir une connexion distante (Windows RDP, Telnet ou SSH), mais souvent avec des niveaux d&#8217;accréditations trop faibles pour pouvoir exécuter les commandes listées ci-dessus. Alors comment faire ?</p><p>Sun a pensé à tout. Si on regarde de prés une distribution d&#8217;une JVM, on remarque un binaire de type démon &#8216;jstatd&#8217;.</p><ul><li><a
href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstatd.html" title="jstatd" >jstatd</a> est un démon qui surveille la création et la destruction des JVM et fourni une interface qui permet à des outils distants de se connecter aux JVM qui s&#8217;exécutent sur la machine. Exactement ce qu&#8217;il nous faut, non ?</li></ul><p>Le moyen le plus simple est d&#8217;exécuter jstatd de la façon suivante:</p><pre class="brush: bash; title: ; notranslate">
#nohup jstatd -J-Djava.security.policy=all.policy &amp;
#cat all.policy
grant codebase &quot;file:${java.home}/../lib/tools.jar&quot; {
   permission java.security.AllPermission;
};
#
</pre><p>A partir de ce moment, il est possible d&#8217;utiliser les logiciels présentés ci-dessus.</p><ul><li><strong>jps</strong>, en précisant le nom de la machine distante. Noter l&#8217;apparition d&#8217;un nouveau processus java:  sun.tools.jstatd.Jstatd</li></ul><pre class="brush: bash; title: ; notranslate">
D:xebia-blog&gt;jps -l myremoteserver
5697 weblogic.Server
28636 sun.tools.jstatd.Jstatd
22791 weblogic.Server
29726 activity.jar
6324 weblogic.Server
</pre><ul><li><strong>jstatd</strong> et <strong>visualgc</strong> en précisant le <em>virtual machine identifier</em> avec le format lvmid@servername</li></ul><pre class="brush: bash; title: ; notranslate">
D:xebia-blog&gt;jstat -gcutil 29726@myremoteserver 1s
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  0,00  99,78   0,00  83,38  33,14   8476  474,694  1227  445,801  920,495
  0,00  99,78   0,00  83,38  33,14   8476  474,694  1227  445,801  920,495
  0,00  78,41  77,46  42,98  33,14   8478  474,784  1227  446,133  920,917
 79,47   0,00  43,86  78,69  33,14   8481  474,971  1227  446,133  921,104
  0,00  82,64  76,48  63,39  33,13   8484  475,206  1228  446,649  921,855
  0,00  82,64  76,48  63,39  33,13   8484  475,206  1228  446,649  921,855
 85,47   0,00  77,78  74,92  33,13   8485  475,350  1228  446,649  921,999
</pre><ul><li>Au lancement de <strong>visualvm</strong>, il suffit d&#8217;ajouter le nom du serveur &#8216;myremoteserver&#8217; au noeud <em>remote</em> pour voir apparaître l&#8217;ensemble des JVM s&#8217;exécutant sur ce serveur. Il est possible alors de se connecter à l&#8217;une des machines virtuelles pour pouvoir avoir accès à:</li><li>Onglet <strong>Overview</strong> donne des informations générales (PID, Host, JVM Version, JVM Flags)</li></ul><div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-overview.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-overview-300x290.png" alt="" title="visualvm-jstatd-overview" width="300" height="290" class="aligncenter size-medium wp-image-886" /></a></div><ul><li>Onglet <strong>Monitor</strong> affiche des graphiques sur la consommation de ressources (Mémoire, Threads, &#8230;)</li></ul><div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-monitor.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-monitor-300x290.png" alt="" title="visualvm-jstatd-monitor" width="300" height="290" class="aligncenter size-medium wp-image-885" /></a></div><p>La copie d&#8217;écran suivante montre <strong>visualgc</strong> intégré sous forme de plugin dans <strong>visualvm</strong></p><div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-visualgc-2.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-visualgc-2-300x292.png" alt="" title="visualvm-jstatd-visualgc-2" width="300" height="292" class="aligncenter size-medium wp-image-880" /></a></div><p>Cependant l&#8217;utilisation seule de <strong>jstatd</strong> n&#8217;est pas suffisante si l&#8217;on veut avoir accès aux MBeans JMX par <strong>jconsole</strong> et à l&#8217;activité des Threads avec <strong>visualvm</strong>. Il est nécessaire d&#8217;ajouter les paramètres suivants au <em>démarrage</em> de la JVM</p><pre class="brush: bash; title: ; notranslate">
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
</pre><p>il est alors possible de connecter <strong>jconsole</strong> en utilisant la commande suivante:</p><pre class="brush: bash; title: ; notranslate">
D:xebia-blog&gt;jconsole myremoteserver:9999
</pre><p>Avec l&#8217;outil <strong>visualvm</strong>, deux nouveaux onglets sont maintenant disponibles:</p><ul><li>Onglet <strong>Threads</strong> affiche l&#8217;activité de l&#8217;ensemble des threads et permet d&#8217;obtenir facilement un thread dump</li></ul><div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-thread.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-thread-300x292.png" alt="" title="visualvm-jstatd-thread" width="300" height="292" class="aligncenter size-medium wp-image-887" /></a></div><div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-threadump.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-threadump-300x292.png" alt="" title="visualvm-jstatd-threadump" width="300" height="292" class="aligncenter size-medium wp-image-888" /></a></div><ul><li>Onglet <strong>MBeans</strong> affiche l&#8217;ensemble des MBeans JMX</li></ul><div
align="center"> <a
href="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-mbeans.png"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/10/visualvm-jstatd-mbeans-300x292.png" alt="" title="visualvm-jstatd-mbeans" width="300" height="292" class="aligncenter size-medium wp-image-884" /></a></div><h3><a
name="Enlocal"></a>Conclusion</h3><p>Vous êtes maintenant armés pour scruter votre application qui s&#8217;exécute dans votre JVM. Vouloir rendre votre application performante est une bonne idée. Cependant, l&#8217;expérience montre qu&#8217;il faut commencer absolument par analyser le code Java.<br
/> Exemple: Traitements inutiles ou redondants, accès à la base de données peu efficaces (trop ou pas assez de données manipulées),&#8230;<br
/> Il n&#8217;existe pas de paramètre magique dans la JVM (ou dans le Serveur d&#8217;application) qui permet à une application mal écrite de devenir performante.</p><p>Ce n&#8217;est que par la suite que l&#8217;on peut <em>tuner</em> la JVM. Si vous vous lancez dans cette aventure (passionnante) commencez par lire cet article de Kirk Pepperdine ,<br
/> <a
href="http://kirk.blog-city.com/advice_on_jvm_heap_tuning_dont_touch_that_dial.htm" title="My advice on JVM heap tuning, keep your fingers off the knobs!" >My advice on JVM heap tuning, keep your fingers off the knobs!</a></p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/10/22/diagnostic-dune-jvm-a-distance/feed/</wfw:commentRss> <slash:comments>10</slash:comments> </item> <item><title>fr.xebia.concurrent.CyclicLatch</title><link>http://blog.xebia.fr/2008/09/24/frxebiaconcurrentcycliclatch/</link> <comments>http://blog.xebia.fr/2008/09/24/frxebiaconcurrentcycliclatch/#comments</comments> <pubDate>Wed, 24 Sep 2008 09:03:44 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=726</guid> <description><![CDATA[&#8230;.ou comment effectuer un traitement régulièrement Avec l&#8217;arrivée de l&#8217;api java.util.concurrent dans le JDK 5, la programmation concurrente est à la portée de tous. Auparavant, il fallait : soit être un expert des APIs de bas niveau et être prêt à passer des nuits blanches à mettre au point le système, soit se tourner vers [...]]]></description> <content:encoded><![CDATA[<p><em>&#8230;.ou comment effectuer un traitement régulièrement</em></p><p>Avec l&#8217;arrivée de l&#8217;api <code>java.util.concurrent</code> dans le JDK 5, la <a
href="http://blog.xebia.fr/2008/08/13/programmation-concurrentielle-notions-fondamentales/" title="programmation concurrente" >programmation concurrente</a> est à la portée de tous. Auparavant, il fallait :</p><ul><li>soit être un expert des APIs de bas niveau et être prêt à passer des nuits blanches à mettre au point le système,</li><li>soit se tourner vers les serveurs d&#8217;applications J2EE et leur implémentation JMS et EJB Message Driven Bean. Dans ce cas-là, la lourdeur de l&#8217;API JMS et les contraintes de persistance et de transaction (par défaut) des serveurs JMS viendront mettre à mal au final l&#8217;utilisation de traitements parallèles et concurrents.</li></ul><p>Dans le cadre d&#8217;un de mes projets, j&#8217;ai eu besoin d&#8217;implémenter le comportement suivant :</p><ul><li>les producteurs, N Threads effectuent une tâche qui entre autres collecte des données.</li><li>le consommateur, 1 Thread collecte ces données pour les agréger.</li></ul><p>Dans un premier temps, je me tourne vers une <a
href="http://java.sun.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html" title="java.util.concurrent.BlockingQueue" >java.util.concurrent.BlockingQueue</a> partagée entre les producteurs et le consommateur. Cette conception fonctionne jusqu&#8217;au moment où je me suis aperçu que</p><ol><li>le traitement effectué par mon consommateur pouvait être long et coûteux en ressources : il faut donc éviter d&#8217;effectuer le traitement au fil de l&#8217;eau et attendre d&#8217;avoir un certain nombre de données dans la file.</li><li>les producteurs, suivant la vie de l&#8217;application, pouvaient à un instant donné être très nombreux (beaucoup de données en peu de temps) ou au contraire peu nombreux. Dans ce dernier cas, le remplissage de ma file prendrait des heures et je ne pouvais attendre cette condition pour lancer mon traitement.</li></ol><h3><a
name="Cahierdescharges"></a>Cahier des charges</h3><p>Je me suis donc fixé le cahier des charges suivant :<br
/> Le consommateur doit vider l&#8217;ensemble de la queue et effectuer le traitement si :</p><ul><li>au moins N éléments ont été déposés (cf 1.)</li><li>S secondes se sont écoulées depuis la dernière collecte (cf 2.)</li></ul><p>J&#8217;ai commencé, bien sûr, par examiner l&#8217;API <code>java.util.concurrent</code>. Deux éléments de synchronisation ont attiré mon attention sans réellement convenir à mon besoin.</p><ul><li><a
href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html" title="java.util.concurrent.CountDownLatch" >java.util.concurrent.CountDownLatch</a> permet de signaler à un ensemble de threads que N opérations sont terminées.</li><li><a
href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CyclicBarrier.html" title="java.util.concurrent.CyclicBarrier" >java.util.concurrent.CyclicBarrier</a> permet à un ensemble de threads de s&#8217;attendre à un point d&#8217;exécution donnée.</li></ul><p>J&#8217;ai décidé de mixer les deux pour écrire <a
href="http://code.google.com/p/xebia-france/source/browse/trunk/concurrent/cycliclatch/src/main/java/fr/xebia/concurrent/CyclicLatch.java" title="fr.xebia.concurrent.CyclicLatch" >fr.xebia.concurrent.CyclicLatch</a></p><h3><a
name="Utilisation"></a>Utilisation</h3><p>Une instance de la classe <code>fr.xebia.concurrent.CyclicLatch</code> est créée avec les paramètres suivants :</p><ul><li>une valeur N  qui indique le nombre de fois avant de que le <em>Latch</em> ne soit libéré</li><li>une valeur S  qui indique le timeout</li></ul><pre class="brush: java; title: ; notranslate">
// création d'un CyclicLatch avec N=100 et S=10 secondes
latch = new CyclicLatch(100, 10, TimeUnit.SECONDS);
</pre><p>Cette instance est partagée entre les producteurs et le consommateur.</p><ul><li>A chaque traitement terminé, chaque producteur va décrémenter le Latch.</li></ul><pre class="brush: java; title: ; notranslate">
public class Producer {
	public void doit() {
		//Perform its own business...
		latch.countDown();
	}
}
</pre><ul><li>Le consommateur va se mettre en attente du latch</li></ul><pre class="brush: java; title: ; notranslate">
public class Consummer {
	public void run() {
		while (true) {
			latch.await() // attente avec les valeurs par défauts
			//ou
			latch.await(30,TimeUnit.Secondes) // attente de 30 secondes
			// Perform its own business....
		}
	}
}
</pre><h3><a
name="Implmentation"></a>Implémentation</h3><p>La classe <code>CyclicLatch</code> est implémentée autour</p><ul><li>d&#8217;un attribut de type CountDownLatch</li></ul><pre class="brush: java; title: ; notranslate">
final public class CyclicLatch {
	private final int initialcount;
	private CountDownLatch latch;
	private final ReentrantLock lock = new ReentrantLock();
	public CyclicLatch(int initialcount) {
		this.latch = new CountDownLatch(initialcount);
	}
}
</pre><ul><li>de 2 méthodes, <code>countDown()</code> et <code>await()</code>.</li></ul><p>La méthode <code>countDown()</code> verrouille l&#8217;accès au <em>latch</em> et délègue au <code>CountDownLatch</code>.</p><pre class="brush: java; title: ; notranslate">
	public void countDown() {
		try {
			lock.lock();
			latch.countDown();
		} finally {
			lock.unlock();
		}
	}
</pre><p>La méthode <code>await()</code> délègue au CountDownLatch.await(long, TimeUnit)<br
/> Extrait de javadoc  : <em>Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted or the specified waiting time elapses.</em></p><p>Et ensuite effectue reset safe du CountDownLatch</p><pre class="brush: java; title: ; notranslate">
	public boolean await(long timeout, TimeUnit unit)
			throws InterruptedException {
		log(&quot;Waiting for latch of &quot;+this.initialcount+&quot;  &amp; &quot; + timeout + &quot; seconds timeout&quot;);
		boolean result = latch.await(timeout, unit);
		/* Reset Latch, on timeout &amp; on overflow */
		try {
			lock.lock();
			log(&quot;Reset Latch....&quot; + latch);
			latch = new CountDownLatch(initialcount);
		} finally {
			lock.unlock();
		}
		return result;
	}
</pre><p>L&#8217;implémentation complète du <a
href="http://code.google.com/p/xebia-france/source/browse/trunk/concurrent/cycliclatch/" title="CyclicLatch" >CyclicLatch</a> permet de fixer les paramètres de taille et de timeout (méthode await()) ou à chaque attente du consommateur de positionner un nouveau timeout (méthode {{await(long, TimeUnit)}})</p><h3><a
name="Tests"></a>Tests</h3><p>Dans le <em>repository</em> de Xebia-France, vous trouverez le <a
href="http://code.google.com/p/xebia-france/source/browse/trunk/concurrent/cycliclatch/" title="code complet du CyclicLatch" >code complet du CyclicLatch</a> et un exemple de mise en œuvre avec la classe <a
href="http://code.google.com/p/xebia-france/source/browse/trunk/concurrent/cycliclatch/src/test/java/fr/xebia/xke/concurrency/NProducers1ConsumerTimedTest.java" title="fr.xebia.xke.concurrency.NProducers1ConsumerTimedTest" >fr.xebia.xke.concurrency.NProducers1ConsumerTimedTest</a>. Cette classe crée 4 producteurs qui remplissent une <code>BlockinQueue</code>. Le consommateur doit lire les messages en utilisant bien sûr un <code>CyclicLatch</code>. Suivant le paramétrage du <em>latch</em> on obtient les comportements suivants :</p><ul><li>CyclicLatch taille 100, time out 30 secondes. Les traces, ci-dessous, montre que le <em>latch</em> a été déclenché sur &#8216;Overflow&#8217; donc plus de 100 messages dans la file, au bout d&#8217;environs 2.5 secondes</li></ul><pre class="brush: java; title: ; notranslate">
main Consumer.Consumer()
MyBasket.start()
Thread Consumer #0 Consumer.run()
Thread Consumer #0 Waiting for latch of 100  &amp; 5 seconds timeout
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@45a877[Count = 0]
Thread Consumer #0 OverFlow, 2.4278326s
Thread Consumer #0 messages #100
Thread Consumer #0 Waiting for latch of 100  &amp; 5 seconds timeout
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@126b249[Count = 0]
Thread Consumer #0 OverFlow, 2.5149238s
Thread Consumer #0 messages #100
Thread Consumer #0 Waiting for latch of 100  &amp; 5 seconds timeout
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@182f0db[Count = 0]
Thread Consumer #0 OverFlow, 2.5150535s
Thread Consumer #0 messages #100
Thread Consumer #0 Waiting for latch of 100  &amp; 5 seconds timeou
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@192d342[Count = 0]
Thread Consumer #0 OverFlow, 2.5142925s
Thread Consumer #0 messages #100
Thread Consumer #0 Waiting for latch of 100  &amp; 5 seconds timeout
10062 main done
MyBasket.stop()
</pre><ul><li>CyclicLatch taille 100, time out 2 secondes. Les traces, ci-dessous, montrent qui le <em>latch</em> a été déclenché maintenant sur timeout avec une file qui contient environ 80 messages.</li></ul><pre class="brush: java; title: ; notranslate">
main Consumer.Consumer()
MyBasket.start()
Thread Consumer #0 Consumer.run()
Thread Consumer #0 Waiting for latch of 100  &amp; 2 seconds timeout
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@45a877[Count = 20]
Thread Consumer #0 TimeOut,  2.0013237s
Thread Consumer #0 messages #80
Thread Consumer #0 Waiting for latch of 100  &amp; 2 seconds timeout
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@126b249[Count = 20]
Thread Consumer #0 TimeOut,  2.000778s
Thread Consumer #0 messages #80
Thread Consumer #0 Waiting for latch of 100  &amp; 2 seconds timeout
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@182f0db[Count = 20]
Thread Consumer #0 TimeOut,  2.0010734s
Thread Consumer #0 messages #80
Thread Consumer #0 Waiting for latch of 100  &amp; 2 seconds timeout
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@192d342[Count = 20]
Thread Consumer #0 TimeOut,  2.0014079s
Thread Consumer #0 messages #80
Thread Consumer #0 Waiting for latch of 100  &amp; 2 seconds timeout
Thread Consumer #0 Reset Latch....java.util.concurrent.CountDownLatch@6b97fd[Count = 20]
Thread Consumer #0 TimeOut,  2.001409s
Thread Consumer #0 messages #80
Thread Consumer #0 Waiting for latch of 100  &amp; 2 seconds timeout
10078 main done
MyBasket.stop()
</pre><h3><a
name="Conclusion"></a>Conclusion</h3><p>La programmation concurrente est vraiment passionnante, mais il faut absolument devenir <strong>paranoïaque</strong>. En effet, il faut envisager tous les cas possibles: chaque instruction doit être envisagée comme pouvant être interrompue. Le simple conseil que je vous donnerais est de commencer par synchroniser toutes les sections critiques (mot-clé <code>synchronized</code>). Ensuite, et après réflexion et bench, vous pourrez passer à des verrouillages de plus bas niveau si nécessaire (les JVM modernes ont fait d&#8217;énormes progrès dans ce domaine!)</p><p>Depuis que j&#8217;ai implémenté cette classe pour un projet et un besoin précis, je trouve régulièrement un nouveau cas d&#8217;utilisation. Le dernier en date est l&#8217;affichage dynamique dans une application Swing de graphes <a
href="http://www.jfree.org/jfreechart/" title="JFreeChart" >JFreeChart</a> d&#8217;un très grand nombre de valeurs en fonction du temps.</p><p>Et vous, que ferez-vous du CyclicLatch ?</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/09/24/frxebiaconcurrentcycliclatch/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>WebLogic Persistent Store</title><link>http://blog.xebia.fr/2008/08/06/weblogic-persistent-store/</link> <comments>http://blog.xebia.fr/2008/08/06/weblogic-persistent-store/#comments</comments> <pubDate>Wed, 06 Aug 2008 06:43:48 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[J2EE]]></category> <category><![CDATA[JMS]]></category> <category><![CDATA[Weblogic]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=553</guid> <description><![CDATA[Le serveur d&#8217;applications Weblogic permet de déclarer des serveurs JMS. À chaque serveur JMS est associé un Persistent Store, emplacement destiné à persister les messages JMS en cas d&#8217;interruptions de service entre la publication d&#8217;un message et sa consommation. Deux supports possibles : File Persistence Store, un répertoire accessible par le serveur Weblogic composé d&#8217;un [...]]]></description> <content:encoded><![CDATA[<p>Le serveur d&#8217;applications Weblogic permet de déclarer des serveurs JMS. À chaque serveur JMS est associé un Persistent Store, emplacement destiné à persister les messages JMS en cas d&#8217;interruptions de service entre la publication d&#8217;un message et sa consommation. Deux supports possibles :</p><ul><li>File Persistence Store, un répertoire accessible par le serveur Weblogic composé d&#8217;un ou plusieurs fichiers de structures binaires (.DAT)</li><li>JDBC Persistence Store, ensemble de tables contenues dans une base de données relationnelle et accessible à travers une &#8216;DataSource&#8217;. La structure des tables et leur contenu sont exclusiment gérés par le serveur d&#8217;applications.</li></ul><p>Le <a
href="http://edocs.bea.com/wls/docs92/config_wls/store.html#compare" title="choix de l'un des deux types de stockage" >choix de l&#8217;un des deux types de stockage</a> est principalement dicté par des contraintes d&#8217;architecture et d&#8217;exploitation; les avantages de l&#8217;un sont les inconvénients de l&#8217;autre.</p><p>Jusqu&#8217;à la version 8 de Weblogic, il était impossible de pouvoir les administrer, en particulier pouvoir les ouvrir, analyser ou dumper leur contenu.</p><p>À partir de la version 9, le serveur d&#8217;applications propose un outil : weblogic.store.Admin</p><pre class="brush: java; title: ; notranslate">
java -classpath ${WLS_DIR}/servir/lib/weblogic.jar weblogic.store.Admin
</pre><p>Les commandes principales sont : <a
href="http://blog.xebia.fr/2008/08/06/weblogic-persistent-store/#Open">open</a>, <a
href="http://blog.xebia.fr/2008/08/06/weblogic-persistent-store/#Dump">dump</a> et <a
href="http://blog.xebia.fr/2008/08/06/weblogic-persistent-store/#Compact">compact</a>.</p><h3><a
name="Open"></a>Open</h3><p>La première opération à effectuer est de se connecter au Persistent Store, soit par <em>openfile</em>, soit par <em>openjdbc</em>. Le reste des commandes resteront identiques vis-à-vis du type de store.<br
/> <code><br
/> <strong>storeadmin-> openfile -store FileStore_auto_1 -dir FileStore_auto_1</strong><br
/> &lt;Jul 25, 2008 4:03:48 PM MEST&gt; &lt;Info&gt; &lt;Store&gt; &lt;BEA-280050&gt; &lt;Persistent store "FileStore_auto_1" opened: directory="FileStore_auto_1" writePolicy="Cache-Flush" blockSize=512 direc  tIO=false driver="NIO"&gt;<br
/> INFO: Store FileStore_auto_1 opened successfully<br
/> storeadmin->list<br
/> INFO: Currently open stores :<br
/> FileStore_auto_1<br
/> <strong>storeadmin-></strong><br
/> </code></p><h3><a
name="Dump"></a>Dump</h3><p>Cette commande permet d&#8217;obtenir le contenu du store et de le transférer dans un fichier<br
/> <code><br
/> <strong>storeadmin-> dump -store FileStore_auto_1 -out /tmp/dump_FileStore_auto_1.log</strong><br
/> INFO: Dump from FileStore_auto_1 to /tmp/dump_FileStore_auto_1.log.xml successful<br
/> </code></p><p>Le contenu du fichier indique le nombre total de messages, le nombre de création, lecture, mise à jour et suppression avec le détail par connexion.</p><pre class="brush: xml; title: ; notranslate">
&lt;PersistentStore Name=&quot;FileStore_auto_1&quot; Open=&quot;true&quot;&gt;
  &lt;IOLayer&gt;
    &lt;FileStore Directory=&quot;FileStore_auto_1&quot; WritePolicy=&quot;Cache-Flush&quot; BlockSize=&quot;452&quot; SupportOSDirectIO=&quot;false&quot; HeapVersion=&quot;2&quot;&gt;&lt;/FileStore&gt;
  &lt;/IOLayer&gt;
  &lt;Statistics&gt;
    &lt;NumObjects&gt;36737&lt;/NumObjects&gt;
    &lt;Creates&gt;0&lt;/Creates&gt;
    &lt;Reads&gt;0&lt;/Reads&gt;
    &lt;Updates&gt;0&lt;/Updates&gt;
    &lt;Deletes&gt;0&lt;/Deletes&gt;
    &lt;PhysicalWrites&gt;0&lt;/PhysicalWrites&gt;
    &lt;PhysicalReads&gt;0&lt;/PhysicalReads&gt;
  &lt;/Statistics&gt;
....
&lt;/PersistentStore&gt;
</pre><p>Il existe une option à la commande dump qui permet d&#8217;avoir non seulement les statistiques, mais également le contenu des éléments, ici les messages JMS<br
/> <code><br
/> <strong>storeadmin->dump -store FileStore_auto_1 -out /tmp/dump_FileStore_auto_1.log.deep -deep</strong><br
/> INFO: Dump from FileStore_auto_1 to /tmp/dump_FileStore_auto_1.log.deep.xml successful<br
/> </code><br
/> <strong>Attention</strong> : la taille de ce fichier peut être extrêmement importante, c&#8217;est une projection XML de données stockées en mode binaire&nbsp;!</p><pre class="brush: xml; title: ; notranslate">
&lt;Connection Name=&quot;weblogic.messaging.wlsbJMSServer_auto_1.header&quot; Kind=&quot;normal&quot; Typecode=&quot;3&quot;&gt;
  &lt;Statistics&gt;
    &lt;NumObjects&gt;0&lt;/NumObjects&gt;
    &lt;Creates&gt;0&lt;/Creates&gt;
    &lt;Reads&gt;0&lt;/Reads&gt;
    &lt;Updates&gt;0&lt;/Updates&gt;
    &lt;Deletes&gt;0&lt;/Deletes&gt;
  &lt;/Statistics&gt;
  &lt;Records&gt;
    &lt;Record TypeCode=&quot;3&quot; SlotNum=&quot;1798&quot; HandleNum=&quot;2490510606351&quot; FileNum=&quot;0&quot; BlockNum=&quot;148446&quot; NumBlocks=&quot;15&quot;&gt;
      &lt;RecordContents&gt;    0: 0001 0000 0101 0000 0000 0000 0006 0000   ................
   16: 0000 0000 ba74 0000 0000 0005 0801 0000   .....t..........
   32: 0000 0017 e64a 0000 0000 0000 1bce 7fff   .....J..........
   48: ffff 0008 1e2d 0204 0000 0000 0000 0030   .....-.........0
   64: 0000 0002 0066 0011 5245 504f 5254 494e   .....f..REPORTIN
   80: 4744 4154 4154 5950 4500 6800 0000 0200   GDATATYPE.h.....
   96: 6600 074d 5347 5459 5045 0068 0000 0001   f..MSGTYPE.h....
  112: 0c00 0001 1b59 bea7 0e00 0000 0000 0c63   .....Y.........c
  128: ce00 0000 0002 0000 1bce aced 0005 7372   ..............sr
  144: 0037 636f 6d2e 6265 612e 776c 692e 7265   .7com.bea.wli.re
  160: 706f 7274 696e 672e 6a6d 7370 726f 7669   porting.jmsprovi
  176: 6465 722e 7275 6e74 696d 652e 5265 706f   der.runtime.Repo
  192: 7274 4d65 7373 6167 6576 850c c3d6 d6bf   rtMessagev......
  208: 8502 0004 5b00 0a62 696e 5061 796c 6f61   ....[..binPayloa
</pre><h3><a
name="Compact"></a>Compact</h3><p>L&#8217;ajout et la suppression d&#8217;éléments dans le store peuvent engendrer de la fragmentation. L&#8217;outil permet d&#8217;effectuer un compactage d&#8217;un PersistenceStore <strong>non-ouvert</strong>.<br
/> <code><br
/> <strong>storeadmin-> close -store FileStore_auto_1</strong><br
/> INFO: Store FileStore_auto_1 closed successfully<br
/> <strong>storeadmin-> compact -dir FileStore_auto_1 -tempdir /var/weblogic/</strong><br
/> &lt;Jul 25, 2008 4:26:16 PM MEST&gt; &lt;Info&gt; &lt;Store&gt; &lt;BEA-280050&gt; &lt;Persistent store "FILESTORE_AUTO_1" opened: directory="/var/weblogic/STOREADMIN_46757" writePolicy="Cache-Flush" blockSize=512 directIO=false driver="NIO"&gt;<br
/> INFO: Original FileStore_auto_1 moved to /var/weblogic/STOREADMIN_46757<br
/> INFO: Compacting store ... FILESTORE_AUTO_1<br
/> INFO: Store FILESTORE_AUTO_1 opened successfully<br
/> &lt;Jul 25, 2008 4:26:21 PM MEST&gt; &lt;Info&gt; &lt;Store&gt; &lt;BEA-280050&gt; &lt;Persistent store "STOREADMIN_FILESTORE_AUTO_1" opened: directory="FileStore_auto_1" writePolicy="Cache-Flush" blockSize=512 directIO=false driver="NIO"&gt;<br
/> INFO: Store STOREADMIN_FILESTORE_AUTO_1 created and opened successfully<br
/> INFO: Copy from FILESTORE_AUTO_1 to STOREADMIN_FILESTORE_AUTO_1 successful<br
/> INFO: Store FILESTORE_AUTO_1 closed successfully<br
/> INFO: Store STOREADMIN_FILESTORE_AUTO_1 closed successfully<br
/> INFO: Renamed STOREADMIN_FILESTORE_AUTO_1 to FILESTORE_AUTO_1<br
/> INFO: ... Compacted store FILESTORE_AUTO_1<br
/> INFO: Compact of FileStore_auto_1 successful : pre-compact files in /var/weblogic/STOREADMIN_46757<br
/> <strong>storeadmin-></strong><br
/> </code></p><p>Un dernier conseil : il est déconseillé de lancer cet outil alors que le serveur d&#8217;applications est en pleine charge: cela peut provoquer des effets de bords indésirables, du temps de réponse en berne à la corruption irréparable du Persistence Store.</p><p>Référence: <a
href="http://edocs.bea.com/wls/docs92/config_wls/store.html#wp1149755" title="Administering a Persistent Store " >Administering a Persistent Store </a></p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/08/06/weblogic-persistent-store/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Exception synchronisée</title><link>http://blog.xebia.fr/2008/07/02/exception-synchronisee/</link> <comments>http://blog.xebia.fr/2008/07/02/exception-synchronisee/#comments</comments> <pubDate>Wed, 02 Jul 2008 06:00:33 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[exception]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2008/07/02/exception-synchronisee/</guid> <description><![CDATA[Symptômes Lors d&#8217;un test de performance sur une application J2EE, je note que celle-ci a des soucis de montée en charge. Généralement une ou deux thread dumps peuvent mettre en évidence les points de contentions. Dans mon cas, rien de probant. Je repense alors à l&#8217;article publié sur notre blog Chroniques de la performance : [...]]]></description> <content:encoded><![CDATA[<h3><a
name="Symptmes"></a>Symptômes</h3><p>Lors d&#8217;un test de performance sur une application J2EE, je note que celle-ci a des soucis de montée en charge. Généralement une ou deux thread dumps peuvent mettre en évidence les points de contentions. Dans mon cas, rien de probant. Je repense alors à l&#8217;article publié sur notre blog <a
href="http://blog.xebia.fr/2007/11/29/chroniques-de-la-performance-a-propos-de-contentions/" title="Chroniques de la performance : À propos de contentions..." >Chroniques de la performance : À propos de contentions&#8230;</a>. Je récupère les sources de l&#8217;agent et l&#8217;installe sur le serveur d&#8217;application, Weblogic 8.1 &#8211; JVM 1.4.2. Lancement du tir&#8230;.</p><p>Dès le début de phase plateau, l&#8217;agent affiche régulièrement une partie du code que je n&#8217;aurais pas soupçonné: la bibliothèque <a
href="http://ibatis.apache.org" title="iBatis" >iBatis</a> qui gère l&#8217;accès aux données.</p><pre class="brush: java; title: ; notranslate">
[JTPROF] Contention report [id=-1250505672,thread=ExecuteThread: '14' for queue: 'weblogic.kernel.Default',blocked=210ms]
[JTPROF] Stack trace:
[JTPROF]         com.ibatis.sqlmap.engine.accessplan.EnhancedPropertyAccessPlan.&lt;init&gt; (EnhancedPropertyAccessPlan.java:29)
[JTPROF]         com.ibatis.sqlmap.engine.accessplan.AccessPlanFactory.getAccessPlan (AccessPlanFactory.java:62)
[JTPROF]         com.ibatis.sqlmap.engine.exchange.JavaBeanDataExchange.initialize (JavaBeanDataExchange.java:63)
[JTPROF]         com.ibatis.sqlmap.engine.mapping.parameter.BasicParameterMap.setParameterMappingList (BasicParameterMap.java:93)
[JTPROF]         com.ibatis.sqlmap.engine.builder.xml.SqlStatementParser.applyInlineParameterMap (SqlStatementParser.java:431)
[JTPROF]         com.ibatis.sqlmap.engine.builder.xml.SqlStatementParser.processSqlStatement (SqlStatementParser.java:215)
[JTPROF]         com.ibatis.sqlmap.engine.builder.xml.SqlStatementParser.parseGeneralStatement (SqlStatementParser.java:120)
</pre><p>Les temps de blocage affichés vont de 20ms à 500ms !</p><h3><a
name="Analyse"></a>Analyse</h3><p>A la lecture de cette pile d&#8217;appel, je me dis <em>&laquo;&nbsp;encore un bloc synchronisé mal placé dans <a
href="http://ibatis.apache.org" title="iBatis" >iBatis</a>&laquo;&nbsp;</em>. L&#8217;avantage avec l&#8217;open source, comme son nom l&#8217;indique, est que l&#8217;on a accès aux sources. J&#8217;ai donc ouvert la classe EnhancedPropertyAccessPlan qui, à ma grande déception, infirma ma 1ère intuition :</p><pre class="brush: java; title: ; notranslate">
27  EnhancedPropertyAccessPlan(Class clazz, String[] propertyNames) {
28    super(clazz, propertyNames);
29    bulkBean = BulkBean.create(clazz, getGetterNames(propertyNames), getSetterNames(propertyNames), getTypes(propertyNames));
30  }
</pre><p>La ligne #29 indique l&#8217;appel à une méthode statique de la classe &laquo;&nbsp;BulkBean&nbsp;&raquo; qui appartient à la bibliothèque <a
href="http://cglib.sourceforge.net" title="cgLib" >cgLib</a>, bien connue pour accélérer efficacement la création de beans Proxy . Idem: cette méthode n&#8217;est pas &#8216;synchronized&#8217;. Alors pourquoi l&#8217;agent m&#8217;indique cette méthode ?<br
/> Les grands moyens : injection de traces manuelles dans le code d&#8217;iBatis afin de comprendre ce qu&#8217;il se trame. Après de nombreux allers-retours de type &#8216;essais-erreurs&#8217;, je finis par trouver l&#8217;origine du problème : chaque appel à la méthode <em>BulkBean.create()</em> engendre une levée d&#8217;exception <em>NoClassDefFoundError</em>.<br
/> En effet, le packaging de l&#8217;ear est incomplet : <em>cglib.jar</em> est bien présente mais il manque l&#8217;une de ses dépendances : <a
href="http://asm.objectweb.org/" title="asm" >asm</a>. Or le code de la méthode <em>BulkBean.create()</em> s&#8217;appuie essentiellement sur l&#8217;API d&#8217;asm.<br
/> Cependant le packaging n&#8217;est pas le seul coupable, iBatis est également fautive ! La méthode <a
href="http://ibatis.apache.org/docs/java/dev/com/ibatis/sqlmap/engine/accessplan/AccessPlanFactory.html" title="AccessPlanFactory.getAccessPlan" >AccessPlanFactory.getAccessPlan</a> est extrêmement défensive : l&#8217;appel à EnhancedPropertyAccessPlan est gardé par un bloc <em>try&#8230;catch(Throwable)</em>. L&#8217;ajout d&#8217;un message de log de type &laquo;&nbsp;Erreur&nbsp;&raquo; aurait été le bienvenue, au moins la première fois.</p><pre class="brush: java; title: ; notranslate">
60:       if (bytecodeEnhancementEnabled) {
61:        try {
62:          plan = new EnhancedPropertyAccessPlan(clazz, propertyNames);
63:        } catch (Throwable t) {
64:          try {
65:            plan = new PropertyAccessPlan(clazz, propertyNames);
66:         } catch (Throwable t2) {
67:            plan = new ComplexAccessPlan(clazz, propertyNames);
68:          }
69:        }
</pre><h3><a
name="Explications"></a>Explications</h3><p>La levée d&#8217;une exception dans une méthode oblige la JVM à rendre l&#8217;appel synchronisé afin de garantir un traitement par le <em>catch</em> cohérent. Il ne faudrait pas que les données (attributs, paramètres, variables) aient été modifiées par un autre thread entre la levée de l&#8217;exception et son éventuel traitement.</p><p>Pour se convaincre de ce phénomène, il suffit d&#8217;écrire une simple classe de test : 10 threads, chaque thread appelle une méthode qui suivant un paramètre lève une <a
href="http://java.sun.com/javase/6/docs/api/java/lang/Exception.html" title="Exception" >Exception</a>, une <a
href="http://java.sun.com/javase/6/docs/api/java/lang/Error.html" title="Error" >Error</a> ou ne fait rien, et ceci 1 000 000 de fois. Le résultat :</p><ul><li>lorsque la méthode ne lève aucune Exception ou Erreur : Temps de réponse : 89 ms</li><li>lorsque la méthode lève une exception : Temps de réponse 5892 ms, 66 fois plus lent !</li></ul><p>Règle: <em>La levée d&#8217;exception doit rester un cas exceptionnel et ne dois en aucun cas devenir un design pattern, c&#8217;est même un<strong> anti-pattern</strong></em>.</p><pre class="brush: java; title: ; notranslate">
public class AntiPattern {
	class NotEvenException extends Exception {
	}
	boolean isEven(int nb) {
		try {
			if (nb % 2 &gt; 0)
				throw new NotEvenException();
			return true;
		} catch (NotEvenException e) {
			return false;
		}
	}
}
</pre><p>Note : Une fois le packaging complet, l&#8217;agent <em>jtprof</em> ne mentionne plus du tout cette zone de l&#8217;application.</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/07/02/exception-synchronisee/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>Les plans de déploiement Weblogic</title><link>http://blog.xebia.fr/2008/04/17/les-plans-de-deploiement-weblogic/</link> <comments>http://blog.xebia.fr/2008/04/17/les-plans-de-deploiement-weblogic/#comments</comments> <pubDate>Thu, 17 Apr 2008 09:33:25 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Exploitation]]></category> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Administration]]></category> <category><![CDATA[Déploiement]]></category> <category><![CDATA[Weblogic]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2008/04/17/les-plans-de-deploiement-weblogic/</guid> <description><![CDATA[&#171;&#160;Il faudrait pouvoir changer le nom de la DataSource en fonction des environnements&#160;&#187; &#171;&#160;Ouh la la, c&#8217;est compliqué, il faut décompresser l&#8217;archive de l&#8217;application MonApp.ear et les 5 fichiers .war et les 8 fichiers .jar des ejb. Ça prendra 3 semaines minimum, et sans la documentation!&#160;&#187; (La fonctionnalité &#171;&#160;plans de déploiement&#160;&#187; décrite dans cette article [...]]]></description> <content:encoded><![CDATA[<p><em>&laquo;&nbsp;Il faudrait pouvoir changer le nom de la DataSource en fonction des environnements&nbsp;&raquo;</em><br
/> <em>&laquo;&nbsp;Ouh la la, c&#8217;est compliqué, il faut décompresser l&#8217;archive de l&#8217;application MonApp.ear et les 5 fichiers .war et les 8 fichiers .jar des ejb. Ça prendra 3 semaines minimum, et sans la documentation!&nbsp;&raquo;</em></p><p><em><strong>(La fonctionnalité &laquo;&nbsp;plans de déploiement&nbsp;&raquo; décrite dans cette article est disponible à partir de WebLogic 9)</strong></em></p><p>Lors de l&#8217;<a
href="http://blog.xebia.fr/2008/03/11/packagez-vos-sources-de-donnees-avec-weblogic/" title="article précédent" >article précédent</a>, nous avions montré comment packager un pool de connexions JDBC avec un EAR. Il semble évident que si cette solution est intéressante, elle n&#8217;est suffisante pour paramétrer cette application dans différents environnements projets (Recette, Pré-Production ou Production). Il n&#8217;est pas envisageable que pour chaque environnement, il faille ouvrir l&#8217;archive, modifier le fichier XML avec les nouveaux paramètres et pour finir de la refermer.<br
/> L&#8217;idée des plans de déploiement est de laisser l&#8217;archive telle quelle et de lui associer au moment du déploiement les nouveaux paramètres. Un plan de déploiement est un fichier XML qui reprend l&#8217;ensemble des nouveaux paramètres à surcharger.</p><p>Reprenons l&#8217;application MyWebApplicationEAR décrite dans la première partie et appliquons un plan de déploiement pour modifier quelques paramètres.</p><h3><a
name="Prparationdelenvironnementdetr"></a>Préparation de l&#8217;environnement de travail</h3><pre class="brush: plain; title: ; notranslate">
mkdir DeployementPlan
mkdir DeployementPlan/MyWebApplicationEAR
mkdir DeployementPlan/MyWebApplicationEAR/app
cp MyWebApplicationEAR.ear DeployementPlan/app
#vérifions la structure de répertoire
find DeployementPlan
./MyWebApplicationEAR
./MyWebApplicationEAR/app
./MyWebApplicationEAR/app/MyWebApplicationEAR.ear
</pre><h3><a
name="Gnrationdutemplateduplan"></a>Génération du template du plan</h3><p>WebLogic fournit un outil qui permet de générer un template de plan de déploiement basé sur les différents éléments de l&#8217;ear passé en paramètre.</p><pre class="brush: plain; title: ; notranslate">
cd D:xebia-blogdeploymentplan
java -classpath ${WLS_HOME}/server/lib/weblogic jar weblogic.PlanGenerator -root MyWebApplicationEAR
Generating plan for application MyWebApplicationEARappMyWebApplicationEAR.ear
Export option is: dependencies
Exporting properties...
Saving plan to D:xebia-blogdeploymentplanMyWebApplicationEARplanplan.xml...
&lt;4 avr. 2008 18 h 03 CEST&gt; &lt;Info&gt; &lt;J2EE Deployment SPI&gt; &lt;BEA-260072&gt; &lt;Saved configuration for application, MyWebApplicationEAR.ear&gt;
MyWebApplicationEAR
+---app
|       MyWebApplicationEAR.ear
|
---plan
        plan.xml
</pre><p>Le fichier template du plan (plan.xml) a été créé dans le répertoire plan</p><h3><a
name="Structuredufichierplanxml"></a>Structure du fichier plan.xml</h3><p>A ce niveau du processus, le fichier plan.xml contient uniquement la définition des différents modules qui composent l&#8217;archive EAR. On retrouve donc:</p><ul><li>un module MyWebApplicationEAR.ear, de type EAR, avec 3 descripteurs de déploiement (weblogic-application.xml, application.xml et ds-jdbc.xml)</li><li>un module MyWebApplication.war, de type WAR, avec 2 descripteurs de déploiement (web.xml et weblogic.xml)</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;deployment-plan xmlns=&quot;http://www.bea.com/ns/weblogic/90&quot;
 xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xsi:schemaLocation=&quot;http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-deployment-plan.xsd&quot;
 global-variables=&quot;false&quot;&gt;
  &lt;application-name&gt;MyWebApplicationEAR.ear&lt;/application-name&gt;
  &lt;!-- Descripteurs portés par l'EAR --&gt;
  &lt;module-override&gt;
    &lt;module-name&gt;MyWebApplicationEAR.ear&lt;/module-name&gt;
    &lt;module-type&gt;ear&lt;/module-type&gt;
    &lt;module-descriptor external=&quot;false&quot;&gt;
      &lt;root-element&gt;weblogic-application&lt;/root-element&gt;
      &lt;uri&gt;META-INF/weblogic-application.xml&lt;/uri&gt;
    &lt;/module-descriptor&gt;
    &lt;module-descriptor external=&quot;false&quot;&gt;
      &lt;root-element&gt;application&lt;/root-element&gt;
      &lt;uri&gt;META-INF/application.xml&lt;/uri&gt;
    &lt;/module-descriptor&gt;
    &lt;module-descriptor external=&quot;false&quot;&gt;
      &lt;root-element&gt;jdbc-data-source&lt;/root-element&gt;
      &lt;uri&gt;META-INF/ds-jdbc.xml&lt;/uri&gt;
    &lt;/module-descriptor&gt;
  &lt;/module-override&gt;
  &lt;!-- Descripteurs portés par le WAR--&gt;
  &lt;module-override&gt;
    &lt;module-name&gt;MyWebApplication.war&lt;/module-name&gt;
    &lt;module-type&gt;war&lt;/module-type&gt;
    &lt;module-descriptor external=&quot;false&quot;&gt;
      &lt;root-element&gt;weblogic-web-app&lt;/root-element&gt;
      &lt;uri&gt;WEB-INF/weblogic.xml&lt;/uri&gt;
    &lt;/module-descriptor&gt;
    &lt;module-descriptor external=&quot;false&quot;&gt;
      &lt;root-element&gt;web-app&lt;/root-element&gt;
      &lt;uri&gt;WEB-INF/web.xml&lt;/uri&gt;
    &lt;/module-descriptor&gt;
  &lt;/module-override&gt;
  &lt;config-root xsi:nil=&quot;true&quot;&gt;&lt;/config-root&gt;
&lt;/deployment-plan&gt;
</pre><h3><a
name="Paramtrageduplanenutilisantlac"></a>Paramétrage du plan en utilisant la console d&#8217;administration</h3><p>Notre plan est vide, il faut maintenant indiquer les paramètres à modifier. Dans un premier temps, le plus simple est d&#8217;utiliser la console d&#8217;administration du domaine.</p><ol><li>Déployer l&#8217;application en sélectionnant le répertoire <code>DeployementPlan/MyWebApplicationEAR</code>.</li><li>Accepter l&#8217;ensemble des valeurs par défaut (Next, Next, Finish)</li><li>Activer les modifications.</li></ol><p>Remarque : On voit que le fichier plan.xml est indiqué comme &#8216;Deployment Plan&#8217;</p><div
align="center"> <object
classid='clsid:\D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0' data='http://blog.xebia.fr/wp-content/uploads/2008/04/deploy-700x406.swf' height='407' type='application/x-shockwave-flash2-preview' width='700' ><param
name='data' value='http://blog.xebia.fr/wp-content/uploads/2008/04/deploy-700x406.swf'/><param
name='loop' value='false'/><param
name='menu' value='false'/><param
name='movie' value='http://blog.xebia.fr/wp-content/uploads/2008/04/deploy-700x406.swf'/><param
name='quality' value='high'/><param
name='scale' value='exactfit'/><param
name='src' value='http://blog.xebia.fr/wp-content/uploads/2008/04/deploy-700x406.swf'/><param
name='type' value='application/x-shockwave-flash2-preview'/><embed
height='407' pluginspage='https://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash' quality='high' src='http://blog.xebia.fr/wp-content/uploads/2008/04/deploy-700x406.swf' type='application/x-shockwave-flash2-preview' width='700' /></object></div><h3><a
name="Paramtragepourunenvironnementd"></a>Paramétrage pour un environnement de Recette.</h3><ol><li>Sélectionner le module MyWebApplicationDS</li><li>Dans le menu Configuration / ConnectionPool, modifier les propriétés UserName et Password (Recette/Recette) et Maximum Capacity=10 et Web Session Timeout (in seconds) = 360.</li><li>Après les différentes phases de sauvegarde, les modifications sont inscrites directement dans le fichier plan/plan.xml, les fichiers de configuration du domaine Weblogic (config/config.xml et consorts) restent inchangés. La console WebLogic indique cette différence par un bouton <strong>&#8216;ReleaseConfiguration&#8217;</strong> et non <strong>&#8216;Apply Changes&#8217;</strong>.</li></ol><div
align="center"> <object
classid='clsid:\D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0' data='http://blog.xebia.fr/wp-content/uploads/2008/04/config-plan-700x400.swf' height='407' type='application/x-shockwave-flash2-preview' width='700' ><param
name='data' value='http://blog.xebia.fr/wp-content/uploads/2008/04/config-plan-700x400.swf'/><param
name='loop' value='false'/><param
name='menu' value='false'/><param
name='movie' value='http://blog.xebia.fr/wp-content/uploads/2008/04/config-plan-700x400.swf'/><param
name='quality' value='high'/><param
name='scale' value='exactfit'/><param
name='src' value='http://blog.xebia.fr/wp-content/uploads/2008/04/config-plan-700x400.swf'/><param
name='type' value='application/x-shockwave-flash2-preview'/><embed
height='407' pluginspage='https://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash' quality='high' src='http://blog.xebia.fr/wp-content/uploads/2008/04/config-plan-700x400.swf' type='application/x-shockwave-flash2-preview' width='700' /></object></div><h3><a
name="Structuredufichierplanxml"></a>Structure du fichier plan.xml</h3><p>Si on examine les modifications faites par la Console Weblogic sur le fichier plan.xml, on peut noter:</p><ul><li>l&#8217;apparition d&#8217;un ensemble de nœuds gardé par &lt;variable-definition/&gt;. Il contient un ensemble de couples de variables (name, value) qui correspondent aux paramètres modifiés</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;deployment-plan xmlns=&quot;http://www.bea.com/ns/weblogic/90&quot;
   xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; ...&gt;
  &lt;application-name&gt;MyWebApplicationEAR&lt;/application-name&gt;
  &lt;!-- Bloc Variable Definition --&gt;
  &lt;variable-definition&gt;
    &lt;variable&gt;
      &lt;name&gt;JDBCDriverParams_PasswordEncrypted_12040376123280&lt;/name&gt;
      &lt;value&gt;{3DES}QZJ2MfqOliA=&lt;/value&gt;
    &lt;/variable&gt;
    &lt;variable&gt;
      &lt;name&gt;JDBCConnectionPoolParams_MaxCapacity_12040378132185&lt;/name&gt;
      &lt;value&gt;10&lt;/value&gt;
    &lt;/variable&gt;
    &lt;variable&gt;
      &lt;name&gt;JDBCProperty_user_Value_12040378358436&lt;/name&gt;
      &lt;value&gt;recette&lt;/value&gt;
    &lt;/variable&gt;
    &lt;variable&gt;
      &lt;name&gt;SessionDescriptor_timeoutSecs_12040384414060&lt;/name&gt;
      &lt;value&gt;360&lt;/value&gt;
    &lt;/variable&gt;
  &lt;/variable-definition&gt;
  .....
&lt;/deployment-plan&gt;
</pre><ul><li>la modification des nœuds <module-descriptor/>. Pour chaque variable qui concerne le module, une expression <a
href="http://fr.wikipedia.org/wiki/XPath" title="XPath" >XPath</a> est définie pour permettre au serveur d&#8217;application d&#8217;effectuer la substitution avec la nouvelle valeur.</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;deployment-plan xmlns=&quot;http://www.bea.com/ns/weblogic/90&quot;
   xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; ...&gt;
....
   &lt;module-descriptor external=&quot;false&quot;&gt;
      &lt;root-element&gt;jdbc-data-source&lt;/root-element&gt;
      &lt;uri&gt;META-INF/ds-jdbc.xml&lt;/uri&gt;
      &lt;variable-assignment&gt;
        &lt;name&gt;JDBCDriverParams_PasswordEncrypted_12040376123280&lt;/name&gt;
        &lt;xpath&gt;/jdbc-data-source/jdbc-driver-params/password-encrypted&lt;/xpath&gt;
      &lt;/variable-assignment&gt;
      &lt;variable-assignment&gt;
        &lt;name&gt;JDBCConnectionPoolParams_MaxCapacity_12040378132185&lt;/name&gt;
        &lt;xpath&gt;/jdbc-data-source/jdbc-connection-pool-params/max-capacity&lt;/xpath&gt;
      &lt;/variable-assignment&gt;
      &lt;variable-assignment&gt;
        &lt;name&gt;JDBCProperty_user_Value_12040378358436&lt;/name&gt;
        &lt;xpath&gt;/jdbc-data-source/jdbc-driver-params/properties/property/[name=&quot;user&quot;]/value&lt;/xpath&gt;
      &lt;/variable-assignment&gt;
    &lt;/module-descriptor&gt;
....
&lt;/deployment-plan&gt;
</pre><p>A partir de ce plan créé pour un environnement de type &#8216;Recette&#8217; (<a
href="http://blog.xebia.fr/wp-content/uploads/2008/04/plan-recette.xml" title="plan-recette.xml" >plan-recette.xml</a>), il est facile de le décliner pour d&#8217;autres environnement, ex la &#8216;Production&#8217; (<a
href="http://blog.xebia.fr/wp-content/uploads/2008/04/plan-production.xml" title="plan production">plan-production.xml</a>). Les changements sont :</p><ul><li>les propriétés UserName et Password (Production/Production) et</li><li>la propriété Maximum Capacity=20.</li></ul><pre class="brush: plain; title: ; notranslate">
DeployementPlanMyWebApplicationEAR
+---app
|       MyWebApplicationEAR.ear
|
---plan
        plan-production.xml
        plan-recette.xml
</pre><p>(Note: le fichier plan.xml a été renommé en &#8216;plan-recette.xml&#8217;).</p><h3><a
name="Utilisationduplan"></a>Utilisation du plan</h3><p>Une fois les plans créés, il est très facile avec <a
href="http://blog.xebia.fr/2007/05/09/weblogic-scripting-tools/" title="WLST">WLST</a> de déployer l&#8217;application sur l&#8217;environnement cible avec son plan de déploiement.<br
/> Note : Une fois les fichiers de plan de déploiement créés, il n&#8217;est pas nécessaire de conserver une arborescence ./app et ./plan comme établi en début d&#8217;article.</p><p>Exemple: déploiement de l&#8217;application MyWebApplicationEAR en mode production.</p><pre class="brush: plain; title: ; notranslate">
deploy(appName='MyWebApplicationEAR',path='/vers/monfichier/ear/MyWebApplicationEAR.ear', planPath=/vers/mon/plan/MyWebApplicationEAR/plan/plan-production.xml')
</pre><p>Vérification avec l&#8217;application MyWebApplication:</p><div
align="center"> <img
src="http://blog.xebia.fr/wp-content/uploads/2008/04/6-mode-production2.png" border="0" alt="" /></div><p>Les plans de déploiement peuvent également servir à mettre à jour les paramètres de l&#8217;application si celle-ci est déjà déployée dans le serveur WebLogic</p><ul><li>Soit avec la console d&#8217;administration, deployement &#8211;> update</li></ul><div
align="center"> <img
src="http://blog.xebia.fr/wp-content/uploads/2008/04/7-update-resized.png" border="0" alt="" /></div><ul><li>Soit avec la commande WLST <a
href="http://edocs.bea.com/wls/docs100/config_scripting/reference.html#wp1039405" title="updateApplication" >updateApplication</a> ou <a
href="http://edocs.bea.com/wls/docs100/config_scripting/reference.html#wp1024321" title="redeploy" >redeploy</a></li></ul><p>Exemple:</p><pre class="brush: java; title: ; notranslate">
updateApplication(''MyWebApplicationEAR','/vers/mon/plan/MyWebApplicationEAR/plan/plan-production-tuning.xml')
</pre><h3><a
name="Conclusion"></a>Conclusion</h3><p>Les plans de déploiement :</p><ul><li>répondent à un besoin longtemps exprimé par les utilisateurs: pouvoir modifier le paramétrage d&#8217;une application sans à nécessiter de lourdes procédures d&#8217;extraction des descripteurs de déploiement enfouis dans les archives J2EE (.ear/.jar/.war).</li><li>permettent de séparer clairement les rôles: d&#8217;un côté les développeurs créent l&#8217;application, de l&#8217;autre le &#8216;déployeur&#8217; ou l&#8217;administrateur adapte l&#8217;application à l&#8217;environnement cible.</li></ul><div
align="center"> <img
src="http://blog.xebia.fr/wp-content/uploads/2008/04/deploymentplan.png" border="0" alt="" /></div><p><a
href="http://edocs.bea.com/wls/docs91/deployment/plan.html" title="Documentation BEA,Deploying Applications to WebLogic Server" >Documentation BEA,Deploying Applications to WebLogic Server</a></p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/04/17/les-plans-de-deploiement-weblogic/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>Activer un aspect par JMX</title><link>http://blog.xebia.fr/2008/03/19/activer-un-aspect-par-jmx/</link> <comments>http://blog.xebia.fr/2008/03/19/activer-un-aspect-par-jmx/#comments</comments> <pubDate>Wed, 19 Mar 2008 09:00:34 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[AOP]]></category> <category><![CDATA[JMX]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2008/03/19/activer-un-aspect-par-jmx/</guid> <description><![CDATA[En mai 2007, Manuel Eveno expliquait comment avec la programmation orientée aspect (AOP) et l&#8217;outil Jamon, il est facile de relever des points de mesure dans une application Java / J2EE. Cependant, il existe des situations (exemple : environnement de Production) où l&#8217;on aimerait pouvoir activer temporairement ou désactiver complètement ce type d&#8217;aspects. Dans cet [...]]]></description> <content:encoded><![CDATA[<p>En mai 2007, Manuel Eveno <a
href="http://blog.xebia.fr/2007/05/02/la-prise-de-mesure-en-aop-avec-jamon">expliquait</a> comment avec la programmation orientée aspect (AOP) et l&#8217;outil Jamon, il est facile de relever des points de mesure dans une application Java / J2EE. Cependant, il existe des situations (exemple : environnement de Production) où l&#8217;on aimerait pouvoir activer temporairement ou désactiver complètement ce type d&#8217;aspects. Dans cet article, je vais expliquer comment avec l&#8217;AOP on peut activer un aspect par JMX.</p><p>Voici l&#8217;aspect PerfMonitor présenté par Manuel dans son article : le pointcut <em>monitor</em> concerne l&#8217;exécution de la méthode methodToMonitor de la classe fr.xebia.appz.ClassToMonitor, quel que soit son nombre de paramètres et sa visibilité. L&#8217;advice de prise de mesure est appliqué avant et après le pointcut <em>monitor</em>.</p><pre class="brush: java; title: ; notranslate">
public aspect PerfMonitor {
	pointcut monitor() :
              execution(* fr.xebia.appz.ClassToMonitor.methodToMonitor(..)) ;
	Object around() : monitor() {
		Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
		try {
			return proceed();
		} finally {
			if (monitor != null)
				monitor.stop();
		}
	}
}
</pre><h4>Ajouter l&#8217;attribut &#8216;enabled&#8217; à l&#8217;aspect</h4><p>Tout d&#8217;abord, il faut ajouter un attribut &#8216;enabled&#8217; à l&#8217;aspect et modifier l&#8217;advice pour prendre en compte l&#8217;état de l&#8217;attribut. Voici le nouveau code de l&#8217;aspect <a
href="http://code.google.com/p/xebia-france/source/browse/trunk/aop/aspect-exposed-by-jmx/src/main/java/fr/xebia/aop/PerfMonitor.aj">PerfMonitor </a>:</p><pre class="brush: java; title: ; notranslate">
public aspect PerfMonitor {
	private boolean enabled = true;
	public boolean isEnabled() {
		return enabled;
	}
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}
	pointcut monitorEnabled() : if(aspectOf().isEnabled());
	pointcut monitor() :
                execution(* fr.xebia.appz.ClassToMonitor.methodToMonitor(..)) ;
	Object around() : monitor() &amp;&amp; monitorEnabled() {
		Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
		try {
			return proceed();
		} finally {
			if (monitor != null)
				monitor.stop();
		}
	}
}
</pre><p>Quelques remarques :</p><ul><li>l&#8217;attribut &#8216;enabled&#8217; est initialisé à la valeur &#8216;true&#8217; par défaut.</li><li> l&#8217;attribut est accessible par les deux méthodes à la manière &#8216;JavaBean&#8217;, isEnabled(), setEnabled()</li><li>un nouveau pointcut <em>monitorEnabled</em> a été défini. Il retourne &#8216;true&#8217; si l&#8217;appel de la méthode de l&#8217;aspect isEnabled() retourne &#8216;true&#8217;. L&#8217;instruction aspectOf() retourne une référence sur l&#8217;aspect, comme le mot-clé <strong>this</strong> en Java retourne une référence sur l&#8217;objet lui-même.</li><li>l&#8217;advice a été modifié pour prendre compte le nouveau pointcut. Il sera activé que si les pointcuts <em>monitor</em> et <em>monitorEnabled</em> sont vérifiés.</li></ul><p>A partir de là, si la valeur l&#8217;attribut &#8216;enabled&#8217; est égale à false, il n&#8217;y aura pas de prise de mesure par l&#8217;API Jamon.</p><h4>Exposition JMX</h4><p>Avoir un attribut &#8216;enabled&#8217; est intéressant mais pas suffisant. Il faut pouvoir modifier sa valeur dynamiquement et modifier le comportement au runtime sans nécessiter un redémarrage de la JVM. On pense aussitôt à l&#8217;API JMX. Mais comment exposer un aspect par JMX alors qu&#8217;à aucun moment on n&#8217;est maître de son instanciation ? Un aspect n&#8217;est pas une classes sur laquelle on peut appliquer l&#8217;operateur <em>new()</em>.</p><p>Les possibilités offertes par l&#8217;AOP à travers l&#8217;aspect &#8216;<a
href="http://code.google.com/p/xebia-france/source/browse/trunk/aop/aspect-exposed-by-jmx/src/main/java/fr/xebia/aop/Management.aj">Management</a>&#8216; vont nous permettre l&#8217;inimaginable !</p><pre class="brush: java; title: ; notranslate">
public aspect Management {
	public interface ManagedBean {
		public boolean isEnabled();
		public void setEnabled(boolean enabled);
	}
	private pointcut managedBeanConstruction(ManagedBean bean) :
                  execution(ManagedBean.new(..)) &amp;&amp; this(bean);
	after(ManagedBean bean) returning: managedBeanConstruction(bean) {
		ObjectName registered = getMBeanExporter()
				.registerManagedResource(bean);
		System.out.println(&quot;Bean &quot; + bean
				+ &quot; is exposed with this object name &quot; + registered);
	}
	declare parents: PerfMonitor implements ManagedBean;
	private MBeanExporter getMBeanExporter() {
		///Spring Framework Stuff !
	}
}
</pre><p>L&#8217;exposition JMX se fait en 3 temps :</p><ul><li>Le pointcut <em>managedBeanConstruction</em> est vérifié lors de l&#8217;exécution de l&#8217;instanciation de toute classe implémentant l&#8217;interface ManagedBean.</li><li> L&#8217;advice suivant est appliqué après le retour du pointcut <em>managedBeanConstruction</em> : il récupère une instance de type <a
href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/jmx/export/MBeanExporter.html">org.springframework.jmx.export.MBeanExporter</a>, une classe qui permet d&#8217;exposer n&#8217;importe quelle classes à l&#8217;intérieur d&#8217;un MBeanServer, sans qu&#8217;il soit nécessaire de définir l&#8217;ensemble des informations spécifique à l&#8217;API JMX, puis enregistre l&#8217;instance de type ManagedBean passé en paramètre comme MBean JMX.</li><li> Le code &#8216;declare parents: PerfMonitor implements ManagedBean&#8217; indique que maintenant la classe PerfMonitor implémente l&#8217;interface ManagedBean. C&#8217;est de l&#8217;<strong>Injection d&#8217;interfaces</strong> ! L&#8217;instruction &#8216;déclare parent&#8217; permet modifier l&#8217;arbre d&#8217;héritage d&#8217;une classe: dérivation, ajout d&#8217;interfaces,&#8230; Dans notre cas, le contrat défini par l&#8217;interface ManagedBean ajouté à notre Aspect PerfMonitor est déjà rempli par l&#8217;aspect lui-même (méthodes isEnabled() et setEnabled()).</li></ul><p>Au runtime, dès que le framework <a
href="http://www.eclipse.org/aspectj/">AspectJ</a> va procéder à l&#8217;instanciation de l&#8217;aspect PerfMonitor sous la forme d&#8217;une classe Java qui implémente l&#8217;interface ManagedBean, l&#8217;aspect sera exposé en tant que MBean JMX.</p><p>Le screencast suivant détaille les deux aspects (Management et PerfMonitor) et montre sur un exemple très simple le comportement de l&#8217;aspect en fonction de la valeur de l&#8217;attribut &#8216;enabled&#8217; modifié par l&#8217;outil <a
href="http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html">JConsole</a></p><p><object
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="704" height="656"><param
name="movie" value="http://content.screencast.com/flvplayer.swf"></param><param
name="quality" value="high"></param><param
name="bgcolor" value="#FFFFFF"></param><param
name="flashVars" value="thumb=http://content.screencast.com/media/6e121654-15e6-41dd-a7df-a5a68b77434a_094aeff0-f5ac-4b50-8f92-641991139d9a_static_0_0_Thumbnail.gif&#038;content=http://content.screencast.com/media/9946056e-980d-4205-a401-28d838876a16_094aeff0-f5ac-4b50-8f92-641991139d9a_static_0_0_aopjmxscreencast.flv&#038;width=704&#038;height=656"></param><param
name="allowFullScreen" value="true"></param><param
name="scale" value="showall"></param><param
name="allowScriptAccess" value="always"></param> <embed
src="http://content.screencast.com/flvplayer.swf" quality="high" bgcolor="#FFFFFF" width="704" height="656" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/media/6e121654-15e6-41dd-a7df-a5a68b77434a_094aeff0-f5ac-4b50-8f92-641991139d9a_static_0_0_Thumbnail.gif&#038;content=http://content.screencast.com/media/9946056e-980d-4205-a401-28d838876a16_094aeff0-f5ac-4b50-8f92-641991139d9a_static_0_0_aopjmxscreencast.flv&#038;width=704&#038;height=656" allowFullScreen="true" scale="showall"></embed></object></p><p>L&#8217;ensemble des sources est disponible dans le repository <a
href="http://code.google.com/p/xebia-france/source/browse/trunk/aop/aspect-exposed-by-jmx/">SVN de Xebia France</a>.</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/03/19/activer-un-aspect-par-jmx/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Packagez vos sources de données avec WebLogic</title><link>http://blog.xebia.fr/2008/03/11/packagez-vos-sources-de-donnees-avec-weblogic/</link> <comments>http://blog.xebia.fr/2008/03/11/packagez-vos-sources-de-donnees-avec-weblogic/#comments</comments> <pubDate>Tue, 11 Mar 2008 12:00:13 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[J2EE]]></category> <category><![CDATA[Weblogic]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2008/03/11/packagez-vos-sources-de-donnees-avec-weblogic/</guid> <description><![CDATA[Cet article inaugure une série autour de fonctions avancées et souvent méconnues apparues dans les dernières versions du serveur d&#8217;application WebLogic. Une application J2EE utilise généralement une ou plusieurs sources de données (datasources). La spécification J2EE permet au mieux de référencer le nom JNDI de la source de données dans le descripteur de déploiement de [...]]]></description> <content:encoded><![CDATA[<p><em>Cet article inaugure une série autour de fonctions avancées et souvent méconnues apparues dans les dernières versions du serveur d&#8217;application WebLogic.</em></p><p>Une application J2EE utilise généralement une ou plusieurs sources de données (<em>datasources</em>).  La spécification J2EE permet au mieux de référencer le nom JNDI de la source de données dans le descripteur de déploiement de l&#8217;application (ou de la web-app). En revanche, le paramétrage complet de la source de données (Type, URL JDBC, Taille du Pool,&#8230;) est une opération spécifique à chaque serveur d&#8217;application. Lorsque vient le temps de la livraison de l&#8217;application en dehors de l&#8217;environnement de développement (Intégration, Recette, &#8230;), les équipes fournissent généralement l&#8217;archive de l&#8217;application à déployer et un document d&#8217;installation au format Word. Il décrit, à l&#8217;aide de nombreuses copies d&#8217;écran, les opérations à effectuer à travers l&#8217;application d&#8217;administration pour déclarer et paramétrer les sources de données avant de procéder au déploiement du fichier MonApplication.ear proprement dit. Cet article montre comment avec le serveur d&#8217;application Weblogic 9+, il est possible d&#8217;associer, à l&#8217;application à déployer, l&#8217;ensemble des ses ressources, en particulier, le paramétrage de ses sources de données.</p><p>Exemple: Pour illustrer mon propos, j&#8217;utiliserai une application web, MyWebApplication, qui affiche des informations sur une connexion JDBC obtenue par une DataSource inscrite dans l&#8217;arbre JDNI. Cette application est classiquement packagée sous forme d&#8217;une archive web, MyWebApplication.war, elle-même encapsulée dans une archive MyWebApplicationEAR.ear.</p><p><a
href='http://blog.xebia.fr/wp-content/uploads/2008/03/mywebapplicationear.ear' title='mywebapplicationear.ear'>télécharger MyWebApplicationEAR.ear</a> et retrouver l&#8217;ensemble des sources dans le repository <a
href="http://code.google.com/p/xebia-france/source/browse">SVN de Xebia France</a>, branche /svn/trunk/wls/deployment.</p><p>Si on déploie cette application et que la source de données MyDataSource n&#8217;est pas correctement installée, par exemple suite à un mauvais paramétrage du nom JNDI, on obtient l&#8217;erreur suivante:</p><pre class="brush: java; title: ; notranslate">
javax.naming.NameNotFoundException:
Unable to resolve 'MyDataSource'. Resolved ''; remaining name 'MyDataSource'
</pre><div
align="center"> <img
src='http://blog.xebia.fr/wp-content/uploads/2008/03/namenotfoundexception.png' alt='NameNotFoundException.png' /></div><p>Depuis la version 9, le serveur d&#8217;application WebLogic offre un moyen de packager les ressources JDBC dans l&#8217;archive ear.</p><p><strong>Etapes</strong></p><p>Dans le fichier META-INF/weblogic-application.xml,spécifique à l&#8217;éditeur, déclarer un module de type JDBC.</p><pre class="brush: xml; title: ; notranslate">
&lt;wls:module&gt;
  &lt;wls:name&gt;MyWebApplicationDS&lt;/wls:name&gt;
  &lt;wls:type&gt;JDBC&lt;/wls:type&gt;
  &lt;wls:path&gt;META-INF/ds-jdbc.xml&lt;/wls:path&gt;
&lt;/wls:module&gt;
</pre><p>Cette configuration indique que le fichier ds-jdbc.xml placé dans le répertoire META-INF de l&#8217;archive contient des élements de configuration de type &#8216;source de données&#8217; (<wls:type>JDBC</wls:type>)</p><ul><li> l&#8217;extension -jdbc.xml est obligatoire (sic !)</li><li> le répertoire de stockage du fichier xml est libre. Il est possible de placer ces modules dans un répertoire autre que &#8216;META-INF/&#8217;, par exemple &#8216;modules/&#8217;.</li><li> si <a
href="http://www.eclipse.org/webtools/">Eclipse WTP</a>est utilisé comme IDE, déposer les modules dans le répertoire META-INF/ et ils seront automatiquement intégrés au packaging de l&#8217;EAR et déployés sur le serveur d&#8217;application.</li></ul><p>Contenu du fichier META-INF/ds-jdbc.xml:</p><pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;jdbc-data-source xmlns=&quot;http://www.bea.com/ns/weblogic/90&quot;
    xmlns:sec=&quot;http://www.bea.com/ns/weblogic/90/security&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xmlns:wls=&quot;http://www.bea.com/ns/weblogic/90/security/wls&quot;
    xsi:schemaLocation=&quot;http://www.bea.com/ns/weblogic/90/domain.xsd&quot;&gt;
    &lt;name&gt;MyDevDataBase&lt;/name&gt;
    &lt;jdbc-driver-params&gt;
        &lt;url&gt;jdbc:oracle:thin:@localhost:1521:xe&lt;/url&gt;
        &lt;driver-name&gt;oracle.jdbc.OracleDriver&lt;/driver-name&gt;
        &lt;properties&gt;
            &lt;property&gt;
                &lt;name&gt;user&lt;/name&gt;
                &lt;value&gt;weblogic&lt;/value&gt;
            &lt;/property&gt;
        &lt;/properties&gt;
        &lt;password-encrypted&gt;weblogic&lt;/password-encrypted&gt;
    &lt;/jdbc-driver-params&gt;
    &lt;jdbc-connection-pool-params&gt;
        &lt;initial-capacity&gt;1&lt;/initial-capacity&gt;
        &lt;max-capacity&gt;5&lt;/max-capacity&gt;
        &lt;capacity-increment&gt;1&lt;/capacity-increment&gt;
        &lt;shrink-frequency-seconds&gt;900&lt;/shrink-frequency-seconds&gt;
        &lt;test-connections-on-reserve&gt;true&lt;/test-connections-on-reserve&gt;
        &lt;test-table-name&gt;SQL SELECT 1 FROM DUAL&lt;/test-table-name&gt;
    &lt;/jdbc-connection-pool-params&gt;
    &lt;jdbc-data-source-params&gt;
        &lt;jndi-name&gt;MyDataSource&lt;/jndi-name&gt;
        &lt;scope&gt;Global&lt;/scope&gt;
    &lt;/jdbc-data-source-params&gt;
&lt;/jdbc-data-source&gt;
</pre><p>On retrouve l&#8217;ensemble des informations que l&#8217;on pourrait renseigner dans la console d&#8217;administration de WebLogic.</p><p>Si on ajoute ce fichier à l&#8217;archive MyWebApplicationEAR.ear, le déploiement de cet EAR va engendrer la création d&#8217;une nouvelle source de données déployée dans l&#8217;arbre JNDI sous le nom &#8216;MyDataSource&#8217;. Elle sera accessible à toutes les applications déployées dans le serveur (scope=Global).</p><div
align="center"> <img
src='http://blog.xebia.fr/wp-content/uploads/2008/03/screen2.png' alt='Global Mode' /></div><p>Si on se connecte à la console d&#8217;administration, on peut apercevoir quelques différences.<br
/> Le point marquant est que la source de données n&#8217;est pas présente dans l&#8217;arborescence Services &#8211;> JDBC &#8211;> DataSources, comme d&#8217;habitude. Elle n&#8217;est visible que si on sélectionne le &#8216;JDBC Module&#8217;. (Deployments &#8211;> MyWebApplicationEAR &#8211;> MyWebApplicationDS). A partir de là, on accède au paramétrage et aux données de monitoring de la source de données.</p><p>Ce screencast montre les différents éléments déployés dans la console d&#8217;adminstration de Weblogic.</p><div
align="center"> <img
src="http://blog.xebia.fr/wp-content/plugins/flash-video-player/default_video_player.gif" /></div><p>Dans l&#8217;exemple précédent, la source de données est globale à l&#8217;ensemble du serveur d&#8217;application. Il est possible de restreindre la visibilité de cette source de données, seulement à l&#8217;application. Les changements à effectuer sont:</p><ul><li>dans le fichier web.xml (spécifications J2EE)<pre class="brush: xml; title: ; notranslate">
&lt;resource-ref&gt;
    &lt;res-ref-name&gt;MyDataSource&lt;/res-ref-name&gt;
    &lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt;
    &lt;res-auth&gt;Container&lt;/res-auth&gt;
&lt;/resource-ref&gt;
</pre></li><li>dans le fichier META-INF/ds-jdbc.xml<pre class="brush: xml; title: ; notranslate">
&lt;jdbc-data-source&gt;
  .....
  &lt;jdbc-data-source-params&gt;
        &lt;jndi-name&gt;MyDataSource&lt;/jndi-name&gt;
        &lt;scope&gt;Application&lt;/scope&gt;
    &lt;/jdbc-data-source-params&gt;
&lt;/jdbc-data-source&gt;
</pre></li></ul><p><br/></p><div
align="center"> <img
src='http://blog.xebia.fr/wp-content/uploads/2008/03/screen3.png' alt='Application Mode' /></div><p><strong>Et la sécurité ?</strong><br
/> La première remarque est généralement: &laquo;&nbsp;Le mot de passe est en clair dans le fichier XML !&nbsp;&raquo;. C&#8217;est exact ! Si l&#8217;objectif de ce packaging est de pouvoir installer rapidement un environnement de développement ou une plateforme de démonstration, ce n&#8217;est pas gênant. Sinon, il est toujours possible de crypter le mot de passe dans le fichier XML avec le commande weblogic.security.Encrypt. Attention ! le cryptage du mot de passe dépend du domaine sur lequel l&#8217;application va être déployée (le domaine est d&#8217;ailleurs précisé par la propriété -Dweblogic.RootDirectory).</p><pre class="brush: plain; title: ; notranslate">
java -classpath ${WLS_HOME}/server/lib/weblogic.jar -Dweblogic.RootDirectory=./mywlsdomain weblogic.security.Encrypt weblogic
{3DES}QdEw5GGOy4GM/8QwBmTEbg==
</pre><p>Il ne reste qu&#8217;à copier ce mot de passe crypté dans la balise password-encrypted.</p><pre class="brush: xml; title: ; notranslate">
&lt;password-encrypted&gt;{3DES}QdEw5GGOy4GM/8QwBmTEbg==&lt;/password-encrypted&gt;
</pre><p>Référence: http://e-docs.bea.com/wls/docs90/admin_ref/utils.html#encrypt</p><p><strong>Et en cas de mauvais paramétrage ?</strong><br
/> Modifions l&#8217;url de la source de données (ex changement de port 1521 &#8211;> 1525) et déployons l&#8217;archive. Echec du déploiement! Le serveur conserve l&#8217;environnement cohérent et refuse d&#8217;effectuer le déploiement.</p><pre class="brush: plain; title: ; notranslate">
&lt;26 févr. 2008 12 h 11 CET&gt; &lt;Warning&gt; &lt;Deployer&gt; &lt;BEA-149004&gt; &lt;Failures were detected while initiating distribute task for application 'MyWebApplicationEAR'.&gt;
&lt;26 févr. 2008 12 h 11 CET&gt; &lt;Warning&gt; &lt;Deployer&gt; &lt;BEA-149078&gt; &lt;Stack trace for message 149004
weblogic.application.ModuleException:
at weblogic.jdbc.module.JDBCModule.prepare(JDBCModule.java:289)
at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:93)
at weblogic.application.internal.flow.DeploymentCallbackFlow$1.next(DeploymentCallbackFlow.java:360)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:26)
at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:56)
Truncated. see log file for complete stacktrace
weblogic.common.ResourceException: weblogic.common.ResourceException: Could not create pool connection.
The DBMS driver exception was: Exception d'E/S: The Network Adapter could not establish the connection
at weblogic.jdbc.common.internal.ConnectionEnvFactory.createResource(ConnectionEnvFactory.java:236)
at weblogic.common.resourcepool.ResourcePoolImpl.makeResources(ResourcePoolImpl.java:1073)
at weblogic.common.resourcepool.ResourcePoolImpl.makeResources(ResourcePoolImpl.java:995)
at weblogic.common.resourcepool.ResourcePoolImpl.start(ResourcePoolImpl.java:214)
at weblogic.jdbc.common.internal.ConnectionPool.doStart(ConnectionPool.java:1042)
Truncated. see log file for complete stacktrace
&gt;
</pre><p>Si on observe le cycle de vie d&#8217;une application, du développement à la mise en production, on s&#8217;aperçoit que le mécanisme exposé est intéressant mais pas suffisant. En effet, il existe de grandes différences d&#8217;infrastructure et de contraintes entre les environnements typé &#8216;Développement&#8217; et les environnements typés &#8216;Production&#8217;: Charge nominale supportée, Haute disponibilité, Typologie réseau (DMZ, Intranet&#8230;),&#8230; Ces différences impliquent un paramétrage différent du serveur d&#8217;application. Dans un prochain article, nous verrons comment utiliser les plans de déploiement pour configurer l&#8217;application et l&#8217;adapter facilement à ces différents environnements.</p><p>Documentation Officielle BEA <a
href="http://e-docs.bea.com/wls/docs90/jdbc_admin/packagedjdbc.html">http://e-docs.bea.com/wls/docs90/jdbc_admin/packagedjdbc.html</a></p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/03/11/packagez-vos-sources-de-donnees-avec-weblogic/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Xebia Web Framework Contest</title><link>http://blog.xebia.fr/2007/10/26/xebia-web-framework-contest/</link> <comments>http://blog.xebia.fr/2007/10/26/xebia-web-framework-contest/#comments</comments> <pubDate>Fri, 26 Oct 2007 04:42:36 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[GWT]]></category> <category><![CDATA[JSF]]></category> <category><![CDATA[Struts2]]></category> <category><![CDATA[Web]]></category> <category><![CDATA[Wicket]]></category> <category><![CDATA[XKE]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/10/26/xebia-web-framework-contest/</guid> <description><![CDATA[Pour tous les consultants de Xebia France, le dernier vendredi de chaque mois est important : c&#8217;est le jour du XKE, le Xebia Knowledge Exchange. L&#8217;ensemble des consultants est rassemblé pour échanger durant une journée entière sur tous les sujets liés à l&#8217;écosystème Java / J2EE ainsi que les méthodes agiles. D&#8217;habitude la journée est [...]]]></description> <content:encoded><![CDATA[<p>Pour tous les consultants de Xebia France, le dernier vendredi de chaque mois est important : c&#8217;est le jour du XKE, le Xebia Knowledge Exchange. L&#8217;ensemble des consultants est rassemblé pour échanger durant une journée entière sur tous les sujets liés à l&#8217;écosystème Java / J2EE ainsi que les méthodes agiles. D&#8217;habitude la journée est découpée en plusieurs sessions allant de 45 mn à 3 h, suivant les sujets et le mode d&#8217;interaction (de la présentation formelle à des travaux pratiques sur des sujets complexes).</p><p>Le mois dernier, nous avons décidé de faire du XKE le Xebia Web Framework Contest, un concours de développement autour des framework de présentation.</p><p>4 équipes ont développé la même application web, chacune avec un framework (très) différent. Les frameworks retenus étaient :</p><ul><li>Strut2,</li><li>Google Web ToolKit,</li><li>Wicket,</li><li>My Faces (JSF).</li></ul><p>8h30 certains, les plus scolaires, sont déjà arrivés et aiguisent leurs environnements, se concertent sur les rôles de chacun.<br
/> 9h00 tout le monde est là, certains prennent leur café en discutant de tout sauf du concours qui les attend alors que d’autres sont fin prêts …<br
/> 9h30 les spécifications, tenues secrètes jusqu’au jour J sont enfin distribuées aux équipes et là : grande surprise et grande rigolade ….<br
/> <em><br
/> Wanda Zeller, directrice d&#8217;un réseau de call girls international, a décidé d&#8217;augmenter son volume d&#8217;affaire en mettant en ligne un site de réservation interactif de ses protégées. Mme Zeller, que son activité contraint à la discrétion, a délégué son chargé d&#8217;affaires, M. Moussaud, de relayer ses exigences et de piloter les développements. Mme Zeller, qui vit avec son temps, dispose d&#8217;ores et déjà d&#8217;un système de réservation qu&#8217;utilisent les opérateurs de son call-center marocain. Afin de limiter les efforts de développement, il a été décidé de réutiliser les services métier mis au point pour ce système de réservation, et de limiter les développements à la couche de présentation.<br
/> </em></p><p>Les spécifications de nouveaux lots seront ensuite distribuées à un rythme assez soutenu, à raison d’une toutes les heures trente. Chacune ayant pour but d’adresser un pan particulier.</p><ul><li>Le premier lot mettait en place les mécanismes de recherche simple et un système de panier avec commande.</li><li>Le lot 2 apportait la couche &laquo;&nbsp;sécurité&nbsp;&raquo; sur les commandes.</li><li>Le lot 3 ajoutait la mise en place d’un workflow de validation des commandes.</li><li>Enfin le dernier lot mettait l&#8217;accent sur l&#8217;aspect validation.</li></ul><p>Après une journée intense de développement, chaque équipe est venue présenter son œuvre et donner son avis sur les avantages et inconvénients de la solution étudiée.</p><h3>Google Web Toolkit</h3><p>L&#8217;équipe a bataillé un moment pour trouver quels fichiers étaient à synchroniser entre les membres de l&#8217;équipe et ceux qui ne l&#8217;étaient pas. Pour ne pas perdre de temps (c&#8217;était quand même un concours !), la synchronisation s&#8217;est faite finallement par clé USB !</p><p>Ce qui avait séduit l&#8217;équipe avec ce framework nouvelle génération est le concept du &#8216;Tout-Java&#8217;: le client et le serveur sont codés en java, GWT se charge de la génération des pages web et du javascript. Mais ce modèle à des contraintes:</p><ul><li>Implémentation d&#8217;une interface IsSerialisable pour tout objet qui transite entre le client et le serveur (réglé depuis la version 1.4).</li><li>Support de Java 1.4 (seulement), donc il faut oublier les génériques et les annotations pour la partie client (fonctionnalité programmé pour la future version 1.5 ).</li><li>Le concept client-serveur reste quand même assez déroutant quand depuis des années on manipule chaque jours des objets de type Request/Response, des pages JSP/Html ou des actions &#8216;Struts&#8217;.</li></ul><p>La conclusion de l&#8217;équipe est qu&#8217;il faut vraiment aborder GWT comme un framework Client Riche avec un concept de client/serveur; les outils se chargeant entièrement de l&#8217;exposition en mode Web (JSP/CSS/AJax). Le coût d&#8217;entrée semble assez important et les composants graphiques limités (il n&#8217;est pas évident d&#8217;intégrer des composants d&#8217;une maquette HTML existante). Donc GWT est un outil à suivre en attendant la maturité.</p><h4>Synthèse de l&#8217;équipe :</h4><p><strong>Les bons points :</strong></p><ul><li>Gestion transparente des différents browsers.</li><li>Possibilité d&#8217;utiliser un debugger Java (celui de l&#8217;environnement de développement choisi, Eclipse par exemple).</li><li>Beaucoup de buzz autour du projet. Notamment concernant les extensions graphiques (portage de plusieurs librairies AJAX), début d&#8217;intégration avec Spring.</li><li>Un retour à la programmation graphique par composant.</li><li>Facile de mettre en place une IHM simple.</li></ul><p><strong>Les mauvais points :</strong></p><ul><li>Seule une partie du JRE est supportée côté client et pour les DTO utilisés par les RCPs (ex: pas toutes les collections).</li><li>Besoin d&#8217;un mapping objet métier/DTO utilisés par GWT (Serializable et un constructeur public par défaut).</li><li>Manque guide de bonnes pratiques et de la documentation en général.</li><li>Les API ne sont pas toutes détaillées.</li><li>Il n&#8217;y a que des composants graphiques &laquo;&nbsp;simples&nbsp;&raquo;. Si l&#8217;on veut utiliser des composants plus évolués, il faut soit les coder ou bien se tourner vers des librairies de widgets GWT Open Source &laquo;&nbsp;non Google&nbsp;&raquo;.</li></ul><p><strong>Les points non abordés :<br
/> </strong></p><ul><li>Possibilité de faire des tests unitaires.</li><li>Internationalisation.</li><li>JavaScript Native Interface (JSNI).</li><li>Exposition de services via Web Services/JSON/XML.</li><li>Facilité/difficulté du respect d&#8217;une charte graphique.</li><li>Authentification.</li><li>Respect des standards, facilité de référencement.</li><li>Intégration à l&#8217;IDE Idea (semble assez poussée, gestion des CSS et modules à partir du code Java).</li></ul><h3>Struts 2</h3><p>L&#8217;équipe avait préparé un template de projet Struts2 avant le XKE, projet Eclipse/Maven 2, web.xml déjà configuré, librairies installées, et différents tests &laquo;&nbsp;Hello World&nbsp;&raquo; de plugins (zero conf, etc&#8230;).<br
/> Résultat : c&#8217;est l&#8217;équipe gagnante.</p><p>L&#8217;équipe n&#8217;a pas rencontré de difficultés particulières, et a décidé de développer l&#8217;application avec ses tests unitaires, ce qui n&#8217;était peut être pas nécessaire dans le cadre du concours, mais qui a permis de démontrer la facilité avec laquelle les actions Struts2 peuvent être testées unitairement (le gros défaut de Struts 1).</p><h4>Synthèse de l&#8217;équipe :</h4><p><strong>Les bons points :</strong></p><ul><li><strong>Testabilité :</strong> écrire des tests unitaires pour les actions, qui sont de simples POJOs, est très simple.</li><li><strong>Modularité des filtres sur les actions :</strong> les piles d&#8217;Interceptors sont très pratiques pour appliquer des filtres différents aux actions (authentification etc.). Mais est-ce réellement si utile ? A part le classique interceptor d&#8217;authentification qui ne s&#8217;applique pas aux actions de type &laquo;&nbsp;login&nbsp;&raquo; et &laquo;&nbsp;forgotten password&nbsp;&raquo;, a-t-on vraiment besoin de tant de modularité sur les filtres ?</li><li><strong>Simplicité :</strong> Struts 2 est simple à utiliser par une équipe projet. Sa modularité et sa testabilité le rendent parfaitement adapté au travail en équipe.</li><li><strong>Prédictibilité par son efficacité et son classicisme :</strong> Struts2 est un framework éprouvé aux concepts très répandus (&laquo;&nbsp;Action based&nbsp;&raquo;, Orienté Objet simple) qui ne causera pas de mauvaise surprise. Struts 2 sera prédictible sur un projet.</li><li><strong>Elégance des interactions HTTP :</strong> URL claires et un modèle post-and-redirect fiable (double submit) et efficace (bookmarkable) malgré WW-1714  qui est en cours de résolution.</li><li><strong>Souplesse de l&#8217;interface graphique :</strong> le mécanisme de template est très pratique mettre en œuvre la charte graphique d&#8217;un site ou d&#8217;une application. SiteMesh est un complément naturel très efficace.</li><li><strong>Débuggabilité :</strong> des tags de debug (facilement désactivables pour la production) et un browser de configuration simplifient le troubleshooting (voir également  les mauvais points sur la débuggabilité de Struts2).</li><li><strong>Coût d&#8217;entrée réduit :</strong> le framework est plus simple à appréhender que Struts 1.</li><li><strong>Form beans :</strong> aucun fichier de configuration, on peut passer de simples POJO à la vue Tests unitaires : les actions sont testables facilement avec JUnit, les actions sont des POJO.</li><li><strong>Templates :</strong> intégration avec Sitemesh aisée pour les templates, les templates Sitemesh ont accès aux tags Struts grâce au plugin struts2-sitemesh.</li><li><strong>Ajax :</strong> tags Ajax (support Ajax basé sur le toolkit Dojo) simplifient, voir masquent, l&#8217;utilisation de dojoSpring: support de Spring, on choisit le framework d&#8217;injection à utiliser dans la configuration.</li><li><strong>Expression Language :</strong> les taglibs utilisent OGNL, plus puissant que JSTL, Communauté: framework MVC le plus téléchargé du moment (http://www.jroller.com/TedHusted/entry/struts_skyrockets ) , les mailing lists sont très actives.</li></ul><p><strong>Les mauvais points :</strong></p><ul><li><strong>Hétérogénéité / dispersion :</strong> Struts 2 se disperse en proposant souvent plusieurs solutions pour un sujet sans qu&#8217;aucune ne soit pleinement satisfaisante.<ul><li>Trois technos pour le HTML : JSP, Freemarker et Velocity.</li><li>Plusieurs projets de configuration par annotations : Zero config etc.</li></ul></li><li><strong>Configuration propriétaire</strong> (struts.xml).<ul><li>Spring est le standard de-facto pour configurer l&#8217;assemblage des composants d&#8217;une application. Il serait très pratique de pouvoir configurer Struts2 dans les fichiers Spring grâce au mécanisme d&#8217;extension de configuration  introduit dans Spring 2 à l&#8217;instar de la configuration d&#8217;Apache CXF  (e.g. <jaxws:endpoint> , <jms:destination> etc.).</jms:destination></jaxws:endpoint></li></ul></li><li><strong>Productivité modérée :</strong> c&#8217;est probablement un écueil du classicisme et de la testabilité (découplage actions-pojo de la présentation) mais la productivité n&#8217;est pas stupéfiante.</li><li><strong>Debuggabilité :</strong> Struts2 n&#8217;affiche aucun message d&#8217;erreur en cas de coquille sur les variables de scripting (i.e. manipulées par OGNL) aussi bien dans les page web (jsp, ftl ou velocity) que dans la config (paramètres dans les redirections &#8230;). Le problème est en cours de résolution.</li><li><strong>Performances :</strong> l&#8217;application doit être configurée d&#8217;une certaine manière pour obtenir des performances acceptables (http://struts.apache.org/2.x/docs/performance-tuning.html). OGNL est plus lent que JSTL dans certains cas (mais est aussi plus riche).</li><li><strong>Développement :</strong> l&#8217;équipe de commiteurs est réduite, les trous de sécurité prennent du temps à être corrigés.</li><li><strong>Ajax :</strong> Le support Ajax est intégré dans le cœur de Struts2, pas sous forme de plugin, une mise à jour de dojo toolkit demande de sortir une nouvelle version de Struts2 (va changer dans Struts 2.1).</li><li><strong>Documentation :</strong> il est parfois difficile de se repérer dans la documentation, certaines pages font parfois référence à webwork, elle n&#8217;est pas tout le temps à jour (c&#8217;est bien évidemment lié au faible nombre de commiteurs sur le projet).</li></ul><p><strong>Conclusion :</strong></p><p>Struts2 est basé sur l&#8217;excellent WebWork 2.2, les bases sont saines. En revanche, les nouveaux développements Struts 2.0 ont pris du temps, et certains ont été remis en cause dans le futur Struts 2.1. Struts 2.1 est plein de promesses, les performances devraient être meilleures (mise à jour vers OGNL 2.7, vers Dojo 0.9,&#8230;), et le plugin SmartURLs devrait permettre de se passer de la configuration explicite, pour se rapprocher encore du paradigme &laquo;&nbsp;Convention over Configuration&nbsp;&raquo;. Le projet tend vers une consolidation des différents plugins, et a appris de ses erreurs depuis la première release de Struts2. Aujourd&#8217;hui nous pouvons conseiller d&#8217;attendre la première release stable et éprouvée de Struts 2.1 (Struts 2.1.0 devrait sortir à la fin Octobre 2007) pour démarrer un nouveau projet. La branche 2.0 ne va plus évoluer, et le saut 2.0 vers 2.1 ne sera pas forcément transparent!</p><h3>JSF/My Faces</h3><p>Ce groupe de Travail a véritablement bataillé durant toute la journée et le bilan affiché en fin de journée est un peu mitigé.</p><p><strong>Les bons points :</strong></p><ul><li>Concepts proches des frameworks Struts 2 et Spring MVC</li><li>Utilisation de POJO simple</li><li>La tentative de standardisation</li><li>Le support des éditeurs</li></ul><p><strong>Les mauvais points :</strong></p><ul><li>Complexité de mise en oeuvre</li><li>Manque de documentation</li><li>Manque de transparence sur le fonctionnement du framework</li><li>Impossibilité de mixer JSF avec d&#8217;autres composants (Tag JSP 2.0, Taglibs tierces, etc.)</li></ul><h4>Synthèse de l&#8217;équipe :</h4><ul><li>Dès le début JSF présente la spécificité d&#8217;utiliser un buffer spécifique pour écrire la response.</li><li>Il n&#8217;est pas possible d&#8217;utiliser directement du code HTML à l&#8217;intérieur de tags JSF ! Vous devez baliser tout vos blocs html par &lt;f:verbatim&gt; (bye bye xhtml) ou utiliser la tablig htmLib pour remplacer tous vos tags html par le tag <htm:xxx> équivalent (perfs ?).</htm:xxx></f:verbatim></li><li>Autre impact, plus gênant : l&#8217;intégration du code JSF avec les autres taglib. JSF ne dispose pas de certains tags intégrés de base dans d&#8217;autres frameworks. Par exemple, en JSF les conditions et les boucles n&#8217;existent pas. Et comme on atteint vite les limites des fonctionnalités offertes par les taglib JSF, on aimerait bien pouvoir retourner sur du JSTL ; mais là encore vous vous heurterez à des problèmes de compatibilité à cause du &laquo;&nbsp;buffer JSF&nbsp;&raquo; mentionné plus haut.</li><li>La gestion des templates n&#8217;existant pas non plus dans JSF, il faut utiliser struts-tiles.</li><li>Côté gestion des erreurs justement, on peut dire que JSF n&#8217;est pas bavard. Pour certains problèmes de navigation la page appelante est simplement réaffichée, sans aucun message d&#8217;erreur ! Autant dire que certains bugs deviennent très difficiles à analyser.</li><li>Autre détail, le nom des tags dans les taglib ou même pour les fichiers de conf ne sont pas très intuitifs, mais si vous avez besoin, des plugins permettent de vous imprégner du vocabulaire JSF assez rapidement.</li></ul><p><strong>Conclusion :</strong></p><p>JSF n&#8217;est clairement pas le framework le plus productif, en tous cas pas sur une journée car le coût d&#8217;entrée est lourd. Et même une fois habitué au framework, on peut se demander comment être productif sans remontée d&#8217;erreur et quelles limites posera cette gestion de buffer spécifique dans le cadre d&#8217;un vrai projet ?</p><h3>Wicket</h3><p>On peut considérer Wicket comme la bonne surprise de cette journée. Replaçons le contexte. Au moment des choix de chaque consultant, certains ont préféré partir sur la nouveauté (Wicket) par rapport à l&#8217;ancien solide et fiable (ex : Struts 2). Les différents contraintes de leur vie professionnelle n&#8217;ont pas permis aux membres de cette équipe d&#8217;affiner le sujet avant le jour J. Seul un rapide coup d&#8217;œil sur le &laquo;&nbsp;HelloWorld&nbsp;&raquo; de Wicket le soir précédant la compétition. C&#8217;est donc sans grandes connaissances qu&#8217;ils ont abordés ce concours. A la fin de la journée, ils avaient implémentés globalement l&#8217;ensemble du Lot 1 (Rappel: My Faces et GWT n&#8217;y sont pas arrivés !). C&#8217;est là que le framework choisit intervient.</p><p><strong>Les bons points :</strong></p><ul><li>Prise en main rapide</li><li>Véritable séparation entre la partie cliente et la partie serveur (utilisation de plain HTML)</li><li>Retour à la programmation graphique des composants</li><li>Mécanismes de templating par héritage Java</li><li>Pas de fichier de configuration : une classe définie dans le web.xml sert de point d&#8217;entrée</li><li>Navigation entre les pages définies en Java (ex: new Link(PageSuivante.class))</li><li>Démarrage rapide (notamment grâce à l&#8217;archetype Maven2)</li></ul><p><strong>Les mauvais points :</strong></p><ul><li>Documentation très très succinte malgré l&#8217;existence d&#8217;exemples<ul><li>Pas d&#8217;explication des concepts de base (navigation, gestion de la session, templating, etc)</li></ul></li></ul><p><strong>Les points non abordés :</strong></p><ul><li>Possibilité de faire des tests unitaires</li><li>Validation de formulaire</li><li>Internationalisation</li><li>Intégration de composant Ajax</li></ul><h4>Synthèse de l&#8217;équipe :</h4><p>Les concepts de wicket sont les suivants :</p><ul><li>Séparation très claire entre la présentation (.html) et les actions métiers (.java).</li><li>Pas de longue configuration xml, le seul fichier xml est le web.xml.</li><li>Une création automatique d&#8217;un squelette d&#8217;application avec un seul artefact maven. (est-ce maven la réelle clé de la productivité ?)</li><li>Haute réutilisation des maquettes html (fournie avec les spécifications) : le positionnement des éléments dynamiques utilisent principalement des balises HTML de type <span></span> &lt;span&gt; avec un attribut &laquo;&nbsp;wicket.id&nbsp;&raquo;.</li></ul><p><strong>Conclusion :</strong></p><p>En un mot, un framework web simple, facile et pragmatique. Ces 3 qualificatifs ont permis à l&#8217;équipe d&#8217;aller très vite une fois les concepts acquis. Ils ont cependant beaucoup &laquo;&nbsp;ralé&nbsp;&raquo; sur le manque de documentation. Seuls les exemples fournis leur ont permis de déjouer et de comprendre les subtilités du framework. Il faut cependant relativiser cet enthousiasme :</p><ul><li>Que vaut wicket sur des fonctions avancées comme la validation de formulaire ou un workflow d&#8217;écran avec suivant et précédent ?</li><li>Est-il seulement un buzzword du moment ou va-t-il perdurer ?</li></ul><h3>Alors qui est le gagnant ?</h3><ul><li><strong>Catégorie &laquo;&nbsp;Couverture&nbsp;&raquo;</strong>, l&#8217;équipe Struts2 a implémenté le plus de fonctionnalités, c&#8217;est indéniable. En revanche déception vis à vis du rendement !</li><li><strong>Catégorie &laquo;&nbsp;Découverte&nbsp;&raquo;</strong>, Wicket a été une révélation pour beaucoup d&#8217;entre nous ! Une fois passée la barrière de la découverte, le développement est rapide et efficace.</li></ul><p>Pour des raisons évidentes de bonne moralité, nous ne pouvons mettre en ligne les différentes applications développées &#8230;</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/10/26/xebia-web-framework-contest/feed/</wfw:commentRss> <slash:comments>26</slash:comments> </item> <item><title>Laissez les coder !</title><link>http://blog.xebia.fr/2007/09/06/laissez-les-coder/</link> <comments>http://blog.xebia.fr/2007/09/06/laissez-les-coder/#comments</comments> <pubDate>Thu, 06 Sep 2007 07:30:55 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[développement]]></category> <category><![CDATA[projet]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/09/06/laissez-les-coder/</guid> <description><![CDATA[Les grands intégrateurs ont depuis longtemps institué un chemin d’évolution basé sur la gestion de projets. Les jeunes débutants, le plus souvent de formation ingénieurs, sont rapidement formés à encadrer des équipes de développeurs et à piloter les projets : la voie royale ! Ces dernières années, vue la complexité technique des nouvelles architectures, une [...]]]></description> <content:encoded><![CDATA[<p>Les grands intégrateurs ont depuis longtemps institué un chemin d’évolution basé sur la gestion de projets. Les jeunes débutants, le plus souvent de formation ingénieurs, sont rapidement formés à encadrer des équipes de développeurs et à piloter les projets : la voie royale ! Ces dernières années, vue la complexité technique des nouvelles architectures, une autre voie a émergé : la filière technique. Cette dernière destinée à promouvoir les compétences techniques et d’architectures applicatives, plus en adéquation avec une formation initiale d’ingénieur. Cependant la pression économique impose que ces personnes progressent rapidement vers une spécialité, une expertise (J2EE ; Les bases de données ; La sécurité …) et en les affectant de plus en plus à des missions en parallèle (2 jours chez Untel, 1 jour sur le projet Bidule). Cette rapidité de progression pose toujours le même souci : qui développe réellement l’application ? Très souvent des stagiaires ou, dans le meilleur des cas, de très jeunes embauchés après leur formation.</p><p>Les techniques de développement demandent de plus en plus d’être polyvalent : de l’écriture de requêtes SQL à la présentation des données dans une page JSP. Cette polyvalence ne s’acquière pas en quelques années et nécessite également de rester à jour dans ses connaissances. Alors pourquoi propulser ces personnes dans d’autres fonctions ?</p><p>Intégrer dans une équipe de développement un ou plusieurs développeurs expérimentés permet deux choses :</p><ul><li>Accélérer les phases de codage et de validation technique et fonctionnelle : l’expérience permet de réduire le nombre d’allers retours entre ces deux étapes.</li><li>Créer une continuité de savoir et d’intérêt entre de jeunes débutants et des profils tels que les chefs de projets voire même les architectes.</li></ul><p>Reste à définir la notion d’expérience. Deux composantes rentrent en jeux : les années passées à exercer cette compétence, 3 à 5 ans et surtout le nombre de projets, 5 à 10. Ce dernier point est très important : confronter sa compétence à différents clients, technologies ou architectures est essentiel pour aguerrir les meilleurs développeurs !</p><p>Alors laissez les coder !</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/09/06/laissez-les-coder/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>JConsole et WebLogic 9</title><link>http://blog.xebia.fr/2007/06/28/jconsole-et-weblogic-9/</link> <comments>http://blog.xebia.fr/2007/06/28/jconsole-et-weblogic-9/#comments</comments> <pubDate>Thu, 28 Jun 2007 13:57:49 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[jconsole]]></category> <category><![CDATA[JMX]]></category> <category><![CDATA[t3]]></category> <category><![CDATA[Weblogic]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/06/28/jconsole-et-weblogic-9/</guid> <description><![CDATA[JConsole est un outil disponible à partir du JDK 5.0 qui repose sur l&#8217;API JMX pour afficher et suivre les métriques d&#8217;une machine virtuelle Java. Les différentes catégories sont : L&#8217;état de la mémoire et des garbages collections. Les threads, liste et activité, comme sur un Thread Dump. Les chargement des classes . Les suivi [...]]]></description> <content:encoded><![CDATA[<p>JConsole est un outil disponible à partir du JDK 5.0 qui repose sur l&#8217;API <span ><a
href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement" >JMX</a></span> pour afficher et suivre les métriques d&#8217;une machine virtuelle Java.<br
/> Les différentes catégories sont :</p><ul><li>L&#8217;état de la <span ><a
href="http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html#memory" >mémoire</a></span> et des garbages collections.</li><li>Les <span ><a
href="http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html#thread" >threads</a></span>, liste et activité, comme sur un Thread Dump.</li><li>Les chargement des <span ><a
href="http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html#class_loading" >classes </a></span>.</li><li>Les <span ><a
href="http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html#MBeans" >suivi</a></span> et la gestion des MBeans.</li><li>Des informations générales sur la JVM (ClassPath, Library Path, Argument de la JVM, &#8230;).</li></ul><p>Il existe deux façons de connecter une JConsole sur une machine virtuelle Java 5 :</p><h3><a
name="JConsoleetWebLogic9-Enlocal"></a>En local</h3><p>Le mode local nécessite que la JConsole et la machine virtuelle soient sur la même machine. Il suffit alors d&#8217;ajouter au démarrage de la machine virtuelle la propriété : <code>-Dcom.sun.management.jmxremote.</code><br
/> Note : A partir du JDK 6, cette propriété est positionnée par défaut, donc toutes les JVM pourront être monitorées &#8216;Out Of the Box&#8217;.</p><p>L&#8217;exécutable de la JConsole est situé dans &lt;JAVA_HOME&gt;/bin. Au démarrage, la JConsole affiche l&#8217;ensemble des JVM accessibles.</p><h3><a
name="JConsoleetWebLogic9-Adistance"></a>A distance</h3><p>JMX définit le protocole RMI comme protocole d&#8217;échange. Par défaut, on considère qu&#8217;il existe deux implémentations de RMI :</p><ul><li>JRMP (Java Remote Method Protocol)</li><li>IIOP (Internet Inter-Orb Protocol)</li></ul><p>Le serveur d&#8217;applications BEA Weblogic propose une implémentation supplémentaire (et plus performante), le <span ><a
href="http://edocs.bea.com/wls/docs92/rmi/rmi_t3.html" >protocole T3</a></span>.</p><p>La suite de ce billet détaille la configuration à mettre en place pour chacun des trois protocoles, et les avantages et inconvénients de chacun.</p><h4><a
name="JConsoleetWebLogic9-JRMP"></a>JRMP</h4><p>Pour accéder à une JVM par JRMP, il faut ajouter les propriétés suivantes :</p><p>[CODE]<br
/> -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345<br
/> -Dcom.sun.management.jmxremote.ssl=false<br
/> -Dcom.sun.management.jmxremote.authenticate=false<br
/> [/CODE]</p><p>Note : Les paramètres com.sun.management.jmxremote.ssl=false et com.sun.management.jmxremote.authenticate=false introduisent une large faille de sécurité sur la JVM (ni authentification, ni cryptage des données échangées). La mise en place d&#8217;une authentification est possible en définissant une liste d&#8217;utilisateurs dans le fichier &lt;Java_Home&gt;/jre/lib/management/jmxremote.password. Tout est détailé sur &#8216;Luis-Miguel Alventosa&#8217;s Blog&#8217; : <a
href="http://blogs.sun.com/lmalventosa/entry/jmx_authentication_authorization">Authentication and Authorization in JMX RMI connectors</a>. Le cryptage par SSL est possible mais très lourd à mettre en place (génération de certificats)</p><p>Avec la JConsole, il existe alors deux moyens de se connecter :</p><ul><li>Soit par l&#8217;onglet &#8216;Remote&#8217; en précisant le nom ou l&#8217;adresse IP de la machine et le port spécifié par la propriété com.sun.management.jmxremote.port.</li><li>Soit par l&#8217;onglet &#8216;Advanced&#8217; en spécifiant l&#8217;URL suivante : service:jmx:rmi:///jndi/rmi://192.168.199.131:7001:12345/jmxrmi. La construction de l&#8217;URL est en partie expliquée dans la javadoc de la classe <span ><a
href="http://java.sun.com/j2se/1.5.0/docs/api/javax/management/remote/JMXServiceURL.html" >JMXServiceURL</a></span>. Les champs User Name et Password restent vides.</li></ul><p><b>Avantages</b> : Simplicité de mise en œuvre et de connexion (Onglet &#8216;Remote&#8217;).<br
/> <b>Inconvénient</b> : Sécurité.</p><h4><a
name="JConsoleetWebLogic9-IIOP"></a>IIOP</h4><p>Java RMI Over IIOP permet de s&#8217;interfacer avec les ORB, spécifiés par CORBA (Common Object Request Broker Architecture). Les serveurs d&#8217;applications certifiés J2EE se doivent de supporter le protocole IIOP (RMI/IIOP). Pour connecter une JConsole sur un serveur d&#8217;applications WebLogic 9.x avec le protocole IIOP, il est nécessaire d&#8217;activer ce protocole et de déclarer un utilisateur afin de s&#8217;authentifier. La procédure est décrite <span ><a
href="http://e-docs.bea.com/wls/docs90/ConsoleHelp/taskhelp/channels/EnableAndConfigureIIOP.html" >ici</a></span>. La JVM nécessite d&#8217;être démarrée avec l&#8217;option :</p><p><code>-Dcom.sun.management.jmxremote</code></p><p>Dans la JConsole, il est faut utiliser l&#8217;onglet &#8216;Advanced&#8217; et indiquer l&#8217;url suivante :<br
/> <code>service:jmx:rmi:///jndi/iiop://192.168.199.131:7001/weblogic.management.mbeanservers.runtime</code></p><p><b>Avantage</b> : -<br
/> <b>Inconvénients</b> : Compliqué à paramétrer, complexité liée au protocole IIOP.</p><h4><a
name="JConsoleetWebLogic9-T3"></a>T3</h4><p>J2EE 1.0 n&#8217;imposait pas le support d&#8217;IIOP. BEA a alors mis au point T3, un protocole propriétaire plus performant. Depuis, le protocole T3 est le protocole par défaut pour accéder aux différents objets distants hébergés sur un serveur d&#8217;applications WebLogic. Puisque T3 implémente RMI, il est possible de brancher la JConsole à une JVM avec T3.</p><p>Tout d&#8217;abord il faut :</p><ul><li>Ajouter le jar weblogic.jar au lancement de la JConsole.</li><li>Indiquer les <span ><a
href="http://java.sun.com/j2se/1.5.0/docs/api/javax/management/remote/JMXConnectorFactory.html">&#8216;ClientProviders&#8217;</a></span> fournis par BEA (propriété jmx.remote.protocol.provider.pkgs).</li></ul><p>[CODE]<br
/> set JAVA_HOME=D:\bea\alsb21\jdk150_04<br
/> %JAVA_HOME%\bin\jconsole.exe<br
/> -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -J-Djava.class.path=%JAVA_HOME%\lib\jconsole.jar;D:\bea\alsb21\weblogic91\server\lib\weblogic.jar;%JAVA_HOME%\lib\tools.jar</pre><p>[/CODE]</p><p>Pour se connecter, il faut utiliser le mode 'advanced' et indiquer :</p><ul><li>JMXURL : <code>service:jmx:t3://192.168.199.131:7001/jndi/weblogic.management.mbeanservers.runtime</code></li><li>UserName : weblogic</li><li>Password : ********</li></ul><p>Il faut que l'utilisateur possède les droits d'administration.</p><p> <a
href='http://blog.xebia.fr/wp-content/uploads/2007/06/jmx-connection-failed.jpg' title='JMX Connection Failed'><img
src='http://blog.xebia.fr/wp-content/uploads/2007/06/jmx-connection-failed.miniature.jpg' alt='JMX Connection Failed' /></a></p><p>Après activation des logs et analyse j'ai remarqué que les <em>credentials</em> (UserName et Password) n'étaient pas transférés au moment du lookup de l'objet MBeanServer. Pour y remédier, il suffit d'écrire un nouveau 'ClientProvider' du protocole T3 qui va effectuer cette manipulation : transfert de la propriété 'jmx.remote.credentials' vers 'java.naming.security.principal' et 'java.naming.security.credentials'.</p><p>[JAVA]<br
/> package fr.xebia.jmx.remote.t3;</p><p>import java.io.IOException;<br
/> import java.util.HashMap;<br
/> import java.util.Map;</p><p>import javax.management.remote.JMXConnector;<br
/> import javax.management.remote.JMXServiceURL;</p><p>public class ClientProvider extends<br
/> weblogic.management.remote.t3.ClientProvider {</p><p> public JMXConnector newJMXConnector(JMXServiceURL jmxserviceurl, Map map)<br
/> throws IOException {<br
/> Map newMap = checkCredentials(map);<br
/> return super.newJMXConnector(jmxserviceurl, newMap);<br
/> }</p><p> @SuppressWarnings("unchecked")<br
/> private Map checkCredentials(Map map) {<br
/> if (!map.containsKey("java.naming.security.principal")<br
/> &#038;&#038; !map.containsKey("java.naming.security.credentials")) {<br
/> if (map.containsKey("jmx.remote.credentials")) {<br
/> Map newMap = new HashMap();<br
/> newMap.putAll(map);<br
/> String[] cred = (String[]) map.get("jmx.remote.credentials");<br
/> newMap.put("java.naming.security.principal", cred[0]);<br
/> newMap.put("java.naming.security.credentials", cred[1]);<br
/> return newMap;<br
/> }<br
/> }<br
/> return map;<br
/> }<br
/> }</p><p>[/JAVA]</p><p>Il faut ensuite ajuster la ligne de commande (ajout de la classe fr.xebia.jmx.remote.t3.ClientProvider au classpath et modification de la propriété jmx.remote.protocol.provider.pkgs).</p><p>[CODE]<br
/> set JAVA_HOME=D:\bea\alsb21\jdk150_04<br
/> %JAVA_HOME%\bin\jconsole.exe<br
/> -J-Djmx.remote.protocol.provider.pkgs=fr.xebia.jmx<br
/> -J-Djava.class.path=t3jconsole.jar,%JAVA_HOME%\lib\jconsole.jar;D:\bea\alsb21\weblogic91\server\lib\weblogic.jar;%JAVA_HOME%\lib\tools.jar<br
/> [/CODE]</p><p>Avec les mêmes informations rentrées dans l'onglet 'Advanced', vous serez maintenant connecté à votre serveur d'applications WebLogic 9 avec la JConsole en utilisant le protocole T3.</p><p><b>Avantage</b> : Pas de paramétrage supplémentaire (l'activation du protocole IIOP et la déclaration du user IIOP nécessitent un redémarrage du serveur).<br
/> <b>Inconvénient</b> : Il est impossible de brancher la JConsole avant que le serveur soit 'Running', donc pas de suivi du démarrage du serveur.</p><h3><a
name="JConsoleetWebLogic9-Conclusion"></a>Conclusion</h3><p>La JConsole permet rapidement de voir le comportement mémoire, le CPU et les traitements d'un serveur d'applications. Désormais, pensez à ajouter le '-Dcom.sun.management.jmxremote' sur l'ensemble de vos JVM 5.0 afin de permettre un diagnostic rapide en cas de problème.</p><h3><a
name="JConsoleetWebLogic9-Références"></a>Références</h3><ul><li><span ><a
href="http://www.labo-sun.com/resource-fr-articles-1180-1-java-reseau-jmx-et-jconsole.htm" >JMX et JConsole</a></span> au labo Sun de Sup Info.</li><li><span ><a
href="http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html" >Using jconsole</a></span> sur le site de Sun.</li><li><span ><a
href='http://blog.xebia.fr/wp-content/uploads/2007/06/t3jconsole.zip' title='Fichier T3Console.Jar (.java et .class)'>Fichier T3Console.Jar (.java et .class)</a></span></li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/06/28/jconsole-et-weblogic-9/feed/</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>WebLogic Scripting Tools</title><link>http://blog.xebia.fr/2007/05/09/weblogic-scripting-tools/</link> <comments>http://blog.xebia.fr/2007/05/09/weblogic-scripting-tools/#comments</comments> <pubDate>Wed, 09 May 2007 12:33:05 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[J2EE]]></category> <category><![CDATA[JMX]]></category> <category><![CDATA[MBean]]></category> <category><![CDATA[Weblogic]]></category> <category><![CDATA[WLST]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/05/09/weblogic-scripting-tools/</guid> <description><![CDATA[Dans un post précédent, j&#8217;ai expliqué comment exposer un MBean avec Spring dans WebLogic Server 8.1. Je vais vous montrer comment interagir avec ce MBean avec WLST. WebLogic Scripting Tool (WLST) est un outil en ligne de commande qui permet de surveiller et gérer des instances WebLogic Server. Cet outil de scripting est basé sur [...]]]></description> <content:encoded><![CDATA[<p>Dans un post <a
href="http://blog.xebia.fr/2007/02/21/exposer-un-mbean-avec-spring-dans-weblogic-server-81/">précédent</a>, j&#8217;ai expliqué comment exposer un MBean avec Spring dans WebLogic Server 8.1. Je vais vous montrer comment interagir avec ce MBean avec WLST.</p><p>WebLogic Scripting Tool (WLST) est un outil en ligne de commande qui permet de surveiller et gérer des instances WebLogic Server. Cet outil de scripting est basé sur le langage Jython[1], une implémentation du langage Python 100% Java. A l&#8217;origine, cet outil a été développé pour WebLogic 8.1.x. Il est disponible en version 5.4 [2] sur le site CodeShare, le repository des projets open source liés au monde des serveurs WebLogic. A partir de la version 9.0 de WebLogic Server, WLST a été intégré à la distribution et est complètement supporté par BEA.</p><p>Avec WLST il est possible :</p><ul><li>De parcourir la configuration d&#8217;un domaine et ses paramètres runtime.</li><li>D&#8217;éditer la configuration d&#8217;un domaine et de sauvegarder ces modifications.</li><li>D&#8217;accéder à l&#8217;ensemble des MBean du serveur (MBean WebLogic, MBean WebLogic Integration, Mbean WebLogic Portal, MBean défini par les utilisateurs).</li><li>D&#8217;automatiser les procédures de déploiement d&#8217;application et de configuration.</li></ul><p>Procédure d&#8217;installation de WLST pour WebLogic 8.1 :</p><ol><li>Télécharger wlst_v64.zip</li><li>Extraire l&#8217;archive dans un répertoire (ex c:\wlst)</li><li>Créer un script de lancement (ex c:\wlst\wlst.cmd)</li><p><code>title WLST<br
/> set WL_HOME=D:\bea\bea815\weblogic81<br
/> Set JAVA_HOME=D:\bea\bea815\jdk142_08<br
/> set WLST_HOME=c:\wlst<br
/> set CLASSPATH=%WLST_HOME%\wlst.jar;%WLST_HOME%\jython.jar;%WL_HOME%\server\lib\weblogic.jar<br
/> %JAVA_HOME%\bin\java  weblogic.WLST %*<br
/> </code></p><li>Lancer le script wlst.cmd</li></ol><p>Note : pour les utilisateurs d&#8217;un serveur WebLogic 9.x, le script de lancement se trouve dans le répertoire %WL_HOME%\common\bin\wlst.cmd</p><p>Au lancement vous devez obtenir :<br
/> <code>Initializing WebLogic Scripting Tool (WLST) ...<br
/> Welcome to WebLogic Server Administration Scripting Shell<br
/> Type help() for help on available commands<br
/> wls:/(offline)&gt;</code></p><p>La première étape est de se connecter à un serveur. Cette action s&#8217;effectue avec la commande connect(login, password, url). Si votre domaine comporte un serveur d&#8217;admin et des serveurs managés, il est préférable de se connecter au serveur d&#8217;administration qui vous donnera l&#8217;accès à l&#8217;ensemble des serveurs du domaine.<br
/> <code>wls:/(offline)&gt; connect('weblogic','weblogic','t3://localhost:7001')<br
/> Connecting to weblogic server instance running at t3://localhost:7001 as username weblogic ...<br
/> Successfully connected to Admin Server 'myserver' that belongs to domain 'wlsdomain'.<br
/> wls:/wlsdomain/config&gt;</code></p><p>A partir de là, vous pouvez parcourir l&#8217;ensemble du domaine avec les commandes ls() et cd().<br
/> <code>wls:/wlsdomain/config&gt; ls();<br
/> drw-   ApplicationManager<br
/> drw-   Applications<br
/> drw-   BasicRealms<br
/> drw-   BridgeDestination<br
/> drw-   BridgeDestinationCommon<br
/> drw-   CachingRealms<br
/> drw-   Clusters<br
/> drw-   ConversationService<br
/> drw-   CustomRealm<br
/> …..<br
/> -rw-   AdministrationMBeanAuditingEnabled false<br
/> -rw-   AdministrationPort                         9002<br
/> -rw-   AdministrationPortEnabled               false<br
/> -rw-   ArchiveConfigurationCount	      5<br
/> -r--   CachingDisabled                            true<br
/> ...<br
/> </code>La commande affiche les différents paramètres avec leur mode d&#8217;accès (r:read, w:write, d: répertoire). Le contenu d&#8217;un élément de type d peut etre accédé avec la commande cd()<br
/> <code>wls:/wlsdomain/config&gt; cd ('Servers')<br
/> wls:/wlsdomain/config/Servers&gt; ls()<br
/> drw-   myserver<br
/> wls:/wlsdomain/config/Servers&gt; cd('ExecuteQueues/weblogic.kernel.Default')<br
/> wls:/wlsdomain/config/Servers/myserver/ExecuteQueues/weblogic.kernel.Default&gt;</code></p><p>L&#8217;appel à la commande ls() affiche l&#8217;ensemble des paramètres liés à la queue d&#8217;exécution &#8216;weblogic.kernel.Default&#8217;.</p><p>Les commandes get() et set() permettent de manipuler les paramètres des Mbean. En effet, les fonctions offertes par les différentes consoles d&#8217;administration de WebLogic Platform ne sont en réalité que des appels à des Mbeans fournis par le serveur WebLogic. Tout ce vous pouvez faire avec la console, vous pouvez le faire avec WLST.</p><p>Exemple de modification de la valeur &#8216;ThreadCount&#8217;.<br
/> <code>wls:/wlsdomain/config/Servers/myserver/ExecuteQueues/weblogic.kernel.Default&gt; get('ThreadCount')<br
/> 15<br
/> wls:/wlsdomain/config/Servers/myserver/ExecuteQueues/weblogic.kernel.Default&gt; set('ThreadCount','20')<br
/> wls:/wlsdomain/config/Servers/myserver/ExecuteQueues/weblogic.kernel.Default&gt; get('ThreadCount')<br
/> 20</code></p><p>L&#8217;une des grandes forces de WLST est sa capacité à exécuter des scripts afin de rendre automatisable l&#8217;ensemble des opérations d&#8217;administration.<br
/> Dans le répertoire d&#8217;installation de WLST, créer un fichier texte : ex1.py</p><pre class="brush: python; title: ; notranslate">
connect('weblogic','weblogic','t3://localhost:7001')
cd ('/Servers/myserver/ExecuteQueues/weblogic.kernel.Default')
print &quot;Afficher le nombre de thread:&quot;+str(get('ThreadCount'))
set('ThreadCount','25')
disconnect()
</pre><p>Lancez une autre instance de l&#8217;interpréteur WLST et exécuter le script ex1.py<br
/> <code>wls:/(offline)&gt; execfile('ex1.py')<br
/> Connecting to weblogic server instance running at t3://localhost:7001 as username weblogic ...<br
/> Successfully connected to Admin Server 'myserver' that belongs to domain 'wlsdomain'.<br
/> Afficher le nombre de thread:20<br
/> Disconnected from weblogic server: myserver<br
/> wls:/(offline)&gt;</code><br
/> Si vous retournez sur le précédent interpréteur WLST et exécutez la commande get(&#8216;ThreadCount&#8217;), la valeur &#8217;25&#8242; devrait apparaître.</p><p>Le script suivant ex2.py exécute la même opération que ex1.py en définissant une fonction python. Attention, en python, l&#8217;indentation fait partie du langage !</p><pre class="brush: python; title: ; notranslate">
def modifierThreadCount(executequeue, valeur):
cd ('/Servers/myserver/ExecuteQueues/'+executequeue)
print &quot;Afficher le nombre de thread:&quot;+str(get('ThreadCount'))
set('ThreadCount',valeur)
connect('weblogic','weblogic','t3://localhost:7001')
modifierThreadCount('weblogic.kernel.Default',15)
disconnect()
</pre><p><code>wls:/(offline)&gt; execfile('ex2.py')</code></p><p>Revenons à notre MBean développé précédemment. WLST permet de manipuler non seulement les MBeans BEA mais également nos propres MBeans. Le script suivant recherche les MBeans à partir d&#8217;un nom (), de lire et modifier les attributs.</p><pre class="brush: python; title: ; notranslate">
def manipulation():
#recherche de tous les MBeans qui portent le nom 'testBean', quelque soit le package.
testBeans = mbs.queryMBeans(ObjectName(&quot;*:*,name=testBean&quot;), None)
#parcours de la liste de resultat
for tb in testBeans:
#affichage de l'objectName
objectName = tb.getObjectName()
print 'ObjectName : '+str(objectName)
print 'Lecture des Attributs Age et Name'
age = mbs.getAttribute(objectName,&quot;Age&quot;);
name = mbs.getAttribute(objectName,&quot;Name&quot;);
print &quot;Age=&quot;+str(age)+&quot;, Name=&quot;+name
#Modification des valeurs
print &quot;Modification de l'attribut Name&quot;
mbs.setAttribute(objectName,Attribute('Name','J2EE'));
print &quot;La nouvelle valeur de l'attribut Name est &quot;+mbs.getAttribute(objectName,&quot;Name&quot;)
connect('weblogic','weblogic','t3://localhost:7001')
manipulation()
disconnect()
</pre><p>Différentes remarques :</p><ul><li>Ce script est la transposition de la classe de test Java test.xebia.management.JMXClient3</li><li>La recherche n&#8217;est pas limitée au nom d&#8217;un Mbean, il est également possible d&#8217;effectuer des recherches par type</li><li>La variable &#8216;mbs&#8217; est une variable globale définie par WLST, elle correspond à la position courante dans la hiérarchie des MBeans. L&#8217;ensemble des variables est documenté sur cette page[4]</li></ul><p>L&#8217;exécution de ce script donne le résultat suivant :<br
/> <code>wls:/(offline)&gt; execfile('ex3.py')<br
/> Connecting to weblogic server instance running at t3://localhost:7001 as username weblogic ...<br
/> Successfully connected to Admin Server 'myserver' that belongs to domain 'wlsdomain'.<br
/> ObjectName : bean:name=testBean<br
/> Lecture des Attributs Age et Name<br
/> Age=2, Name=xebia<br
/> Modification de l'attribut Name<br
/> La nouvelle valeur de l'attribut Name est J2EE<br
/> Disconnected from weblogic server: myserver<br
/> wls:/(offline)&gt;</code></p><p>L&#8217;ajout de WLST à la plateforme WebLogic est une bonne évolution vers une réelle industrialisation des serveurs d&#8217;applications de la gamme BEA. Il existe un autre mode d&#8217;interaction proposé par WLST : WLST Offline. Il permet de créer et de paramétrer des domaines WebLogic sans être connecté. Ce mode est l&#8217;équivalent de ce que propose le domaine &#8216;Wizard&#8217;.</p><p>Source: <a
href="http://blog.xebia.fr/wp-content/uploads/2007/04/wlst.zip">scripts WLST [zip]</a></p><p><strong>Référence</strong>:</p><p>[1] http://www.jyton.org</p><p>[2] WLST 8.4 pour WLS 8.1</p><p>https://codesamples.projects.dev2dev.bea.com/servlets/Scarab?id=S13</p><p>[3] Documentation 9.x</p><p>http://e-docs.bea.com/wls/docs90/config_scripting/using_WLST.html</p><p>[4] WLST Variable Reference</p><p>http://e-docs.bea.com/wls/docs92/config_scripting/reference.html#wp1178147</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/05/09/weblogic-scripting-tools/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Le top 10 des problèmes de performances des applications J2EE</title><link>http://blog.xebia.fr/2007/05/03/le-top-10-des-problemes-de-performances-des-applications-j2ee/</link> <comments>http://blog.xebia.fr/2007/05/03/le-top-10-des-problemes-de-performances-des-applications-j2ee/#comments</comments> <pubDate>Thu, 03 May 2007 12:38:22 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[J2EE]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/05/03/le-top-10-des-problemes-de-performances-des-applications-j2ee/</guid> <description><![CDATA[Depuis deux mois et demi, Vincent Partington a déroulé sur le blog de Xebia.com, les 10 principaux problèmes de performance des applications Java / J2EE. Voici le classement: #10 &#8211; Logging excessif #09 &#8211; Mauvaise configuration du serveur d&#8217;application #08 &#8211; Usage incorrecte de Java EE #07 &#8211; Utilisation abusive du XML #06 &#8211; Mauvaise [...]]]></description> <content:encoded><![CDATA[<p>Depuis deux mois et demi, Vincent Partington a déroulé sur le blog de Xebia.com, les 10 principaux problèmes de performance des applications Java / J2EE. Voici le classement:</p><ul><li>#10 &#8211; <a
href="http://blog.xebia.com/2007/02/18/ejapp-top-10-countdown-10-excessive-logging/">Logging excessif</a></li><li>#09 &#8211; <a
href="http://blog.xebia.com/2007/02/25/ejapp-top-10-countdown-9-incorrect-application-server-configuration/">Mauvaise configuration du serveur d&#8217;application</a></li><li>#08 &#8211; <a
href="http://blog.xebia.com/2007/03/09/ejapp-top-10-countdown-8-incorrect-usage-of-java-ee/">Usage incorrecte de Java EE</a></li><li>#07 &#8211; <a
href="http://blog.xebia.com/2007/03/19/ejapp-top-10-countdown-7-unnecessary-use-of-xml/">Utilisation abusive du XML</a></li><li>#06 &#8211; <a
href="http://blog.xebia.com/2007/03/26/ejapp-top-10-countdown-6-improper-caching/">Mauvaise utilisation des fonctions de &#8216;Cache&#8217;</a></li><li>#05 &#8211; <a
href="http://blog.xebia.com/2007/04/02/ejapp-top-10-countdown-5-excessive-memory-usage/">Consommation mémoire</a></li><li>#04 &#8211; <a
href="http://blog.xebia.com/2007/04/16/ejapp-top-10-countdown-4-badly-performing-libraries/">Mauvaises performances des bibliothèques tierces</a></li><li>#03 &#8211; <a
href="http://blog.xebia.com/2007/04/22/ejapp-top-10-countdown-3-incorrectly-implemented-concurrency/">Mauvaise gestion de la concurrence</a></li><li>#02 &#8211; <a
href="http://blog.xebia.com/2007/04/25/ejapp-top-10-countdown-2-unnecessary-remoting/">Utilisation abusive de la distribution</a></li><li>#01 &#8211; <a
href="http://blog.xebia.com/2007/04/29/ejapp-top-10-countdown-1-incorrect-database-usage/">Mauvaise utilisation de la base de données</a></li></ul><p>De ce classement, Vincent Partington tire les conclusions suivantes:</p><ul><li>Tout d&#8217;abord, les architectes et développeurs Java devraient considérer la performance comme une exigence de leur application, à toutes les étapes du projet.</li><li>Ensuite, les équipes de développement ont besoin de collaborer avec des personnes qui peuvent les aider à améliorer les performances de leurs applications, en particulier les administrateurs de serveurs d&#8217;applications et les DBA.</li><li>Enfin, la performance requiert des connaissances dans un grand nombre de domaines, dont ce Top Ten met en avant les plus critiques. Pour un tour d&#8217;horizon plus complet, un bon point de départ est le site web <a
href="http://www.javaperformancetuning.com/tips/index.shtml">the Java Performance Tuning</a></li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/05/03/le-top-10-des-problemes-de-performances-des-applications-j2ee/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>Exposer un MBean avec Spring dans WebLogic Server 8.1</title><link>http://blog.xebia.fr/2007/02/21/exposer-un-mbean-avec-spring-dans-weblogic-server-81/</link> <comments>http://blog.xebia.fr/2007/02/21/exposer-un-mbean-avec-spring-dans-weblogic-server-81/#comments</comments> <pubDate>Wed, 21 Feb 2007 12:06:57 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[J2EE]]></category> <category><![CDATA[JMX]]></category> <category><![CDATA[MBean]]></category> <category><![CDATA[Spring]]></category> <category><![CDATA[Weblogic]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/02/21/exposer-un-mbean-avec-spring-dans-weblogic-server-81/</guid> <description><![CDATA[La spécification liée aux extensions de management, plus connue sous le nom de JMX est l&#8217;un des plus ancienne du JCP. Elle porte le n°3. Cependant, elle n&#8217;a été validée qu&#8217;en Juillet 2000 et communément utilisée que très récemment. Il a fallut attendre les serveurs d&#8217;application J2EE 1.4 ou le JSE 5 pour voir cette [...]]]></description> <content:encoded><![CDATA[<p>La spécification liée aux extensions de management, plus connue sous le nom de JMX est l&#8217;un des plus ancienne du JCP. Elle porte le <a
href="http://jcp.org/en/jsr/detail?id=3">n°3</a>. Cependant, elle n&#8217;a été validée qu&#8217;en Juillet 2000 et communément utilisée que très récemment. Il a fallut attendre les serveurs d&#8217;application J2EE 1.4 ou le JSE 5 pour voir cette technologie devenir massivement diffusée en version 1.2. Auparavant chaque éditeur proposait sa propre implémentation avec des versions incompatibles entre elles.</p><p>Le serveur d&#8217;application WebLogic 8.1 utilise massivement cette technologie pour permettre de configurer et monitorer les serveurs. La console d&#8217;administration n&#8217;est qu&#8217;une interface graphique à ces MBeans (Management Bean). Cependant il peut être intéressant d&#8217;exposer des MBean supplémentaires :</p><ul><li>MBean type &#8216;Facade&#8217; : Aggregation de MBeans existants pour unifier la gestion et limiter les appels</li><li>MBean type &#8216;Composite&#8217; : Exposition de méthodes de haut niveau qui synthétisent un ensemble de MBean et de données techniques</li><li>MBean type &#8216;Applicatifs&#8217; : Interface de gestion non plus au niveau technique (serveur d&#8217;application) mais fonctionelle</li></ul><p>Voici donc les étapes à suivre et les pièges à éviter pour exposer un MBean avec le framework <a
href="http://www.springframework.org">Spring 2.0</a> dans <a
href="http://www.bea.com/framework.jsp?CNT=index.htm&amp;FP=/content/products/weblogic/server/">WebLogic 8.1</a>. L&#8217;environnement de développement est Eclipse 3.2 avec WTP.</p><ul
type="disc"><li>Créons un projet de type &#8216;Dynamic Web Project&#8217; (nom WeblogicSpringMBean) avec le target runtime &#8216;Generic BEA WebLogic Server 8.1&#8242;</li><li>Ajoutons au répertoire WEB-INF/lib, les bibliothèque spring.jar et common-logging.jar.</li><li>Implémentons notre MBean de test (très simple): fr.xebia.management.InfoMBean</li></ul><pre class="brush: java; title: ; notranslate">
package fr.xebia.management;
public class InfoMBean {
	private String name;
	private int age;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
</pre><p>Le framework Spring va nous permettre d&#8217;assembler et d&#8217;exposer ce MBean.</p><ul><li>Créons dans le répertoire WEB-INF le fichier d&#8217;assemblage Spring applicationContext.xml</li><li>Déclarons le bean associé au MBean InfoMBean</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE beans PUBLIC &quot;-//SPRING//DTD BEAN 2.0//EN&quot;
     &quot;http://www.springframework.org/dtd/spring-beans-2.0.dtd&quot;&gt;
&lt;beans&gt;
 &lt;bean id=&quot;infombean&quot; class=&quot;fr.xebia.management.InfoMBean&quot;&gt;
   &lt;property name=&quot;name&quot; value=&quot;xebia&quot;&gt;&lt;/property&gt;
   &lt;property name=&quot;age&quot; value=&quot;2&quot;&gt;&lt;/property&gt;
 &lt;/bean&gt;
&lt;/beans&gt; </pre><ul><li>Déclarons le server de MBeans de WebLogic</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;weblogicMBeanServer&quot;
   class=&quot;org.springframework.jmx.support.WebLogicJndiMBeanServerFactoryBean&quot;/&gt;
</pre><ul><li>Déclarons le bean qui va permettre d&#8217;exposer le bean en tant que MBean (org.springframework.jmx.export.MBeanExporter)</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;exporter&quot; class=&quot;org.springframework.jmx.export.MBeanExporter&quot;&gt;
	&lt;property name=&quot;beans&quot;&gt;
		&lt;map&gt;
			&lt;entry key=&quot;bean:name=testBean&quot; value-ref=&quot;infombean&quot; /&gt;
		&lt;/map&gt;
	&lt;/property&gt;
	&lt;property name=&quot;server&quot; ref=&quot;weblogicMBeanServer&quot; /&gt;
&lt;/bean&gt;
</pre><p>Il reste à paramétrer le fichier web.xml pour permettre de charger cette configuration au démarrage du serveur. La servlet org.springframework.web.context.ContextLoaderServlet va se charger, au démarrage, d&#8217;assembler les beans à partir du fichier applicationContext.xml et d&#8217;exposer le MBean.</p><pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE web-app PUBLIC &quot;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&quot;
&quot;http://java.sun.com/dtd/web-app_2_3.dtd&quot;&gt;
&lt;web-app id=&quot;WebApp_ID&quot;&gt;
  &lt;display-name&gt;WebLogicSpringMBean&lt;/display-name&gt;
  &lt;servlet&gt;
	&lt;servlet-name&gt;context&lt;/servlet-name&gt;
	&lt;servlet-class&gt;org.springframework.web.context.ContextLoaderServlet&lt;/servlet-class&gt;
	&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
  &lt;/servlet&gt;
&lt;/web-app&gt;
</pre><p>Si on se base sur les différentes documentations [1] c&#8217;est terminé.<br
/> Dans l&#8217;environnement Eclipse, démarrer le serveur et deployer l&#8217;application (La commande &#8216;Run On Server&#8217; se charge des deux opérations).</p><p><strong>Première Difficulté</strong> : Lors du déploiement de l&#8217;application WeblogicSpringMBean.war, le serveur répond :</p><p><code>javax.servlet.ServletException: Error creating bean with name 'weblogicMBeanServer' defined in ServletContext resource<br
/> [/WEB-INF/applicationContext.xml]: Invocation of init method failed;<br
/> nested exception is org.springframework.jmx.MBeanServerNotFoundException: Could not find WebLogic's MBeanHome object in JNDI;<br
/> nested exception is j<strong>avax.naming.NoPermissionException</strong>: <strong>User <anonymous> does not have permission on weblogic.management.home to perform lookup operation</anonymous></strong>.</code></p><p><strong>Solution</strong> :il faut exécuter la servlet avec le rôle Admin</p><ul><li>Editer le fichier web.xml pour déclarer le rôle admin</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;web-app id=&quot;WebApp_ID&quot;&gt;
	&lt;display-name&gt;WebLogicSpringMBean&lt;/display-name&gt;
	&lt;servlet&gt;
		&lt;servlet-name&gt;context&lt;/servlet-name&gt;
		&lt;servlet-class&gt;org.springframework.web.context.ContextLoaderServlet&lt;/servlet-class&gt;
		&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
		&lt;run-as&gt;
			&lt;role-name&gt;admin&lt;/role-name&gt;
		&lt;/run-as&gt;
	&lt;/servlet&gt;
	&lt;security-role&gt;
		&lt;role-name&gt;admin&lt;/role-name&gt;
	&lt;/security-role&gt;
&lt;/web-app&gt;
</pre><ul><li>Créer dans le répertoire WEB-INF un fichier weblogic.xml qui va associer le rôle admin avec le user weblogic</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;weblogic-web-app&gt;
	&lt;security-role-assignment&gt;
		&lt;role-name&gt;admin&lt;/role-name&gt;
		&lt;principal-name&gt;weblogic&lt;/principal-name&gt;
	&lt;/security-role-assignment&gt;
&lt;/weblogic-web-app&gt;
</pre><ul><li>Redéployer l&#8217;application</li></ul><p>Ecrivons un client de test pour interroger notre MBean. Pour des soucis de commodités, nous allons le coder dans le même projet que notre MBean. Le code suivant permet retrouver tous les MBean dont le nom est &#8216;testBean&#8217;.</p><pre class="brush: java; title: ; notranslate">
public static void main(String[] args) throws Exception {
	Environment env = new Environment();
	env.setProviderUrl(&quot;t3://localhost:7001&quot;);
	env.setSecurityPrincipal(&quot;weblogic&quot;);
	env.setSecurityCredentials(&quot;weblogic&quot;);
	Context ctx = env.getInitialContext();
	System.out.println(&quot;Recherche du MBeanHome&quot;);
	MBeanHome home  = (MBeanHome) ctx.lookup(MBeanHome.LOCAL_JNDI_NAME);
	RemoteMBeanServer server = home.getMBeanServer();
	System.out.println(&quot;Recherche de tous les MBeans dont le nom est 'testBean' [*:*,name=testBean]&quot;);
	Set results = server.queryMBeans(new ObjectName(&quot;*:*,name=testBean&quot;),
			null);
	for (Iterator iter = results.iterator(); iter.hasNext();) {
		ObjectInstance oi = (ObjectInstance) iter.next();
		ObjectName objectName = oi.getObjectName();
		System.out.println(objectName);
	}
}
</pre><p>Sur la sortie console on obtient :</p><p><code> Recherche du MBeanHome<br
/> Recherche de tous les MBeans dont le nom est 'testBean' [*:*,name=testBean]<br
/> bean:name=testBean<br
/> </code></p><p>Donc notre MBean est exposé sur le serveur WebLogic.</p><p>Rajoutons une ligne de code pour obtenir la valeur de l&#8217;attribut MBean (JMXClient2.java)</p><pre class="brush: java; title: ; notranslate">
for (Iterator iter = results.iterator(); iter.hasNext();) {
  ObjectInstance oi = (ObjectInstance) iter.next();
  ObjectName objectName = oi.getObjectName();
  System.out.println(objectName);
  System.out.println(server.getAttribute(objectName, &quot;Name&quot;));
  System.out.println(server.getAttribute(objectName, &quot;Age&quot;));
}
</pre><p><strong>Deuxième Difficulté</strong> : Sur l&#8217;appel de la méthode server.getAttribute(), le serveur lance une Exception :</p><p><code>javax.management.ReflectionException: The target object class class javax.management.modelmbean.ModelMBeanOperationInfo could not be found.</code></p><p>Cette exception indique un problème lié au code de WebLogic géré par le classloader système qui doit accéder à une classe chargée par le classloader de l&#8217;application Web. Le classloader d&#8217;un module J2EE (jar,war,ear) <em>dérive</em> du classloader système, et non l&#8217;inverse.</p><p><strong>Solution</strong> : D&#8217;après le Bug Tracker de Spring [2], il faut, pour exposer notre MBean, utiliser une bibliothèque tierce packagée dans l&#8217;application Web: Le projet Apache Common Modeler [3]</p><ul><li>Copions le fichier commons-modeler-2.0.jar dans le répertoire WEB-INF/lib</li><li>Dérivons la classe org.springframework.jmx.export.MBeanExporter et surchargeons la méthode createModelMBean()</li></ul><pre class="brush: java; title: ; notranslate">
package fr.xebia.management;
import javax.management.MBeanException;
import javax.management.modelmbean.ModelMBean;
import org.springframework.jmx.export.MBeanExporter;
public class CommonModelerBeanExporter extends MBeanExporter {
	protected ModelMBean createModelMBean() throws MBeanException {
		return new org.apache.commons.modeler.BaseModelMBean();
	}
}
</pre><ul><li>Modifions l&#8217;assemblage Spring pour utiliser cette classe à la place MBeanExporter</li></ul><pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;exporter&quot; class=&quot;fr.xebia.management.CommonModelerBeanExporter&quot;&gt;
	&lt;property name=&quot;beans&quot;&gt;
		&lt;map&gt;
			&lt;entry key=&quot;bean:name=testBean&quot; value-ref=&quot;infombean&quot; /&gt;
		&lt;/map&gt;
	&lt;/property&gt;
	&lt;property name=&quot;server&quot; ref=&quot;weblogicMBeanServer&quot; /&gt;
&lt;/bean&gt;
</pre><p>Apres avoir redéployé l&#8217;application, le client de test JMXClient2.java permet d&#8217;afficher la valeur de l&#8217;attribut &#8216;Name&#8217; et &#8216;Age&#8217; du MBean</p><p><code>class test.xebia.management.JMXClient2<br
/> Recherche du MBeanHome<br
/> Recherche de tous les MBeans dont le nom est 'testBean' [*:*,name=testBean]<br
/> bean:name=testBean<br
/> 2<br
/> </code></p><p>Les valeurs affichées sont celles indiqués dans le fichier d&#8217;assemblage Spring.</p><p>Le client de test JMXClient3 modifie la valeur des attribut du MBean.</p><p><code>class test.xebia.management.JMXClient3<br
/> Recherche du MBeanHome<br
/> Recherche de tous les MBeans dont le nom est 'testBean' [*:*,name=testBean]<br
/> bean:name=testBean<br
/> Modification de l'attribut Name=J2EE<br
/> Modification de l'attribut Age=4<br
/> </code></p><p>Si on relance le client de test JMXClient2, on doit obtenir les valeur J2EE et 4: L&#8217;instance du MBean est unique sur le server WebLogic.</p><p><code>class test.xebia.management.JMXClient2<br
/> Recherche du MBeanHome<br
/> Recherche de tous les MBeans dont le nom est 'testBean' [*:*,name=testBean]<br
/> bean:name=testBean<br
/> J2EE<br
/> 4<br
/> </code></p><p>Le projet Eclipse est disponible : <a
href='http://blog.xebia.fr/wp-content/uploads/2007/04/weblogicspringmbean.zip' title='weblogicspringmbean.zip'>weblogicspringmbean.zip</a>. Il n&#8217;inclut pas le fichier spring.jar.</p><p>Avec le support en natif par la JVM, la technologie JMX va devenir de plus en plus présente dans les applications J2EE pour offrir une gestion à deux niveaux :</p><ul><li>gestion technique : paramétrage de niveaux de log, accès à des statistiques (Pools de Connexion, Transaction, &#8230;)</li><li>gestion fonctionnelle : par exemple, l&#8217;application va pouvoir exposer elle-même des indicateurs à destinations des utilisateurs et pilotes fonctionnels. Aujourd&#8217;hui, ces indicateurs sont généralement calculés à grands coups de requêtes dans la base de données.</li></ul><p>Un prochain post montrera comment accéder à ce bean en utilisant le langage WLST (WebLogic Scripting Tool).</p><p><strong>Référence</strong>:</p><p>[1] <a
href="http://static.springframework.org/spring/docs/2.0.x/reference/jmx.html">Documentation Spring 2.0 JMX</a><br
/> [2] <a
href="http://opensource2.atlassian.com/projects/spring/browse/SPR-1395?page=all">JIRA Spring</a><br
/> [3] <a
href="http://jakarta.apache.org/commons/modeler/">Apache Common Modeler</a></p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/02/21/exposer-un-mbean-avec-spring-dans-weblogic-server-81/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>Java Open Source : ce qui va changer</title><link>http://blog.xebia.fr/2006/11/15/java-open-source-ce-qui-va-changer/</link> <comments>http://blog.xebia.fr/2006/11/15/java-open-source-ce-qui-va-changer/#comments</comments> <pubDate>Wed, 15 Nov 2006 15:58:15 +0000</pubDate> <dc:creator>Benoit Moussaud</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Open Source]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2006/11/15/java-open-source-ce-qui-va-changer/</guid> <description><![CDATA[Sun l&#8217;a annonc&#233; hier: la nouvelle license de Java (langage, compilateur) est la license GPL, la plus ouverte des licence du monde open source. Cette annonce n&#8217;est pas une r&#233;volution mais une &#233;volution naturelle de Java. Cette nouvelle va, par exemple, permettre de placer la JVM au coeur des distributions Linux, voire m&#234;me au niveau [...]]]></description> <content:encoded><![CDATA[<p>Sun l&#8217;a annonc&eacute; hier: la nouvelle license de Java (langage, compilateur) est la license GPL, la plus ouverte des licence du monde open source. Cette annonce n&#8217;est pas une r&eacute;volution mais une &eacute;volution naturelle de Java. Cette nouvelle va, par exemple, permettre de placer la JVM au coeur des distributions Linux, voire m&ecirc;me au niveau Kernel.</p><p>Guillaume Bodet, directeur technique de <a
href="http://www.xebia.fr/">Xebia</a>, r&eacute;pond aux <a
href="http://www.lemondeinformatique.fr/dossiers/lire-java-open-source-ce-qui-va-changer-14-page-3.html">questions</a> d&#8217;Olivier Rafal (Le Monde Informatique) concernant les impacts et les cons&eacute;quences de cette nouvelle licence.</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2006/11/15/java-open-source-ce-qui-va-changer/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> </channel> </rss>
