<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;C0UMSH87fyp7ImA9WhRUEEw.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788</id><updated>2012-01-19T23:14:49.107+01:00</updated><category term="avis" /><category term="nexus" /><category term="java" /><category term="livre" /><category term="esb" /><category term="soa" /><category term="maven" /><category term="jbi" /><category term="spring integration" /><category term="réflexion" /><category term="apache camel" /><category term="présentation" /><category term="archetype" /><category term="cargo" /><category term="jrebel" /><category term="cloudbees" /><category term="divers" /><category term="jetty" /><category term="jetspeed" /><category term="perfomance" /><category term="intégration continue" /><category term="architecture" /><category term="jms" /><category term="eip" /><category term="jmx" /><category term="jgroups" /><title>Je toile ou j* au choix...</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>51</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/jetoile" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="jetoile" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CE4ESXs7eCp7ImA9WhRRGEw.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-5780995097419306614</id><published>2011-12-02T08:29:00.001+01:00</published><updated>2011-12-02T09:01:48.500+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-02T09:01:48.500+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="avis" /><category scheme="http://www.blogger.com/atom/ns#" term="architecture" /><category scheme="http://www.blogger.com/atom/ns#" term="divers" /><title>Resign Patterns : les nouveaux patterns</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-mP_z1e0Qo6M/TtiCRYS_PVI/AAAAAAAAAgQ/Dntolyd6oUg/s1600/Fail.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="179" src="http://2.bp.blogspot.com/-mP_z1e0Qo6M/TtiCRYS_PVI/AAAAAAAAAgQ/Dntolyd6oUg/s320/Fail.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cet article est une traduction "libre" de l'excellent papier de &lt;a href="mailto:mitework@yercompany.com"&gt;Michael Duell&lt;/a&gt; qui se nomme &lt;i&gt;&lt;a href="http://www.lsd.ic.unicamp.br/%7Eoliva/fun/prog/resign-patterns"&gt;"Resign Patterns" Ailments of Unsuitable Project-Disoriented Software&lt;/a&gt;&lt;/i&gt;.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En fait, Resign Patterns reprend le principe des Design Patterns tels que décrit par the &lt;i&gt;Gang Of Four&lt;/i&gt; mais en proposant un tout autres types de Patterns... Je vous laisse juger de leur véracité... Je pense qu'ils ont suffisamment fait leurs preuves pour ne pas avoir droit, eux aussi, à leur gloire... ;-)&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Aussi, au même titre que les patterns du GoF, je vous invite à utiliser les dénominations décrites par les Resign Patterns pour vous faire comprendre de vos collègues quand vous parlez du design d'un programme. Ainsi, vous pourrez briller en société mais surtout vous faire comprendre par vos pairs ;-)&amp;nbsp; &lt;/div&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;Dans le même style, je vous conseille les excellents articles suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.xebia.fr/2011/11/29/revue-de-presse-xebia-239#Humourdedveloppeur"&gt;http://blog.xebia.fr/2011/11/29/revue-de-presse-xebia-239#Humourdedveloppeur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.dodgycoder.net/2011/11/yoda-conditions-pokemon-exception.html"&gt;http://www.dodgycoder.net/2011/11/yoda-conditions-pokemon-exception.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Crédit photo :&amp;nbsp;&lt;a href="http://www.flickr.com/photos/esthervargasc/6010520395/"&gt;http://www.flickr.com/photos/esthervargasc/6010520395/&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h1&gt;






Cremational Patterns&lt;/h1&gt;
Cette catégorie de Patterns en regroupe 5 :
&lt;br /&gt;
&lt;h2&gt;






Abject Poverty&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Abject Poverty Pattern&lt;/b&gt;&amp;nbsp;est visible dans les logiciels qui sont si difficiles à tester et à maintenir que cela abouti généralement à un dépassement de budget pharaonique.

&lt;/div&gt;
&lt;h2&gt;






Blinder&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Blinder Pattern&lt;/b&gt; est la solution opportune à un problème sans qu'aucune anticipation n'ait été faite sur de futurs modifications dans les exigences. 
Il est difficile de savoir s'il est nommé de la sorte en raison de la pauvre vision des personnes qui ont faites le design du logiciel pendant la phase de développement, ou du désir de faire souffrir ses yeux pendant la phase de maintenance.

&lt;/div&gt;
&lt;h2&gt;






Fallacy Method&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Fallacy Method Pattern&lt;/b&gt; est visible dans le traitement de cas particuliers. La logique semble correct mais si quiconque tente de tester ces cas aux limites ou s'ils venaient à se produit, alors les erreurs de logiques apparaitraient au grand jour.

&lt;/div&gt;
&lt;h2&gt;






ProtoTry&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;ProtoTry Pattern&lt;/b&gt;&amp;nbsp;offre une façon rapide et sale de développer un logiciel. Généralement, l'intention première est de vouloir réécrire le code utilisant le &lt;b&gt;ProtoTry&lt;/b&gt; mais en l'améliorant en mettant en pratique les leçons apprises pendant la phase de conception. Malheureusement, souvent, un planning inadapté ne le permet pas. Le &lt;b&gt;ProtoTry &lt;/b&gt;est aussi connu sous le nom de &lt;b&gt;code Legacy&lt;/b&gt;.

&lt;/div&gt;
&lt;h2&gt;






Simpleton&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Simpleton Pattern&lt;/b&gt; est un pattern extrèmement complexe utilisé pour faire une tache triviale. Le &lt;b&gt;Simpleton&lt;/b&gt; offre un indicateur fiable sur le niveau de compétence des concepteurs du code.

&lt;/div&gt;
&lt;h1&gt;






Les Destructural Patterns&lt;/h1&gt;
Cette catégorie de Patterns en regroupe 7 :

&lt;br /&gt;
&lt;h2&gt;






Adopter&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
L'&lt;b&gt;Adopter Pattern&lt;/b&gt; fournit un foyer à toutes les fonctions orphelines. Il en résulte une large famille de fonctions qui ne se ressemblent pas et qui n'ont de commun que le fait d'avoir été adopté.

&lt;/div&gt;
&lt;h2&gt;






Brig&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Brig Pattern&lt;/b&gt; est un conteneur de classes pour le mauvais logiciel, aussi connu sous le nom de &lt;b&gt;Module&lt;/b&gt;.

&lt;/div&gt;
&lt;h2&gt;






Compromise&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Compromise Pattern&lt;/b&gt; est utilisé pour trouver un compromis entre la qualité et le planning. Il en résulte généralement un logiciel d'une piètre qualité qui, de plus, est en retard.

&lt;/div&gt;
&lt;h2&gt;






Detonator&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Detonator Pattern&lt;/b&gt; est extrèmement commun mais souvent indétectable. Par exemple, une implémentation fréquente du &lt;b&gt;Detonator Pattern&lt;/b&gt; est l'utilisation des deux derniers chiffres d'une année lors de la manipulation et le calcul appliqué à des dates. La bombe est présente et n'attend qu'à faire son travail...


&lt;/div&gt;
&lt;h2&gt;






Fromage&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Fromage Pattern&lt;/b&gt; est souvent remplis de trous. Il consiste en une multitude de petites astuces qui rendent impossible toute portabilité du code. Généralement, plus il est vieux et plus il sent fort!

&lt;/div&gt;
&lt;h2&gt;






Flypaper&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;FlyPaper Pattern&lt;/b&gt; est écrit par une personne et maintenu par une autre. Cette dernière se retrouve alors coincé et préfèrerait périr avant de se perdre.

&lt;/div&gt;
&lt;h2&gt;






ePoxy&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
L'&lt;b&gt;ePoxy Pattern &lt;/b&gt;est visible dans les modules logiciels fortement couplés. Lorsque le couplage entre modules augmente, c'est qu'il y a souvent le pattern &lt;b&gt;ePoxy&lt;/b&gt; qui lie ces modules.

&lt;/div&gt;
&lt;h1&gt;






Misbehavioral Patterns&lt;/h1&gt;
Cette catégorie de Patterns en regroupe 11 :

&lt;br /&gt;
&lt;h2&gt;






Chain of Possibilities&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Chain of Possibilities Pattern &lt;/b&gt;est visible dans les gros modules peu documenté. Personne n'est sûr de l'étendu de ses fonctionnalités, mais ses possibilités semblent infinis. Il est aussi connu sous le nom de &lt;b&gt;Non-Deterministic Pattern&lt;/b&gt;.

&lt;/div&gt;
&lt;h2&gt;






Commando&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Commando Pattern&lt;/b&gt; est utilisé pour intervenir rapidement et faire que le travail soit fait. Ce pattern est capable de briser toutes les encapsultation afin d'accomplir sa mission. Il ne fait pas de prisonniers.

&lt;/div&gt;
&lt;h2&gt;






Intersperser&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
L'&lt;b&gt;Intersperser Pattern&lt;/b&gt; éparpille ses fonctionnalités dans tout le système, rendant impossible le test, la modification ou même la compréhension d'une fonction.

&lt;/div&gt;
&lt;h2&gt;






Instigator&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
L'&lt;b&gt;Instigator Pattern&lt;/b&gt; semble bénin mais permet de faire des ravages dans d'autres parties du système.

&lt;/div&gt;
&lt;h2&gt;






Momentum&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Momentum Pattern&lt;/b&gt; grossit de manière exponentielle, en taille, en besoin mémoire, en complexité et en temps d'exécution.

&lt;/div&gt;
&lt;h2&gt;






Medicator&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Medicator Pattern&lt;/b&gt; est un tel goulot d'étranglement en terme de performance pour le système que toute autre partie du système semble dopé aux stéroïdes.&lt;/div&gt;
&lt;h2&gt;






Absolver&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
L'&lt;b&gt;Absolver Pattern&lt;/b&gt; est visible dans des problème résolus par des anciens employés. Tant de problèmes historiques ont été résolus par le logiciel que les personnes présentes peuvent absoudre le logiciel de blâme en déclarant que l'&lt;b&gt;Absolver &lt;/b&gt;est responsable de tous les problèmes présents. Aussi connu sous le nom de "&lt;b&gt;It's not in my code&lt;/b&gt;".

&lt;/div&gt;
&lt;h2&gt;






Stake&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Stake Pattern&lt;/b&gt; est visible dans les problèmes dirigés par un logiciel écrit par une personne qui a, depuis lors, choisi la voie du management. Ainsi, même si de nombreux problèmes se produisent, l'auteur du pattern &lt;b&gt;Stake&lt;/b&gt; (qui est donc devenu manageur) empêchera quiconque de réécrire le logiciel sous prétexte qu'il est l'image de la réussite technique du manageur.

&lt;/div&gt;
&lt;h2&gt;






Eulogy&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
&lt;b&gt;L'Eulogy Pattern&lt;/b&gt; est présent dans tous les projets qui emploie les 22 autres Resign Patterns. Il est aussi connu sous le nom de &lt;b&gt;Post Mortem&lt;/b&gt;.

&lt;/div&gt;
&lt;h2&gt;






Tempest Method&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Tempest Method Pattern&lt;/b&gt; et utilisé dans les derniers jours qui précède la livraison du logiciel. Il est caractérisé par un manque de commentaires tout en introduisant un grand nombre de &lt;b&gt;Detonator Pattern&lt;/b&gt;.

&lt;/div&gt;
&lt;h2&gt;



Visitor From Hell&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Le &lt;b&gt;Visitor From Hell Pattern&lt;/b&gt; coïncide avec l'absence de contrôle sur le temps écoulé entre deux vérification d'un tableau. Ainsi, au moins une boucle de contrôle du système aura le pattern &lt;b&gt;Visitor From Hell&lt;/b&gt; qui surchagera les données critiques.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-5780995097419306614?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=QiZ60v4hx_g:lm0IslrC7So:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=QiZ60v4hx_g:lm0IslrC7So:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=QiZ60v4hx_g:lm0IslrC7So:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/5780995097419306614/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/12/resign-patterns-les-nouveaux-patterns.html#comment-form" title="2 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/5780995097419306614?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/5780995097419306614?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/12/resign-patterns-les-nouveaux-patterns.html" title="Resign Patterns : les nouveaux patterns" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-mP_z1e0Qo6M/TtiCRYS_PVI/AAAAAAAAAgQ/Dntolyd6oUg/s72-c/Fail.png" height="72" width="72" /><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;DE8HSXc_eSp7ImA9WhRSGEw.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-8219695535406099338</id><published>2011-11-20T18:51:00.001+01:00</published><updated>2011-11-20T20:20:38.941+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-20T20:20:38.941+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="avis" /><category scheme="http://www.blogger.com/atom/ns#" term="jms" /><title>Devoxx 2011 - What's probably coming in Java Message Service 2.0</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-FB-AoRLfOOs/Tsk-J2XdFUI/AAAAAAAAAgE/CpRpQXHqH5M/s1600/devoxx1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="123" src="http://4.bp.blogspot.com/-FB-AoRLfOOs/Tsk-J2XdFUI/AAAAAAAAAgE/CpRpQXHqH5M/s320/devoxx1.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La semaine dernière, j'ai eu la chance d'aller à Devoxx en Belgique à Anvers.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour ceux, qui ne connaissent pas, je vous invite à aller directement à la&amp;nbsp;pêche&amp;nbsp;aux informations sur le site :&amp;nbsp;&lt;a href="http://www.devoxx.com/display/DV11/Home"&gt;http://www.devoxx.com/&lt;/a&gt;&amp;nbsp;et même à vous y inscrire l'année prochaine et/ou même mieux... d'aller assister à &lt;b&gt;&lt;a href="http://devoxx.fr/"&gt;Devoxx France&lt;/a&gt;&lt;/b&gt;!!&lt;/div&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/II6XiGGlJX0" width="420"&gt;&lt;/iframe&gt;

&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Bon, sinon, pour revenir à nos moutons, cet article est un petit retour de la session de &lt;a href="http://www.devoxx.com/display/DV11/Nigel+Deakin"&gt;Nigel Deakin&lt;/a&gt; présentée à&amp;nbsp;&lt;a href="http://www.devoxx.com/display/DV11/Home"&gt;Devoxx&amp;nbsp;2011&lt;/a&gt;&amp;nbsp;et à laquelle j'ai assisté.&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Elle avait pour objectif de montrer l'avancée des travaux sur JMS 2.0 (&lt;em&gt;Java Message Service&lt;/em&gt;) aussi connu sous le doux nom de &lt;a href="http://jcp.org/en/jsr/detail?id=343"&gt;JSR 343&lt;/a&gt;. A ce jour, en version &lt;em&gt;early draft,&lt;/em&gt; elle devrait être intégrée à JEE7.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cet article a donc pour vocation de tenter de retranscrire ce que nous a présenté Nigel.&lt;/div&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div style="text-align: justify;"&gt;
Pour la repositionner dans son contexte, la JSR343 fait suite à JMS 1.1 (&lt;a href="http://www.jcp.org/en/jsr/detail?id=914"&gt;JSR 914&lt;/a&gt;) et a pour but de :
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Simplifier l'API de JMS :&lt;ul&gt;
&lt;li&gt;En utilisant CDI (&lt;em&gt;Context Dependency Injection&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;En clarifiant certaines&amp;nbsp;ambiguïtés présentes dans les spécifications.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Améliorer l'intégration de JMS avec les serveurs d'application :&lt;ul&gt;
&lt;li&gt;En intégrant plus facilement les problématiques de PaaS (Platform As A Service).&lt;/li&gt;
&lt;li&gt;En permettant le&amp;nbsp;&lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Multitenancy"&gt;multi-tenancy&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;En clarifiant ses relations avec les autres spécifications de JEE7 (ou même ultérieure) : cela est notamment vrai avec la partie MDB (&lt;em&gt;Message-Driven Beans&lt;/em&gt;) de la spécifications des EJB.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ajouter des nouvelles fonctionnalités à l'API.&lt;/li&gt;
&lt;/ul&gt;
Je ne reviendrai pas sur ce qu'est JMS (&lt;em style="text-align: justify;"&gt;Java Message Service&lt;/em&gt;&lt;span class="Apple-style-span" style="text-align: justify;"&gt;) si ce n'est que sa version actuelle est la 1.1 et qu'elle date de 2003, mais le fait que la spécification JMS n'ait pas évoluée depuis 2003, montre bien qu'elle était solide et qu'elle répondait bien à ce pour quoi elle avait été écrite.&lt;/span&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Cependant, autant il n'y a rien à redire quant à la réception d'un message, autant la partie émission était souvent verbeuse puisqu'il était nécessaire&amp;nbsp;pour émettre un message, dans le cas des EJB, de :&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;injecter les factory (&lt;em&gt;ConnectionFactory&lt;/em&gt; et &lt;em&gt;Destination&lt;/em&gt;) à l'aide de l'annotation &lt;em&gt;@Resource&lt;/em&gt;,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;créer la &lt;em&gt;Connection&lt;/em&gt; à l'aide de la &lt;em&gt;ConnectionFactory&lt;/em&gt;,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;créer la &lt;em&gt;Session&lt;/em&gt; à l'aide de la &lt;em&gt;Connection&lt;/em&gt;,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;créer le &lt;em&gt;MessageProducer&lt;/em&gt; à l'aide de la &lt;em&gt;Session&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align: justify;"&gt;
C'est seulement suite à toutes ces actions que l'émission d'un message était possible via la méthode &lt;em&gt;send()&lt;/em&gt;.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En outre, à cela, il fallait, bien sûr, gérer les exceptions &lt;em&gt;checkées&lt;/em&gt; (&lt;em&gt;JMSException&lt;/em&gt; pour ceux à qui cela parle ;-)) mais également la fermeture de la &lt;em&gt;Session&lt;/em&gt; et de la &lt;em&gt;Connection&lt;/em&gt;...&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Enfin, lors de l'utilisation conjointe de JMS et des EJB, certains paramètres de méthodes (notamment lors de la création de la &lt;em&gt;Session&lt;/em&gt;) étaient redondants car gérés par le conteneur EJB (&lt;em&gt;createSession(boolean transacted, int acknowledgeMode)&lt;/em&gt;).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Un des prérequis principals de cette nouvelle version de la spécification est donc la simplification... simplification mais pas à n'importe quel prix puisqu'il était nécessaire de conserver la rétro compatibilité avec les versions ultérieures de la spécification.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Nigel nous a donc présenté certaines des pistes qu'ils avaient (pistes encore ouvertes à discussion).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ce sont ces dernières que je vais essayer de retranscrire ci-dessous dans l'ordre dans lesquelles il les a énoncé.
&lt;/div&gt;
&lt;h1&gt;


Simplification sur la création de Sessions&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Afin de simplifier l'API de JMS pour créer une Session, Nigel nous a présenté deux pistes :&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;Ajout d'une méthode &lt;em&gt;createSession(SessionMode sessionMode)&lt;/em&gt; pour JavaSE où la classe SessionMode pourrait être une classe ayant comme variable d'instance le mode de transaction et le type d'acknowledge.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Ajout d'une méthode &lt;em&gt;createSession()&lt;/em&gt; qui serait utilisée et présente seulement pour JEE.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;


Supprimer la lourdeur des close()&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Afin de rendre moins verbeuse l'utilisation des &lt;em&gt;Connection&lt;/em&gt; et des &lt;em&gt;Session&lt;/em&gt;, une proposition plausible pourrait être de leur faire implémenter l'interface &lt;em&gt;java.lang.AutoCloseable&lt;/em&gt;.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ainsi, il serait alors possible d'avoir les résultats suivants (pour rappel, il ne s'agit que de propositions car cela est toujours à l'étude) :
&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;avec Java 7 dans un contexte JEE :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;@Resource(mappedName="...")
ContextFactory contextFactory;

@Resource(mappepdName="...")
Queue orderQueue;

public void sendMessage(String payload) {
  try (messagingContext mCtx = contextFactory.createContext() ;) {
    TextMessage textMessage = mCtx.createTextMessage(payload);
    mCtx.send(orderQueue, textMessage);
  }
}
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;avec CDI dans un contexte JEE :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;@Resource(mappedName="...")
Queue orderQueue;

@Inject
@MessagingContext(lookup="...")
MessagingContext mCtx;

@Inject
TextMessage textMessage;

public void sendMessage(String payload) {
  textMesage.setText(payload);
  mCtx.send(orderQueue, textMessage);
}
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;toujours avec Java 7 dans un contexte JEE :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;@Inject
@JMSConnection(lookup="...")
@JMSDestination(lookup="...")
MessageProducer producer;

@Inject
TextMessage textMessage;

public void sendMessage(String payload) {
  try {
    textMessage.setText(payload);
    producer.send(textMessage);
  } catch (JMSException e) {
    //todo
  }
}
&lt;/pre&gt;
&lt;h1&gt;


Autres simplifications&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Les autres&amp;nbsp;simplifications&amp;nbsp;d'API envisageables pourraient être :
&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;de ne pas à créer préalablement un objet de type &lt;i&gt;Message&lt;/i&gt; (ce qui pourrait permettrait de faire directement : &lt;em&gt;producer.send(String/Serializable);&lt;/em&gt; ). Cependant, ce type d'API ne permettrait pas de positionner des propriétés sur le message et ne serait pas adapter pour des messages de types &lt;em&gt;BytesMessage&lt;/em&gt; ou &lt;em&gt;StreamMessage&lt;/em&gt;. A ajouter à cela la question de son pendant pour la réception&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;de simplifier la gestion des &lt;em&gt;DurableSubscriber &lt;/em&gt;(&lt;a href="http://download.oracle.com/javaee/1.4/api/javax/jms/Session.html#createDurableSubscriber(javax.jms.Topic, java.lang.String)"&gt;http://download.oracle.com/javaee/1.4/api/javax/jms/Session.html#createDurableSubscriber(javax.jms.Topic, java.lang.String)&lt;/a&gt;), qui, au jour d'aujourd'hui, doivent obligatoirement&amp;nbsp;posséder un identifiant client et un nom de&amp;nbsp;souscription. Ces deux paramètres pourraient être rendus optionnels dans le cadre d'une utilisation conjointe avec les EJB 3.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;


Vers le futur...&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Autre que la simplification des APIs, Nigel nous a présenté ce que pourrait apporter JMS 2.0 dans nos besoins de demain.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ainsi, JMS 2.0 devra, pour répondre aux besoins des problématiques de type SaaS (&lt;em&gt;Software As A Service&lt;/em&gt;), permettre de déclarer ses ressources créées dans un serveur d'applications et de les&amp;nbsp;enregistrer dans un annuaire JNDI (comme c'est actuellement le cas pour les  DataSource).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour ce faire, de nouvelles annotations pourraient voir le jour (par exemple : &lt;em&gt;@JMSConnectionFactoryDefinition&lt;/em&gt; et &lt;em&gt;@JMSDestinationDefinition&lt;/em&gt;) mais également un &lt;a href="http://thecodersbreakfast.net/index.php?post/2008/12/26/Java-%3A-pr%C3%A9sentation-du-Service-Provider-API"&gt;SPI&lt;/a&gt; (&lt;em&gt;Service Provider Interface&lt;/em&gt;) pour le faire de manière programmatique.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Concernant une meilleure intégration avec les serveurs d'applications (ce qui permettrait d'utiliser n'importe quel JMS Provider dans n'importe quel serveur d'application JEE), Nigel propose la solution de JCA (&lt;em&gt;Java Connector Architecture&lt;/em&gt;), un peu comme ce qui existe avec le drivers de bases de données.
&lt;/div&gt;
&lt;h1&gt;


Nouvelles features&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Concernant les nouvelles &lt;em&gt;features&lt;/em&gt; de l'API, Nigel nous a ensuite présenté ce qui pourrait arriver, à savoir (en vrac) :
&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;l'émission de messages avec un&amp;nbsp;acquittement&amp;nbsp;asynchrone du serveur,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;la possibilité pour un client JMS d'utiliser des &lt;em&gt;Future&lt;/em&gt;,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;la possibilité d'émettre un message et de ne pas à avoir à attendre la réception d'un acquittement pour savoir si le message a bien été émis.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align: justify;"&gt;
Il se pourrait également que la propriété &lt;em&gt;JMSXDeliveryCount&lt;/em&gt; ne soit plus optionnelle, ce qui permettrait aux serveurs d'applications de mieux gérer le &lt;em&gt;flood.&amp;nbsp;&lt;/em&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
De même, la gestion des &lt;em&gt;Topics&lt;/em&gt; hiérarchiques pourraient être rendue obligatoire.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Enfin, une meilleure gestion des batch pourrait être possible via de nouvelles API comme par exemple l'introduction de la méthode &lt;em&gt;receive(Message[])&lt;/em&gt;.
&lt;/div&gt;
&lt;h1&gt;


Conclusion&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
En conclusion, je suis assez mitigé par cette session.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En effet, autant, je trouve que certaines propositions permettraient de rendre moins verbeuses l'utilisation de JMS, autant, je ne suis pas convaincu que pouvoir faire la même chose de différentes manières soit une bonne chose (et, cela, même si ça simplifie le travail du développeur...).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En outre, je trouve que, pour la majorité des propositions (même si elles sont totalement viables), l'axe de JEE est trop important.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Enfin, intégrer fortement CDI avec JMS m'embête un peu car cela nécessite de disposer d'un conteneur CDI, chose qui n'est pas toujours le cas dans un contexte Java SE et, même si je trouve CDI sexy, je ne pense pas que la majorité des développeurs ou que nos clients soient prêts à franchir le pas en raison de la complexité intrinsèque à CDI (bien sûr, JMS 2.0 se devait de se tourner vers le futur et CDI se devait d'être pris en compte)... enfin, il ne s'agit que d'un avis personnel... l'avenir nous dira ce qu'il en est... ;-)&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Dernier point (mais là encore, c'est totalement personnel), j'aurais aimé voir une intégration des notions d'EIP (&lt;i&gt;Enterprise Integration Pattern&lt;/i&gt;) même si la notion de &lt;i&gt;filter&lt;/i&gt; (au sens EIP du terme) sort un peu du scope de JMS mais bon... ;-) &lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour conclure, Nigel a bien présenté la direction que pourrait prendre JMS dans un futur proche mais, comme il nous l'a fréquemment fait remarquer, il ne s'agit que de pistes et, d'ailleurs, &lt;a href="http://java.net/projects/jms-spec/pages/Home"&gt;toutes les contributions sont les bienvenues&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-8219695535406099338?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=4AV5GvE9vR0:1VPxz4Eu2Ac:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=4AV5GvE9vR0:1VPxz4Eu2Ac:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=4AV5GvE9vR0:1VPxz4Eu2Ac:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/8219695535406099338/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/11/devoxx-2011-whats-probably-coming-in.html#comment-form" title="3 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/8219695535406099338?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/8219695535406099338?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/11/devoxx-2011-whats-probably-coming-in.html" title="Devoxx 2011 - What's probably coming in Java Message Service 2.0" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-FB-AoRLfOOs/Tsk-J2XdFUI/AAAAAAAAAgE/CpRpQXHqH5M/s72-c/devoxx1.jpg" height="72" width="72" /><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;CkUDRnw-fCp7ImA9WhRSF08.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-7603961998134843156</id><published>2011-11-14T09:00:00.000+01:00</published><updated>2011-11-19T17:31:17.254+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-19T17:31:17.254+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="cloudbees" /><category scheme="http://www.blogger.com/atom/ns#" term="avis" /><category scheme="http://www.blogger.com/atom/ns#" term="intégration continue" /><title>Petite découverte de CloudBees</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-F_mNTL2_BE4/TsACHNBk0fI/AAAAAAAAAdE/Ngcp8YNiDL0/s1600/cloudbees03.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="95" src="http://1.bp.blogspot.com/-F_mNTL2_BE4/TsACHNBk0fI/AAAAAAAAAdE/Ngcp8YNiDL0/s200/cloudbees03.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La semaine dernière, j'ai eu la chance d'assister à un atelier sur &lt;a href="http://www.cloudbees.com/"&gt;CloudBees&lt;/a&gt; chez nos amis de &lt;a href="http://blog.xebia.fr/"&gt;Xebia&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Ce dernier a été organisé avec brio par (je le fais par ordre alphabétique pour éviter tout favoritisme ;-) ) :&lt;/div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Eric Briand&lt;/li&gt;
&lt;li&gt;Simon Caplette&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/#%21/ndeloof"&gt;Nicolas De Loof&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/#%21/cyrilleleclerc"&gt;Cyrille Leclerc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/#%21/olim7t"&gt;Olivier Michallat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/#%21/jlrigau"&gt;Jean-Louis Rigau&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/#%21/eservent"&gt;Emmanuel Servent&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align: justify;"&gt;
Comme d'habitude, organisation bien rodée et atelier préparé aux petits oignons mais ce n'est pas le but de mon article...&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
L'objectif de cet article est, pour ceux qui n'étaient pas présents, de faire un rapide tour d'horizon de ce qui m'a marqué dans la solution qu'apporte Cloudbees avec ses offres DEV@Cloud et RUN@Cloud. Cet article sera&amp;nbsp;surtout focalisé sur la partie usine logicielle offerte par Cloudbees car c'est celle qui a été mise en avant pendant l'atelier et c'est aussi celle qui me semble la plus intéressante du point de vue de mes besoins actuels.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Je vais donc essayer de vous résumer ce que j'ai apprécié... Pour ce faire, je ne reviendrai pas sur le &lt;i&gt;usecase&lt;/i&gt; qui a été utilisé car je pense qu'il vaut mieux assister à l'atelier et qu'il faut bien laisser un peu de suspens... ;-). De même,&amp;nbsp;je ne parlerai ni de l'intérêt du &lt;i&gt;cloud&lt;/i&gt; ni de comment mettre en place DEV@Cloud ou RUN@Cloud.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cet article s'articulera donc en deux parties :&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;la première consistant en un très rapide retour sur ce que propose CloudBees,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;et la deuxième sur ce qui me plait dans une approche telle que celle proposée par CloudBees.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align: justify;"&gt;
&lt;u&gt;PS&lt;/u&gt; : au passage, encore un grand merci aux organisateurs de l'atelier!&lt;/div&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h1&gt;






{DEV,RUN}@Cloud?... Kesako?&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
CloudBees propose deux services DEV@Cloud et RUN@Cloud.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
DEV@Cloud offre, pour sa part, un service de type &lt;strike&gt;PaaS (&lt;i&gt;Platform As A Service&lt;/i&gt;)&lt;/strike&gt;&amp;nbsp;SaaS (&lt;i&gt;Software As A Service&lt;/i&gt;) qui offre un environnement de développement, de construction et de test en s'appuyant sur le &lt;i&gt;cloud&lt;/i&gt;.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
DEV@Cloud permet :&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;de collaborer avec d'autres personnes en s'appuyant sur des SCM/DVCS comme SVN ou Git,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;de construire, tester et déployer de manière continue avec &lt;a href="http://jenkins-ci.org/"&gt;Jenkins&lt;/a&gt;,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;de tester l'application web cible en s'appuyant sur le service à la demande &lt;a href="http://saucelabs.com/"&gt;SauceLab&lt;/a&gt;,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;de controler la qualité du code en s'appuyant sur &lt;a href="http://www.sonarsource.org/"&gt;Sonar&lt;/a&gt;,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;de gérer les&amp;nbsp;artéfacts&amp;nbsp;en utilisant &lt;a href="http://www.jfrog.com/products.php"&gt;Artifactory&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align: justify;"&gt;
RUN@Cloud fournit, quant à lui, un ensemble d'outils permettant de simplifier le processus de déploiement d'une application Java dans le &lt;i&gt;cloud&lt;/i&gt;. Il correspond, pour sa part, un service de type&amp;nbsp;PaaS (&lt;i&gt;Platform As A Service&lt;/i&gt;).&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-aGeioKNPLJc/TsACXTWxgJI/AAAAAAAAAdM/yG4C8B3PmOA/s1600/cloudbees04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="135" src="http://1.bp.blogspot.com/-aGeioKNPLJc/TsACXTWxgJI/AAAAAAAAAdM/yG4C8B3PmOA/s400/cloudbees04.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
&lt;u&gt;PS&lt;/u&gt; : vous aurez remarqué que, pour cette partie, je ne me suis pas trop foulé puisque je n'ai fait que reprendre les informations présentes sur le site... ;-)&lt;/div&gt;
&lt;h1&gt;






C'est bien gentil tout ça et moi, ça m'apporte quoi?&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Comme vous avez pu le constater, DEV@Cloud et RUN@Cloud fournissent tout pleins de services.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cependant, la première question qui me vient à l'esprit quand je vois tout ça, c'est :&amp;nbsp;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
"ben, je fais pareil dans mon usine logicielle... : pourquoi je m'embêterai à payer une solution et surtout, pourquoi serais-je prêt à perdre la main sur mon infra mais aussi qu'on m'enlève l'occasion de m'amuser avec de nouveaux jouets..."&amp;nbsp;&lt;/blockquote&gt;
&lt;div style="text-align: justify;"&gt;
(pour le dernier argument, cela ne regarde que moi... ;-))&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-dDnr_qH0vM0/TsACyBmfmsI/AAAAAAAAAdU/TI3TYA-Ujmc/s1600/Cloudbees01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="283" src="http://2.bp.blogspot.com/-dDnr_qH0vM0/TsACyBmfmsI/AAAAAAAAAdU/TI3TYA-Ujmc/s400/Cloudbees01.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
En fait, les réponses sont simples (et je ne parlerai pas des réponses évidentes de coûts -infra, supervision, maintenance, etc.-).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Déjà revenons sur les possibilités offertes par DEV@Cloud (je n'aborderai pas le fait que CloudBees propose également l'hébergement du SCM, du Repository Manager et de Sonar) :&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En offrant la partie orchestrateur (via Jenkins), on délègue au &lt;i&gt;cloud&lt;/i&gt;&amp;nbsp;le soin de gérer les agents de build. Ainsi, il n'y a plus à administrer la ferme de serveurs succeptibles d'héberger les agents (tâche assez réberbative et ingrate).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
De plus, en combinant la partie &lt;i&gt;build&lt;/i&gt;/&lt;i&gt;package&lt;/i&gt; à la partie RUN@Cloud permettant de déployer de manière continue l'application sur une instance dédiée, cela permet de tester fonctionnellement et de manière intégrer la solution. Encore une fois, en passant par un service de CloudBees, il n'y a plus à se soucier de devoir réserver un serveur ou de devoir déployer un conteneur de servlets puisque cela est fait pour nous.&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Concernant les tests à proprement parler, CloudBees offre une intégration avec &lt;a href="http://saucelabs.com/"&gt;SauceLab&lt;/a&gt; qui se charge de l'exécution des tests Selenium (ie. qui prends à sa charge l'installation des agents Selenium ainsi que leurs configurations en mettant à disposition les browsers (butineurs ;-)) nécessaires à l'exécution des tests Selenium). En outre, SauceLab propose même la vidéo du test exécuté permettant, ainsi,&amp;nbsp;&lt;i&gt;a postériori&lt;/i&gt; d'analyser ce qui a échoué pendant le test. Bien sûr, DEV@Cloud n'offre pas encore la décorrélation entre le test fonctionnel exécuté et la partie vue mais, coté infrastructure, il n'y a plus à se soucier des agents et coté analyse, il n'est plus nécessaire d'analyser les rapports &lt;i&gt;surefire&lt;/i&gt; pour connaitre le test en échec.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Il est également possible d'effectuer un test de charge en s'appuyant sur le plugin maven &lt;a href="http://jmeter.apache.org/"&gt;JMeter&lt;/a&gt;&amp;nbsp;en ciblant l'instance déployée dans RUN@Cloud.&amp;nbsp;L'intégration avec le service&amp;nbsp;&lt;a href="http://newrelic.com/"&gt;New Relic&lt;/a&gt;&amp;nbsp;offre la possibilité de superviser l'activité de l'instance afin d'évaluer son comportement.&amp;nbsp;En outre, en configurant RUN@Cloud de manière &lt;i&gt;scalable&lt;/i&gt;, il est aisé de tester la charge supportée par de multiples instances (pour ce faire, CloudBees passe par un &lt;i&gt;load balancer&lt;/i&gt; qui, si je ne me trompe pas, fonctionne, à ce jour, en &lt;i&gt;round-robin&lt;/i&gt;). L'intégration du service New Relic permet de s'abstraire de la mise en place d'une solution comme Hyperic sur un environnement de recette, chose qui manque régulièrement et qui peut être consommateur en temps. En outre, New Relic permet même de déterminer les points de contension en offrant la possibilité d'activer un profiling à chaud dans l'application cible.&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Concernant le comportement applicatif, l'intégration du service &lt;a href="https://papertrailapp.com/"&gt;Papertrail&lt;/a&gt;&amp;nbsp;offre la possibilité d'accéder aux logs de l'application mais permet également d'agréger les logs pour l'ensemble des instances et de les analyser. Ce dernier point est généralement manquant lors de la mise en place d'un environnement de test/validation/recette pour des questions d'infrastructure mais également de moyen. Aussi, disposer d'un tel service intégré avec l'offre RUN@Cloud dans un contexte de test (mais, bien sûr, pas uniquement) apporte un réel plus dans l'analyse des anomalies et du comportement de l'application.&lt;/div&gt;
&lt;h1&gt;






Conclusion&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Vous l'aurez compris (enfin, je l'espère), les offres DEV@Cloud et RUN@Cloud de CloudBees m'ont vraiment fait bonne impression. Je n'ai fait qu'effleurer les possibilités offertes et je suis sûrement passé à coté de beaucoup de &lt;i&gt;features&lt;/i&gt; mais je tenais tout de même à partager mon ressenti sur ces offres.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
C'est vrai que mon article est très orienté usine logicielle (peut être parce que c'est justement le point de départ de l'atelier) mais, au moins pour ce seul point, il mérite qu'on s'intéresse aux services offerts par CloudBees (et services, il y en a...).&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-Nws_YjWNluM/TsAC_MmnpzI/AAAAAAAAAdc/W78rV1GiHns/s1600/cloudbees02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/-Nws_YjWNluM/TsAC_MmnpzI/AAAAAAAAAdc/W78rV1GiHns/s400/cloudbees02.png" width="231" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Cependant, il reste un point qui me chagrine... en effet, CloudBees offre une excellente forge logicielle clé en main et qui semble parfaitement fonctionnelle mais, à mon sens, ce qui manque le plus est la bonne utilisation de ces outils et surtout, en amont, la bonne compréhension de ce qu'est une bonne usine logicielle et de son importance.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Bien sûr, si le client est réticent, il est toujours possible de faire une approche &lt;i&gt;bottom/up&lt;/i&gt;&amp;nbsp;en attaquant par la forge et en lui montrant le gain mais, je trouve cela dommage que l'on soit obligé d'en arriver là alors qu'il devrait en voir tout le bénéfice (un peu comme maitriser son livrable et son build ou le cycle de vie de son application...) surtout dans un contexte où &lt;i&gt;l'agilité&lt;/i&gt;&amp;nbsp;est un terme de plus en plus courant et qui prone des livraisons fréquentes, chose possible que si l'on dispose d'une bonne méthodologie, d'une bonne forge et que l'on a compris de l'intérêt des TUs, du refactoring et de la revue de code...&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Enfin, je m'égare... ;-)&lt;br /&gt;
Pour revenir à nos moutons, ce que j'ai apprécié avec DEV@Cloud et RUN@Cloud est la grande intéraction et la modularisation des services avec Jenkins. Cependant, même si la solution offerte par CloudBees est de qualité et est simple à mettre en oeuvre en étant clé en main, il reste du ressort de l'équipe de mettre en place les bonnes pratiques pour construire l'usine logicielle sans lesquelles aussi bon que soient les outils et services à sa disposition, cela s'achèvera par un échec (enfin, là, il s'agit de mon humble avis... ;-)).&lt;br /&gt;
&lt;br /&gt;
Pour finir, je tiens à préciser que je n'ai pas testé de manière plus approfondie les différents services offerts par CloudBees autre que ce qui nous a été présenté lors de l'atelier et j'espère ne pas avoir dénaturé le produit. Si des points étaient à ajouter, n'hésitez pas à m'en faire part afin de pouvoir compléter l'approche&amp;nbsp;naïve&amp;nbsp;que je pourrais en avoir ;-)&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
A noter&amp;nbsp;aussi que concernant l'injection de charge, à ce jour, il n'existe pas de possibilité de &lt;i&gt;scaler&lt;/i&gt; les injecteurs dans différents agents, ce qui limite l'intérêt de l'injection (je ne reviendrai pas sur le fait que si l'injecteur est saturé, cela fausse les résultats obtenus pour le SUT (&lt;i&gt;System Under Test&lt;/i&gt;)) mais que cela devrait être résolu dans un futur proche.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;u&gt;PS&lt;/u&gt; : Je tenais aussi à préciser que je ne touche rien pour ce post mais que cela me faisait plaisir de parler d'un truc que j'ai apprécié (et puis je fais ce qui me chante avec mon blog... !! ;-) ) et puis aussi à remercier Stéphanie pour avoir consacré du temps à relire cet article et m'avoir apporté son esprit critique ;-)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-7603961998134843156?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=ptvGLil7d-Q:C1K71K-6BYI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=ptvGLil7d-Q:C1K71K-6BYI:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=ptvGLil7d-Q:C1K71K-6BYI:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/7603961998134843156/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/11/petite-decouverte-de-cloudbees.html#comment-form" title="4 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/7603961998134843156?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/7603961998134843156?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/11/petite-decouverte-de-cloudbees.html" title="Petite découverte de CloudBees" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-F_mNTL2_BE4/TsACHNBk0fI/AAAAAAAAAdE/Ngcp8YNiDL0/s72-c/cloudbees03.png" height="72" width="72" /><thr:total>4</thr:total></entry><entry gd:etag="W/&quot;DEcMRHw8fyp7ImA9WhdaF0Q.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-88100188599877394</id><published>2011-10-20T00:53:00.000+02:00</published><updated>2011-10-28T12:01:25.277+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-28T12:01:25.277+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="divers" /><title>FuseSource Community Day 2011</title><content type="html">&lt;div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-MCxyo51Js9s/Tp9Ovki7AQI/AAAAAAAAAcc/6wlTc_Wq_mg/s1600/FuseCommunityDay03.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="236" src="http://2.bp.blogspot.com/-MCxyo51Js9s/Tp9Ovki7AQI/AAAAAAAAAcc/6wlTc_Wq_mg/s320/FuseCommunityDay03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ce jeudi 13 octobre dernier a eu lieu la troisième édition du FuseSource Community Day à la Défense.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour ceux qui ne connaissent pas la société &lt;a href="http://fusesource.com/"&gt;FuseSource&lt;/a&gt;, il s'agit, en fait, du nouveau nom de Iona et c'est une société spécialisée dans l'open source qui propose un ensemble de produits packagés et intégrés de différentes solutions de la fondation &lt;a href="http://apache.org/"&gt;Apache&lt;/a&gt;.&lt;/div&gt;
&lt;a name='more'&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Parmi ces produits, on peut y trouver :
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://cxf.apache.org/"&gt;Apache CXF&lt;/a&gt;&amp;nbsp;(Fuse Service Framework)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://servicemix.apache.org/home.html"&gt;Apache ServiceMix&lt;/a&gt;&amp;nbsp;(Fuse ESB)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://activemq.apache.org/"&gt;Apache ActiveMQ&lt;/a&gt;&amp;nbsp;(Fuse Message Broker)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://camel.apache.org/"&gt;Apache Camel&lt;/a&gt;&amp;nbsp;(Fuse Mediation Router)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-S69Ivzc92UU/Tp9O7SJIdJI/AAAAAAAAAck/9c-fMf6vfe4/s1600/FuseCommunityDay02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="116" src="http://2.bp.blogspot.com/-S69Ivzc92UU/Tp9O7SJIdJI/AAAAAAAAAck/9c-fMf6vfe4/s320/FuseCommunityDay02.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En fait, si elle propose un package gratuit de ces différents produits, elle offre également un support ainsi que l'accompagnement aux personnes ou entreprises qui le souhaitent en offrant différentes formules. &lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-FyqrGXvCEWU/Tp9O_0y1B9I/AAAAAAAAAcs/m2VkfByPAVQ/s1600/subscriptions_web.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/-FyqrGXvCEWU/Tp9O_0y1B9I/AAAAAAAAAcs/m2VkfByPAVQ/s200/subscriptions_web.JPG" width="198" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Cet accompagnement est d'autant plus crédible que la société participe activement à ces framework puisqu'elle compte en son sein de nombreux commiteurs/créateurs de ces framework, ce qui permet de bénéficier d'une vrai expertise mais, aussi, d'être assurée que les corrections seront bien reversées à la communauté (ça c'est mon coté geek qui parle... ;-) ).&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Pour revenir au FuseSource Community Day, il s'agit d'une journée de conférences allant de la présentation/démonstration des dernières &lt;i&gt;features&lt;/i&gt; d'un produit aux annonces de &lt;i&gt;Roadmap&lt;/i&gt; en passant par des retours clients.&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Vous l'aurez compris, ayant eu l'opportunité d'y participer, je tenais à remercier grandement FuseSource pour cette excellente journée que j'ai passée en leur compagnie : c'était une journée passionnante où j'ai eu la chance de rencontrer quelques-uns des créateurs/commiteurs de ces produits et où j'ai pu assister à des présentations de qualité.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Coté programme, voilà ce que vous avez manqué :
&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;&lt;a href="http://blog.soat.fr/2011/10/fusesource-community-day-des-enterprise-integration-patterns-eips-vers-la-production-avec-apache-camel/"&gt;Des "Enterprise Integration Patterns" (EIPS) vers la Production avec Apache Camel&lt;/a&gt; par &lt;a href="http://twitter.com/#%21/davsclaus"&gt;Claus Ibsen&lt;/a&gt; et &lt;a href="http://twitter.com/#%21/jstrachan"&gt;James Strachan&lt;/a&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;a href="http://blog.soat.fr/2011/10/fusesource-community-day-presentation-client-et-retour-d%e2%80%99experience-par-atos-worldline-et-capgemini/"&gt;Présentation client et retour d’expérience&lt;/a&gt; : Atos Worldline&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;a href="http://blog.soat.fr/2011/10/fusesource-community-day-presentation-client-et-retour-d%e2%80%99experience-par-atos-worldline-et-capgemini/"&gt;Présentation client et retour d’expérience&lt;/a&gt; : CapGemini pour le Ministère de l'Education Nationale&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;a href="http://blog.soat.fr/2011/10/fusesource-community-day-integration-open-source-et-messagerie-avec-fuseesbapache-servicemix/"&gt;Intégration Open Source et messagerie avec FuseESB/Apache ServiceMix&lt;/a&gt; par &lt;a href="http://twitter.com/#%21/gnodet"&gt;Guillaume Nodet&lt;/a&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;a href="http://blog.soat.fr/2011/10/fusesource-community-day-outil-fuse-ide-et-la-strategie-fuse-fabric/"&gt;Outil Fuse IDE et la stratégie Fuse Fabric&lt;/a&gt; par &lt;a href="http://twitter.com/#%21/cmoulliard"&gt;Charles Mouillard&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-Q7z-geUL0W0/Tp9S_k5C4fI/AAAAAAAAAc0/6wZCoU_kNqk/s1600/camelone_banner-noreg.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="99" src="http://1.bp.blogspot.com/-Q7z-geUL0W0/Tp9S_k5C4fI/AAAAAAAAAc0/6wZCoU_kNqk/s320/camelone_banner-noreg.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Normalement des comptes-rendus de quelques-unes des sessions seront bientôt accessible sur le blog de &lt;a href="http://blog.soat.fr/"&gt;So@t&lt;/a&gt; et je mettrai les liens dès qu'ils seront diffusés. 
&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
PS : Je tenais aussi à préciser que je ne touche rien pour ce post mais que cela me faisait plaisir de parler d'une société full open source ;-) &lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
PS2 : Pour ceux qui me connaissent et qui savent que je n'aime pas Apache Camel (cf. &lt;a href="http://jetoile.blogspot.com/2010/03/spring-integration-vs-apache-camel.html"&gt;ici&lt;/a&gt;), cela n'a pas changé mais je veux bien admettre qu'il faut parfois savoir replacer le métier en avant et pas juste faire ses choix en fonction de l'architecture intrinsèque d'un produit ou parce qu'on trouve qu'une API n'est pas assez sexy... ;-)&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Par contre, j'ai trouvé bluffante la présentation sur &lt;a href="http://fabric.fusesource.org/"&gt;Fuse Fabric&lt;/a&gt;&amp;nbsp;et je vous invite vraiment à aller y jeter un oeil...&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-88100188599877394?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=_WYrLBrAsDk:9bCmC7sEgDg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=_WYrLBrAsDk:9bCmC7sEgDg:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=_WYrLBrAsDk:9bCmC7sEgDg:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/88100188599877394/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/10/fusesource-community-day-2011.html#comment-form" title="2 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/88100188599877394?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/88100188599877394?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/10/fusesource-community-day-2011.html" title="FuseSource Community Day 2011" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-MCxyo51Js9s/Tp9Ovki7AQI/AAAAAAAAAcc/6wlTc_Wq_mg/s72-c/FuseCommunityDay03.png" height="72" width="72" /><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;DEABRns7eSp7ImA9WhdUEkk.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-7872211006548341078</id><published>2011-09-28T23:51:00.000+02:00</published><updated>2011-09-28T23:52:37.501+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-28T23:52:37.501+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="divers" /><title>Nouveaux thèmes Blogger</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-TgYvIXQcFyU/ToOQTt_-EOI/AAAAAAAAAbg/6wPciCJZTYQ/s1600/blogger.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="198" src="http://2.bp.blogspot.com/-TgYvIXQcFyU/ToOQTt_-EOI/AAAAAAAAAbg/6wPciCJZTYQ/s200/blogger.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour une fois, ce post n'a pas pour objectif de parler d'une technologie ou d'un évènement en particulier, mais juste d'introduire une nouvelle fonctionnalité de la plateforme de blog Blogger. &lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En effet, il vient d'être offert&amp;nbsp;aux utilisateurs de cette plateforme,&amp;nbsp;la possibilité d'appliquer un thème dit "&lt;i&gt;dynamique&lt;/i&gt;". En fait, il existe 7 thèmes différents qui ont la particularité d'être assez sobres.&lt;/div&gt;
Pour plus d'informations, je vous renvoie vers le &lt;a href="http://googlefrance.blogspot.com/2011/09/les-affichages-dynamiques-sept.html?spref=bl"&gt;blog officiel&lt;/a&gt;&amp;nbsp;de Google France. &lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
En attendant que des utilisateurs en appliquent un, il est possible de prévisualiser tous les blogs sous Blogger avec ces derniers afin de se faire une idée du rendu de vos sites préférés ;-) &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Si on prends l'exemple du mien, vous pouvez vous faire une idée du rendu en allant sur l'url suivante (attention, il semble que cela ne fonctionne pas sous chrome - en tout cas la version sous linux - ) :&lt;br /&gt;
&lt;a href="http://jetoile.blogspot.com/view/sidebar"&gt;http://jetoile.blogspot.com/view/sidebar&lt;/a&gt; 
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-eCaYPvYCSo8/ToOUA945zEI/AAAAAAAAAbo/QPpZT1KkZFY/s1600/01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://2.bp.blogspot.com/-eCaYPvYCSo8/ToOUA945zEI/AAAAAAAAAbo/QPpZT1KkZFY/s400/01.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-ufMavP_v1g8/ToOUEu8wI1I/AAAAAAAAAbw/vNNiT_hleFA/s1600/02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://4.bp.blogspot.com/-ufMavP_v1g8/ToOUEu8wI1I/AAAAAAAAAbw/vNNiT_hleFA/s400/02.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Du coup, j'en profite pour faire un petit sondage... :&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Préférez-vous que mon blog reste avec le thème actuel ou que je lui donne un petit coup de jeune (et dans ce cas, certaines parties risques d'être dégradées).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Je vous laisse y répondre via les commentaires.
&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
S'il n'y a pas de réponses - ce qui est fort probable... - , je ferai selon mes humeurs ;-)&amp;nbsp;&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-7872211006548341078?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=6I3dKdr9Wec:_yUmPeb056w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=6I3dKdr9Wec:_yUmPeb056w:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=6I3dKdr9Wec:_yUmPeb056w:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/7872211006548341078/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/09/nouveaux-themes-blogger.html#comment-form" title="1 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/7872211006548341078?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/7872211006548341078?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/09/nouveaux-themes-blogger.html" title="Nouveaux thèmes Blogger" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-TgYvIXQcFyU/ToOQTt_-EOI/AAAAAAAAAbg/6wPciCJZTYQ/s72-c/blogger.jpg" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;A0QDSXo5fyp7ImA9WhdUEEg.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-4627500353991057353</id><published>2011-09-26T19:49:00.000+02:00</published><updated>2011-09-26T19:49:38.427+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-26T19:49:38.427+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jmx" /><category scheme="http://www.blogger.com/atom/ns#" term="jetty" /><category scheme="http://www.blogger.com/atom/ns#" term="maven" /><title>Jetty, Maven et JMX</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-bGP4Fnvfp1s/TnEtqz-UNkI/AAAAAAAAAa4/KBXNM8QXHKc/s1600/logoArticle.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="162" src="http://2.bp.blogspot.com/-bGP4Fnvfp1s/TnEtqz-UNkI/AAAAAAAAAa4/KBXNM8QXHKc/s320/logoArticle.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Vous avez peut être remarqué que ces derniers temps, j'étais très Maven et JMX. Cet article ne déroge pas à la règle puisque je vais parler de... Maven et de JMX. &lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Enfin pour être plus précis, je vais montrer comment il est facilement possible de déployer une application web dans le conteneur embarqué Jetty via Maven en activant la couche JMX afin de pouvoir tester de manière intégrée cette couche.&lt;/div&gt;
Pour ce faire, je présenterai dans un premier temps le contexte, puis comment cela peut être mise en œuvre. &lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Bien sûr, cet article montre comment j'ai fait mais il ne représente pas la seule manière de faire... ;-). En outre, il ne présente rien de novateur mais je me suis dit que cela pouvait toujours être utile afin d'éviter de faire perdre du temps à d'autres personnes.
&lt;/div&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h1&gt;


Contexte&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Ce paragraphe présente mes motivations pour avoir eu un besoin d'une utilisation d'un Jetty embedded à Maven en activant la couche JMX car, c'est vrai, ce n'est pas un besoin très courant et qu'il peut même sembler, au premier abord, paraitre un peu stupide (en effet, utiliser un Jetty embedded répond plutôt à un besoin de poste de développement ou au pire (et je dis bien au pire!!) à un pseudo TU qui n'est, du coup, pas un TU... (ndlr : enfin, encore une fois, je diverge... ;-) )).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En fait, pour les besoins d'une démonstration, je voulais juste présenter une petite application web qui remontait des métriques via JMX. 
N'ayant pas foncièrement envie d'avoir à décompresser un Jetty sur mon poste, je me suis dit qu'un Jetty embedded dans Maven suffisait largement à ma petite démo.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En outre, cela offrait également la possibilité à n'importe qui de rejouer la démo sans avoir à installer localement un conteneur de Servlets et sans à avoir à modifier le paramétrage de ce dernier pour activer la couche JMX de la JVM.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
L'application web utilisée pour ce petit POC est assez basique puisqu'il ne s'agit que d'un simple Servlet redirigeant vers une simple jsp. &lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ce Servlet incrémentera un compteur exposé en JMX afin de fournir cette métrique basique à la couche de supervision.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Spring 3 sera également utilisé pour lier le tout... &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
En fait, si vous me demandez pourquoi j'ai branché Spring pour une application ausi simple, c'est, en fait, que JMX n'était pas le seul composant que je voulais montrer pendant la petite démonstration...&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Si vous avez l'esprit chagrin et que vous me re-demandez pourquoi je n'ai pas utilisé un aspect, c'est que l'aspect était justement l'autre aspect de ma démo ;-).
&lt;/div&gt;
&lt;h1&gt;


Mise en œuvre&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Pour ce paragraphe de mise en œuvre, je présenterai successivement :
&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;Le code de l'application web utilisé.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;La configuration Maven utilisée permettant de démarrer l'application web dans un Jetty embedded.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Les subtilités de la configuration à effectuer pour ajouter la couche JMX.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;


Application web cible&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Comme annoncé précédemment, notre application web cible se compose de :
&lt;/div&gt;
&lt;ul&gt;
&lt;li style="text-align: justify;"&gt;un Servlet,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;une page JSP,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;un POJO utilisé par Spring pour la partie MBean (Spring aura, à sa charge, sa &lt;i&gt;proxification&lt;/i&gt; en MBean Standard et son enregistrement au sein du MBean Server),
&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;un fichier de configuration web.xml,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;et un fichier de contexte Spring.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align: justify;"&gt;
Il est à noter qu'elle utilisera la spécification 2.5 des Servlets afin de permettre, dans les parties suivantes, de montrer la différence de configuration qu'il existe entre Jetty 6 et 7.
&lt;/div&gt;
&lt;h3&gt;


Code du Servlet&lt;/h3&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class SimpleServlet extends HttpServlet {
    private static Logger LOGGER = LoggerFactory.getLogger(SimpleServlet.class);

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ApplicationContext beanFactory = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
        SimpleCounter jmxTestBean = beanFactory.getBean("simpleCounter", SimpleCounter.class);
        jmxTestBean.inc();

        req.setAttribute("nbInvocation", jmxTestBean.getNbGet());

        RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/simpleDisplay.jsp");
        if (dispatcher != null) {
            dispatcher.forward(req, resp);
        } else {
            LOGGER.warn("unable to get the request dispatcher");
        }
    }
}
&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
On constate que le Servlet est basique. Il n'y a donc rien à dire dessus si ce n'est la récupération du POJO &lt;i&gt;proxifié&lt;/i&gt; par Spring pour incrémenter un compteur qui sera exposé en JMX.

&lt;/div&gt;
&lt;h3&gt;


Code du POJO utilisé comme MBean Standard&lt;/h3&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class SimpleCounter {
    private int nbGet = 0;

    public void inc() {
        this.nbGet++;
    }

    public void setNbGet(int nbGet) {
        this.nbGet = nbGet;
    }

    public int getNbGet() {
        return nbGet;
    }
}
&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
Concernant le POJO, rien de spécial non plus à remarquer. Juste à noter que les setter et getter sont nécessaires afin de rendre l'attribut nbGet accessible en lecture/écriture par la couche cliente JMX.
&lt;/div&gt;
&lt;h3&gt;


Code de la jsp&lt;/h3&gt;
&lt;pre class="brush:html; wrap-lines: false; auto-links: false"&gt;&amp;lt;%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%&amp;gt;
&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&amp;gt;
        &amp;lt;title&amp;gt;simple display&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;This is a simple display&amp;lt;/h1&amp;gt;
        Has been invoked: ${nbInvocation} times
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
Rien de particulier non plus à dire sur la jsp...
&lt;/div&gt;
&lt;h3&gt;


Code du web.xml&lt;/h3&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&amp;lt;web-app version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemalocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&amp;gt;
	&amp;lt;context-param&amp;gt;
		&amp;lt;param-name&amp;gt;contextConfigLocation&amp;lt;/param-name&amp;gt;
		&amp;lt;param-value&amp;gt;classpath:applicationContext*.xml&amp;lt;/param-value&amp;gt;
	&amp;lt;/context-param&amp;gt;
	&amp;lt;listener&amp;gt;
		&amp;lt;listener-class&amp;gt;org.springframework.web.context.ContextLoaderListener&amp;lt;/listener-class&amp;gt;
	&amp;lt;/listener&amp;gt;

	&amp;lt;servlet&amp;gt;
		&amp;lt;servlet-name&amp;gt;SimpleServlet&amp;lt;/servlet-name&amp;gt;
		&amp;lt;servlet-class&amp;gt;fr.jetoile.demo.servlet.SimpleServlet&amp;lt;/servlet-class&amp;gt;
		&amp;lt;init-param&amp;gt;
			&amp;lt;param-name&amp;gt;sleep-time-in-seconds&amp;lt;/param-name&amp;gt;
			&amp;lt;param-value&amp;gt;10&amp;lt;/param-value&amp;gt;
		&amp;lt;/init-param&amp;gt;
		&amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
	&amp;lt;/servlet&amp;gt;

	&amp;lt;servlet-mapping&amp;gt;
		&amp;lt;servlet-name&amp;gt;SimpleServlet&amp;lt;/servlet-name&amp;gt;
		&amp;lt;url-pattern&amp;gt;/sample&amp;lt;/url-pattern&amp;gt;
	&amp;lt;/servlet-mapping&amp;gt;
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
Le fichier descripteur web.xml est classique donc rien de nouveau sur les tropiques ;-).
Comme dit plus haut, c'est ici la version 2.5 des servlets qui est utilisée afin de permettre un choix plus important de conteneurs de Servlets. 

&lt;/div&gt;
&lt;h3&gt;


Code du contexte Spring&lt;/h3&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&amp;lt;beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"&amp;gt;
	&amp;lt;bean class="org.springframework.jmx.support.MBeanServerFactoryBean" id="mbeanServer"&amp;gt;
		&amp;lt;property name="locateExistingServerIfPossible" value="true"&amp;gt;&amp;lt;/property&amp;gt;
	&amp;lt;/bean&amp;gt;

	&amp;lt;bean class="org.springframework.jmx.export.MBeanExporter" id="exporter"&amp;gt;
		&amp;lt;property name="beans"&amp;gt;
			&amp;lt;map&amp;gt;
				&amp;lt;entry key="bean:application=jmx-sample,name=simpleCounter" value-ref="simpleCounter"&amp;gt;&amp;lt;/entry&amp;gt;
			&amp;lt;/map&amp;gt;
		&amp;lt;/property&amp;gt;
 		&amp;lt;property name="server" ref="mbeanServer"&amp;gt;&amp;lt;/property&amp;gt;
	&amp;lt;/bean&amp;gt;

	&amp;lt;bean class="fr.jetoile.demo.jmx.SimpleCounter" id="simpleCounter"&amp;gt;&amp;lt;/bean&amp;gt;
&amp;lt;/beans&amp;gt;
&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
Concernant le fichier descripteur de Spring, on constate que la classe MBeanServerFactoryBean de Spring est utilisée comme moyen de récupération/création du MBeanServer et que c'est le MBeanExporter qui a la charge de l'enregistrement du MBean injecté.

&lt;/div&gt;
&lt;h2&gt;


Application web exécutable via Jetty au sein de Maven&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Afin de permettre une exécution de notre application web dans un Jetty embedded dans Maven, il faut, bien sûr, une structure Maven.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Elle est la suivante :&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-q2jJEYSygfg/TnErFlaNEDI/AAAAAAAAAag/2vgwO_zYc6A/s1600/jmx-sample-tree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="275" src="http://3.bp.blogspot.com/-q2jJEYSygfg/TnErFlaNEDI/AAAAAAAAAag/2vgwO_zYc6A/s320/jmx-sample-tree.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Concernant le fichier descripteur pom.xml, il contiendra, bien sûr, le plugin nécessaire au lancement de jetty.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Afin d'être plus exhaustif, dans notre POC, deux profils Maven seront utilisés afin de pouvoir spécifier la version de Jetty à utiliser (le choix sera laissé entre Jetty 6 et 7). En outre, le port d'écoute est forcé à 9090 :
&lt;/div&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&amp;gt;
	&amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
	&amp;lt;groupId&amp;gt;fr.jetoile.demo&amp;lt;/groupId&amp;gt;
	&amp;lt;artifactId&amp;gt;jmx-sample&amp;lt;/artifactId&amp;gt;
	&amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;
	&amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;

	&amp;lt;properties&amp;gt;
		&amp;lt;java.version&amp;gt;1.5&amp;lt;/java.version&amp;gt;
		&amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;

		&amp;lt;slf4j.version&amp;gt;1.6.1&amp;lt;/slf4j.version&amp;gt;
		&amp;lt;logback.version&amp;gt;0.9.27&amp;lt;/logback.version&amp;gt;
		&amp;lt;commons-lang.version&amp;gt;2.5&amp;lt;/commons-lang.version&amp;gt;
		&amp;lt;spring.version&amp;gt;3.0.6.RELEASE&amp;lt;/spring.version&amp;gt;
		&amp;lt;servlet.version&amp;gt;2.5&amp;lt;/servlet.version&amp;gt;
	&amp;lt;/properties&amp;gt;

	&amp;lt;dependencies&amp;gt;
		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;ch.qos.logback&amp;lt;/groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;logback-classic&amp;lt;/artifactId&amp;gt;
			&amp;lt;version&amp;gt;${logback.version}&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;
		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;org.slf4j&amp;lt;/groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;slf4j-api&amp;lt;/artifactId&amp;gt;
			&amp;lt;version&amp;gt;${slf4j.version}&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;
		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;commons-lang&amp;lt;/groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;commons-lang&amp;lt;/artifactId&amp;gt;
			&amp;lt;version&amp;gt;${commons-lang.version}&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;
		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;spring-context&amp;lt;/artifactId&amp;gt;
			&amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;
		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;spring-web&amp;lt;/artifactId&amp;gt;
			&amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;
		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;javax.servlet&amp;lt;/groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;servlet-api&amp;lt;/artifactId&amp;gt;
			&amp;lt;version&amp;gt;${servlet.version}&amp;lt;/version&amp;gt;
			&amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
		&amp;lt;/dependency&amp;gt;
	&amp;lt;/dependencies&amp;gt;

	&amp;lt;build&amp;gt;
		&amp;lt;plugins&amp;gt;

			&amp;lt;plugin&amp;gt;
				&amp;lt;artifactId&amp;gt;maven-deploy-plugin&amp;lt;/artifactId&amp;gt;
				&amp;lt;version&amp;gt;2.6&amp;lt;/version&amp;gt;
			&amp;lt;/plugin&amp;gt;

			&amp;lt;plugin&amp;gt;
				&amp;lt;artifactId&amp;gt;maven-release-plugin&amp;lt;/artifactId&amp;gt;
				&amp;lt;version&amp;gt;2.1&amp;lt;/version&amp;gt;
			&amp;lt;/plugin&amp;gt;

			&amp;lt;plugin&amp;gt;
				&amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
				&amp;lt;version&amp;gt;2.3.2&amp;lt;/version&amp;gt;
				&amp;lt;configuration&amp;gt;
					&amp;lt;source&amp;gt;${java.version}&amp;lt;/source&amp;gt;
					&amp;lt;target&amp;gt;${java.version}&amp;lt;/target&amp;gt;
					&amp;lt;encoding&amp;gt;UTF-8&amp;lt;/encoding&amp;gt;
				&amp;lt;/configuration&amp;gt;
			&amp;lt;/plugin&amp;gt;

			&amp;lt;plugin&amp;gt;
				&amp;lt;artifactId&amp;gt;maven-resources-plugin&amp;lt;/artifactId&amp;gt;
				&amp;lt;version&amp;gt;2.4.3&amp;lt;/version&amp;gt;
				&amp;lt;configuration&amp;gt;
					&amp;lt;encoding&amp;gt;UTF-8&amp;lt;/encoding&amp;gt;
				&amp;lt;/configuration&amp;gt;
			&amp;lt;/plugin&amp;gt;
		&amp;lt;/plugins&amp;gt;
	&amp;lt;/build&amp;gt;
	
	
	&amp;lt;profiles&amp;gt;
		&amp;lt;profile&amp;gt;
			&amp;lt;id&amp;gt;jetty6&amp;lt;/id&amp;gt;
			&amp;lt;properties&amp;gt;
				&amp;lt;jetty.version&amp;gt;6.1.26&amp;lt;/jetty.version&amp;gt;
			&amp;lt;/properties&amp;gt;
			&amp;lt;build&amp;gt;
				&amp;lt;plugins&amp;gt;
					&amp;lt;plugin&amp;gt;
						&amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
						&amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;
						&amp;lt;version&amp;gt;${jetty.version}&amp;lt;/version&amp;gt;
						&amp;lt;configuration&amp;gt;
							&amp;lt;scanIntervalSeconds&amp;gt;10&amp;lt;/scanIntervalSeconds&amp;gt;
							&amp;lt;webAppConfig&amp;gt;
								&amp;lt;contextPath&amp;gt;/jmx-sample&amp;lt;/contextPath&amp;gt;
							&amp;lt;/webAppConfig&amp;gt;
							&amp;lt;connectors&amp;gt;
							  &amp;lt;connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"&amp;gt;
									&amp;lt;port&amp;gt;9090&amp;lt;/port&amp;gt;
									&amp;lt;host&amp;gt;0.0.0.0&amp;lt;/host&amp;gt;
									&amp;lt;maxIdleTime&amp;gt;60000&amp;lt;/maxIdleTime&amp;gt;
								&amp;lt;/connector&amp;gt;
							&amp;lt;/connectors&amp;gt;		
						&amp;lt;/configuration&amp;gt;
					&amp;lt;/plugin&amp;gt;
				&amp;lt;/plugins&amp;gt;
			&amp;lt;/build&amp;gt;
		&amp;lt;/profile&amp;gt;
		&amp;lt;profile&amp;gt;
			&amp;lt;id&amp;gt;jetty7&amp;lt;/id&amp;gt;
			&amp;lt;properties&amp;gt;
				&amp;lt;jetty.version&amp;gt;7.4.5.v20110725&amp;lt;/jetty.version&amp;gt;
			&amp;lt;/properties&amp;gt;
			&amp;lt;build&amp;gt;
				&amp;lt;plugins&amp;gt;
					&amp;lt;plugin&amp;gt;
						&amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
						&amp;lt;artifactId&amp;gt;jetty-maven-plugin&amp;lt;/artifactId&amp;gt;
						&amp;lt;version&amp;gt;${jetty.version}&amp;lt;/version&amp;gt;
						&amp;lt;configuration&amp;gt;
							&amp;lt;scanIntervalSeconds&amp;gt;10&amp;lt;/scanIntervalSeconds&amp;gt;
							&amp;lt;webAppConfig&amp;gt;
								&amp;lt;contextPath&amp;gt;/jmx-sample&amp;lt;/contextPath&amp;gt;
							&amp;lt;/webAppConfig&amp;gt;
							&amp;lt;connectors&amp;gt;
							    &amp;lt;connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector"&amp;gt;
									&amp;lt;port&amp;gt;9090&amp;lt;/port&amp;gt;
									&amp;lt;host&amp;gt;0.0.0.0&amp;lt;/host&amp;gt;
									&amp;lt;maxIdleTime&amp;gt;60000&amp;lt;/maxIdleTime&amp;gt;
								&amp;lt;/connector&amp;gt;
							&amp;lt;/connectors&amp;gt;		
						&amp;lt;/configuration&amp;gt;
					&amp;lt;/plugin&amp;gt;
				&amp;lt;/plugins&amp;gt;
			&amp;lt;/build&amp;gt;
		&amp;lt;/profile&amp;gt;
	&amp;lt;/profiles&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
Il n'y a rien de particulier à remarquer si ce n'est une version de plugin maven pour Jetty qui diffère, ainsi qu'un changement de package pour le SelectChannelConnector utilisé pour spécifier le port d'écoute.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour démarrer notre Jetty, il ne reste plus qu'à exécuter, au choix, la commande :
&lt;/div&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;mvn -Pjetty6 jetty:run&lt;/pre&gt;
ou :&lt;br /&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;mvn -Pjetty7 jetty:run &lt;/pre&gt;
&lt;h2&gt;


Activation de JMX&lt;/h2&gt;
&lt;div style="text-align: justify;"&gt;
Après avoir montré l'application web ainsi que la configuration du  plugin Maven de Jetty nécessaire à son exécution dans le conteneur embarqué, il est possible de démarrer l'application web dans  le Jetty embedded.
&lt;/div&gt;
&lt;div class="separator" style="clear: both; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-MC5ASoy7hYY/TnEsBl97o9I/AAAAAAAAAao/wKFzpPyRaI0/s1600/visualVM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="117" src="http://1.bp.blogspot.com/-MC5ASoy7hYY/TnEsBl97o9I/AAAAAAAAAao/wKFzpPyRaI0/s320/visualVM.png" style="cursor: move;" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-h1-h-jZ47Ys/TnEr6OFgvnI/AAAAAAAAAak/hkrxFyewmwA/s1600/jconsole.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="318" src="http://1.bp.blogspot.com/-h1-h-jZ47Ys/TnEr6OFgvnI/AAAAAAAAAak/hkrxFyewmwA/s320/jconsole.png" style="cursor: move;" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Cependant, même si nos JConsole ou VisualVM préférés proposent une connexion au MBean Server local (visible au travers notre processus Maven3 org.codehaus.plexus.classworlds.launcher.Launcher), il n'est pas possible d'effectuer une connexion en spécifiant le JMXServiceURL de type : &lt;b&gt;service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi&lt;/b&gt; .&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En effet, par défaut, Jetty ne créé pas de MBeanServer et, à fortiori, n'enregistre aucun connecteur RMI nécessaire à une application JMX cliente.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
A titre informatif, même en démarrant un serveur Jetty en mode standalone, il est nécessaire de préciser, à son démarrage, le fichier de configuration jetty-jmx.xml se trouvant, par défaut, dans son répertoire etc et qu'il faut éditer (pour préciser le port du serveur RMI à démarrer et le JMXServiceURL du connecteur JMX RMI).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour Jetty 7, cela peut être fait, soit en modifiant le fichier start.ini, soit en démarrant Jetty en ligne de commande : 
&lt;/div&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;java -jar start.jar etc/jetty-jmx.xml etc/jetty.xml&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
Pour Jetty 6, cela peut être fait, soit en modifiant le fichier bin/jetty-service.conf, soit en démarrant Jetty en ligne de commande :
&lt;/div&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;java -DOPTIONS=jmx -jar start.jar etc/jetty-jmx.xml etc/jetty.xml&lt;/pre&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Aussi, pour activer la création d'un serveur RMI et créer un MBean Server dans le Jetty embarqué par Maven, il est nécessaire de fournir au plugin le fichier jetty-jmx.xml.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour ce faire, il est possible de spécifier une configuration à Jetty via l'élément : &amp;lt;jettyConfig&amp;gt;
&lt;/div&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;	&amp;lt;profiles&amp;gt;
		&amp;lt;profile&amp;gt;
			&amp;lt;id&amp;gt;jetty6&amp;lt;/id&amp;gt;
			&amp;lt;properties&amp;gt;
				&amp;lt;jetty.version&amp;gt;6.1.26&amp;lt;/jetty.version&amp;gt;
			&amp;lt;/properties&amp;gt;
			&amp;lt;build&amp;gt;
				&amp;lt;plugins&amp;gt;
					&amp;lt;plugin&amp;gt;
						&amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
						&amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;
						&amp;lt;version&amp;gt;${jetty.version}&amp;lt;/version&amp;gt;
						&amp;lt;configuration&amp;gt;
							&amp;lt;scanIntervalSeconds&amp;gt;10&amp;lt;/scanIntervalSeconds&amp;gt;
							&amp;lt;jettyConfig&amp;gt;${basedir}/src/config/jetty-jmx-6.xml&amp;lt;/jettyConfig&amp;gt;
							&amp;lt;webAppConfig&amp;gt;
								&amp;lt;contextPath&amp;gt;/jmx-sample&amp;lt;/contextPath&amp;gt;
							&amp;lt;/webAppConfig&amp;gt;
							&amp;lt;connectors&amp;gt;
							  &amp;lt;connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"&amp;gt;
									&amp;lt;port&amp;gt;9090&amp;lt;/port&amp;gt;
									&amp;lt;host&amp;gt;0.0.0.0&amp;lt;/host&amp;gt;
									&amp;lt;maxIdleTime&amp;gt;60000&amp;lt;/maxIdleTime&amp;gt;
								&amp;lt;/connector&amp;gt;
							&amp;lt;/connectors&amp;gt;
						&amp;lt;/configuration&amp;gt;
					&amp;lt;/plugin&amp;gt;
				&amp;lt;/plugins&amp;gt;
			&amp;lt;/build&amp;gt;
		&amp;lt;/profile&amp;gt;
		&amp;lt;profile&amp;gt;
			&amp;lt;id&amp;gt;jetty7&amp;lt;/id&amp;gt;
			&amp;lt;properties&amp;gt;
				&amp;lt;jetty.version&amp;gt;7.4.5.v20110725&amp;lt;/jetty.version&amp;gt;
			&amp;lt;/properties&amp;gt;
			&amp;lt;build&amp;gt;
				&amp;lt;plugins&amp;gt;
					&amp;lt;plugin&amp;gt;
						&amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
						&amp;lt;artifactId&amp;gt;jetty-maven-plugin&amp;lt;/artifactId&amp;gt;
						&amp;lt;version&amp;gt;${jetty.version}&amp;lt;/version&amp;gt;
						&amp;lt;configuration&amp;gt;
							&amp;lt;scanIntervalSeconds&amp;gt;10&amp;lt;/scanIntervalSeconds&amp;gt;
							&amp;lt;jettyConfig&amp;gt;${basedir}/src/config/jetty-jmx.xml&amp;lt;/jettyConfig&amp;gt;
							&amp;lt;webAppConfig&amp;gt;
								&amp;lt;contextPath&amp;gt;/jmx-sample&amp;lt;/contextPath&amp;gt;
							&amp;lt;/webAppConfig&amp;gt;
							&amp;lt;connectors&amp;gt;
							    &amp;lt;connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector"&amp;gt;
									&amp;lt;port&amp;gt;9090&amp;lt;/port&amp;gt;
									&amp;lt;host&amp;gt;0.0.0.0&amp;lt;/host&amp;gt;
									&amp;lt;maxIdleTime&amp;gt;60000&amp;lt;/maxIdleTime&amp;gt;
								&amp;lt;/connector&amp;gt;
							&amp;lt;/connectors&amp;gt;		
						&amp;lt;/configuration&amp;gt;
					&amp;lt;/plugin&amp;gt;
				&amp;lt;/plugins&amp;gt;
			&amp;lt;/build&amp;gt;
		&amp;lt;/profile&amp;gt;
	&amp;lt;/profiles&amp;gt;&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
La nouvelle arborescence de notre projet devient donc :&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-isxZpdoIozo/TnHVHTqIwRI/AAAAAAAAAbA/urXO-bvkGsM/s1600/jmx-sample-tree2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="314" src="http://1.bp.blogspot.com/-isxZpdoIozo/TnHVHTqIwRI/AAAAAAAAAbA/urXO-bvkGsM/s320/jmx-sample-tree2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En outre, il est nécessaire de démarrer la JVM avec l'option -Dcom.sun.management.jmxremote :
&lt;/div&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;mvn -Dcom.sun.management.jmxremote -Pjetty6 package jetty:run&lt;/pre&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;mvn -Dcom.sun.management.jmxremote -Pjetty7 package jetty:run&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
Suite au lancement du serveur Jetty via Maven, il est alors possible d'y accéder au travers d'un client JMX en mode distant :&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-neKAz6J3YXk/TnEsy6vJiZI/AAAAAAAAAa0/S8go6tW4weA/s1600/connection.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="231" src="http://4.bp.blogspot.com/-neKAz6J3YXk/TnEsy6vJiZI/AAAAAAAAAa0/S8go6tW4weA/s400/connection.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-FlX8ZwRcjTU/TnEsVSwh0yI/AAAAAAAAAas/VxjMj6QeEHU/s1600/visualVM2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="280" src="http://4.bp.blogspot.com/-FlX8ZwRcjTU/TnEsVSwh0yI/AAAAAAAAAas/VxjMj6QeEHU/s400/visualVM2.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-WYs5-5s-Aik/TnEsZ24uHdI/AAAAAAAAAaw/3bTMjhjYLdg/s1600/visualVM3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="280" src="http://3.bp.blogspot.com/-WYs5-5s-Aik/TnEsZ24uHdI/AAAAAAAAAaw/3bTMjhjYLdg/s400/visualVM3.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
A titre informatif, ci-joint les fichiers de configuration de Jetty permettant la création d'un serveur RMI, du MBean Server et du connecteur RMI ainsi que de sa configuration.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour Jetty 6 :
&lt;/div&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd"&amp;gt;

&amp;lt;Configure id="Server" class="org.mortbay.jetty.Server"&amp;gt;
    &amp;lt;Call id="MBeanServer" class="java.lang.management.ManagementFactory" name="getPlatformMBeanServer"/&amp;gt;

    &amp;lt;Get id="Container" name="container"&amp;gt;
      &amp;lt;Call name="addEventListener"&amp;gt;
        &amp;lt;Arg&amp;gt;
          &amp;lt;New class="org.mortbay.management.MBeanContainer"&amp;gt;
            &amp;lt;Arg&amp;gt;&amp;lt;Ref id="MBeanServer"/&amp;gt;&amp;lt;/Arg&amp;gt;
            &amp;lt;Call name="start" /&amp;gt;
          &amp;lt;/New&amp;gt;
        &amp;lt;/Arg&amp;gt;
      &amp;lt;/Call&amp;gt;
    &amp;lt;/Get&amp;gt;

    &amp;lt;Call id="rmiRegistry" class="java.rmi.registry.LocateRegistry" name="createRegistry"&amp;gt;
      &amp;lt;Arg type="int"&amp;gt;1099&amp;lt;/Arg&amp;gt;
    &amp;lt;/Call&amp;gt;
    
    &amp;lt;Call id="jmxConnectorServer" class="javax.management.remote.JMXConnectorServerFactory" name="newJMXConnectorServer"&amp;gt;
      &amp;lt;Arg&amp;gt;
        &amp;lt;New  class="javax.management.remote.JMXServiceURL"&amp;gt;
          &amp;lt;Arg&amp;gt;service:jmx:rmi://localhost:1099/jndi/rmi://localhost:1099/jmxrmi&amp;lt;/Arg&amp;gt;
        &amp;lt;/New&amp;gt;
      &amp;lt;/Arg&amp;gt;
      &amp;lt;Arg/&amp;gt;
      &amp;lt;Arg&amp;gt;&amp;lt;Ref id="MBeanServer"/&amp;gt;&amp;lt;/Arg&amp;gt;
      &amp;lt;Call name="start"/&amp;gt;
    &amp;lt;/Call&amp;gt;
&amp;lt;/Configure&amp;gt;
&lt;/pre&gt;
&lt;div style="text-align: justify;"&gt;
Pour Jetty 7 :
&lt;/div&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"&amp;gt;
&amp;lt;Configure id="Server" class="org.eclipse.jetty.server.Server"&amp;gt;

  &amp;lt;Call id="MBeanServer" class="java.lang.management.ManagementFactory"
    name="getPlatformMBeanServer" /&amp;gt;

  &amp;lt;New id="MBeanContainer" class="org.eclipse.jetty.jmx.MBeanContainer"&amp;gt;
    &amp;lt;Arg&amp;gt;
      &amp;lt;Ref id="MBeanServer" /&amp;gt;
    &amp;lt;/Arg&amp;gt;
  &amp;lt;/New&amp;gt;

  &amp;lt;Get id="Container" name="container"&amp;gt;
    &amp;lt;Call name="addEventListener"&amp;gt;
      &amp;lt;Arg&amp;gt;
        &amp;lt;Ref id="MBeanContainer" /&amp;gt;
      &amp;lt;/Arg&amp;gt;
    &amp;lt;/Call&amp;gt;
  &amp;lt;/Get&amp;gt;

  &amp;lt;Call name="addBean"&amp;gt;
    &amp;lt;Arg&amp;gt;
      &amp;lt;Ref id="MBeanContainer" /&amp;gt;
    &amp;lt;/Arg&amp;gt;
  &amp;lt;/Call&amp;gt;

  &amp;lt;Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log" /&amp;gt;
  &amp;lt;Ref id="MBeanContainer"&amp;gt;
    &amp;lt;Call name="addBean"&amp;gt;
      &amp;lt;Arg&amp;gt;
        &amp;lt;Ref id="Logger" /&amp;gt;
      &amp;lt;/Arg&amp;gt;
    &amp;lt;/Call&amp;gt;
  &amp;lt;/Ref&amp;gt;
  
  &amp;lt;Call name="createRegistry" class="java.rmi.registry.LocateRegistry"&amp;gt;
    &amp;lt;Arg type="java.lang.Integer"&amp;gt;1099&amp;lt;/Arg&amp;gt;
    &amp;lt;Call name="sleep" class="java.lang.Thread"&amp;gt;
       &amp;lt;Arg type="java.lang.Integer"&amp;gt;1000&amp;lt;/Arg&amp;gt;
    &amp;lt;/Call&amp;gt;
  &amp;lt;/Call&amp;gt;
 
 &amp;lt;New id="ConnectorServer" class="org.eclipse.jetty.jmx.ConnectorServer"&amp;gt;
    &amp;lt;Arg&amp;gt;
      &amp;lt;New class="javax.management.remote.JMXServiceURL"&amp;gt;
        &amp;lt;Arg type="java.lang.String"&amp;gt;rmi&amp;lt;/Arg&amp;gt;
        &amp;lt;Arg type="java.lang.String" /&amp;gt;
        &amp;lt;Arg type="java.lang.Integer"&amp;gt;0&amp;lt;/Arg&amp;gt;
        &amp;lt;Arg type="java.lang.String"&amp;gt;/jndi/rmi://localhost:1099/jmxrmi&amp;lt;/Arg&amp;gt;
      &amp;lt;/New&amp;gt;
    &amp;lt;/Arg&amp;gt;
    &amp;lt;Arg&amp;gt;org.eclipse.jetty:name=rmiconnectorserver&amp;lt;/Arg&amp;gt;
    &amp;lt;Call name="start" /&amp;gt;
  &amp;lt;/New&amp;gt;
&amp;lt;/Configure&amp;gt;
&lt;/pre&gt;
&lt;h1&gt;


Conclusion&lt;/h1&gt;
&lt;div style="text-align: justify;"&gt;
Cet article avait pour objectif de montrer comment il pouvait être facile d'activer la couche JMX pour un serveur Jetty embedded dans Maven.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
C'est vrai que démarrer un Jetty embarqué n'a pas pour objectif de faire des tests d'intégration mais cela peut toujours être utile dans le cas d'un POC ou d'une démonstration (qui était d'ailleurs l'objectif de ce petit cas d'usage. ;-) ).&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-4627500353991057353?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=laTjesVaK9s:IZAz8d7KXlQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=laTjesVaK9s:IZAz8d7KXlQ:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=laTjesVaK9s:IZAz8d7KXlQ:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/4627500353991057353/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/09/jetty-maven-et-jmx.html#comment-form" title="3 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/4627500353991057353?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/4627500353991057353?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/09/jetty-maven-et-jmx.html" title="Jetty, Maven et JMX" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-bGP4Fnvfp1s/TnEtqz-UNkI/AAAAAAAAAa4/KBXNM8QXHKc/s72-c/logoArticle.png" height="72" width="72" /><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;CUUMSXo6fyp7ImA9WhdVGE0.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-2074960489779419697</id><published>2011-09-23T20:40:00.001+02:00</published><updated>2011-09-23T20:41:28.417+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-23T20:41:28.417+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="présentation" /><category scheme="http://www.blogger.com/atom/ns#" term="architecture" /><category scheme="http://www.blogger.com/atom/ns#" term="soa" /><title>Présentation sur les problématiques liées à une architecture distribuée</title><content type="html">Ci-dessous se trouve une présentation que j'ai donné dans le cadre de &lt;a href="http://blog.soat.fr/"&gt;So@t&lt;/a&gt; sur les problématiques liées aux architectures distribuées.
Pour information, c'est un retour d'expérience d'une mission qui date un peu puisque c'était en 2007 mais les préconisations restent identiques à ce jour.&lt;br /&gt;
&lt;br /&gt;
Enjoy et n'hésitez pas à commenter ;-)
&lt;br /&gt;
&lt;div id="__ss_9387145" style="width: 425px;"&gt;
&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/jetoile/introduction-sur-les-problmatiques-dune-architecture-distribue" target="_blank" title="Introduction sur les problématiques d'une architecture distribuée"&gt;Introduction sur les problématiques d'une architecture distribuée&lt;/a&gt;&lt;/strong&gt; &lt;iframe frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/9387145" width="425"&gt;&lt;/iframe&gt; &lt;br /&gt;
&lt;div style="padding: 5px 0 12px;"&gt;
View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/jetoile" target="_blank"&gt;jetoile&lt;/a&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-2074960489779419697?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=kafzw-SFszE:kXufOE2s69Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=kafzw-SFszE:kXufOE2s69Y:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=kafzw-SFszE:kXufOE2s69Y:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/2074960489779419697/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/09/presentation-aux-problematiques-dune.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/2074960489779419697?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/2074960489779419697?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/09/presentation-aux-problematiques-dune.html" title="Présentation sur les problématiques liées à une architecture distribuée" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUQFQnc_fSp7ImA9WhdVGE0.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-3322658004697377478</id><published>2011-09-23T20:39:00.001+02:00</published><updated>2011-09-23T20:41:53.945+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-23T20:41:53.945+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="intégration continue" /><category scheme="http://www.blogger.com/atom/ns#" term="présentation" /><category scheme="http://www.blogger.com/atom/ns#" term="maven" /><title>Présentation sur un retour d'expérience pour la mise en oeuvre de Maven 2</title><content type="html">Ci-dessous se trouve une présentation que j'ai donné dans le cadre de &lt;a href="http://blog.soat.fr/"&gt;So@t&lt;/a&gt; sur un retour d'expérience sur Maven 2.&lt;br /&gt;
&lt;br /&gt;
Enjoy et n'hésitez pas à commenter ;-)
&lt;br /&gt;
&lt;div id="__ss_9387075" style="width: 425px;"&gt;
&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/jetoile/prsentation-sur-maven-2-et-petit-retour-dexprience" target="_blank" title="Présentation sur Maven 2 et petit retour d'expérience"&gt;Présentation sur Maven 2 et petit retour d'expérience&lt;/a&gt;&lt;/strong&gt; &lt;iframe frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/9387075" width="425"&gt;&lt;/iframe&gt; &lt;br /&gt;
&lt;div style="padding: 5px 0 12px;"&gt;
View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/jetoile" target="_blank"&gt;jetoile&lt;/a&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-3322658004697377478?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=eSfdkls5YE0:a7K3JQ36u1s:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=eSfdkls5YE0:a7K3JQ36u1s:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=eSfdkls5YE0:a7K3JQ36u1s:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/3322658004697377478/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/09/presentation-et-retour-dexperience-sur.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/3322658004697377478?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/3322658004697377478?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/09/presentation-et-retour-dexperience-sur.html" title="Présentation sur un retour d'expérience pour la mise en oeuvre de Maven 2" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUcDR3g8cCp7ImA9WhdVGE0.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-4831307847190063810</id><published>2011-09-18T17:45:00.000+02:00</published><updated>2011-09-23T20:37:56.678+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-23T20:37:56.678+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="divers" /><title>JugSummerCamp 2011 : C'est fini...</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-NhxpR0-3rBg/TnYMk4tcUDI/AAAAAAAAAbI/6GIdzOKCCtM/s1600/jugsummercamp2011-h.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="97" src="http://4.bp.blogspot.com/-NhxpR0-3rBg/TnYMk4tcUDI/AAAAAAAAAbI/6GIdzOKCCtM/s320/jugsummercamp2011-h.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Voilà, pour ceux qui l'auraient manquée ou qui ne le savaient pas (ouh!!!), le &lt;a href="http://www.jugsummercamp.org/"&gt;JugSummerCamp&lt;/a&gt; a fermé ses portes ce vendredi 16 septembre 2011.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ce fut une journée bien remplie, fatigante mais que du bonheur : des sessions intéressantes, des speakers compétents mais également une super organisation (merci au &lt;a href="http://www.poitoucharentesjug.org/"&gt;Poitou-Charente Java User Group&lt;/a&gt; mais également à tous les sponsors de l'évènement sans qui rien n'aurait été possible... (on les oublie tout le temps... ;-) ))!&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-GVImey5ZDCM/TnYM0eKSWzI/AAAAAAAAAbM/rYl-lDH4DYk/s1600/customLogo.gif.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-GVImey5ZDCM/TnYM0eKSWzI/AAAAAAAAAbM/rYl-lDH4DYk/s200/customLogo.gif.png" width="122" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
C'est toujours un plaisir de rencontrer/retrouver des personnes géniales (je ne citerai pas de noms, ça fait trop lèche... ;-) ).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Donc, en gros, vous l'aurez compris, au vu de mon enthousiasme, merci encore et&amp;nbsp;vivement l'année prochaine!!&lt;/div&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div style="text-align: justify;"&gt;
Bon, et pour les néophytes, je vais tenter de vous présenter succinctement ce que vous avez loupé (pour des CRs, je vous invite à aller voir d'autres sites comme celui de &lt;a href="http://blog.soat.fr/2011/09/jugsummercamp-2011/"&gt;So@t&lt;/a&gt;, de &lt;a href="http://www.touilleur-express.fr/"&gt;Nicolas Martignole&lt;/a&gt; et&amp;nbsp;de &lt;a href="http://cfalguiere.wordpress.com/2011/09/17/le-jug-summer-camp-cest-fini-pour-cette-annee/"&gt;Claude Falguière&lt;/a&gt;).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Le JugSummerCamp est donc une journée entière de conférences se déroulant à La Rochelle plutôt orientées Java.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Pour donner un ordre d'idée, ci-dessous le planning de la journée (pour les résumés des présentations, c'est &lt;a href="https://sites.google.com/site/jugsummercamp/presentations"&gt;ici&lt;/a&gt;) :
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-pZxE-O4uYEY/TnYRCzoJoxI/AAAAAAAAAbY/zcPDT6Nq7fA/s1600/planning.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="281" src="http://1.bp.blogspot.com/-pZxE-O4uYEY/TnYRCzoJoxI/AAAAAAAAAbY/zcPDT6Nq7fA/s400/planning.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Voilà, plus grand chose à ajouter, les présentations parlent d'elles-mêmes... ;-)&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Sur ce, à l'année prochaine alors! ;-)&lt;br /&gt;
[edit]&lt;br /&gt;
Ci-dessous ma modeste contribution :&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.soat.fr/2011/09/jugsummercamp-cdi-osgi-osgi-en-toute-simplicite-par-mathieu-ancelin/"&gt;CDI-OSGi, OSGi en toute simplicité par Mathieu Ancelin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.soat.fr/2011/09/jugsummercamp-de-lintranet-social-au-developpement-sur-le-cloud-par-tugdual-grall/"&gt;De l’intranet social au développement sur le Cloud par Tugdual Grall&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-4831307847190063810?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=lvYoOai20eQ:y-mf8xtjQAA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=lvYoOai20eQ:y-mf8xtjQAA:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=lvYoOai20eQ:y-mf8xtjQAA:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/4831307847190063810/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/09/jugsummercamp-2011-cest-fini.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/4831307847190063810?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/4831307847190063810?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/09/jugsummercamp-2011-cest-fini.html" title="JugSummerCamp 2011 : C'est fini..." /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-NhxpR0-3rBg/TnYMk4tcUDI/AAAAAAAAAbI/6GIdzOKCCtM/s72-c/jugsummercamp2011-h.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DE8FRX0_fSp7ImA9WhdSGUg.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-5141670155803309035</id><published>2011-07-29T18:26:00.000+02:00</published><updated>2011-07-29T18:26:54.345+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-29T18:26:54.345+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="divers" /><title>Retour sur le BreizhCamp 2011</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-MLdvtEQ7N4U/TjLfDRfW5uI/AAAAAAAAAZk/ldnfjvp-c2o/s1600/BreizhCamp.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="136" src="http://3.bp.blogspot.com/-MLdvtEQ7N4U/TjLfDRfW5uI/AAAAAAAAAZk/ldnfjvp-c2o/s320/BreizhCamp.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cela fait un petit moment (plus d'un mois déjà...) qu'a eu lieu le &lt;a href="http://www.breizhcamp.org/"&gt;BreizhCamp&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour les néophytes, BreizhCamp est une journée de conférence sur diverses technologies allant de Python, en passant par .Net pour, finalement finir sur Java.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cette année, elle a eu lieu le vendredi 17 Juin à Rennes dans les locaux de l’&lt;a href="http://www.istic.univ-rennes1.fr/"&gt;ISTIC&lt;/a&gt; et a été organisée par l’équipe du BreizhJug qui comprend :&lt;/div&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://blog.loof.fr/"&gt;Nicolas De loof&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Michel David,&lt;/li&gt;
&lt;li&gt;Julien Coste.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;Ayant eu l'opportunité d'y participer, j'ai rédigé quelques petits compte-rendu de quelques-une des présentations auxquelles j'ai eu la chance d'assister. Les liens se trouvent ci-dessous :&amp;nbsp;&lt;/div&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://blog.soat.fr/2011/06/breizhcamp-applications-mobiles-avec-gwt-2-0-par-salvador-diaz/"&gt;Applications mobiles avec GWT 2.0&lt;/a&gt; par Salvador Diaz&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.soat.fr/2011/06/breizhcamp-deploiement-continu-en-production-par-claude-falguiere/"&gt;Déploiement Continu en production&lt;/a&gt; par Claude Falguière&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.soat.fr/2011/06/breizhcamp-behaviour-driven-development-par-olivier-billard-et-thierry-henrio/"&gt;Behaviour Driven Development&lt;/a&gt; par Olivier Billard et Thierry Henrio&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.soat.fr/2011/07/breizhcamp-j2ee-ma-tuer-ou-comment-survivre-avec-du-legacy-par-emmanuel-hugonnet/"&gt;La vie dans du code legacy&lt;/a&gt; par Emmanuel Hugonnet&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;Le programme complet est &lt;a href="http://www.breizhcamp.org/programme"&gt;ici&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En tout cas, encore un grand merci aux organisateurs ainsi qu’aux speakers et vivement la prochaine édition (en espérant que, la prochaine fois, la Bretagne daigne nous offrir un peu de soleil sans passage pluvieux ;-) )!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-5141670155803309035?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=eodaV-PbQNE:rBIHcXHiZY4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=eodaV-PbQNE:rBIHcXHiZY4:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=eodaV-PbQNE:rBIHcXHiZY4:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/5141670155803309035/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/07/retour-sur-le-breizhcamp-2011.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/5141670155803309035?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/5141670155803309035?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/07/retour-sur-le-breizhcamp-2011.html" title="Retour sur le BreizhCamp 2011" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-MLdvtEQ7N4U/TjLfDRfW5uI/AAAAAAAAAZk/ldnfjvp-c2o/s72-c/BreizhCamp.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUIMSHc6eSp7ImA9WhZUGE0.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-630872268761508170</id><published>2011-06-11T17:53:00.000+02:00</published><updated>2011-06-11T17:53:09.911+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-11T17:53:09.911+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="divers" /><title>Ubuntu 11.04, problème de complétion?</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-PYGo1WbVX3E/TfOOwCue0II/AAAAAAAAAYE/bP0fMBPp99I/s1600/ubuntuLogo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="134" src="http://2.bp.blogspot.com/-PYGo1WbVX3E/TfOOwCue0II/AAAAAAAAAYE/bP0fMBPp99I/s320/ubuntuLogo.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ubuntu 11.04 est sorti depuis le 28 avril 2011. Je ne reviendrai pas ni sur son ergonomie ni sur ses ajouts puisque cela a déjà été débattu sur de nombreux sites/blogs. Cependant, depuis la mise à jour, un point avait tendance à m'agacer.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En effet,&amp;nbsp;dans un shell bash,&amp;nbsp;sur la complétion de la commande ls (entre autre) avec des répertoires contenant des espaces, il ne m'échappait plus ces derniers. Du coup, obligation d'aller les échapper manuellement mais chose encore plus embêtante était qu'il ne me proposait plus le contenu de mon répertoire.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pire, en échappant les espaces et en utilisant la complétion, il me supprimait mon échappement...&lt;/div&gt;Cet article fournira donc une rapide solution pour corriger ce problème.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;b&gt;Symptôme&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
Pour l'arborescence ci-dessous, j'avais le comportement suivant :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-s9j2IBv_w7M/TfODhMgXhYI/AAAAAAAAAXk/imMqhaAW9LY/s1600/ubuntu02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-s9j2IBv_w7M/TfODhMgXhYI/AAAAAAAAAXk/imMqhaAW9LY/s1600/ubuntu02.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Utilisation basique de la complétion :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-YSypzYsV_Zk/TfOBzlrIsVI/AAAAAAAAAXg/-T6-n0Hu5pM/s1600/ubuntu01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="50" src="http://4.bp.blogspot.com/-YSypzYsV_Zk/TfOBzlrIsVI/AAAAAAAAAXg/-T6-n0Hu5pM/s400/ubuntu01.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Avec échappement de l'espace...&lt;br /&gt;
Avant :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-YPHW04jHH0s/TfOEEp0gqDI/AAAAAAAAAXo/t8FKxJedORo/s1600/ubuntu03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="20" src="http://3.bp.blogspot.com/-YPHW04jHH0s/TfOEEp0gqDI/AAAAAAAAAXo/t8FKxJedORo/s320/ubuntu03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Après exécution de la commande Tab :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-MSYG8ZCqVAE/TfOEVNKnNfI/AAAAAAAAAXs/k6heNnlMZhg/s1600/ubuntu04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="21" src="http://2.bp.blogspot.com/-MSYG8ZCqVAE/TfOEVNKnNfI/AAAAAAAAAXs/k6heNnlMZhg/s400/ubuntu04.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Entraînant, bien sûr, une erreur lors de son exécution :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-qdZH3XNVpns/TfOFJ5O3xYI/AAAAAAAAAXw/2ueSn_2rZ9s/s1600/ubuntu05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="58" src="http://1.bp.blogspot.com/-qdZH3XNVpns/TfOFJ5O3xYI/AAAAAAAAAXw/2ueSn_2rZ9s/s400/ubuntu05.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h1&gt;Correctif&lt;/h1&gt;Du coup, après une ou deux recherche sur mon ami google, je suis tombé sur le &lt;a href="https://bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/769866"&gt;bug suivant&lt;/a&gt;.&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;En fait, pour résumer, il semble que cela vienne du script de complétion utilisé par bash.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Aussi pour corriger ce problème, il ne vous reste plus qu'à éditer le fichier &lt;b&gt;/etc/bash_completion&lt;/b&gt; avec les bons droits et à modifier sa ligne 1587 pour y remplacer "default" par "filenames".&lt;/div&gt;&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;# makeinfo and texi2dvi are defined elsewhere.
for i in a2ps awk bash bc bison cat colordiff cp csplit \
    curl cut date df diff dir du enscript env expand fmt fold gperf gprof \
    grep grub head indent irb ld ldd less ln ls m4 md5sum mkdir mkfifo mknod \
    mv netstat nl nm objcopy objdump od paste patch pr ptx readelf rm rmdir \
    sed seq sha{,1,224,256,384,512}sum shar sort split strip tac tail tee \
    texindex touch tr uname unexpand uniq units vdir wc wget who; do
    have $i &amp;amp;&amp;amp; complete -F _longopt -o filenames $i
done
unset i
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Après un petit coup de rechargement du bashrc (qui charge le bash_completion), vous aurez alors résolu votre problème ;-)&lt;/div&gt;Rechargement du ~/.bashrc :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-_e-p2C3ZNPs/TfOJc6I-LoI/AAAAAAAAAX8/Um_QhF9V_18/s1600/ubuntu09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-_e-p2C3ZNPs/TfOJc6I-LoI/AAAAAAAAAX8/Um_QhF9V_18/s1600/ubuntu09.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Utilisation basique de la complétion et exécution :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-2wMokee8xhI/TfOJhXsTgiI/AAAAAAAAAYA/FK6AiN7vDfo/s1600/ubuntu08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-2wMokee8xhI/TfOJhXsTgiI/AAAAAAAAAYA/FK6AiN7vDfo/s1600/ubuntu08.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Utilisation de la complétion après complétion du répertoire :&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-fSXGkhwkeuE/TfOH-TUEJeI/AAAAAAAAAX4/6K1qhgEIt6U/s1600/ubuntu07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="42" src="http://3.bp.blogspot.com/-fSXGkhwkeuE/TfOH-TUEJeI/AAAAAAAAAX4/6K1qhgEIt6U/s320/ubuntu07.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Voilà pour cet article qui, pour une fois, ne parle pas Java mais qui, je l'espère, pourra être utile... ;-)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-630872268761508170?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=_cDCpDvSMYI:cOKWJncBolY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=_cDCpDvSMYI:cOKWJncBolY:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=_cDCpDvSMYI:cOKWJncBolY:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/630872268761508170/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/06/ubuntu-1104-probleme-de-completion.html#comment-form" title="1 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/630872268761508170?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/630872268761508170?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/06/ubuntu-1104-probleme-de-completion.html" title="Ubuntu 11.04, problème de complétion?" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-PYGo1WbVX3E/TfOOwCue0II/AAAAAAAAAYE/bP0fMBPp99I/s72-c/ubuntuLogo.png" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;DEcCRns6cSp7ImA9WhZUGEo.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-7426476454268958486</id><published>2011-06-05T22:45:00.025+02:00</published><updated>2011-06-12T12:54:27.519+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-12T12:54:27.519+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="maven" /><category scheme="http://www.blogger.com/atom/ns#" term="archetype" /><title>Maven pour les nuls... les archetypes</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-l-NZQRxE0vI/TevA5LfJQ_I/AAAAAAAAAXI/IP8zRk4wbeg/s1600/maven-logo-2.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-l-NZQRxE0vI/TevA5LfJQ_I/AAAAAAAAAXI/IP8zRk4wbeg/s1600/maven-logo-2.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Dans le cadre d'une problématique d'une usine logiciel, il peut s'avérer utile de posséder un patron ou template de projet qui fournit les "bonnes" pratiques que doivent respecter l'ensemble des applications du projet.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Bien sûr, notre cher IDE est capable de générer un joli patron de projet. Cependant, il reste toujours nécessaire de modifier la configuration du projet pour y mettre, par exemple :&lt;/div&gt;&lt;ul&gt;&lt;li&gt;la version de jdk,&lt;/li&gt;
&lt;li&gt;les libs utilisées (comme mockito par exemple),&lt;/li&gt;
&lt;li&gt;optionnellement, la configuration de plugins,&lt;/li&gt;
&lt;li&gt;optionnellemet, l'url du SCM,&lt;/li&gt;
&lt;li&gt;ou tout simplement, la référence à un projet parent qui permet de définir, par exemple, la version des librairies ou des plugins utilisés.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Le hic, c'est que, généralement, cela fini par de jolis copier/coller dont le résultat diffère, bien sûr, en fonction du projet qui a servi de template. Le résultat : le syndrome du téléphone arabe sachant qu'en plus, on n'est même plus capable de savoir qu'elle était la référence du départ... embêtant tout ça... surtout pour un projet se voulant industriel...&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En outre, posséder un patron de projet peut également s'avérer utile si vous êtes amené à &lt;em&gt;POCer&lt;/em&gt; des frameworks ou faire des projets perso chez vous...&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Vous l'aurez compris, cet article se focalisera sur les projets construits sur maven où les notions de dépendances, de plugins, d'informations projet sont présentes dans le pom.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cet article a donc pour objectif de montrer comment il est possible de créer un archetype maven qui permet de répondre à ce problème.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Le use case sera simple puisque je m'appuierai sur la création d'un archetype simple pour mes besoins personnels afin de me fournir un patron normalisé (selon mes normes) me permettant de démarrer un POC rapidement pour un artifact de type jar et cela dans le seul but de ne pas avoir à faire moultes copier/coller... ;-)&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A noter qu'il n'y a rien de révolutionnaire dans cet article pour toutes les personnes qui ont quelques connaissances de base en maven mais qu'il peut s'avérer utile (enfin j'espère) pour les autres... ;-) &lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1&gt;Méthodologie&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Afin de créer un archetype, il existe plusieurs méthodes :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;la première consiste à créer l'archetype directement, chose pas trop complexe mais qui demande d'être rodée à la chose,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;la deuxième consiste à créer le projet maven tel que l'on souhaiterait que l'archetype nous le créer et de demander à maven de nous générer l'archetype en lui-même. Suite à cela, il convient de modifier l'archetype généré afin de le rendre configurable (nom des packages, ...).&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Suite à cela, il convient d'installer (ou de déployer) notre archetype au sein de notre repository (global ou distant) afin de le rendre accessible aux autres membres de l'équipe ou tout simplement à soi-même.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Dans mon cas, j'utiliserai la deuxième méthode qui consiste donc à générer l'archetype à partir du projet maven que je souhaite avoir.&lt;/div&gt;&lt;h1&gt;Création du projet de base&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Comme je l'ai dit précédemment, mes besoins sont purement personnels et mon projet devra répondre aux points suivants :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;un seul projet,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;de type jar,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;utilisant un jdk 6,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;déclarant les librairies suivantes : slf4j, logback-classic, commons-lang&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;déclarant les librairies suivantes&amp;nbsp;pour mes TUs&amp;nbsp;: JUnit, mockito, powermock&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;déclarant et configurant le plugin checkstyle et dont les rules seront dans le projet en lui-même&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;déclarant et configurant le plugin assembly afin de me permettre de fournir, au besoin, un livrable&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;déclarant le plugin source afin de me permettre de générer un jar de source&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Bien sûr, il tentera de suivre au mieux les bonnes pratiques maven...&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cette partie n'étant pas bien intéressante et étant spécifique aux besoins de chacun, je la détaillerai donc peu...&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Sa structure :&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ActIqf-Gkv8/TevBObqDojI/AAAAAAAAAXM/TRHrtsoB8L0/s1600/archetype01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-ActIqf-Gkv8/TevBObqDojI/AAAAAAAAAXM/TRHrtsoB8L0/s320/archetype01.png" width="303" /&gt;&lt;/a&gt;&lt;/div&gt;Son pom :&lt;br /&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&lt;project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;&lt;build&gt;&lt;plugins&gt;&amp;lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&amp;gt;
 &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
 &amp;lt;groupId&amp;gt;fr.jetoile&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;project-template&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;

 &amp;lt;properties&amp;gt;
  &amp;lt;java.version&amp;gt;1.6&amp;lt;/java.version&amp;gt;

  &amp;lt;junit.version&amp;gt;4.8.1&amp;lt;/junit.version&amp;gt;
  &amp;lt;slf4j.version&amp;gt;1.6.1&amp;lt;/slf4j.version&amp;gt;
  &amp;lt;logback.version&amp;gt;0.9.27&amp;lt;/logback.version&amp;gt;
  &amp;lt;commons-lang.version&amp;gt;2.5&amp;lt;/commons-lang.version&amp;gt;
  &amp;lt;powermock.version&amp;gt;1.4.7&amp;lt;/powermock.version&amp;gt;
  &amp;lt;mockito.version&amp;gt;1.8.5&amp;lt;/mockito.version&amp;gt;
 &amp;lt;/properties&amp;gt;

 &amp;lt;!-- distributionManagement&amp;gt;
  &amp;lt;repository&amp;gt;
   &amp;lt;id&amp;gt;nexus&amp;lt;/id&amp;gt;
   &amp;lt;url&amp;gt;http://localhost:8080/nexus/content/repositories/releases&amp;lt;/url&amp;gt;
  &amp;lt;/repository&amp;gt;
  &amp;lt;snapshotRepository&amp;gt;
   &amp;lt;id&amp;gt;nexus&amp;lt;/id&amp;gt;
   &amp;lt;name&amp;gt;Nexus snapshot Repository&amp;lt;/name&amp;gt;
   &amp;lt;url&amp;gt;http://localhost:8080/nexus/content/repositories/snapshots&amp;lt;/url&amp;gt;
  &amp;lt;/snapshotRepository&amp;gt;
 &amp;lt;/distributionManagement&amp;gt;
 &amp;lt;scm&amp;gt;
  &amp;lt;developerConnection&amp;gt;scm:svn:svn://localhost/projet/trunk/TODO&amp;lt;/developerConnection&amp;gt;
 &amp;lt;/scm--&amp;gt;


 &amp;lt;developers&amp;gt;
  &amp;lt;developer&amp;gt;
   &amp;lt;email&amp;gt;kmx.petals@gmail.com&amp;lt;/email&amp;gt;
   &amp;lt;id&amp;gt;khanh&amp;lt;/id&amp;gt;
   &amp;lt;roles&amp;gt;
    &amp;lt;role&amp;gt;developer&amp;lt;/role&amp;gt;
   &amp;lt;/roles&amp;gt;
  &amp;lt;/developer&amp;gt;
 &amp;lt;/developers&amp;gt;

 &amp;lt;dependencies&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;ch.qos.logback&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;logback-classic&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${logback.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.slf4j&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;slf4j-api&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${slf4j.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;commons-lang&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;commons-lang&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${commons-lang.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.mockito&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;mockito-all&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${mockito.version}&amp;lt;/version&amp;gt;
   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.powermock&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;powermock-module-junit4&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${powermock.version}&amp;lt;/version&amp;gt;
   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;junit&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;junit&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${junit.version}&amp;lt;/version&amp;gt;
   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.powermock&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;powermock-api-mockito&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${powermock.version}&amp;lt;/version&amp;gt;
   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
  &amp;lt;/dependency&amp;gt;
 &amp;lt;/dependencies&amp;gt;


 &amp;lt;build&amp;gt;
  &amp;lt;plugins&amp;gt;
   &amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-deploy-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.6&amp;lt;/version&amp;gt;
   &amp;lt;/plugin&amp;gt;

   &amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-release-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.1&amp;lt;/version&amp;gt;
   &amp;lt;/plugin&amp;gt;

   &amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.3.2&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
     &amp;lt;source&amp;gt;${java.version}&amp;lt;/source&amp;gt;
     &amp;lt;target&amp;gt;${java.version}&amp;lt;/target&amp;gt;
    &amp;lt;/configuration&amp;gt;
   &amp;lt;/plugin&amp;gt;

   &amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-checkstyle-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.6&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
     &amp;lt;configLocation&amp;gt;src/config/custom-checkstyle.xml&amp;lt;/configLocation&amp;gt;
     &amp;lt;includeTestSourceDirectory&amp;gt;false&amp;lt;/includeTestSourceDirectory&amp;gt;
     &amp;lt;logViolationsToConsole&amp;gt;true&amp;lt;/logViolationsToConsole&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
     &amp;lt;execution&amp;gt;
      &amp;lt;phase&amp;gt;compile&amp;lt;/phase&amp;gt;
      &amp;lt;goals&amp;gt;
       &amp;lt;goal&amp;gt;check&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
     &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
   &amp;lt;/plugin&amp;gt;

   &amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-assembly-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.2.1&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
     &amp;lt;descriptors&amp;gt;
      &amp;lt;descriptor&amp;gt;src/assembly/src.xml&amp;lt;/descriptor&amp;gt;
     &amp;lt;/descriptors&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
     &amp;lt;execution&amp;gt;
      &amp;lt;id&amp;gt;make-assembly&amp;lt;/id&amp;gt;
      &amp;lt;phase&amp;gt;install&amp;lt;/phase&amp;gt;
      &amp;lt;goals&amp;gt;
       &amp;lt;goal&amp;gt;single&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
     &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
   &amp;lt;/plugin&amp;gt;

   &amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-source-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.1.2&amp;lt;/version&amp;gt;
    &amp;lt;executions&amp;gt;
     &amp;lt;execution&amp;gt;
      &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;
      &amp;lt;goals&amp;gt;
       &amp;lt;goal&amp;gt;jar&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
     &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
   &amp;lt;/plugin&amp;gt;
  &amp;lt;/plugins&amp;gt;
 &amp;lt;/build&amp;gt;
&amp;lt;/project&amp;gt;  &lt;/plugins&gt;
 &lt;/build&gt;
&lt;/project&gt;&lt;/pre&gt;Son fichier assembly :&lt;br /&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&lt;assembly&gt;
&lt;/assembly&gt;&amp;lt;assembly&amp;gt;
 &amp;lt;id&amp;gt;bin&amp;lt;/id&amp;gt;
 &amp;lt;formats&amp;gt;
  &amp;lt;format&amp;gt;zip&amp;lt;/format&amp;gt;
 &amp;lt;/formats&amp;gt;
 &amp;lt;includeBaseDirectory&amp;gt;false&amp;lt;/includeBaseDirectory&amp;gt;
 &amp;lt;dependencySets&amp;gt;
  &amp;lt;dependencySet&amp;gt;
   &amp;lt;scope&amp;gt;compile&amp;lt;/scope&amp;gt;
   &amp;lt;useProjectArtifact&amp;gt;true&amp;lt;/useProjectArtifact&amp;gt;
   &amp;lt;useTransitiveDependencies&amp;gt;true&amp;lt;/useTransitiveDependencies&amp;gt;
   &amp;lt;outputDirectory&amp;gt;lib&amp;lt;/outputDirectory&amp;gt;
  &amp;lt;/dependencySet&amp;gt;
 &amp;lt;/dependencySets&amp;gt;

 &amp;lt;fileSets&amp;gt;
  &amp;lt;fileSet&amp;gt;
   &amp;lt;directory&amp;gt;target/&amp;lt;/directory&amp;gt;
   &amp;lt;outputDirectory&amp;gt;sources&amp;lt;/outputDirectory&amp;gt;
   &amp;lt;includes&amp;gt;
    &amp;lt;include&amp;gt;**sources.jar&amp;lt;/include&amp;gt;
   &amp;lt;/includes&amp;gt;
  &amp;lt;/fileSet&amp;gt;
  &amp;lt;fileSet&amp;gt;
   &amp;lt;directory&amp;gt;bin/&amp;lt;/directory&amp;gt;
   &amp;lt;outputDirectory&amp;gt;bin&amp;lt;/outputDirectory&amp;gt;
  &amp;lt;/fileSet&amp;gt;
 &amp;lt;/fileSets&amp;gt;

&amp;lt;/assembly&amp;gt;&lt;/pre&gt;&lt;h1&gt;Création de l'archetype&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;La création de l'archetype est simple puisqu'il suffit de lancer la commande suivante :&lt;/div&gt;&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;mvn archetype:create-from-project&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Suite à cela, notre archetype se trouve dans le répertoire target/generated-sources/archetype et a la structure suivante :&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-QGyUib6583A/TevDZZVezbI/AAAAAAAAAXQ/lHGC3y6oLew/s1600/archetype02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-QGyUib6583A/TevDZZVezbI/AAAAAAAAAXQ/lHGC3y6oLew/s1600/archetype02.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Son pom :&lt;br /&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&lt;project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
&lt;/project&gt;&amp;lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&amp;gt;
  &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;

  &amp;lt;groupId&amp;gt;fr.jetoile&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;project-template-archetype&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;
  &amp;lt;packaging&amp;gt;maven-archetype&amp;lt;/packaging&amp;gt;

  &amp;lt;name&amp;gt;project-template-archetype&amp;lt;/name&amp;gt;

  &amp;lt;build&amp;gt;
    &amp;lt;extensions&amp;gt;
      &amp;lt;extension&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.archetype&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;archetype-packaging&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.0&amp;lt;/version&amp;gt;
      &amp;lt;/extension&amp;gt;
    &amp;lt;/extensions&amp;gt;

    &amp;lt;pluginManagement&amp;gt;
      &amp;lt;plugins&amp;gt;
        &amp;lt;plugin&amp;gt;
          &amp;lt;artifactId&amp;gt;maven-archetype-plugin&amp;lt;/artifactId&amp;gt;
          &amp;lt;version&amp;gt;2.0&amp;lt;/version&amp;gt;
        &amp;lt;/plugin&amp;gt;
      &amp;lt;/plugins&amp;gt;
    &amp;lt;/pluginManagement&amp;gt;
  &amp;lt;/build&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;On constate qu'il y a deux points à noter dans cette structure d'archetype générée :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;le patron de notre template de projet qui sera utilisé par maven lors de l'appel au goal archetype:generate se trouve dans le répertoire src/main/resources/archetype-resources/src,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;dans le répertoire src/main/resources/META-INF/maven, se trouve le fichier archetype-metadata.xml qui contient le descriptif de ce qui doit être généré :&lt;/li&gt;
&lt;/ul&gt;&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="project-template"
    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;
    
  &amp;lt;fileSets&amp;gt;
    &amp;lt;fileSet filtered="true" packaged="true" encoding="UTF-8"&amp;gt;
      &amp;lt;directory&amp;gt;src/main/java&amp;lt;/directory&amp;gt;
      &amp;lt;includes&amp;gt;
        &amp;lt;include&amp;gt;**/*.java&amp;lt;/include&amp;gt;
      &amp;lt;/includes&amp;gt;
    &amp;lt;/fileSet&amp;gt;
    &amp;lt;fileSet filtered="true" packaged="true" encoding="UTF-8"&amp;gt;
      &amp;lt;directory&amp;gt;src/test/java&amp;lt;/directory&amp;gt;
      &amp;lt;includes&amp;gt;
        &amp;lt;include&amp;gt;**/*.java&amp;lt;/include&amp;gt;
      &amp;lt;/includes&amp;gt;
    &amp;lt;/fileSet&amp;gt;
    &amp;lt;fileSet filtered="true" encoding="UTF-8"&amp;gt;
      &amp;lt;directory&amp;gt;src/config&amp;lt;/directory&amp;gt;
      &amp;lt;includes&amp;gt;
        &amp;lt;include&amp;gt;**/*.xml&amp;lt;/include&amp;gt;
      &amp;lt;/includes&amp;gt;
    &amp;lt;/fileSet&amp;gt;
    &amp;lt;fileSet filtered="true" encoding="UTF-8"&amp;gt;
      &amp;lt;directory&amp;gt;src/assembly&amp;lt;/directory&amp;gt;
      &amp;lt;includes&amp;gt;
        &amp;lt;include&amp;gt;**/*.xml&amp;lt;/include&amp;gt;
      &amp;lt;/includes&amp;gt;
    &amp;lt;/fileSet&amp;gt;
    &amp;lt;fileSet filtered="true" encoding="UTF-8"&amp;gt;
      &amp;lt;directory&amp;gt;&amp;lt;/directory&amp;gt;
      &amp;lt;includes&amp;gt;
        &amp;lt;include&amp;gt;README.txt&amp;lt;/include&amp;gt;
      &amp;lt;/includes&amp;gt;
    &amp;lt;/fileSet&amp;gt;
  &amp;lt;/fileSets&amp;gt;
&amp;lt;/archetype-descriptor&amp;gt;
&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A cette étape, il est tout de suite possible d'installer l'archetype dans le repository maven (cf. Mise à disposition de l'archetype) et de l'invoquer (cf. Utilisation et résultat de l'archetype).&lt;br /&gt;
A noter qu'ici, il peut être intéressant de supprimer le support des .project, .classpath et .settings si le template a été géré avec eclipse.&lt;/div&gt;&lt;h1&gt;Transformation de l'archetype&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Dans le cadre de mon petit use case, je n'ai pas beaucoup besoin de &lt;em&gt;customiser&lt;/em&gt; mon archetype. En effet, je souhaite seulement pouvoir demander à l'utilisateur (en l'occurence moi ;-) ), quel sera le nom de ma classe à me générer.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour ce faire, il n'y a qu'à ajouter une propriété dans le fichier src/main/resources/META-INF/maven/archetype-metadata.xml :&lt;/div&gt;&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&amp;lt;requiredProperties&amp;gt;
    &amp;lt;requiredProperty key="className"&amp;gt;
      &amp;lt;defaultValue&amp;gt;MyClass&amp;lt;/defaultValue&amp;gt;
    &amp;lt;/requiredProperty&amp;gt;
&amp;lt;/requiredProperties&amp;gt;
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Modifier le nom des fichiers java :&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Test.java en __className__.java&lt;/li&gt;
&lt;li&gt;TestTest en __className__.java&lt;/li&gt;
&lt;/ul&gt;Et remplacer dans les fichiers respectifs :&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class Test {&lt;/pre&gt;en&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class ${className} {&lt;/pre&gt;et&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class TestTest {&lt;/pre&gt;en&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class ${className}Test {&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;En outre, il faut également modifier le fichier src/test/resources/projects/basic/archetype.properties pour y ajouter la ligne suivante :&lt;/div&gt;&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;className=MyClass
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Enfin, il est possible de figer la version de l'archetype en modifiant le pom du projet ainsi que son artifactId et son groupId.&amp;nbsp;Dans mon cas, il restera identique.&lt;/div&gt;&lt;h1&gt;Mise à disposition de l'archetype&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Une fois que l'archetype a été modifié pour répondre aux besoins, il n'y a plus qu'à exécuter la commande mvn install pour déployer l'archetype dans le repository local et la commande mvn deploy pour le déployer dans le repository partagé.&lt;/div&gt;&lt;h1&gt;Utilisation et résultat de l'archetype&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Une fois l'archetype déployé dans le repository adéquate, il n'y a plus qu'à l'invoquer via la commande :&lt;/div&gt;&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;mvn archetype:generate \
&amp;nbsp;-DarchetypeGroupId=fr.jetoile \
&amp;nbsp;-DarchetypeArtifactId=project-template-archetype \
&amp;nbsp;-DarchetypeVersion=0.0.1-SNAPSHOT \
&amp;nbsp;-DgroupId=fr.jetoile \
&amp;nbsp;-DartifactId=test-archetype
&lt;/pre&gt;Ainsi, le résultat obtenu est le suivant :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-IyLOW6pbUgw/TevFCch0TRI/AAAAAAAAAXU/-8aUatC2M5c/s1600/archetype04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-IyLOW6pbUgw/TevFCch0TRI/AAAAAAAAAXU/-8aUatC2M5c/s1600/archetype04.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Nous avons vu dans cet article qu'il était extrêmement simple de créer un archetype maven, action qui peut s'avérer très utile pour gagner du temps que ce soit pour des besoins personnels ou dans un cadre d'industrialisation du processus d'initialisation d'un projet dans une équipe.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[update]&lt;/b&gt; Je viens de mettre sur github le code :&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;du projet utilisé pour créer l'archetype ainsi que le code de l'archetype :&amp;nbsp;&lt;a href="https://github.com/jetoile/project-template"&gt;https://github.com/jetoile/project-template&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;du projet permettant de créer l'archetype :&amp;nbsp;&lt;a href="https://github.com/jetoile/project-template-archetype"&gt;https://github.com/jetoile/project-template-archetype&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cependant, je n'ai pas invoqué ici le cas de projets multimodules mais le principe reste identique, même s'il est possible d'utiliser d'autres templates (tel que __rootArtifactId__) si l'on souhaite préfixer le nom des modules avec l'artifactId du projet généré ou si l'on souhaite customiser plus finement un nom de répertoire (ou package) : dans ce cas, il peut être souhaitable d'ajouter d'autres propriétés dans le fichier archetype-metadata.xml :&lt;/div&gt;&lt;br /&gt;
&lt;pre class="brush:xml; wrap-lines: false; auto-links: false"&gt;&amp;lt;module id="${rootArtifactId}-core" dir="__rootArtifactId__-core" name="${rootArtifactId}-core"&amp;gt;
      &amp;lt;fileSets&amp;gt;
        &amp;lt;fileSet filtered="true" encoding="UTF-8" packaged="true"&amp;gt;
          &amp;lt;directory&amp;gt;src/main/java&amp;lt;/directory&amp;gt;
          &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*.java&amp;lt;/include&amp;gt;
          &amp;lt;/includes&amp;gt;
        &amp;lt;/fileSet&amp;gt;
        &amp;lt;fileSet filtered="true" encoding="UTF-8" packaged="true"&amp;gt;
          &amp;lt;directory&amp;gt;src/test/java&amp;lt;/directory&amp;gt;
          &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*.java&amp;lt;/include&amp;gt;
          &amp;lt;/includes&amp;gt;
        &amp;lt;/fileSet&amp;gt;
      &amp;lt;/fileSets&amp;gt;
    &amp;lt;/module&amp;gt;
    &amp;lt;module id="${rootArtifactId}-client" dir="__rootArtifactId__-client" name="${rootArtifactId}-client"&amp;gt;
      &amp;lt;fileSets&amp;gt;
        &amp;lt;fileSet filtered="true" encoding="UTF-8" packaged="true"&amp;gt;
          &amp;lt;directory&amp;gt;src/main/java&amp;lt;/directory&amp;gt;
          &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*.java&amp;lt;/include&amp;gt;
          &amp;lt;/includes&amp;gt;
        &amp;lt;/fileSet&amp;gt;
        &amp;lt;fileSet filtered="true" encoding="UTF-8" packaged="true"&amp;gt;
          &amp;lt;directory&amp;gt;src/main/resources&amp;lt;/directory&amp;gt;
          &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*.xml&amp;lt;/include&amp;gt;
            &amp;lt;include&amp;gt;**/*.properties&amp;lt;/include&amp;gt;
          &amp;lt;/includes&amp;gt;
        &amp;lt;/fileSet&amp;gt;
        &amp;lt;fileSet filtered="true" encoding="UTF-8" packaged="true"&amp;gt;
          &amp;lt;directory&amp;gt;src/test/resources&amp;lt;/directory&amp;gt;
          &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*.xml&amp;lt;/include&amp;gt;
            &amp;lt;include&amp;gt;**/*.properties&amp;lt;/include&amp;gt;
          &amp;lt;/includes&amp;gt;
        &amp;lt;/fileSet&amp;gt;
      &amp;lt;/fileSets&amp;gt;
    &amp;lt;/module&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-VL7re_vr97E/TevFPbO9msI/AAAAAAAAAXY/tXBaVB_kG-0/s1600/archetype03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/-VL7re_vr97E/TevFPbO9msI/AAAAAAAAAXY/tXBaVB_kG-0/s320/archetype03.png" width="192" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h1&gt;Pour aller plus loin...&lt;/h1&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Apache Maven&lt;/strong&gt;&amp;nbsp;de N. De Loof, A. Héritier chez Pearson&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Better Builds with Maven&lt;/strong&gt;&amp;nbsp;:&amp;nbsp;&lt;a href="http://repo.exist.com/dist/maestro/1.7.0/BetterBuildsWithMaven.pdf"&gt;http://repo.exist.com/dist/maestro/1.7.0/BetterBuildsWithMaven.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Maven. Definitive Guide&lt;/strong&gt;&amp;nbsp;:&amp;nbsp;&lt;a href="http://www.sonatype.com/products/maven/documentation/book-defguide"&gt;http://www.sonatype.com/products/maven/documentation/book-defguide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Site de maven&lt;/strong&gt;&amp;nbsp;:&amp;nbsp;&lt;a href="http://maven.apache.org/"&gt;http://maven.apache.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-7426476454268958486?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=oftBj70zX88:ckswTZZb6DE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=oftBj70zX88:ckswTZZb6DE:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=oftBj70zX88:ckswTZZb6DE:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/7426476454268958486/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/06/maven-pour-les-nuls-les-archetypes.html#comment-form" title="2 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/7426476454268958486?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/7426476454268958486?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/06/maven-pour-les-nuls-les-archetypes.html" title="Maven pour les nuls... les archetypes" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-l-NZQRxE0vI/TevA5LfJQ_I/AAAAAAAAAXI/IP8zRk4wbeg/s72-c/maven-logo-2.gif" height="72" width="72" /><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;DUIBRXY5eCp7ImA9WhZWGEU.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-6990079871298020010</id><published>2011-05-20T12:32:00.000+02:00</published><updated>2011-05-20T12:32:34.820+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-20T12:32:34.820+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="nexus" /><category scheme="http://www.blogger.com/atom/ns#" term="maven" /><title>Les repositories Manager pour les nuls... focus sur Nexus</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-E8NziC8CXkk/TdY_sPIbLmI/AAAAAAAAAWY/kSnZW5IE2_g/s1600/nexus01.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-E8NziC8CXkk/TdY_sPIbLmI/AAAAAAAAAWY/kSnZW5IE2_g/s1600/nexus01.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cela fait un moment que je n'ai pas bloggé faute de temps mais également d'inspiration... (ça c'est dit et ça, on s'en fout d'un coté ;-) ) Cet article parlera des repository manager. Rien de nouveau à l'horizon puisque la problématique et les solutions existent depuis un moment mais ayant dû en mettre un en place récemment et au vu de nombreuses questions que l'on m'a posées, je vais ici coucher sur "papier" ce qu'est un repository manager, c'est à dire quelques uns de ses concepts clés. En outre, cela me servira également d'aide mémoire et je me dis qu'une piqûre de rappel ne fait jamais de mal... ;-)&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour ce faire, je vais m'appuyer sur l'excellent repository manager &lt;a href="http://www.sonatype.com/products.html"&gt;Nexus de Sonatype&lt;/a&gt; et plus particulièrement (comme à mon habitude... ;-) ) sur &lt;a href="http://www.sonatype.com/repository-management-with-nexus-book.html"&gt;sa documentation officielle&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Par contre, je ne reviendrai pas sur les concepts de base de maven comme la définition de ce que sont les repositories local et distant.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enfin, ici, j'utiliserai la même dénomination que le guide Nexus pour le terme organisation qui devra être pris au sens large du terme (entreprise, projet open source, poste local, ...).&lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1 style="text-align: justify;"&gt;Un repository Manager pour quoi faire?&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Ce paragraphe fournit une courte introduction sur les repository Manager, qui pour ceux qui en douteraient encore, permet de répondre à deux problématiques :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;il agit comme un proxy configurable entre votre organisation et les repositories publics maven,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;il permet d'organiser l'endroit où se feront les déploiements des projets maven spécifiques à l'organisation.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;En fait, ils sont le pendant de ce que sont les outils SCM (&lt;em&gt;Source Code Management&lt;/em&gt;) au code source mais appliqué aux dépendances et aux artéfacts maven générés par le build.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Aussi, un repository Manager est un élément clé d'une usine logicielle en permettant, entre autre, une meilleure collaboration entre les développeurs et la mise à disposition de leurs binaires.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En effet, fournir un proxy (faisant également office de cache) à un repository maven public distant permet d'accélérer le processus de build en évitant les téléchargements inutiles sur internet : si une dépendance particulière est nécessaire (ainsi que ses dépendances transitives), elle ne sera téléchargée qu'une et une seule fois du repository public distant et sera mise à disposition de &lt;strong&gt;tous&lt;/strong&gt; les développeurs.&amp;nbsp;En outre, si un projet dépend de dépendances snapshot, maven, par défaut, tente d'accéder, à chaque build, aux repositories distants afin de vérifier s'il n'existe pas une version plus récente que celle présente dans le repository local. Le fait d'avoir un repository manager permet de &lt;em&gt;scheduler&lt;/em&gt;&amp;nbsp;ces mises à jour en fonction du besoin afin d'éviter un traffic trop important et parfois inutile.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;De plus, un repository Manager permet à l'organisation de garder le contrôle de ce qui est téléchargé par maven empêchant ainsi à nos chers développeurs (dont je fais parti) de tirer n'importe quelle dépendance (ainsi que n'importe quelle version) dans son projet mais également de contrôler les licences des dépendances utilisés (c'est vrai que cela serait dommage de voir son projet tomber dans l'open source juste à cause d'une licence un peu trop contaminatrice...).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enfin, un repository manager permet de fournir un repository partagé par tout ou parti de l'organisation offrant ainsi un repository privé où peuvent être entreposés les binaires de cette dernière, les rendant ainsi accessibles à tout ou parti des équipes de développement. Ces binaires pouvant être dans un état stable (release) ou en cours de développement (snapshot) permettent ainsi aux développeurs de ne pas à avoir à récupérer et à builder les sources lorsqu'une dépendance à une librairie interne est nécessaire.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Dernier point qui peut avoir son importance, mais si l'organisation se retrouve coupé d'internet ou que les repositories publics maven sont indisponibles, cela n'impacte pas les développeurs (modulo le fait qu'ils n'aient pas besoin d'une dépendance ne se trouvant pas sur le repository manager) qui peuvent alors continuer à travailler et même à releaser leurs projets, et cela même s'ils disposent d'un repository local vierge.&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Retour sur les types de repositories possibles&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Cet article prenant ses racines dans la documentation officielle de Nexus, il est possible que certains types de repositories présentés ci-dessous ne soient pas offerts par d'autres implémentations. Cependant, les concepts sont similaires même si certaines subtilités peuvent être présentes dans d'autres solutions.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Nexus offre 3 types de repositories :&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Z4HaCDB8Eho/TdZAASMnH8I/AAAAAAAAAWc/96XhX5UdsQQ/s1600/nexus05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-Z4HaCDB8Eho/TdZAASMnH8I/AAAAAAAAAWc/96XhX5UdsQQ/s1600/nexus05.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;strong&gt;Proxy Repository&lt;/strong&gt; qui, comme son nom l'indique peut être vu comme le proxy d'un repository distant. Par défaut, Nexus vient configuré avec les proxies suivants :&amp;nbsp;&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;apache-snapshots (&lt;a href="http://people.apache.org/repo/m2-snapshot-repository"&gt;http://people.apache.org/repo/m2-snapshot-repository&lt;/a&gt;),&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;codehaus-snapshot (&lt;a href="http://snapshots.repository.codehaus.org/"&gt;http://snapshots.repository.codehaus.org/&lt;/a&gt;), &amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;et maven-central-repo (&lt;a href="http://repo1.maven.org/maven2/"&gt;http://repo1.maven.org/maven2/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;div style="text-align: justify;"&gt;&lt;strong&gt;Hosted Repository&lt;/strong&gt; qui sont des repositories hébergés par Nexus. Par défaut, Nexus vient configuré avec les hosted repositories suivants :&amp;nbsp;&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;em&gt;3rd Party&lt;/em&gt; devant être utilisé pour des librairies non présentes dans les repositories maven publics&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;em&gt;Releases&lt;/em&gt; devant être utilisé pour les librairies stable de l'organisation&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;em&gt;Snapshots&lt;/em&gt; devant être utilisé pour les librairies en cours de développement de l'organisation&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Virtual Repository&lt;/strong&gt; qui peut être vu comme un adaptateur de repositories au format différents que ceux attendus. Par défaut, Nexus vient configuré avec 2 virtual repository permettant la conversion de repository au format maven 1 et 2 vers (respectivement) des repositories au format maven 2 et maven 1.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-2j9iQR-sn4Q/TdZAGVFRyiI/AAAAAAAAAWg/4D9WVWTH-38/s1600/nexus02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="131" src="http://3.bp.blogspot.com/-2j9iQR-sn4Q/TdZAGVFRyiI/AAAAAAAAAWg/4D9WVWTH-38/s400/nexus02.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En outre, Nexus propose la notion de &lt;strong&gt;groupe&lt;/strong&gt; qui permet de combiner de multiples repositories sous la même url d'accès. Ainsi, cela permet d'alléger la configuration du fichier settings.xml en offrant, sous la houlette d'un groupe, l'aggrégation de plusieurs repositories pouvant être de différentes natures.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Par exemple, Nexus vient configuré avec les deux groupes suivants :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;em&gt;public&lt;/em&gt; qui regroupe les repositories&amp;nbsp;3rd Party,&amp;nbsp;releases et snapshots du repository maven-central-repo,&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-DIrq1MhM_oQ/TdZAOhG1WtI/AAAAAAAAAWk/hKnBf0lI2mo/s1600/nexus03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="360" src="http://1.bp.blogspot.com/-DIrq1MhM_oQ/TdZAOhG1WtI/AAAAAAAAAWk/hKnBf0lI2mo/s400/nexus03.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li style="text-align: justify;"&gt;et &lt;em&gt;public-snapshots&lt;/em&gt; qui regroupe les repositories apache snapshots et codehaus snapshot.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-AMfb7cXEBPg/TdZAUedthTI/AAAAAAAAAWo/8GTVLZCGYys/s1600/nexus04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="322" src="http://1.bp.blogspot.com/-AMfb7cXEBPg/TdZAUedthTI/AAAAAAAAAWo/8GTVLZCGYys/s400/nexus04.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;Il est à noter que l'ordre de déclaration des repositories dans un groupe a son importance puisque la recherche est ordonnée et que dès que la librairies est trouvée, la recherche s'arrête et l'artéfact rendu (ainsi, il convient de mettre le repository succeptible de posséder les librairies les plus recherchés en premier).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En outre, il est possible d'associer à un groupe des routes qui se comportent comme des filtres permettant ainsi d'inclure ou d'exclure des repositories. Cette fonctionnalité peut, par exemple, être utilisée afin d'être sûr que les artéfacts récupérés dans un groupe donné ne sont que ceux de l'organisation (en s'appuyant sur le &lt;em&gt;groupId&lt;/em&gt; maven).&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-AxzBLRMUcQA/TdZAcBJX_oI/AAAAAAAAAWs/btqGC8lg5r8/s1600/nexus06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/-AxzBLRMUcQA/TdZAcBJX_oI/AAAAAAAAAWs/btqGC8lg5r8/s400/nexus06.png" width="355" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h1 style="text-align: justify;"&gt;Gestion des repositories dans le cas où plusieurs équipes accèdent au même repository Manager&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Ces recommandations s'appuient sur le chapitre 17 du guide sur Nexus.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Les façons les plus communes pour supporter différentes équipes est :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;d'associer&amp;nbsp;spécifiquement&amp;nbsp;à chaque équipe/projet deux repositories (un repository release et un repository snapshot) en leurs associant les bons droits.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;d'avoir un ou des ensembles de deux repositories (release et snapshot) pour l'ensemble de l'organisation et de contrôler l'accès en utilisant des repository target dans la gestion des privilèges d'accès par un rôle aux repositories. Ce sont ces rôles qui peuvent ensuite être associés aux utilisateurs pour gérer la sécurité.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-bK8Hh_gtn-c/TdZAqwhpudI/AAAAAAAAAWw/cCWKhZDbaTI/s1600/nexus07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="251" src="http://2.bp.blogspot.com/-bK8Hh_gtn-c/TdZAqwhpudI/AAAAAAAAAWw/cCWKhZDbaTI/s400/nexus07.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-z7V2gLhRfqM/TdZA0XKmyjI/AAAAAAAAAW0/tqsv5yFtymc/s1600/nexus08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="380" src="http://1.bp.blogspot.com/-z7V2gLhRfqM/TdZA0XKmyjI/AAAAAAAAAW0/tqsv5yFtymc/s400/nexus08.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-mQZmpHgoHkw/TdZA7Xrs5oI/AAAAAAAAAW4/2LplkYKr-1Y/s1600/nexus09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="380" src="http://3.bp.blogspot.com/-mQZmpHgoHkw/TdZA7Xrs5oI/AAAAAAAAAW4/2LplkYKr-1Y/s400/nexus09.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-pOaBDAUQ5v0/TdZBAv3nkrI/AAAAAAAAAW8/kpJampXGKe0/s1600/nexus10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="281" src="http://4.bp.blogspot.com/-pOaBDAUQ5v0/TdZBAv3nkrI/AAAAAAAAAW8/kpJampXGKe0/s400/nexus10.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h1 style="text-align: justify;"&gt;Trucs et astuces en vrac...&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Enfin, ce paragraphe liste en vrac un certain nombre de points qu'il peut être nécessaire de prendre en compte lors de la mise en oeuvre d'un repository Manager.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ayant la flemme de commenter les différents points, je ne jetterai que les idées sans ordre de préférence en laissant le soin à chacun de les prendre en compte... ou pas... ;-)&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Utilisation et mise en oeuvre de repository de &lt;em&gt;Staging&lt;/em&gt;.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Attention au &lt;em&gt;distributionManagement&lt;/em&gt; se trouvant dans le pom parent (ce qui est une bonne pratique malgré tout) : il peut être nécessaire de positionner cette information dans le fichier settings.xml via des propriétés afin de permettre une éventuelle migration&amp;nbsp;du repository Manager sur&amp;nbsp;un autre serveur (et s'il n'est pas possible d'avoir un DNS) et cela sans avoir à maintenir à tout jamais une redirection apache (cf. bonnes pratiques maven) (&lt;a href="http://maven.40175.n5.nabble.com/Can-t-specify-distributionManagement-in-settings-xml-td3181781.html"&gt;http://maven.40175.n5.nabble.com/Can-t-specify-distributionManagement-in-settings-xml-td3181781.html&lt;/a&gt;).&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Le repository Manager étant un élément clé de l'usine logicielle au même titre qu'un annuaire d'entreprise pour une entreprise, il peut s'apparenter à un &lt;em&gt;Single Point Of Failure&lt;/em&gt; (même s'il est possible de le mirrorer). Aussi, il convient de superviser le serveur avec soin (CPU, RAM, IO, espace disque, ...) et si possible de posséder une machine dédiée à cette tache. En outre, il convient de faire attention, si une VM est utilisée, de lui affecter suffisamment de ressources qu'elles soient réseau ou autre.&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Mettre en place un Repository Manager, même s'il s'agit d'une tache aisée, peut demander du temps mais également quelques connaissances de base. Aussi, il ne faut pas prendre cette tache à la légère, en particulier concernant les choix d'organisation des différents repositories ainsi que des choix de sécurité. En effet, migrer d'une solution à une autre, même si cela est généralement possible, peut avoir des conséquences sur l'ensemble du parc informatique de développement.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Un repository Manager (ou plutôt ses&amp;nbsp;hosted&amp;nbsp;repositories) contenant les binaires et éventuellement les livrables des projets, il est important de le sauvegarder avec soin.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Il convient de réfléchir aux besoins de mettre en place une authentification des différents repositories et, dans ce cas, du besoin de la coupler à un annuaire.&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Il convient de faire attention à l'ordre de résolution des différents repositories au risque de diminuer les performances de recherche et de téléchargement des différentes librairies.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Il convient de bien configurer les différentes taches d'administration et de maintenance du repository Manager (reindéxation, suppression des snaphots obsolètes, ...).&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-q-ibFGeayTU/TdZBL9AfMxI/AAAAAAAAAXA/4AZv5qunm_A/s1600/nexus11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="363" src="http://1.bp.blogspot.com/-q-ibFGeayTU/TdZBL9AfMxI/AAAAAAAAAXA/4AZv5qunm_A/s400/nexus11.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enfin un point transverse, mais si la sécurité est mise en place sur les repositories et qu'elle utilise une authentification pour chaque utilisateur, il est possible de crypter les mots de passe plutôt que de les avoir en clair dans le fichier settings.xml (&lt;a href="http://sonatype.com/books/maven-book/reference/appendix-settings-sect-encrypting-passwords.html"&gt;http://sonatype.com/books/maven-book/reference/appendix-settings-sect-encrypting-passwords.html&lt;/a&gt;&amp;nbsp;et&amp;nbsp;&lt;a href="http://maven.apache.org/guides/mini/guide-encryption.html"&gt;http://maven.apache.org/guides/mini/guide-encryption.html&lt;/a&gt;).&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Conclusion&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Vous aurez compris (si vous avez lu juste qu'au bout cet article) que cet article correspond plus à un aide-mémoire qu'à une vrai explication de ce qu'est un repository Manager... ;-)&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Concernant les trucs et astuces, si vous en avez d'autre, je suis preneur et je me ferai un plaisir les intégrer dans la rubrique trucs et astuces ;-)&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Pour aller plus loin...&lt;/h1&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Pdf de Sonatype sur Nexus&lt;/strong&gt;&amp;nbsp;:&amp;nbsp;&lt;a href="http://www.sonatype.com/repository-management-with-nexus-book.html"&gt;http://www.sonatype.com/repository-management-with-nexus-book.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Apache Maven&lt;/strong&gt; de N. De Loof, A. Héritier chez Pearson&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Better Builds with Maven&lt;/strong&gt; : &lt;a href="http://repo.exist.com/dist/maestro/1.7.0/BetterBuildsWithMaven.pdf"&gt;http://repo.exist.com/dist/maestro/1.7.0/BetterBuildsWithMaven.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt; &lt;strong&gt;Maven. Definitive Guide&lt;/strong&gt; : &lt;a href="http://www.sonatype.com/products/maven/documentation/book-defguide"&gt;http://www.sonatype.com/products/maven/documentation/book-defguide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Site de maven&lt;/strong&gt; : &lt;a href="http://maven.apache.org/"&gt;http://maven.apache.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-6990079871298020010?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=OY4MLJotdQg:g_GyKMPx5s0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=OY4MLJotdQg:g_GyKMPx5s0:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=OY4MLJotdQg:g_GyKMPx5s0:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/6990079871298020010/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/05/les-repositories-manager-pour-les-nuls.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/6990079871298020010?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/6990079871298020010?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/05/les-repositories-manager-pour-les-nuls.html" title="Les repositories Manager pour les nuls... focus sur Nexus" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-E8NziC8CXkk/TdY_sPIbLmI/AAAAAAAAAWY/kSnZW5IE2_g/s72-c/nexus01.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0MFSHg5eip7ImA9WhdXE0o.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-6359521361675373398</id><published>2011-03-22T01:03:00.007+01:00</published><updated>2011-08-26T17:10:19.622+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-26T17:10:19.622+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="perfomance" /><title>MicroBenchmark : par la pratique</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh4.googleusercontent.com/-VYpiI5ySjEA/TYKVFQyw27I/AAAAAAAAAU0/XDPtplNTTKQ/s1600/perf03.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" height="173" src="https://lh4.googleusercontent.com/-VYpiI5ySjEA/TYKVFQyw27I/AAAAAAAAAU0/XDPtplNTTKQ/s1600/perf03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Cet article fait suite à mon article précédent afin de donner mon rapide retour d'expérience sur quelques écueils qui peuvent être commis lors de l'écriture d'un microBenchmark et dans lesquels je suis, bien sûr, tombé :(. Pour remettre dans le contexte, c'est l'écriture de ce benchmark qui a entrainé l'écriture de mon article précédent suite aux résultats que j'ai pu constater et pour lesquels j'ai eu l'aide de&amp;nbsp;&lt;a href="http://jetoile.blogspot.com/2011/03/microbenchmark-par-la-pratique.html#remerciement"&gt;mes camarades&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1&gt;Contexte&lt;/h1&gt;Un collègue me&amp;nbsp;disait que le foreach était moins performant qu'une boucle for en raison du fait que l'invocation d'une opération supplémentaire (la méthode next()) rendait l'opération plus lente en raison de la pile de notre cher compteur ordinal (pour ceux qui ne se rappelleraient pas, je vous renvoie sur vos cours d'assembleur ;-) ), enfin que, du moins, en .Net ça marchait comme ça. Ma réponse : "ben j'en sais rien" puisque je ne savais pas quelles étaient les optimisations faites par le compilateur (ouais, je sais, super les sujets de conversation...).&lt;br /&gt;
Du coup,&amp;nbsp;ni une, ni deux, j'ai ouvert mon IDE préféré et j'y ai jeté quelques lignes de code pour avoir ma réponse, et là... ce fut le drame... : des résultats bizarres sont apparus...&lt;br /&gt;
Ce petit article a donc pour objectif de vous fournir le résultat de ce qu'il faut faire et ne pas faire lors de l'écriture d'un microBenchmark mais également de fournir la réponse que tout le monde attend, à savoir :&amp;nbsp;&lt;b&gt;qui est réellement le plus fort entre le for et le foreach&lt;/b&gt;&amp;nbsp;(ça peut éviter d'avoir à perdre 5 minutes de test...).&lt;br /&gt;
Bien sûr, n'étant pas expert dans ce domaine, il s'agit juste d'un retour d'expérience dont je vous laisse seul juge de la véracité... ;-)&lt;br /&gt;
&lt;u&gt;Premier disclaimer&lt;/u&gt; : contrairement à ce que j'ai présenté dans mon &lt;a href="http://jetoile.blogspot.com/2011/03/microbenchmark-mode-d.html"&gt;post précédent&lt;/a&gt;, je n'effectuerai pas, ici, différents tirs sur différentes architectures d'ordinateurs, VM ou avec différentes options. En effet, ce qui m'intéresse dans cet article est d'entrevoir ce qui peut se passer dans la VM et comment cela peut impacter les performances d'un petit bout de code.&lt;br /&gt;
&lt;u&gt;Deuxième disclaimer&lt;/u&gt; : lors de la procédure d'élagage, un coefficient de 0,5 sera utilisé afin de lisser au maximum mes résultats et cela, en raison de pics très importants observés (pics liés, comme nous le verrons par la suite soit, au warm-up de la JVM, soit au GC).&lt;br /&gt;
&lt;h1&gt;Procédure de test et analyse&lt;/h1&gt;&lt;h2&gt;Première tentative&lt;/h2&gt;&lt;h3&gt;Scénario&lt;/h3&gt;Ma première tentative de benchmark était la suivante :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;on instancie une liste d'un chaîne de caractère,&lt;/li&gt;
&lt;li&gt;on itère dessus sans rien faire,&lt;/li&gt;
&lt;li&gt;on regarde le temps passé.&lt;/li&gt;
&lt;/ul&gt;Ce petit test sera exécuté une centaine de fois afin de pouvoir lisser le résultat.&lt;br /&gt;
Le code utilisé pour faire ce petit test est le suivant :&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class IterableBenchmark0 {

    private final static int NB_ITEM = 100000;
    private final static int NB_TEST = 100;

    static List&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;String&amp;gt;(NB_ITEM);

    static {
        for (int i = 0; i &amp;lt; NB_ITEM; i++) {
            list.add(Integer.toString(i));
        }
    }

    public static void main(String[] args) {
        Long[] res = new Long[NB_TEST];
        for (int j = 0; j &amp;lt; NB_TEST; j++) {

            long startTime = System.nanoTime();
            for (int i = 0; i &amp;lt; list.size(); i++) {
            }

            // for (String value : list) {
            // }

            // int i = 0;
            // while (i &amp;lt; list.size()) {
            // i++;
            // }

            res[j] = (System.nanoTime() - startTime);
        }

        long total = 0;
        for (int j = 0; j &amp;lt; NB_TEST; j++) {
            total += res[j];
            System.out.println(res[j]);
        }
        System.out.println("sum : " + total);
        System.out.println("moy : " + total / NB_TEST);
    }
}&lt;/pre&gt;On y constate, bien sûr, que la récupération des métriques n’encadre que l’opération à tester mais, également, que l’instanciation et l’initialisation de l’&lt;i&gt;ArrayList&lt;/i&gt; utilisé ici sont faites en dehors du test.&lt;br /&gt;
&lt;h3&gt;Résultats&lt;/h3&gt;Suite à ce test, les résultats obtenus ont été les suivants :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/-lI9NU2jROeg/TYfWEzjCs-I/AAAAAAAAAU8/9qW3rgg2xJM/s1600/naif_res01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="50" src="https://lh5.googleusercontent.com/-lI9NU2jROeg/TYfWEzjCs-I/AAAAAAAAAU8/9qW3rgg2xJM/s320/naif_res01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-BjIbhc2E824/TYfWbycgbTI/AAAAAAAAAVA/xi74Zdu2He0/s1600/naif_res02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="https://lh3.googleusercontent.com/-BjIbhc2E824/TYfWbycgbTI/AAAAAAAAAVA/xi74Zdu2He0/s320/naif_res02.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Après élagage des résultats abérants (procédé commun à tous tes des charges), ces résultats peuvent être réduits aux résultats suivants (ici, k = 0,5) :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/-Ld9lihH08bE/TYfWw4vaxFI/AAAAAAAAAVE/zVJXILl4wtg/s1600/naif_res03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="168" src="https://lh5.googleusercontent.com/-Ld9lihH08bE/TYfWw4vaxFI/AAAAAAAAAVE/zVJXILl4wtg/s320/naif_res03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;A noter que ce graphique n'a été issu que d'un seul tir... mais, si vous daignez croire mes dires, il est assez représentatif des autres tirs.&lt;br /&gt;
&lt;h3&gt;Analyse&lt;/h3&gt;Les résultats précédents montrent clairement une différence entre les tirs avec et sans élagages (normal me direz-vous). Cependant, elles apparaissent principalement sur les deux premières itérations de notre boucle chargée d'itérer notre &lt;i&gt;List&lt;/i&gt;.&lt;br /&gt;
En outre, après élagage, on constate, malgré tout, qu'une nette différence persiste entre les boucles for et while et notre foreach.&lt;br /&gt;
A titre informatif, c'est à ce moment là que j'ai dû appeler mes amis (ça ne vous rappelle pas quelque chose...?) &amp;nbsp;pour obtenir une analyse plus précise des résultats que je ne comprenais pas... :(&lt;br /&gt;
Du coup (et là, je ne vais pas me fouler ;-) ), je vous cite les réponses des différents intéressés (et oui, il est possible d'avoir plusieurs amis... (si cela vous amuse, je vous laisse deviner qui a dit quoi) que je remercie encore une fois ;-) :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;première réponse :&lt;/li&gt;
&lt;/ul&gt;&lt;blockquote&gt;Ces résultats sont parfaitement logiques.&lt;br /&gt;
Pour for et while, la VM s'aperçoit au bout de quelques itérations que la boucle est inutile.&lt;br /&gt;
- on connaît le nombre d'itérations sans avoir besoin d'itérer réellement sur la liste (list.size() est fixe) ;&lt;br /&gt;
- la boucle n'a aucun "side-effect" en-dehors.&lt;br /&gt;
Du coup, la boucle entière est éliminée, d'où les temps nuls.&lt;br /&gt;
Pour for-each, c'est plus compliqué :&lt;br /&gt;
- La notation syntaxique "for-each" est compilée sous la forme d'un parcours d'itérateur :&lt;br /&gt;
for (Iterator it=list.iterator(); it.hasNext; ) { ... }&lt;br /&gt;
Du coup, impossible de connaître le nombre d'itérations à l'avance : la JVM est obligée de tout parcourir&lt;br /&gt;
- En plus, pour éviter les modifications concurrentes de la collection (celles qui lancent le fameux ConcurrentModificationException), la méthode next() effectue des vérifications, qui prennent du temps.&lt;br /&gt;
Bref, dans ce cas, for-each est moins performant, ou du moins, nettement moins optimisable, que "for" ou "while"&lt;br /&gt;
Si tu veux un test plus représentatif des performances réelles, moins sujettes à des optimisations agressives, il faut que les boucles aient un "side-effect" (par exemple, ajouter chaque élément parcouru dans une seconde liste, située en-dehors de la boucle).&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;deuxième réponse :&lt;/li&gt;
&lt;/ul&gt;&lt;blockquote&gt;(...) la Hotspot utilise la zone "code cache" pour cacher des informations à la volée et compiler du code plus optimisé grâce à JIT en fonction des hotspots détectés.&amp;nbsp;Je viens de retrouver un post sur le blog de Sun qui confirme ce mécanisme. Il montre un exemple sur l'optimisation d'une boucle while:&amp;nbsp;&lt;a _mce_href="http://blogs.sun.com/ahe/entry/hotspot_and_other_compilers" href="http://blogs.sun.com/ahe/entry/hotspot_and_other_compilers"&gt;http://blogs.sun.com/ahe/entry/hotspot_and_other_compilers&lt;/a&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;troisième réponse :&lt;/li&gt;
&lt;/ul&gt;&lt;blockquote&gt;&lt;div&gt;Alors tout d'abord, je pense que comparer le for et le foreach n'a pas de sens en soi...&amp;nbsp;En effet, il ne faut pas oublier que quand tu écrit ton code Java, celui-ci est compilé en .class (bytecode).&lt;/div&gt;&lt;div&gt;Ces .class sont alors interprétés ou compilés à la volées (par le compilateur Just In Time).&amp;nbsp;&lt;/div&gt;&lt;div&gt;De plus, comme tout micro-benchmark Java, il faut se méfier des résultats.&lt;/div&gt;&lt;div&gt;Tout simplement, le comportement de la JVM (Hotspot) change du tout au tout en fonction des&amp;nbsp;paramètres VM (-server et -client, les cycles d'optimisation...)&lt;/div&gt;&lt;div&gt;Ensuite, si ton code est fort utilisé, il sera automatiquement "inliné" par le JIT...&amp;nbsp;&lt;/div&gt;&lt;/blockquote&gt;Je pense que les conclusions à tirer sont claires... le code testé est erroné : mon Compilateur Planning m'a inliné le code à tester et le fait que les deux premières itérations soit si élevées par rapport aux autres résultats est lié au&amp;nbsp;&lt;b&gt;warm-up&lt;/b&gt;&amp;nbsp;de ma JVM.&lt;br /&gt;
&lt;h2&gt;Deuxième tentative&lt;/h2&gt;&lt;h3&gt;Scénario&lt;/h3&gt;Du coup, suite à ma première tentative de benchmark infructueuse, deuxième essai en apprenant de mes erreurs... :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;on instancie une liste d'un chaîne de caractère,&lt;/li&gt;
&lt;li&gt;on itère dessus en ajoutant un effet de bord afin d'empêcher mon Compilateur Planning de m'inliner mon code,&lt;/li&gt;
&lt;li&gt;on regarde le temps passé.&lt;/li&gt;
&lt;/ul&gt;Comme précédemment, ce petit test sera exécuté une centaine de fois afin de pouvoir lisser le résultat.&lt;br /&gt;
Le code utilisé pour faire ce petit test est le suivant :&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class IterableBenchmark1 {

    private final static int NB_ITEM = 100000;
    private final static int NB_TEST = 100;

    static List&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;String&amp;gt;(NB_ITEM);

    static {
        for (int i = 0; i &amp;lt; NB_ITEM; i++) {
            list.add(Integer.toString(i));
        }
    }

    static StringBuilder sideEffect = new StringBuilder();

    public static void main(String[] args) {
        Long[] res = new Long[NB_TEST];
        for (int j = 0; j &amp;lt; NB_TEST; j++) {

            long startTime = System.nanoTime();
            for (int i = 0; i &amp;lt; list.size(); i++) {
                sideEffect.append(list.get(i));
            }

            // for (String value : list) {
            // sideEffect.append(value);
            // }

            // int i = 0;
            // while (i &amp;lt; list.size()) {
            // sideEffect.append(list.get(i));
            // i++;
            // }

            res[j] = (System.nanoTime() - startTime);
        }

        long total = 0;
        for (int j = 0; j &amp;lt; NB_TEST; j++) {
            total += res[j];
            System.out.println(res[j]);
        }
        System.out.println("sum : " + total);
        System.out.println("moy : " + total / NB_TEST);
    }
}&lt;/pre&gt;&lt;h3&gt;Résultats&lt;/h3&gt;Suite à ce test, les résultats obtenus ont été les suivants :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/--yfx7Mdby8c/TYfXtahEIoI/AAAAAAAAAVI/uscIVmjqEsQ/s1600/sideEffect_res01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="46" src="https://lh5.googleusercontent.com/--yfx7Mdby8c/TYfXtahEIoI/AAAAAAAAAVI/uscIVmjqEsQ/s320/sideEffect_res01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh4.googleusercontent.com/-Sze5evxC3P0/TYfX867p4ZI/AAAAAAAAAVM/gZU-aP_AeyY/s1600/sideEffect_res02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="https://lh4.googleusercontent.com/-Sze5evxC3P0/TYfX867p4ZI/AAAAAAAAAVM/gZU-aP_AeyY/s320/sideEffect_res02.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Après élagage des résultats aberrants (procédé commun à tous tests des charges), ces résultats peuvent être réduits aux résultats suivants (ici, k = 0,5) :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-3ekZo0BCGY4/TYfYLLB_TiI/AAAAAAAAAVQ/mz52DXajycg/s1600/sideEffect_res03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="168" src="https://lh3.googleusercontent.com/-3ekZo0BCGY4/TYfYLLB_TiI/AAAAAAAAAVQ/mz52DXajycg/s320/sideEffect_res03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;A noter que ce graphique n'est toujours isssu que d'un seul tir...&lt;br /&gt;
&lt;h3&gt;Analyse&lt;/h3&gt;Les résultats semblent enfin cohérents! ouf...!&lt;br /&gt;
En effet, on constate que, mis à part les &lt;b&gt;GC&lt;/b&gt;, et le &lt;b&gt;warm-up&lt;/b&gt; de ma VM, mon Compilateur Planning n'a pas réussi à inliner mon code et me fournit, du coup, le résultat attendu.&lt;br /&gt;
Après un coup d'élagage me permettant de me débarrasser de mes pics liés au GC, mes courbes sont lissées et se chevauchent même.&lt;br /&gt;
Enfin, j'ai ma réponse (mais je garde ça pour plus tard même si je suppose que, du coup, vous connaissez le fin mot de l'histoire!... mais attendez, ne partez pas... la suite est intéressante également ;-))&lt;br /&gt;
&lt;h2&gt;Troisième tentative&lt;/h2&gt;&lt;h3&gt;Scénario&lt;/h3&gt;Bon, il est vrai, j'ai obtenu mon résultat sur ma deuxième tentative.&lt;br /&gt;
Cependant, pendant la présentation de Joshua Bloch (cf. &lt;a href="http://jetoile.blogspot.com/2011/03/microbenchmark-mode-d.html"&gt;post précédent&lt;/a&gt;), un point m'a particulièrement intéressé : le framework &lt;b&gt;Caliper&lt;/b&gt;.&lt;br /&gt;
En effet, ce framework semble être fait pour répondre aux problématiques des microBenchmark.&lt;br /&gt;
Du coup, je vais, ici, montrer comment je l'ai utilisé ainsi que les résultats qu'il m'a fourni.&lt;br /&gt;
Deux raisons à cela :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;valider mes résultats précédents afin de vérifier que je n'ai rien laissé passer...&lt;/li&gt;
&lt;li&gt;m'amuser un peu... ;-)&lt;/li&gt;
&lt;/ul&gt;&lt;u&gt;Disclaimer&lt;/u&gt; :&amp;nbsp;cette partie n'abordera ni comment installer, ni comment utiliser Caliper. Elle est juste fournie à titre indicatif.&lt;br /&gt;
Le code utilisé pour faire cette troisième tentative est le suivant :&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class IterableBenchmark2 extends SimpleBenchmark {

    private final static int NB_ITEM = 100000;

    List list = new ArrayList(NB_ITEM);
    StringBuilder sideEffect = null;

    @Override
    protected void setUp() throws Exception {
        for (int i = 0; i &amp;lt; NB_ITEM; i++) {
            list.add(Integer.toString(i));
        }
        sideEffect = new StringBuilder();
    }

    public StringBuilder timeFor(int reps) {
        for (int i = 0; i &amp;lt; reps; ++i) {
            for (int j = 0; j &amp;lt; list.size(); j++) {
                sideEffect.append(list.get(j));
            }
        }
        return sideEffect;
    }

    public StringBuilder timeForeach(int reps) {
        for (int i = 0; i &amp;lt; reps; ++i) {
            for (String value : list) {
                sideEffect.append(value);
            }
        }
        return sideEffect;
    }

    public StringBuilder timeWhile(int reps) {
        for (int i = 0; i &amp;lt; reps; ++i) {
            int j = 0;
            while (j &amp;lt; list.size()) {
                sideEffect.append(list.get(j));
                j++;
            }
        }
        return sideEffect;
    }

    public static void main(String[] args) throws Exception {
        Runner.main(IterableBenchmark3.class, args);
    }
}&lt;/pre&gt;On remarque ici, que, plutôt que d'exécuter via un script extérieur mon tir, j'ai préféré le faire en invoquant directement le &lt;i&gt;main()&lt;/i&gt;.&lt;br /&gt;
&lt;h3&gt;Résultats&lt;/h3&gt;Suite à ce test, les résultats obtenus ont été les suivants :&lt;br /&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;0% Scenario{vm=java, trial=0, benchmark=For} 3535251,80 ns; σ=197827,29 ns @ 10 trials
33% Scenario{vm=java, trial=0, benchmark=Foreach} 3676070,55 ns; σ=190018,30 ns @ 10 trials
67% Scenario{vm=java, trial=0, benchmark=While} 3508898,75 ns; σ=222565,30 ns @ 10 trials

benchmark   ms linear runtime
      For 3,54 ============================
  Foreach 3,68 ==============================
    While 3,51 ============================

vm: java
trial: 0&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh4.googleusercontent.com/-Z8j93HQc0m4/TYfcBM-QiFI/AAAAAAAAAVU/4IS1Gu0Lon4/s1600/caliper01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="295" src="https://lh4.googleusercontent.com/-Z8j93HQc0m4/TYfcBM-QiFI/AAAAAAAAAVU/4IS1Gu0Lon4/s320/caliper01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/-q4_o_I_LbNw/TYfff5hOmXI/AAAAAAAAAVg/8G7hPEZSc_A/s1600/caliper011.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="59" src="https://lh5.googleusercontent.com/-q4_o_I_LbNw/TYfff5hOmXI/AAAAAAAAAVg/8G7hPEZSc_A/s320/caliper011.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Ces résultats sont donnés avec une seul tir.&lt;br /&gt;
Pour montrer comme il est aisé d'effectuer plusieurs tirs avec Caliper (tir qui lance à chaque fois une nouvelle JVM dans un process - process au sens UNIX du terme - différent), modifions juste notre méthode &lt;i&gt;main()&lt;/i&gt; pour y passer d'autres options :&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public static void main(String[] args) throws Exception {
        Runner.main(IterableBenchmark3.class, new String[] { "--trials", "5"});
    }
&lt;/pre&gt;Ce qui donne le résultat suivant :&lt;br /&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;0% Scenario{vm=java, trial=0, benchmark=For} 3425915,23 ns; σ=207711,73 ns @ 10 trials
 7% Scenario{vm=java, trial=1, benchmark=For} 3453313,87 ns; σ=193613,25 ns @ 10 trials
13% Scenario{vm=java, trial=2, benchmark=For} 3807062,28 ns; σ=278917,43 ns @ 10 trials
20% Scenario{vm=java, trial=3, benchmark=For} 3807244,53 ns; σ=283377,19 ns @ 10 trials
27% Scenario{vm=java, trial=4, benchmark=For} 3808771,58 ns; σ=270090,07 ns @ 10 trials
33% Scenario{vm=java, trial=0, benchmark=Foreach} 3504679,81 ns; σ=190093,88 ns @ 10 trials
40% Scenario{vm=java, trial=1, benchmark=Foreach} 3620052,15 ns; σ=216116,18 ns @ 10 trials
47% Scenario{vm=java, trial=2, benchmark=Foreach} 3519711,06 ns; σ=173384,58 ns @ 10 trials
53% Scenario{vm=java, trial=3, benchmark=Foreach} 3527981,05 ns; σ=232274,54 ns @ 10 trials
60% Scenario{vm=java, trial=4, benchmark=Foreach} 3549837,79 ns; σ=196295,32 ns @ 10 trials
67% Scenario{vm=java, trial=0, benchmark=While} 3628542,80 ns; σ=223275,59 ns @ 10 trials
73% Scenario{vm=java, trial=1, benchmark=While} 3569981,43 ns; σ=225773,17 ns @ 10 trials
80% Scenario{vm=java, trial=2, benchmark=While} 3596601,06 ns; σ=266773,47 ns @ 10 trials
87% Scenario{vm=java, trial=3, benchmark=While} 3493799,14 ns; σ=220276,60 ns @ 10 trials
93% Scenario{vm=java, trial=4, benchmark=While} 3642079,85 ns; σ=185312,29 ns @ 10 trials

benchmark trial   ms linear runtime
      For     0 3,43 ==========================
      For     1 3,45 ===========================
      For     2 3,81 =============================
      For     3 3,81 =============================
      For     4 3,81 ==============================
  Foreach     0 3,50 ===========================
  Foreach     1 3,62 ============================
  Foreach     2 3,52 ===========================
  Foreach     3 3,53 ===========================
  Foreach     4 3,55 ===========================
    While     0 3,63 ============================
    While     1 3,57 ============================
    While     2 3,60 ============================
    While     3 3,49 ===========================
    While     4 3,64 ============================

vm: java&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh6.googleusercontent.com/-0jMElON2GG0/TYfeIplU2lI/AAAAAAAAAVY/8Ws8IPu8_l8/s1600/caliper02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="https://lh6.googleusercontent.com/-0jMElON2GG0/TYfeIplU2lI/AAAAAAAAAVY/8Ws8IPu8_l8/s320/caliper02.png" width="274" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-Lm7FexMT_jg/TYffb2Hsi3I/AAAAAAAAAVc/xspieQ1S0pc/s1600/caliper021.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="169" src="https://lh3.googleusercontent.com/-Lm7FexMT_jg/TYffb2Hsi3I/AAAAAAAAAVc/xspieQ1S0pc/s320/caliper021.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h3&gt;Analyse&lt;/h3&gt;On constate ici que les résultats obtenus avec Caliper sont cohérents avec ceux obtenus précédemment (ie. les résultats sont similaires quelque soit la méthode d'itération), même si on remarque une légère différence due au bruit ajouté par l'utilisation du framework, bruit qui ne doit pas être pris en compte puisque si un tel framework venait à être utilisé, tous les résultats analysés seraient, évidemment, issus de l'utilisation de Caliper. En outre, n'oublions pas qu'il faut raisonner en terme de statistique et non en terme de chiffre pur...&lt;br /&gt;
&lt;h2&gt;Quatrième tentative... juste pour le fun&lt;/h2&gt;&lt;h3&gt;Scénario&lt;/h3&gt;Cette avant dernière tentative est juste faite pour le fun pour montrer le comportement de Caliper avec un microBenchmark douteux... ie. notre premier test ;-).&lt;br /&gt;
Aussi, reprenons notre troisième tentative et supprimons les effets de bord :&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class IterableBenchmark3 extends SimpleBenchmark {

    private final static int NB_ITEM = 100000;

    List list = new ArrayList(NB_ITEM);

    @Override
    protected void setUp() throws Exception {
        for (int i = 0; i &amp;lt; NB_ITEM; i++) {
            list.add(Integer.toString(i));
        }
    }

    public void timeFor(int reps) {
        for (int i = 0; i &amp;lt; reps; ++i) {
            for (int j = 0; j &amp;lt; list.size(); j++) {
            }
        }
    }

    public void timeForeach(int reps) {
        for (int i = 0; i &amp;lt; reps; ++i) {
            for (String value : list) {
            }
        }
    }

    public void timeWhile(int reps) {
        for (int i = 0; i &amp;lt; reps; ++i) {
            int j = 0;
            while (j &amp;lt; list.size()) {
                j++;
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Runner.main(IterableBenchmark3.class, args);
    }
}&lt;/pre&gt;&lt;h3&gt;Résultats&lt;/h3&gt;Suite à ce test, les résultats obtenus ont été les suivants :&lt;br /&gt;
&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;0% Scenario{vm=java, trial=0, benchmark=For}  Failed to execute java -cp /home/khanh/eclipse-workspace/benchmark/target/classes:/home/khanh/eclipse-workspace/caliper-read-only/caliper/target/classes:/home/khanh/.m2/repository/com/google/code/gson/gson/1.7-SNAPSHOT/gson-1.7-SNAPSHOT.jar:/home/khanh/.m2/repository/com/google/guava/guava/r07/guava-r07.jar:/home/khanh/.m2/repository/com/google/code/java-allocation-instrumenter/java-allocation-instrumenter/2.0/java-allocation-instrumenter-2.0.jar com.google.caliper.InProcessRunner --warmupMillis 3000 --runMillis 1000 --measurementType TIME --marker //ZxJ/ -Dbenchmark=For fr.soat.blog.benchmark.IterableBenchmark3
starting Scenario{vm=java, trial=0, benchmark=For}
[caliper] [starting warmup]
[caliper] [starting measured section]
Error: Doing 2x as much work didn't take 2x as much time! Is the JIT optimizing away the body of your benchmark?&lt;/pre&gt;&lt;h3&gt;Analyse&lt;/h3&gt;La bonne surprise est que Caliper nous indique clairement que JIT a optimisé notre code et que, donc, notre microBenchmark est erroné!&lt;br /&gt;
A voir s'il se comporte ainsi avec tous les microBenchmark erronés...&lt;br /&gt;
&lt;h2&gt;Cinquième tentative... allez, une dernière pour la route&lt;/h2&gt;&lt;h3&gt;Scénario&lt;/h3&gt;Cette dernière tentative permet de voir ce qui se passerait si on désactivait JIT via l'option -Xint.&lt;br /&gt;
Pour rappel, l'option Xint permet de :&lt;br /&gt;
&lt;blockquote&gt;Operate in interpreted-only mode. Compilation to native code is disabled, and all bytecodes are executed by the interpreter. The performance benefits offered by the Java HotSpot Client VM's adaptive compiler will not be present in this mode.&lt;/blockquote&gt;Le code utilisé est celui de notre première tentative.&lt;br /&gt;
&lt;h3&gt;Résultats&lt;/h3&gt;Suite à ce test, les résultats obtenus ont été les suivants :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/-ADT5BxKL07Y/TYfgAZ0s5aI/AAAAAAAAAVk/8pgxSKpcnL0/s1600/xint_res01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="40" src="https://lh5.googleusercontent.com/-ADT5BxKL07Y/TYfgAZ0s5aI/AAAAAAAAAVk/8pgxSKpcnL0/s320/xint_res01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh4.googleusercontent.com/-amtITqXqdR4/TYfgjLGINcI/AAAAAAAAAVo/3R_TdGss_N4/s1600/xint_res02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="https://lh4.googleusercontent.com/-amtITqXqdR4/TYfgjLGINcI/AAAAAAAAAVo/3R_TdGss_N4/s320/xint_res02.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;Après élagage des résultats aberrants (procédé commun à tous tes des charges), ces résultats peuvent être réduits aux résultats suivants (k = 1) :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh4.googleusercontent.com/-JZbaG93Z9UE/TYfgohOePMI/AAAAAAAAAVs/jgcwFKpjXl8/s1600/xint_res03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="198" src="https://lh4.googleusercontent.com/-JZbaG93Z9UE/TYfgohOePMI/AAAAAAAAAVs/jgcwFKpjXl8/s320/xint_res03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;A noter que ce graphique n'est toujours issu que d'un seul tir...&lt;br /&gt;
&lt;h3&gt;Analyse&lt;/h3&gt;Bien sûr, ces résultats ne sont pas du tout représentatifs puisque le byte code est seulement interprété par la JVM et que cela ne représente pas la réalité. Cette dernière tentative n'est présentée qu'à titre indicatif afin de constater les différences qu'il peut y avoir entre le code que l'on écrit (ou compilé) et le code qui est réellement exécuté.&lt;br /&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;Voilà, j'arrive à la fin de mes conclusions que je vous cite en vrac ;-) :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;faire un microBenchmark est difficile et cet article ne montre qu'une ébauche des difficultés que cela peut poser,&lt;/li&gt;
&lt;li&gt;il est plus simple d'utiliser un outil qui sait bien faire son travail,&lt;/li&gt;
&lt;li&gt;il ne faut pas toujours se fier à ce que l'on peut constater : le risque que le cas observé ne soit pas représentatif de la réalité est élevé,&lt;/li&gt;
&lt;li&gt;de manière générale, on peut dire qu'il y a match nul entre le for et le foreach (en tout cas, dans notre cas de figure!).&lt;/li&gt;
&lt;/ul&gt;Bon, un dernier mot : cet article n'apportera rien aux personnes déjà sensibilisées à ce type de problématiques et ce qu'on peut retenir est qu'il ne faut pas tenter d'optimiser inutilement son code (cf. &lt;a href="http://jetoile.blogspot.com/2011/03/microbenchmark-mode-d.html"&gt;article précédent&lt;/a&gt;). Je trouvais juste les résultats intéressants à montrer ;-)&lt;br /&gt;
&lt;br /&gt;
Ah oui, encore une chose, pour information, mon ordinateur possède les caractéristiques suivantes :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/-yR2nGEaMbxE/TYh5vTtnKdI/AAAAAAAAAWA/J4KlOIGwCWc/s1600/ordi01.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="262" src="https://lh5.googleusercontent.com/-yR2nGEaMbxE/TYh5vTtnKdI/AAAAAAAAAWA/J4KlOIGwCWc/s320/ordi01.PNG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ul&gt;&lt;/ul&gt;&lt;h1 id="remerciement"&gt;Remerciements&lt;/h1&gt;Par ordre alphabétique :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Zouheir Cadi (&lt;b&gt;@ZouheirCadi&lt;/b&gt;),&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://thecodersbreakfast.net/"&gt;Olivier Croisier&lt;/a&gt; (&lt;b&gt;@OlivierCroisier&lt;/b&gt;),&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.opensides.fr/"&gt;Arnault Jeanson&lt;/a&gt; (&lt;b&gt;@ArnaultJeanson&lt;/b&gt;),&lt;/li&gt;
&lt;li&gt;Séven Lemesle (&lt;b&gt;@slemesle&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;et &lt;a href="http://blog.ostyn.fr/"&gt;François Ostyn&lt;/a&gt; (&lt;b&gt;@ostynf&lt;/b&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;h1&gt;Pour aller plus loin...&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Présentation de Joshua Blosh sur Parleys&lt;/b&gt; : &lt;a href="http://www.parleys.com/#sl=0&amp;amp;st=5&amp;amp;id=2103"&gt;http://www.parleys.com/#sl=0&amp;amp;st=5&amp;amp;id=2103&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Site du framework Caliper&lt;/b&gt; : &lt;a href="http://code.google.com/p/caliper/"&gt;http://code.google.com/p/caliper/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Présentation de Cliff Click&lt;/b&gt; : &lt;a href="http://www.azulsystems.com/events/javaone_2009/session/2009_J1_Benchmark.pdf"&gt;http://www.azulsystems.com/events/javaone_2009/session/2009_J1_Benchmark.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Page Wiki de Sun sur le microBenchmark&lt;/b&gt; : &lt;a href="http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks"&gt;http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Page de google Android sur la gestion des perfomances&amp;nbsp; d’Android&lt;/b&gt; : &lt;a href="http://developer.android.com/guide/practices/design/performance.html"&gt;http://developer.android.com/guide/practices/design/performance.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-6359521361675373398?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=XKGZoIGC66c:zE9QDIdwVIc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=XKGZoIGC66c:zE9QDIdwVIc:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=XKGZoIGC66c:zE9QDIdwVIc:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/6359521361675373398/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/03/microbenchmark-par-la-pratique.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/6359521361675373398?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/6359521361675373398?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/03/microbenchmark-par-la-pratique.html" title="MicroBenchmark : par la pratique" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/-VYpiI5ySjEA/TYKVFQyw27I/AAAAAAAAAU0/XDPtplNTTKQ/s72-c/perf03.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0YARH07fip7ImA9WhdXE0o.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-1738912832847574177</id><published>2011-03-18T00:25:00.005+01:00</published><updated>2011-08-26T17:05:45.306+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-26T17:05:45.306+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="perfomance" /><title>MicroBenchmark : mode d'emploi</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh4.googleusercontent.com/-VYpiI5ySjEA/TYKVFQyw27I/AAAAAAAAAU0/XDPtplNTTKQ/s1600/perf03.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" height="173" src="https://lh4.googleusercontent.com/-VYpiI5ySjEA/TYKVFQyw27I/AAAAAAAAAU0/XDPtplNTTKQ/s1600/perf03.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cet article fait suite à une petite discussion que j'ai eue récemment avec un collègue sur qui était le plus fort entre le for et le foreach. Question qui peut paraitre, au premier abord, stupide mais qui m'a fait pas mal me creuser les neurones sur des points qui n'ont pas grand chose à voir avec le problème initial... (mais là, je m'avance un peu sur mon article... ;-) ).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enfin, pour revenir au sujet initial (qui était, je le répète : "qui était le plus fort entre le for et foreach"), j'ai donc décidé de me faire un petit benchmark pour tester la performance des deux. Et là, ce fut le début des galères...&lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;Je m'explique : suite à l'écriture rapide d'un petit benchmark pour tester mes deux méthodes d'itérations, j'ai obtenu des résultats qui pouvaient paraître &lt;i&gt;bizarres&lt;/i&gt;&amp;nbsp;(enfin bizarres pour moi). S'en est alors suivi de multiples discussions avec (par ordre alphabétique) Zouheir Cadi (&lt;span class="screen-name screen-name-ZouheirCadi pill"&gt;@ZouheirCadi)&lt;/span&gt;,&amp;nbsp;&lt;a href="http://thecodersbreakfast.net/"&gt;Olivier Croisier&lt;/a&gt; (&lt;span class="screen-name screen-name-OlivierCroisier pill"&gt;@OlivierCroisier)&lt;/span&gt;,&amp;nbsp;&lt;a href="http://www.opensides.fr/"&gt;Arnault Jeanson&lt;/a&gt; (&lt;span class="screen-name screen-name-ArnaultJeanson pill"&gt;@ArnaultJeanson)&lt;/span&gt;, Séven Lemesle (&lt;span class="screen-name screen-name-slemesle pill"&gt;@slemesle&lt;/span&gt;) et &lt;a href="http://blog.ostyn.fr/"&gt;François Ostyn&lt;/a&gt; (&lt;span class="screen-name screen-name-ostynf pill"&gt;@ostynf)&lt;/span&gt; que je tiens d'ailleurs à remercier pour leurs lumières et leur disponibilité.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Je vous passe les résultats (cela fera l'effet d'un &lt;a href="http://jetoile.blogspot.com/2011/03/microbenchmark-par-la-pratique.html"&gt;article ultérieur&lt;/a&gt;) pour en revenir juste à la notion de Benchmark qui s'avère être beaucoup plus complexe que cela peut paraitre.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Aussi, suite à cette longue introduction (qui, mis à part raconter ma vie, n'apporte pas grand chose mais qui permet de positionner le contexte ;-) ), je vais donc tenter de montrer en quoi le fait de benchmarker un simple petit bout de code peut amener à des résultats erronés et peut être quelque chose de non trivial.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour ce faire, je ne vais pas me casser trop la tête mais juste vous faire un petit compte rendu de&amp;nbsp;la présentation&amp;nbsp;de Monsieur Joshua Bloch (&lt;i&gt;himself&lt;/i&gt;) qu'il a donné en 2010 à Devoxx sur l'importance du micro-benchmark ou plus précisément sur les optimisations des performances (encore merci à François pour le lien! ;-) ).&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Un peu de vocabulaire...&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Avant de commencer, nous allons d'abord définir ce qu'est un microBenchmark : un microBenchmark a pour objectif de mesurer les performances d'une petite portion de code. Ces tests s'exécutent généralement en un laps très court de temps (de l'ordre de la milliseconde) et ne font généralement pas d'opérations d'entrée/sortie (sauf, si bien sûr, c'est le but du microBenchmark). Le microBenchmark est très différent du &lt;i&gt;profiling&lt;/i&gt; qui a pour cible l'application complète et qui fournit des résultats se voulant représentatifs de la réalité alors que le microBenchmark a vraiment pour objectif de se focaliser sur une portion de code très restreinte afin d'observer ses performances "brutes" sans se soucier d'un éventuel contexte d'exécution.&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Le premier point que l'on peut se demander est : faut-il optimiser son code?&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;La réponse ne diffère pas de celle fourni par le livre "&lt;i&gt;Effective Java&lt;/i&gt;" de Joshua Bloch : il ne faut pas tenter d'optimiser son code sauf dans certains cas comme lorsque l'on développe un API, un framework ou un langage (comme Groovy par exemple). En effet, écrire du code qui se veut optimisé peut conduire à complexifier le code le rendant ainsi illisible mais peut surtout avoir l'effet contraire en le rendant plus lent.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En effet, à l'époque, il était possible d'évaluer les performances d'un programme en comptant le nombre d'instructions qui était exécutées, c'est-à-dire en comptant le nombre de cycles des opérations. Cependant, cela n'est actuellement plus possible en raison de la trop grande différence qu'il existe entre le code écrit et le code qui est réellement exécuté par le processeur. Les coupables :&amp;nbsp;le nombre de couches qui augmente avec notamment&amp;nbsp;un langage de plus en plus compliqué qui s'appuie sur de plus en plus de librairies mais également sur une JVM de plus en plus complexe. A ces différentes couches logicielles vient également s'ajouter une couche matérielle qui se complexifie également et que peu de personnes peuvent prétendre maîtriser : les nouvelles architectures de processeurs, les unités de calculs fournies par les GPU, la gestion de la RAM. Et bien sûr, tout cela en y ajoutant le système d'exploitation.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Du coup, prédire les performances d'un bout de code devient quelque chose de non déterministe qu'il devient très difficile d'estimer.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Prenons un exemple simple : A votre avis, quel est le plus performant entre l'opérande &amp;amp;&amp;amp; (&lt;i&gt;et conditionnel&lt;/i&gt;) et l'opérande &amp;amp; (&lt;i&gt;et logique&lt;/i&gt;)?&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A première vue, on pourrait se dire que le &lt;i&gt;et conditionnel&lt;/i&gt;&amp;nbsp;est plus performant puisque la deuxième condition n'est pas obligatoirement évaluée. Cependant, cela n'est pas si simple. En effet, avec un bonne architecture (processeur, compilateur, ...), les deux conditions du&amp;nbsp;&lt;i&gt;et logique&lt;/i&gt; peuvent être évaluées en parallèle, ce qui est généralement plus rapide que de laisser au processeur le soin de &lt;i&gt;deviner &lt;/i&gt;si la deuxième condition doit être évaluée (dans le cas du &lt;i&gt;et conditionnel&lt;/i&gt;). Bien sûr, cela dépend du compilateur et de la capacité de la machine d'exécution (capacité du &lt;i&gt;Just-In-Time Compiler&lt;/i&gt;&amp;nbsp;ou de la famille de processeur utilisée) à traiter l'opération (modulo bien sûr que les conditions ne soient pas trop complexes).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Du coup, prédire de manière absolue laquelle de ces deux opérandes est la plus performante est quasi-impossible et le seul moyen de le savoir est de le mesurer.&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Mesurer, oui!... mais comment?&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh4.googleusercontent.com/-Ay1I5wIy1g4/TYKYAd7UcQI/AAAAAAAAAU4/ZIDUoDTyD6Y/s1600/question.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="https://lh4.googleusercontent.com/-Ay1I5wIy1g4/TYKYAd7UcQI/AAAAAAAAAU4/ZIDUoDTyD6Y/s320/question.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;copyright photo : &lt;a href="http://www.flickr.com/photos/susyna/3643831785/sizes/m/in/photostream/"&gt;http://www.flickr.com/photos/susyna/3643831785/sizes/m/in/photostream/&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;
Mesurer... cela semble simple, cependant, il est facile de se douter que les mesures relevées dépendent de l'environnement d'exécution. Plus grave encore, sur une même machine, l'exécution successive d'un même test (que l'on appellera &lt;i&gt;tir&lt;/i&gt; par la suite) peut remonter des résultats très différents (différences qui peuvent atteindre 20%).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En outre, il est aisé de constater que si, lors d'un tir, le même test est effectué un grand nombre de fois, les métriques remontées ne sont pas linéaires. En effet, on constate trois phases&amp;nbsp;(si on se concentre sur le temps de réponse d'une ou d'un ensemble d'opérations)&amp;nbsp;:&amp;nbsp;&lt;/div&gt;&lt;ul style="text-align: justify;"&gt;&lt;li&gt;la première phase où les temps observés sont élevés. Cette phase correspond au &lt;i&gt;warm-up&lt;/i&gt; de la JVM,&lt;/li&gt;
&lt;li&gt;la seconde phase où les temps observés diminuent et stagnent. Cette phase correspond à la phase de stabilisation de la JVM,&lt;/li&gt;
&lt;li&gt;et la troisième phase où les temps diminuent. Cette dernière phase correspond à la phase de &lt;i&gt;speed up&lt;/i&gt; de la JVM.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Ainsi, pour résumer, un benchmark doit effectuer un grand nombre de tirs qui doivent contenir plusieurs itérations du code à tester afin de permettre à la JVM de se stabiliser.&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Les raisons de tous ces soucis?&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;En fait, si prédire les performances d'une opération par rapport à une autre est difficile, cela est paradoxalement dû à l'augmentation de la complexité de nos systèmes, complexité croissante entrainée par la recherche de la performance. En effet, ces optimisations d'exécution ont entraînées l'inline de code, le cache ainsi que beaucoup d'heuristiques (Paradoxal tout ça... n'est-il pas?).&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Je m'explique (enfin pour être plus précis, Joshua Bloch explique ;-) ) : en fait, le thread &lt;i&gt;compilateur planning&lt;/i&gt; utilise de nombreuses heuristiques pour décider ce qu'il faut &lt;i&gt;inliner&lt;/i&gt;. Ces décisions sont prises en fonction d'informations locales et peuvent avoir un impact global. En outre le &lt;i&gt;compilateur planning&lt;/i&gt; est exécuté par un thread tournant en tache de fond et dont le comportement peut varier pendant son exécution. Il est donc non déterministe.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Du coup, il est quasiment impossible de prédire quelles seront les performances d'une application et plus embêtant de savoir si une opération sera plus performante qu'une autre dans un contexte donné.&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Et moi? Du coup, je fais quoi? Comment puis-je connaitre le gain de performances de mon code?&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Et bien, la solution est statistique! Il faut mesurer les performances (en effectuant de nombreux tirs tels que cela a été décrit précédemment) du bout de code critique à surveiller régulièrement et en sortir des statistiques. Ce sont ces statistiques qui sont les seules métriques garantes des performance du code. Cependant, il est important de conserver les métriques de tous les tirs (qui pour rappel effectue l'opération de multiples fois) même si elles peuvent sembler aberrantes (bien sûr, si on suspecte que les résultats obtenus sont biaisés en raison d'un événement extérieur - comme une réindexation du disque dur ou le passage de l'anti-virus -, il ne faut pas les garder). Il convient alors de sortir de cet ensemble de tirs les métriques adéquates (moyenne, médiane, écart-type, ...).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, ce sont ces résultats obtenus qui doivent être comparés dans le temps afin de déterminer l'impact d'une modification sur le bout de code à surveiller (en terme de performance).&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Conclusion&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Ainsi, vous l'aurez compris (enfin j'espère ;-) ), Le microbenchmark est un exercice bien plus complexe qu'il en a l'air et il ne suffit pas d'ouvrir son eclipse et de jeter trois lignes de code dans un &lt;i&gt;main()&lt;/i&gt;. Bien sûr, cela permet de se donner un ordre de grandeur mais qui est souvent non représentatif de la réalité et dont le comportement sera, presque à coup sûr, différent dans son contexte d'exécution de ce qui est observé dans son &lt;i&gt;main()&lt;/i&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cependant, il faut garder à l'esprit qu'il reste fortement déconseillé de tenter d'optimiser son code au risque de faire pire que mieux et surtout de rendre son code illisible et donc immaintenable.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Du coup (et toujours d'après Joshua Bloch) :&lt;/div&gt;&lt;ul style="text-align: justify;"&gt;&lt;li&gt;Si vous êtes développeur, utiliser les librairies &lt;i&gt;high-level&lt;/i&gt; et déléguer les problématiques de performances aux couches inférieures (inférieures au sens géographique du terme bien sûr! ;-) ). Même si cela peut être dur à admettre, accepter de ne pas savoir et de ne pas pouvoir prédire les performances de votre code.&lt;/li&gt;
&lt;li&gt;Si vous êtes développeur de librairies, langages, frameworks ou de JVM, alors il faut apprendre à éviter les sources d'étonnement en s'appuyant sur des bonnes pratiques de développement (comme privilégier l'accès aux variables d'instances en jouant sur le niveau de visibilité plutôt que d'utiliser des getter/setter, ...) mais surtout mesurer constamment (tel que cela a été décrit) et faire des statistiques pour déterminer le comportement global au niveau performance.&lt;/li&gt;
&lt;li&gt;Si vous êtes un ayatolla (comme Doug Lea ou Cliff Dick), alors il faut prêcher la bonne parole autour de vous pour éviter les écueils dans lesquels il ne faut pas tomber.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Bien sûr (et cela conclura cet article), il faut garder à l'esprit qu'une optimisation ne s'applique potentiellement qu'à une famille de processeurs, VM ou architecture matérielle, et qu'au vu de la difficulté de prédire de quoi seront constitués nos ordinateurs de demain ou de prédire des optimisations qu'apporteront nos prochaines JVM, tout le travail effectué à l'instant t risque d'être totalement obsolète et erroné demain!&amp;nbsp;&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Pour aller plus loin...&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Présentation de Joshua Bloch sur Parleys&lt;/b&gt; : &lt;a href="http://www.parleys.com/#sl=0&amp;amp;st=5&amp;amp;id=2103"&gt;http://www.parleys.com/#sl=0&amp;amp;st=5&amp;amp;id=2103&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Site du framework Caliper&lt;/b&gt; : &lt;a href="http://code.google.com/p/caliper/"&gt;http://code.google.com/p/caliper/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Présentation de Cliff Click&lt;/b&gt; : &lt;a href="http://www.azulsystems.com/events/javaone_2009/session/2009_J1_Benchmark.pdf"&gt;http://www.azulsystems.com/events/javaone_2009/session/2009_J1_Benchmark.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Page Wiki de Sun sur le microBenchmark&lt;/b&gt; : &lt;a href="http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks"&gt;http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Page de google Android sur la gestion des perfomances&amp;nbsp; d'Android&lt;/b&gt; : &lt;a href="http://developer.android.com/guide/practices/design/performance.html"&gt;http://developer.android.com/guide/practices/design/performance.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Blog de Peter Ahé sur les compilateurs Java&lt;/b&gt; :&amp;nbsp;&lt;a href="http://blogs.sun.com/ahe/entry/hotspot_and_other_compilers"&gt;http://blogs.sun.com/ahe/entry/hotspot_and_other_compilers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-1738912832847574177?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=-7b2sfn7b3A:EsOzPEjos7I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=-7b2sfn7b3A:EsOzPEjos7I:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=-7b2sfn7b3A:EsOzPEjos7I:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/1738912832847574177/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/03/microbenchmark-mode-d.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/1738912832847574177?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/1738912832847574177?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/03/microbenchmark-mode-d.html" title="MicroBenchmark : mode d&amp;#39;emploi" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/-VYpiI5ySjEA/TYKVFQyw27I/AAAAAAAAAU0/XDPtplNTTKQ/s72-c/perf03.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CE4AQ3Y8eSp7ImA9Wx9bFkg.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-3800133365704828580</id><published>2011-02-24T23:46:00.003+01:00</published><updated>2011-02-25T17:55:42.871+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-25T17:55:42.871+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jmx" /><category scheme="http://www.blogger.com/atom/ns#" term="jgroups" /><title>Pour les gouverner tous - partie 3/3</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s1600/jmx_jgroups01.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" height="173" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s320/jmx_jgroups01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cet article fait suite à mes précédents posts (&lt;a href="http://jetoile.blogspot.com/2011/01/pour-les-gouverner-tous-partie-13.html"&gt;ici&lt;/a&gt; et &lt;a href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-23.html"&gt;là&lt;/a&gt;) et à pour objectif d'intégrer la partie JMX à mon petit POC JGroups afin d'offrir une solution permettant de rendre complètement scalable la partie supervision/administration par JMX d'une application distribuée (ie. d'aggréger tous les MBeans au sein de tous les serveurs JMX). Pour rappel, le post précédent introduisait JGroups dans une petite application qui permettait à chaque instance d'une application d'obtenir la valeur d'une donnée offerte par les autres instances.&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: 32px; font-weight: bold;"&gt;Expression du besoin et conception&lt;/span&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;Comme je l'ai expliqué &lt;a href="http://jetoile.blogspot.com/2011/01/pour-les-gouverner-tous-partie-13.html"&gt;ici&lt;/a&gt;, le principe est simple :&amp;nbsp;en démarrant son application qui aura à sa charge d'appeler un petit bout de code de notre toolkit,&amp;nbsp;tous les MBeans se trouvant sur les autres serveurs JMX (modulo que l'application qui les ait démarrés ait démarré en instanciant notre toolkit) doivent être&amp;nbsp;remonter dans notre serveur JMX courant. Réciproquement, tous les MBeanServer devront enregistrer les MBeans offerts par notre instance d'application.&lt;/div&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;Pour ce faire, notre toolkit gérera la partie JMX, c'est-à-dire qu'il&amp;nbsp;créera un connecteur JMX serveur (connecteur s'appuyant sur le protocole RMI) permettant d'accéder au MBeanServer courant (ie. il utilisera le MBeanServer s'il en existe un ou, dans le cas échéant, il en créera un) et qu'il l'exposera aux autres instances en fournissant un stub de la partie connecteur JMX cliente. Ce stub permettra aux autres instances d'instancier la couche de communication nécessaire vers le MBeanServer cible.&amp;nbsp;C'est ce stub qui sera transmis par JGroups (et qui remplacera donc la donnée partagée de notre POC JGroups).&lt;/div&gt;Ca va? Tout le monde suit? Bon, on va pouvoir accélérer... ;-)&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;Ainsi, lorsqu'une nouvelle instance sera démarrée dans le système, les instances déjà présentes seront notifiées de l'arrivé d'un nouveau membre dans la vue (concepts &lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html"&gt;JGroups&lt;/a&gt; et&amp;nbsp;cf. &lt;a href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-23.html"&gt;post précédent&lt;/a&gt;). Suite à cela, elles récupèreront le stub du JMXConnector du nouveau MBeanServer (toujours cf. &lt;a href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-23.html"&gt;post précédent&lt;/a&gt;) qui leur permettra de créer un proxy dynamique correspondant aux MBeans présents dans le MBeanServer cible. Ce proxy dynamique sera instancié et enregistré comme étant un nouveau MBean dans le MBeanServer de l'instance courante.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cependant, ce proxy dynamique ne pourra pas être utilisé directement (sinon ça serait trop simple). En effet, la méthode statique &lt;i&gt;JMX.newMBeanProxy()&lt;/i&gt; permet de créer un proxy dynamique du MBean standard d'un MBeanServer distant ou local. Cependant, il n'est pas possible de l'enregistrer comme MBean au sein d'un MBeanServer car il ne répond alors pas à la règle : "un MBean doit implémenter une interface de type MBean ou DynamicMBean".&amp;nbsp;Aussi, la solution retenue a été de &lt;em&gt;wrapper&lt;/em&gt; ce proxy dynamique dans un MBean dynamique. Ce wrapper fera donc passe-plat (en utilisant la réflexion) avec le proxy dynamique récupéré par la méthode &lt;em&gt;JMX.newMBeanProxy()&lt;/em&gt; lors de l'invocation d'opérations dessus (pour ce faire, il s'appuiera sur les normes spécifiées par JMX pour l'accès en lecture/écriture aux variables d'instance).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En outre, pour le cas spécifique des MXBeans (un certain nombre de MXBean est spécifié par JMX :&amp;nbsp;&lt;a href="http://download.oracle.com/javase/6/docs/api/"&gt;http://download.oracle.com/javase/6/docs/api/&lt;/a&gt;), un traitement particulier sera effectué. En effet, JMX offre la possibilité de créer directement un proxy de l'interface d'un MXBean donné via la méthode statique &lt;em&gt;ManagementFactory.newPlatformMXBeanProxy()&lt;/em&gt;. Aussi, pour les MXBeans, notre wrapper ne sera pas utilisé puisqu'il est possible d'enregistrer directement au sein de notre MBeanServer courant le MXBean distant.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Bien sûr, encore une fois, cela aurait été trop simple s'il n'y avait pas un mais... ;-) En effet, la spécification JMX précise qu'il est possible d'avoir plusieurs MXBeans de type &lt;strong&gt;MemoryPoolMXBean&lt;/strong&gt;, &lt;strong&gt;MemoryManagerMXBean&lt;/strong&gt; et &lt;strong&gt;GarbageCollector&lt;/strong&gt; (cf. &lt;a href="http://download.oracle.com/javase/6/docs/api/"&gt;http://download.oracle.com/javase/6/docs/api/&lt;/a&gt;). Dans ces cas précis, ce sont les propriétés de ces MXBeans qui permettent de les différencier : un traitement particulier sera donc effectué dans ces cas précis puisqu'une recherche pour décrouvrir les propritétés du &lt;b&gt;MXBean&lt;/b&gt; sera faite.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En outre, un cas particulier lié à la JRE 6 de Sun (Hostpot) a, ici, été traité (du coup, cela rend le code proposé adhérent à notre jdk...) puisque le MXBean &lt;strong&gt;HotpostDiagnostic&lt;/strong&gt; a fait l'objet d'une attention particulière...&lt;/div&gt;&lt;h1&gt;Mise en oeuvre&lt;/h1&gt;&lt;h2&gt;Intégration de JMX&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="text-decoration: underline;"&gt;Note&lt;/span&gt; : à noter que le code présenté dans cet article comporte quelques raccourcis et n'a pour objectif que de montrer les points clé. Aussi, certaines portions (comme, entre autre, la gestion des threads, des exceptions ou les méthodes &lt;em&gt;equals(),&lt;/em&gt;&amp;nbsp;&lt;em&gt;hashCode()&amp;nbsp;&lt;/em&gt;ou &lt;em&gt;toString()&lt;/em&gt;) ne sont pas présentes par soucis de clarté. Le code complet peut être trouvé&amp;nbsp;sur GitHub :&amp;nbsp;&lt;a href="https://github.com/jetoile/jmanager4all"&gt;https://github.com/jetoile/jmanager4all&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ici, la donnée, traduite par la classe &lt;strong&gt;Data&lt;/strong&gt; dans mon &lt;a href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-23.html"&gt;article précédent&lt;/a&gt;, sera remplacée par le stub au &lt;strong&gt;JMXConnector&lt;/strong&gt;. Ce stub sera créé par la classe utilisée pour instancier les objets nécessaires à la bonne initalisation du toolkit et il sera encapsulé dans la classe&amp;nbsp;&lt;strong&gt;JManagerConnector&lt;/strong&gt; (à noter, bien sûr que la classe &lt;strong&gt;RMIConnector&lt;/strong&gt; (implémentation de&amp;nbsp;l'interface &lt;strong&gt;JMXConnector&lt;/strong&gt;)&amp;nbsp;utilisée ici est sérialisable) lors de sa transmission entre les différentes instances de l'application.&lt;/div&gt;&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class JManagerConnector implements Serializable {
 private String location;
 private JMXConnector connector;

 public JManagerConnector() {
 }

 public String getLocation() {
  return location;
 }

 public void setLocation(final String location) {
  this.location = location;
 }

 public JMXConnector getConnector() {
  return connector;
 }

 public void setConnector(final JMXConnector connector) {
  this.connector = connector;
 }
}
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Du point de vue création des objets JMX exposés (ie. le &lt;strong&gt;JMXConnector&lt;/strong&gt; et son stub) et de l'initialisation de ces derniers (ie. démarrage du connecteur), cela sera fait, comme dit précédemment, par notre classe qui nous servira de point d'entrée à notre toolkit &lt;strong&gt;JManager4All&lt;/strong&gt; :&lt;/div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class JManager4All {

    final static private Logger LOGGER = LoggerFactory.getLogger(JManager4All.class);

    private static final String CONNECTOR_PROTOCOL = "rmi";

    private JMXConnectorServer jmxConnector;
    private JMXServiceURL jmxServiceUrl;
    final private JManagerConnector jmanagerConnector = new JManagerConnector();
    private final MBeanServer mBeanServer;
    final private JMXConnectorStubCache connectorsStub = new JMXConnectorStubCache();

    private JGroupsBindingComponent jmanagerBindingComponent;
    public JManager4All(final int port) {
        try {
            this.jmxServiceUrl = new JMXServiceURL(CONNECTOR_PROTOCOL, null, port);
        } catch (MalformedURLException e) {
            LOGGER.error("unable to create JMXServiceURL: {}", e);
        }
        this.mBeanServer = ManagementFactory.getPlatformMBeanServer();
        init();
    }

    private void init() {
        try {
            this.jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(this.jmxServiceUrl, null, mBeanServer);
            this.jmxConnector.start();

            final ObjectName objectName = new ObjectName(":type=csserver, name=csserver");
            mBeanServer.registerMBean(this.jmxConnector, objectName);
            this.jmanagerConnector.setConnector(this.jmxConnector.toJMXConnector(null));

            this.jmanagerBindingComponent = new JGroupsBindingComponent(this.jmanagerConnector);
            this.jmanagerBindingComponent.setConnectorsStub(this.connectorsStub);
        } catch (Exception e) {
            LOGGER.error("unable to init: {}", e);
        }
    }

    public void stop() throws IOException {
        this.jmxConnector.stop();
        this.jmanagerBindingComponent.stop();
    }

    public void start() {
        this.jmanagerBindingComponent.start();
    }

    public JManagerConnector getStubConnector() {
        return this.jmanagerConnector;
    }
}
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;On remarquera également que cette classe instancie et démarre une instance d'un &lt;strong&gt;JGroupsBindingComponent&lt;/strong&gt; qui s'occupe de la couche communication pour récupérer nos stubs du système (ici, ça sera JGroups). Je ne reviendrai pas sur les détails d'implémentation de cette partie puisque cela a déjà été traité &lt;a href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-23.html"&gt;ici&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A noter également que nos stubs seront conservés dans un cache &lt;strong&gt;JMXConnectorStubCache&lt;/strong&gt; qui déclenchera, lorsqu'un élément (ie. un stub d'un &lt;strong&gt;JMXConnector&lt;/strong&gt;) sera ajouté ou supprimé, la récupération de nos &lt;b&gt;MBean&lt;/b&gt; distant et leur enregistrement au sein du &lt;b&gt;MBeanServer&lt;/b&gt; courant (resp. leur suppression).&lt;/div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class JMXConnectorStubCache implements Serializable {

 volatile private Map&amp;lt;JManagerAddress, JMXConnector&amp;gt; connectorsStub = Collections.synchronizedMap(new HashMap&amp;lt;JManagerAddress, JMXConnector&amp;gt;());

 synchronized public Map&amp;lt;JManagerAddress, JMXConnector&amp;gt; getValue() {
  return this.connectorsStub;
 }

 synchronized public JMXConnector put(JManagerAddress key, JMXConnector value) {
  JMXConnector result = this.connectorsStub.put(key, value);
  MBeanHandler mBeanHandler = new MBeanHandler(key, value);
  mBeanHandler.handleAdd();
  return result;
 }

 synchronized public JMXConnector remove(JManagerAddress key) {
  JMXConnector result = this.connectorsStub.remove(key);
  MBeanHandler mBeanHandler = new MBeanHandler(key, result);
  mBeanHandler.handleRemove();
  return result;
 }
}
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Ce dernier point nous amène au paragraphe suivant, à savoir la récupération des MBeans distants et leur enregistrement.&lt;/div&gt;&lt;h2 style="text-align: justify;"&gt;Récupération des MBeans distants et enregistrement&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;La récupération des MBeans distants est globalement simple et suit le schéma suivant (cet algorithme ne s'applique pas aux MXBeans) :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;à partir du &lt;strong&gt;JMXConnector&lt;/strong&gt; client, récupération du &lt;strong&gt;MBeanServerConnection&lt;/strong&gt;,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;à partir du &lt;strong&gt;MBeanServerConnection&lt;/strong&gt;, une recherche est lancée sur le &lt;strong&gt;MBeanServer&lt;/strong&gt; distant pour récupérer l'ensemble des &lt;strong&gt;ObjectInstance&lt;/strong&gt; présenst sur ce dernier,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;pour chaque &lt;strong&gt;ObjectInstance&lt;/strong&gt; qui n'est pas dans le domaine JMX "&lt;em&gt;remote&lt;/em&gt;" (qui sera le domaine utilisé pour stocker les proxy des MBeans distants), création d'un proxy dynamique représentant l'objet exposé par le MBean et encapsulation de ce dernier dans la classe &lt;strong&gt;MBeanWrapper&lt;/strong&gt; qui est un &lt;strong&gt;DynamicMBean&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;div style="text-align: justify;"&gt;enfin enregistrement&amp;nbsp;de chaque &lt;strong&gt;DynamicMBean&lt;/strong&gt; créé dans le &lt;strong&gt;MBeanServer&lt;/strong&gt; local via un &lt;strong&gt;ObjectName&lt;/strong&gt; défini grâce à :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;ses propriétés,&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;son domaine JMX distant sous forme de propriété "&lt;em&gt;subdomain&lt;/em&gt;",&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;mais également avec une propriété permettant de connaitre la provenance du MBean (propriété qui sera appelée "&lt;em&gt;instance&lt;/em&gt;").&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class MBeanHandler {
 private static final String DOMAIN_REMOTE = "remote";

 private static final Logger LOGGER = LoggerFactory.getLogger(MBeanHandler.class);

 private final MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
 private final JMXConnector connector;
 private final JManagerAddress address;

 public MBeanHandler(final JManagerAddress address, final JMXConnector connector) {
  this.connector = connector;
  this.address = address;
 }

 void handleAdd() throws Exception {
  if (connector != null) {
   connector.connect();
   ObjectName objectName = new ObjectName("*:*");
   final MBeanServerConnection mBeanServerConnection = connector.getMBeanServerConnection();

   final Set&amp;lt;ObjectInstance&amp;gt; instances = mBeanServerConnection.queryMBeans(objectName, null);

   for (ObjectInstance objectInstance : instances) {
    final ObjectName distantObjectName = objectInstance.getObjectName();
    if (DOMAIN_REMOTE.equals(distantObjectName.getDomain())) {
     continue;
    }
    final ObjectName newObjectName = new ObjectName(DOMAIN_REMOTE + ":instance=" + address + ", " + "subdomain=" + distantObjectName.getDomain()
      + ", " + distantObjectName.getKeyPropertyListString());
    final MBeanInfo mBeanInfo = mBeanServerConnection.getMBeanInfo(distantObjectName);
    registerRemoteMBean(mBeanServerConnection, distantObjectName, newObjectName, mBeanInfo);
   }
  }
 }

 private void registerRemoteMBean(final MBeanServerConnection mBeanServerConnection, final ObjectName distantObjectName, final ObjectName newObjectName,
   final MBeanInfo mBeanInfo) throws Exception {
  Object mBean = getRemoteMBean(mBeanServerConnection, mBeanInfo, distantObjectName);
  if (mBean != null) {
   mbeanServer.registerMBean(mBean, newObjectName);
  }
 }

 public Object getRemoteMBean(final MBeanServerConnection mBeanServerConnection, final MBeanInfo mBeanInfo, final ObjectName distantObjectName)
   throws Exception {
  if (!Boolean.parseBoolean((String) mBeanInfo.getDescriptor().getFieldValue("mxbean"))) {
   LOGGER.debug("current mxBeanInfo : {}", mBeanInfo);
   final Class&amp;lt;?&amp;gt; clazz = Class.forName(mBeanInfo.getClassName());
   final Class&amp;lt;?&amp;gt;[] interfazes = clazz.getInterfaces();
   if (interfazes.length == 1) {
    LOGGER.debug("current interface : {}", interfazes[0]);
    final Object proxy = JMX.newMBeanProxy(mBeanServerConnection, distantObjectName, interfazes[0]);
    final MBeanWrapper mBeanWrapper = new MBeanWrapper(mBeanInfo, proxy);
    return mBeanWrapper;
   }
  }
  return null;
 }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;public class MBeanWrapper implements DynamicMBean {

 static final private Logger LOGGER = LoggerFactory.getLogger(MBeanWrapper.class);

 private final MBeanInfo mBeanInfo;
 private final Object proxy;

 public MBeanWrapper(final MBeanInfo mBeanInfo, final Object proxy) {
  this.mBeanInfo = mBeanInfo;
  this.proxy = proxy;
 }

 @Override
 public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
  MBeanAttributeInfo[] mBeanAttributeInfos = mBeanInfo.getAttributes();
  for (MBeanAttributeInfo mBeanAttributeInfo : mBeanAttributeInfos) {
   if (StringUtils.equals(attribute, mBeanAttributeInfo.getName())) {
    if (mBeanAttributeInfo.isReadable()) {
     return invokeGetter(attribute, mBeanAttributeInfo);
    } else {
     return null;
    }
   }
  }
  return null;
 }

 Object invokeGetter(String attribute, MBeanAttributeInfo mBeanAttributeInfo) {
  try {
   Method method = null;
   if (mBeanAttributeInfo.isIs()) {
    method = this.proxy.getClass().getMethod("is" + StringUtils.capitalize(attribute), new Class[0]);
    return method.invoke(this.proxy, new Object[0]);
   } else {
    method = this.proxy.getClass().getMethod("get" + StringUtils.capitalize(attribute), new Class[0]);
    return method.invoke(this.proxy, new Object[0]);
   }
  } catch (Exception e) {
   LOGGER.error("unable to get remote attribute info {}: {}", attribute, e);
  }
  return null;
 }

 @Override
 public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
  MBeanAttributeInfo[] mBeanAttributeInfos = mBeanInfo.getAttributes();
  for (MBeanAttributeInfo mBeanAttributeInfo : mBeanAttributeInfos) {
   if (StringUtils.equals(attribute.getName(), mBeanAttributeInfo.getName())) {
    if (mBeanAttributeInfo.isWritable()) {
     invokeSetter(attribute, mBeanAttributeInfo);
    } else {
     return;
    }
   }
  }
  return;
 }

 void invokeSetter(Attribute attribute, MBeanAttributeInfo mBeanAttributeInfo) {
  try {
   Method method = null;
   if (mBeanAttributeInfo.isIs()) {
    method = this.proxy.getClass().getMethod("set" + StringUtils.capitalize(attribute.getName()), boolean.class);
    method.invoke(this.proxy, attribute.getValue());
   } else {
    method = this.proxy.getClass().getMethod("set" + StringUtils.capitalize(attribute.getName()), attribute.getValue().getClass());
    method.invoke(this.proxy, attribute.getValue());
   }
  } catch (Exception e) {
   LOGGER.error("unable to set remote attribute info {}: {}", attribute, e);
  }
 }

 @Override
 public AttributeList getAttributes(String[] attributes) {
  AttributeList result = new AttributeList();
  for (String attribute : attributes) {
   Attribute currentAttribute;
   try {
    currentAttribute = new Attribute(attribute, getAttribute(attribute));
    result.add(currentAttribute);
   } catch (Exception e) {
    LOGGER.error("unable to get remote attribute info {}: {}", attribute, e);
   }
  }
  return result;
 }

 @Override
 public AttributeList setAttributes(AttributeList attributes) {
  AttributeList result = new AttributeList();
  for (int i = 0; i &amp;lt; attributes.size(); i++) {
   Attribute attribute = (Attribute) attributes.get(i);
   try {
    setAttribute(attribute);
    result.add(attribute);
   } catch (Exception e) {
    LOGGER.error("unable to set remote attribute {}: {}", attribute.getName(), e);
   }
  }
  return result;
 }

 @Override
 public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
  Class[] paramTypes = null;
  if (signature != null) {
   paramTypes = new Class[signature.length];
   for (int i = 0; i &amp;lt; signature.length; ++i) {
    paramTypes[i] = signature[i].getClass();
   }
  }

  try {
   Method method = this.proxy.getClass().getMethod(actionName, paramTypes);
   return method.invoke(this.proxy, params);
  } catch (Exception e) {
   LOGGER.error("unable to invoke {}: {}", actionName, e);
  }
  return null;
 }

 @Override
 public MBeanInfo getMBeanInfo() {
  return this.mBeanInfo;
 }
}
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;On voit donc que le processus n'est pas&amp;nbsp;vraiment&amp;nbsp;compliqué. Pour le cas des MXBeans, cela est un peu plus sioux... mais globalement pas compliqué non plus ;-)&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En effet, plusieurs cas se présentent :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Pour les &lt;strong&gt;MXBeans&lt;/strong&gt; de types (type au sens propriété JMX) &lt;strong&gt;&lt;em&gt;Compilation&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;ClassLoading&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;Memory&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;OperationSystem&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;Runtime&lt;/em&gt;&lt;/strong&gt; et&amp;nbsp;&lt;strong&gt;&lt;em&gt;Threading&lt;/em&gt;&lt;/strong&gt;, cela ne pose pas de problèmes puisque la spécification JMX nous dit qu'il n'y a qu'un seul MBean de ce type dans le &lt;strong&gt;MBeanServer&lt;/strong&gt; pour domaine &lt;em&gt;java.lang&lt;/em&gt;. Dans ce cas, il suffit juste d'instancier un proxy dynamique du MXBean lui-même et de l'enregistrer avec le "bon" &lt;strong&gt;ObjectName&lt;/strong&gt;.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;par contre, pour les &lt;strong&gt;MXBeans&lt;/strong&gt; de types &lt;em&gt;&lt;strong&gt;MemoryPool&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;GarbageCollector&lt;/strong&gt;&lt;/em&gt; et &lt;em&gt;&lt;strong&gt;MemoryManager&lt;/strong&gt;&lt;/em&gt;, vu qu'il peut y en avoir plusieurs, une recherche est effectuée (en limitant la recherche aux &lt;strong&gt;MBeans&lt;/strong&gt; voulus bien sûr...) sur le &lt;strong&gt;MBeanServer&lt;/strong&gt; distant afin d'obtenir (mais également d'instancier) le bon type de proxy dynamique mais également les bonnes propriétés sous lequel il est enregistré.&lt;/li&gt;
&lt;/ul&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;final private static Map&amp;lt;String, Class&amp;lt;?&amp;gt;&amp;gt; MXBEAN_MAP = new HashMap&amp;lt;String, Class&amp;lt;?&amp;gt;&amp;gt;();
 static {
  MXBEAN_MAP.put(ManagementFactory.COMPILATION_MXBEAN_NAME, CompilationMXBean.class);
  MXBEAN_MAP.put(ManagementFactory.CLASS_LOADING_MXBEAN_NAME, ClassLoadingMXBean.class);
  MXBEAN_MAP.put(ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
  MXBEAN_MAP.put(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);
  MXBEAN_MAP.put(ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
  MXBEAN_MAP.put(ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
  MXBEAN_MAP.put("java.util.logging:type=Logging", LoggingMXBean.class);
 }

 public RemoteMXBeanHandler() {
 }

 public Object getRemoteMBean(final MBeanServerConnection mBeanServerConnection, final MBeanInfo mBeanInfo, final ObjectName distantObjectName)
   throws Exception {
  if (Boolean.parseBoolean((String) mBeanInfo.getDescriptor().getFieldValue("mxbean"))) {
   LOGGER.debug("current mxBeanInfo : {}", mBeanInfo);
   Object proxy = getMxBeanProxy(mBeanServerConnection, mBeanInfo, distantObjectName);
   return proxy;
  }
  return null;
 }

 private Object getMxBeanProxy(final MBeanServerConnection mBeanServerConnection, final MBeanInfo mBeanInfo, final ObjectName distantObjectName)
   throws IOException {
  String distantName = distantObjectName.toString();
  int index = distantName.indexOf(",");
  String substring = distantName.substring(0, (index != -1) ? index : distantName.length());
  Class&amp;lt;?&amp;gt; mBeanClass = MXBEAN_MAP.get(substring);
  if (mBeanClass != null) {
   return ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection, distantName, mBeanClass);
  } else if (!StringUtils.equals(ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE, substring)
    &amp;amp;&amp;amp; !StringUtils.equals(ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE, substring)
    &amp;amp;&amp;amp; !StringUtils.equals(ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE, substring)
    &amp;amp;&amp;amp; !StringUtils.contains(substring, "com.sun.management")) {
   return ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
  } else {
   return null;
  }
 }

 private void handleSpecificMXBean(final MBeanServerConnection mBeanServerConnection) throws Exception {
  // cf. http://download.oracle.com/javase/6/docs/api/

  // traitement particulier pour les MXBeans de type MemoryPoolMXBean
  registerOtherMxBean(mBeanServerConnection, ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE, MemoryPoolMXBean.class);
  // traitement particulier pour les MXBeans de type MemoryManagerMXBean
  registerOtherMxBean(mBeanServerConnection, ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE, MemoryManagerMXBean.class);
  // traitement particulier pour les MXBeans de type GarbageCollector
  registerOtherMxBean(mBeanServerConnection, ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE, GarbageCollectorMXBean.class);

  // traitement particulier pour les MXBeans de type Hotspot
  registerOtherMxBean(mBeanServerConnection, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
 }

 private void registerOtherMxBean(final MBeanServerConnection mBeanServerConnection, String type, Class&amp;lt;?&amp;gt; clazz) throws Exception {
  final ObjectName requestedObjectName = new ObjectName(type + ",*");
  final Set&amp;lt;ObjectName&amp;gt; objectNames = mBeanServerConnection.queryNames(requestedObjectName, null);
  for (ObjectName objectName : objectNames) {
   final Object proxy = ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection, objectName.getCanonicalName(), clazz);
   final ObjectName newObjectName = new ObjectName("remote:instance=" + address + ", " + "subdomain=" + objectName.getDomain() + ", "
     + objectName.getKeyPropertyListString());
   mbeanServer.registerMBean(proxy, newObjectName);
  }
 }
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Pour le cas particulier du &lt;strong&gt;MXBean&lt;/strong&gt; &lt;em&gt;&lt;strong&gt;HotspotDiagnostic&lt;/strong&gt;&lt;/em&gt;, je vous laisse le soin de jeter un oeil sur le code... ;-)&lt;/div&gt;&lt;h2 style="text-align: justify;"&gt;Désenregistrement d'une instance (et donc de ses MBeans associés)&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Bien entendu, si une instance venait à disparaitre, il est nécessaire de désenregistrer ses &lt;strong&gt;MBeans&lt;/strong&gt; pour chaque instance de l'application encore présente.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Là encore, la principe est ultra-simple puisqu'il suffit de récupérer l'ensemble des MBeans qui se trouvent dans le domaine JMX "&lt;em&gt;remote&lt;/em&gt;" (qui pour rappel est le domaine utilisé pour enregistrer tous nos proxy) avec la "bonne" propriété (à savoir la propriété "&lt;em&gt;instance&lt;/em&gt;" qui doit valoir la valeur de l'adresse de l'instance à supprimer) et de les désenregistrer du &lt;strong&gt;MBeanServer&lt;/strong&gt; local.&lt;/div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;void handleRemove() throws Exception {
  final ObjectName queryObjectName = new ObjectName(DOMAIN_REMOTE + ":instance=" + address + ",*");
  final Set&amp;lt;ObjectName&amp;gt; objectNames = mbeanServer.queryNames(queryObjectName, null);
  for (ObjectName objectName : objectNames) {
   LOGGER.debug("remove from mBeanServer objectName : {}", objectName);
   mbeanServer.unregisterMBean(objectName);
  }
 }
&lt;/pre&gt;&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;On a vu tout au long de cette article comment il était possible d'utiliser JMX coté client (on récupère des &lt;strong&gt;MBeans&lt;/strong&gt; distants) mais également coté serveur (on créé des &lt;strong&gt;MBeans&lt;/strong&gt;). Bien sûr, la couche JGroups n'est qu'un prétexte mais je trouvais intéressant de pouvoir s'appuyer sur ce dernier pour être notifié de changement dans le système. Si je suis motivé, j'intégrerais peut être une implémentation NoSQL pour stocker et partager les JMXConnector ou un truc du genre... ;-)&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Par contre, je n'ai pas testé le comportement dans le cas où des notifications seraient émises... en outre, si un service de &lt;strong&gt;Relation&lt;/strong&gt; JMX était utilisé, je pense que cela pourrait poser quelques soucis...&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A noter que je suis tombé tout récemment sur &lt;a href="http://blog.infin-it.fr/2010/08/05/aggregateur-jmx-2/"&gt;une autre solution&lt;/a&gt; (que je n'ai pas testé) qui permet d'aggréger des informations JMX au sein d'un même serveur &lt;strong&gt;MBeanServer&lt;/strong&gt;. La cible n'est pas tout à fait identique mais peut être suffisante pour la plupart des cas... par contre, il faut aimer Spring... ;-)&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Pour aller plus loin...&lt;/h1&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;b&gt;Site officiel de JGroups&lt;/b&gt; :&amp;nbsp;&lt;a href="http://www.jgroups.org/"&gt;http://www.jgroups.org/&lt;/a&gt; &lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;b&gt;Wiki de JGroups&lt;/b&gt; :&amp;nbsp;&lt;a href="http://community.jboss.org/wiki/JGroups"&gt;http://community.jboss.org/wiki/JGroups&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;b&gt;Site de la JSR 3 -&amp;nbsp;&lt;/b&gt;&lt;em&gt;&lt;b&gt;Java Management Extensions (JMX) Specification&lt;/b&gt;&amp;nbsp;&lt;/em&gt;:&amp;nbsp;&lt;a href="http://www.jcp.org/en/jsr/detail?id=3"&gt;http://www.jcp.org/en/jsr/detail?id=3&lt;/a&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;b&gt;Site de la JSR 160 -&amp;nbsp;&lt;/b&gt;&lt;em&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;&lt;em&gt;&lt;b&gt;Java Management Extensions (JMX) Remote API&lt;/b&gt;&lt;/em&gt;&lt;/span&gt;&amp;nbsp;&lt;/em&gt;:&amp;nbsp;&lt;a href="http://jcp.org/en/jsr/detail?id=160"&gt;http://jcp.org/en/jsr/detail?id=160&lt;/a&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;b&gt;Site officiel d'Oracle sur JMX&lt;/b&gt; :&amp;nbsp;&lt;a href="http://www.oracle.com/technetwork/java/javase/tech/docs-jsp-135989.html"&gt;http://www.oracle.com/technetwork/java/javase/tech/docs-jsp-135989.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-3800133365704828580?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=41tfuuB2viU:r9GsS5N7pnU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=41tfuuB2viU:r9GsS5N7pnU:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=41tfuuB2viU:r9GsS5N7pnU:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/3800133365704828580/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-33.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/3800133365704828580?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/3800133365704828580?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-33.html" title="Pour les gouverner tous - partie 3/3" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s72-c/jmx_jgroups01.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkYFR384fip7ImA9Wx9bFUU.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-2677983267117299404</id><published>2011-02-20T18:44:00.002+01:00</published><updated>2011-02-24T23:55:16.136+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-24T23:55:16.136+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jgroups" /><title>Pour les gouverner tous - partie 2/3</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s1600/jmx_jgroups01.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" height="173" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s320/jmx_jgroups01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cet article fait suite à mon &lt;a href="http://jetoile.blogspot.com/2011/01/pour-les-gouverner-tous-partie-13.html"&gt;article précédent&lt;/a&gt; et a pour objectif de présenter un petit POC (&lt;em&gt;Proof Of Concept&lt;/em&gt;) simplicime mettant en oeuvre JGroups&amp;nbsp;en version 2.11.0.GA (la dernière version stable à ce jour). Le principe est de montrer comment il est possible d'utiliser JGroups pour permettre à plusieurs instances d'une même application de se partager les valeurs d'une donnée. Enfin, pour être plus précis, cet objet partagé ne le sera pas vraiment (ndlr : partagé) par toutes les instances mais il s'agira plutôt de permettre à chaque nouvelle instance de récupérer la valeur d'une donnée auprès des autres instance déjà présentes dans le système. En outre, les autres instances déjà présentes devront recevoir directement la valeur de la donnée de la nouvelle instance.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;L'autre raison d'être de cet article permettra d'introduire la couche protocolaire utilisée par mon petit POC qui permet de rendre distribuable un agent JMX dans une architecture distribuée.&lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1 style="text-align: justify;"&gt;Spécification des besoins/pré-requis&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Ce projet s'appuiera sur les pré-requis suivant :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;a href="http://www.slf4j.org/"&gt;slf4j&lt;/a&gt;/&lt;a href="http://logback.qos.ch/"&gt;logback&lt;/a&gt; pour la partie log&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;a href="http://maven.apache.org/index.html"&gt;maven 3&lt;/a&gt; (ou 2 au choix) pour la partie build&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;et... &lt;a href="http://www.jgroups.org/"&gt;JGroups&lt;/a&gt; dans sa version 2.11.0.GA ;-)&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Coté tests unitaires, je m'excuse préalablement auprès de vous, mais il n'y en aura pas... et cela pour deux raisons que je vous laisse choisir :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;je suis flemmard ;-) mais surtout, je n'ai pas envie de mocker la terre entière.&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;ce petit programme est plus une utilisation basique de JGroups et, le produit fonctionnant bien, je ne vois pas l'intérêt de le retester. En outre, ici, il est plus intéressant de tester de manière intégrée que de manière unitaire en raison de l'aspect distribué de l'application.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Comme je l'ai mentionné précédemment dans l'introduction, le but de cet article est simple :&amp;nbsp;une application dispose de plusieurs instances qui se trouvent sur des JVM distinctes (il peut donc s'agir d'instances exécutées sur une ou plusieurs machines).&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Si une nouvelle instance est démarrée, elle doit pouvoir demander à toutes les autres instances de l'application la valeur d'une donnée X afin, par exemple, de connaître leur état.&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;De plus, toutes les instances déjà existantes dans le système doivent pouvoir être notifiées de l'arrivée d'une nouvelle instance et, par la même occasion, recevoir sa valeur courante de la donnée X.&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Enfin, si une instance disparait du sytème (arrêt, ...), toutes les instances doivent automatiquement supprimer en leur sein la valeur de la donnée de l'instance incriminée.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Coté configuration de JGroups, cet article s'appuiera sur une configuration par défaut, c'est à dire une configuration en UDP.&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Architecture de l'application&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Comme vous pouvez vous en douter, l'architecture de l'application sera simple puisque JGroups fournit nativement de nombreuses possibilités. Aussi, je ne présenterai pas de super conception.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Par contre, si les termes &lt;b&gt;ReceiverAdapter&lt;/b&gt;, &lt;b&gt;MembershipListener&lt;/b&gt; ou &lt;b&gt;View&lt;/b&gt; ne vous parlent pas, je vous renverrai :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;soit, à mon &lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html"&gt;article&lt;/a&gt; sur JGroups ;-)&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;soit (mieux), à la &lt;a href="http://www.jgroups.org/ug.html"&gt;documentation&lt;/a&gt; officielle de ce dernier.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Notre application sera composée de trois parties :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;La partie donnée : la classe &lt;b&gt;Data&lt;/b&gt; représentera la donnée à faire transiter. Il s'agira d'un simple POJO qui sera, bien sûr, sérialisable.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;La partie notification de changement de l'infrastructure (ie. arrivé ou arrêt d'une instance dans le système) : la classe &lt;b&gt;ChangeInfraListener&lt;/b&gt; qui implémentera l'interface &lt;i&gt;MembershipListener&lt;/i&gt; et donc la méthode&lt;i&gt; viewAccepted()&lt;/i&gt; &lt;em&gt;call-backé&lt;/em&gt; par JGroups pour notifier d'un changement au niveau d'une des ses vues.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;La partie qui aura à sa charge l'exposition de la donnée représentée par la classe &lt;i&gt;Data&lt;/i&gt; et qui aura initialisera l'application : la classe &lt;b&gt;JGroupsClient&lt;/b&gt; qui étendra la classe &lt;i&gt;ReceiverAdapter&lt;/i&gt; afin de permettre aux autres instances d'interargir avec.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Coté canaux, l'application en utilisera un seul canal : le canal "&lt;i&gt;channel&lt;/i&gt;" qui sera utilisé pour être être notifié de changement d'état sur la vue (il sera donc connecté à la classe implémentant l'interface &lt;i&gt;MembershipListener&lt;/i&gt; (ie. &lt;i&gt;ChangeInfraListener&lt;/i&gt;) et qui sera également&amp;nbsp;utilisé pour la communication point à point entre les différentes instances : pour rappel, à un membre d'une vue est associée une adresse unique et une vue contient l'ensemble des membres de cette dernière.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A noter que pour la récupération de la donnée au démarrage d'une instance, il aurait également été possible d'implémenter les méthodes &lt;i&gt;getState()&lt;/i&gt; et &lt;i&gt;setState()&lt;/i&gt; (en combinaison de l'utilisation de la méthode &lt;i&gt;connect(&amp;lt;String&amp;gt; , &amp;lt;Address&amp;gt;, &amp;lt;String&amp;gt;, &amp;lt;long&amp;gt;)&lt;/i&gt; sur l'instance de Channel utilisée). Cependant, il était, quand même nécessaire d'implémenter la méthode &lt;i&gt;viewAccepted()&lt;/i&gt; afin d'être notifié du démarrage ou de l'arrêt d'une instances dans le système et cela aurait été redondant avec les notifications reçues (en effet, récupérer l'état des autres instances des membres de la vue ne dispense pas de recevoir l'état de la vue via la méthode &lt;i&gt;viewAccepted()&lt;/i&gt;). Aussi, je n'ai pas utilisé cette fonctionnalité de JGroups.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Diagramme de séquence lors de la connexion d'une nouvelle instance de l'application au système, coté nouvelle instance mais aussi coté&amp;nbsp;instances déjà présentes dans le système :&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-DsKcW_KWIZM/TWFDF_0MbsI/AAAAAAAAAUw/EAXva9PJsm8/s1600/jgroups_seq_diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="260" src="http://4.bp.blogspot.com/-DsKcW_KWIZM/TWFDF_0MbsI/AAAAAAAAAUw/EAXva9PJsm8/s400/jgroups_seq_diagram.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h1&gt;Mise en oeuvre&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;A noter que le code écrit ici ne contiendra pas les imports par souci de lisibilité.&lt;/div&gt;&lt;h2 style="text-align: justify;"&gt;La classe JGroupsClient&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Commençons donc par la mise en oeuvre de la classe &lt;b&gt;JGroupsClient&lt;/b&gt; :&lt;/div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;package com.jetoile.jgroups.sample;
public class JGroupsClient extends ReceiverAdapter {

    final static private Logger LOGGER = LoggerFactory.getLogger(JGroupsClient.class);

    final private Data data = new Data();
    private RpcDispatcher rpcDispatcher;
    private Channel channel;

    public JGroupsClient(final String data) {
        this.data.setData(data);
    }

    public void stop() throws IOException {
        this.channel.close();
    }

    public void start() throws ChannelException {
        this.channel = new JChannel("default-udp.xml");

        final ChangeInfraListener changeSetListener = new ChangeInfraListener(channel);
        rpcDispatcher = new RpcDispatcher(this.channel, null, changeSetListener, this);
        changeSetListener.setRpcDispatcher(rpcDispatcher);
        this.channel.connect("privateChannel");
        this.data.setAddress(this.channel.getAddress());
    }

    public Data getData() {
        return this.data;
    }
}
&lt;/pre&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Dans cette classe, on observe donc que l'on a :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;la méthode start() qui a à sa charge la partie connexion à JGroups,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;la méthode&lt;i&gt; getData()&lt;/i&gt; qui correspond à la méthode exposée utilisée pour transmettre la valeur de la donnée aux autres instances.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;h2 style="text-align: justify;"&gt;La classe ChangeInfraListener&lt;/h2&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Pour la classe&amp;nbsp;&lt;b&gt;ChangeInfraListener&lt;/b&gt;, nous aurons&amp;nbsp;:&lt;/div&gt;&lt;/div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;package com.jetoile.jgroups.sample;

public class ChangeInfraListener implements MembershipListener {

    final static private Logger LOGGER = LoggerFactory.getLogger(ChangeInfraListener.class);

    final private Map&amp;lt;Address, String&amp;gt; dataCache = new HashMap&amp;lt;Address, String&amp;gt;();

    final private Channel privateChannel;

    private RpcDispatcher rpcDispatcher;

    public ChangeInfraListener(final Channel privateChannel) {
        this.privateChannel = privateChannel;
    }

    public void setRpcDispatcher(RpcDispatcher rpcDispatcher) {
        this.rpcDispatcher = rpcDispatcher;
    }

    @Override
    public void viewAccepted(View new_view) {
        // when a new member is up
        List&amp;lt;Address&amp;gt; newAddresses = getNewAddresses(new_view.getMembers());

        newAddresses.remove(privateChannel.getAddress());

        List&amp;lt;Address&amp;gt; ads = new ArrayList&amp;lt;Address&amp;gt;();
        for (Address ad : newAddresses) {
            if (!dataCache.containsKey(ad)) {
                ads.add(ad);
            }
        }

        if (!ads.isEmpty()) {
            MethodCall methodCall = new MethodCall("getData", new Object[] {}, new Class[] {});
            LOGGER.debug("invoke remote getData on: {}", ads);

            RspList resps = rpcDispatcher.callRemoteMethods(ads, methodCall, RequestOptions.SYNC);
            LOGGER.debug("after invoke getData - nb result {}", resps.numReceived());

            if (resps.numReceived() == 0) {
                LOGGER.debug("retry...");
                resps = rpcDispatcher.callRemoteMethods(ads, methodCall, RequestOptions.SYNC);
            }

            for (Object resp : resps.getResults()) {
                Data data = (Data) resp;
                LOGGER.debug("new data: {}", data);
                dataCache.put(data.getAddress(), data.getData());
            }
        }

        List&amp;lt;Address&amp;gt; olds = getObsoleteAddresses(new_view.getMembers());
        for (Address old : olds) {
            LOGGER.debug("remove data: {}", old);
            dataCache.remove(old);
        }
    }

    @Override
    public void suspect(Address suspected_mbr) {
        // NOTHING TO DO
    }

    @Override
    public void block() {
        // NOTHING TO DO
    }

    List&amp;lt;Address&amp;gt; getNewAddresses(Vector&amp;lt;Address&amp;gt; newMembers) {
        List&amp;lt;Address&amp;gt; result = new ArrayList&amp;lt;Address&amp;gt;();
        for (Address address : newMembers) {
            if (!this.dataCache.containsKey(address)) {
                result.add(address);
            }
        }
        return result;
    }

    List&amp;lt;Address&amp;gt; getObsoleteAddresses(Vector&amp;lt;Address&amp;gt; newMembers) {
        List&amp;lt;Address&amp;gt; result = new ArrayList&amp;lt;Address&amp;gt;();
        for (Address address : this.dataCache.keySet()) {
            if (!newMembers.contains(address)) {
                result.add(address);
            }
        }
        return result;
    }
}
&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="text-align: justify;"&gt;Dans cette classe, on observe que la&amp;nbsp;méthode &lt;i&gt;viewAccepted()&lt;/i&gt;&amp;nbsp;(qui est la méthode &lt;i&gt;call-backé&lt;/i&gt; par JGroups lors d'une modification de la vue (ie. lors de la connexion ou de la déconnexion d'un autre membre du groupe)), invoque, si un nouveau membre est apparu, l'appel de la méthode&amp;nbsp;distante&amp;nbsp;&lt;i&gt;getData() &lt;/i&gt;sur la nouvelle instance en question.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="text-align: justify;"&gt;Il est intéressant de noter l'utilisation qui est faite de la classe &lt;b&gt;RequestOptions&lt;/b&gt; mais également le fait que les méthode &lt;i&gt;block()&lt;/i&gt; et &lt;i&gt;suspect()&lt;/i&gt;&amp;nbsp;n'ont pas été spécifiées dans notre cas d'utilisation.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 style="text-align: justify;"&gt;La classe Data&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Enfin, la classe&lt;b&gt; Data&lt;/b&gt; qui sera utilisée est la suivante (par souci de lisibilité, les méthodes &lt;i&gt;equals()&lt;/i&gt; et &lt;i&gt;hashCode()&lt;/i&gt; ne sont pas détaillées ici) :&lt;/div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;package com.jetoile.jgroups.sample;

public class Data implements Serializable {
 private Address address;
 private String data;

 public Data() {
 }

 public Address getAddress() {
  return address;
 }

 public void setAddress(final Address address) {
  this.address = address;
 }

 public String getData() {
  return data;
 }

 public void setData(String data) {
  this.data = data;
 }

 @Override
 public int hashCode() {
  // cf. gitHub
  return 0;
 }

 @Override
 public boolean equals(Object obj) {
  // cf. gitHub
  return true;
 }

 @Override
 public String toString() {
  return "Data [address=" + address + ", data=" + data + "]";
 }
}
&lt;/pre&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Cette classe, comme on peut le remarquer, n'a rien de particulier, si ce n'est qu'elle est sérialisable.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, on peut voir que l'implémentation est très simple (je ne commenterai donc pas ce qui est fait ici...).&lt;/div&gt;&lt;h1 style="text-align: justify;"&gt;Exécution et utilisation&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;L'exécution, quant à elle, pourra se faire avec une classe de type :&lt;/div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;package com.jetoile.jgroups.sample.sample;

public class JGroupsClientTest {

 public static void main(String[] args) throws ChannelException {
  JGroupsClient jgroupsClient = new JGroupsClient("toto");
  jgroupsClient.start();
 }
}&lt;/pre&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;A noter que si les différentes instances venaient à ne pas se voir, cela peut provenir d'un souci avec la configuration réseau et qu'il est possible de palier à ce problème en forçant l'utilisation d'adresse IPV4 avec l'option JVM suivante :&lt;/div&gt;&lt;pre class="brush:bash; wrap-lines: false; auto-links: false"&gt;-Djava.net.preferIPv4Stack=true
&lt;/pre&gt;&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;On a vu ici que&amp;nbsp;permettre la communication d'instances d'une application de manière distribuée était aisée avec JGroups. Bien sûr (et comme je l'ai fait remarqué précédemment), la notion de&lt;i&gt; tuning&lt;/i&gt; de JGroups (ie. la configuration de la couche protocolaire - cf. &lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#protocoles"&gt;mon article précédent&lt;/a&gt;) n'a pas été abordée, mais cela doit être fait en fonction des besoins de l'infrastructure (trafic&amp;nbsp;réseau, firewall, sécurité, ...) et je laisse donc ce point à la convenance de chacun ;-).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ici se&amp;nbsp;clôture&amp;nbsp;donc la partie JGroups de notre petit POC jmanager4all qui nous a permis de voir comment JGroups répondait à notre besoin mais également comment il allait être utilisé par la suite.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Le prochain article s'attaquera donc à la partie interopérabilité avec JMX.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A oui... j'oubliais... le code de se petit POC se trouve sur GitHub :&amp;nbsp;&lt;a href="https://github.com/jetoile/jgroups-sample"&gt;https://github.com/jetoile/jgroups-sample&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-2677983267117299404?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=09xR6MYDu2s:_86zro5iOnQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=09xR6MYDu2s:_86zro5iOnQ:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=09xR6MYDu2s:_86zro5iOnQ:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/2677983267117299404/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-23.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/2677983267117299404?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/2677983267117299404?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-23.html" title="Pour les gouverner tous - partie 2/3" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s72-c/jmx_jgroups01.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkMDQnkyfSp7ImA9Wx9bFUU.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-3893760519456613037</id><published>2011-01-31T22:24:00.001+01:00</published><updated>2011-02-25T00:01:13.795+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-25T00:01:13.795+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jmx" /><category scheme="http://www.blogger.com/atom/ns#" term="jgroups" /><title>Pour les gouverner tous -  partie 1/3</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s1600/jmx_jgroups01.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" height="173" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s320/jmx_jgroups01.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour ceux qui l'auraient manqués (comment ça? Personne ne me suit... :( ), j'ai annoncé dans un post précédent que j'avais ouvert un compte sur GitHub pour hoster du code. Bien sûr, il y avait une petite idée derrière... ;-)&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En fait, l'idée est partie d'un constat assez simple : sur différent projet, à chaque fois que j'ai voulu mettre en place JMX, ce qui m'a toujours &lt;em&gt;profondément&lt;/em&gt; attristé était de ne pas pouvoir regrouper l'ensemble des informations des MBeans à un même endroit, c'est-à-dire, qu'il me fallait me demander où se trouvait tel ou tel MBean dans mon système alors que j'aurais aimé pouvoir me connecter sur n'importe quelle instance de mon système et y trouver tous les MBeans présents dans mon système. Enfin, pour être plus précis, j'aurais aimé pouvoir me connecter à n'importe quelle JVM qui hébergeait mon application et avoir accès à tous les serveurs JMX.&lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;Bien sûr, me direz-vous, il existe des solutions comme Hyperic qui permettent d'agréger toutes les informations et d'offrir une solution à mon problème. Cependant, cela ne répondait pas à une des problématiques que j'ai pu avoir il y a quelques temps : dans le cas où il ne doit pas y avoir de serveurs dans mon système (même passif), une telle solution n'est pas envisageable. En effet, dans l'architecture de cette application, tous les noeuds de mon système étaient au même niveau hiérarchique afin d'éviter d'avoir un single point of failure. Aussi, introduire un manageur pour administrer mon système n'était pas envisageable. En outre, un autre des pré-requis de ce projet était qu'il n'y avait pas de connaissance préalable de où tournait mon application (au sens scalabilité du terme) : tout poste était&amp;nbsp;susceptible&amp;nbsp;de démarrer l'application sans qu'un serveur centralisé n'en ait connaissance.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Aussi, vous l'aurez compris, l'idée est, ici, de proposer une ébauche de solution pour répondre à la problématique précédemment citée : pour n'importe quelle application&amp;nbsp;susceptible&amp;nbsp;d'être exécutée de manière distributée, être capable d'avoir sur chacune la connaissance (connaissance au sens supervision et administration et non au sens applicatif du terme...) de l'état de mes autres instances.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En outre, cette petite mise en oeuvre était également un bon prétexte pour utiliser JGroups et JMX et montrer comment il était possible de les utiliser.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;La problématique étant posée, je vous propose donc une petite boite à outils permettant de faire cela de manière simple : en démarrant son application et en positionnant un agent sur la JVM, elle permet de remonter dans le serveur JMX courant tous les MBeans se trouvant sur les autres serveurs JMX (modulo qu'ils aient été démarrés par une JVM où l'agent aurait ếté mis).&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour ce faire, un premier choix a été de m'appuyer sur JGroups pour connaitre et être informé de l'état de mon système : je n'avais pas envie de gérer toutes les problématiques de Heartbeat &amp;amp; co. et j'ai donc décidé de déléguer à JGroups cette problématique. En outre, cela permettait une plus grande configuration de la couche de découverte et de surveillance de mon système puisque JGroups possédait déjà une grande facilité de configuration.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;La série d'articles qui suivra expliquera donc comment cela fonctionne et sur quoi je me suis appuyé pour le faire.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Elle sera découpée en deux parties :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;La &lt;a href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-23.html"&gt;première partie&lt;/a&gt; fournira une sorte de pseudo exemple d'utilisation de JGroups en proposant une solution permettant lors de l'utilisation d'une application distribuée de récupérer et de conserver localement l'état d'un objet distant dans une sorte de cache tout en supprimant cet objet si l'application distante est arrêtée.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;La &lt;a href="http://jetoile.blogspot.com/2011/02/pour-les-gouverner-tous-partie-33.html"&gt;deuxième partie&lt;/a&gt; ajoutera l'utilisation de JMX pour permettre la récupération des MBeans distants ainsi que leurs enregistrement dans le MBeanServer courant.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-3893760519456613037?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=OzTZxtQrQe4:-nVB4rcT7ag:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=OzTZxtQrQe4:-nVB4rcT7ag:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=OzTZxtQrQe4:-nVB4rcT7ag:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/3893760519456613037/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/01/pour-les-gouverner-tous-partie-13.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/3893760519456613037?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/3893760519456613037?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/01/pour-les-gouverner-tous-partie-13.html" title="Pour les gouverner tous -  partie 1/3" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_XLL8sJPQ97g/TUcoTratqiI/AAAAAAAAAUQ/Gmc1h0rvA2w/s72-c/jmx_jgroups01.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEQERn46eyp7ImA9Wx9VFEw.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-6276760851247024337</id><published>2011-01-30T20:37:00.001+01:00</published><updated>2011-01-30T20:38:27.013+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-30T20:38:27.013+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="divers" /><title>Ouverture d'un compte GitHub</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TUW89rVpt-I/AAAAAAAAAUM/iuvXdlFSGAE/s1600/github.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TUW89rVpt-I/AAAAAAAAAUM/iuvXdlFSGAE/s1600/github.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Voilà, ça fait quelques jours que je travaille sur un petit projet perso.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Aussi, afin de pouvoir le &lt;i&gt;hoster&lt;/i&gt;, je me suis créé un compte sur GitHub :&amp;nbsp;&lt;a href="https://github.com/jetoile"&gt;https://github.com/jetoile&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour toutes informations sur Git, je vous renvoie sur le site :&amp;nbsp;&lt;a href="http://blog.gitfr.net/"&gt;http://blog.gitfr.net/&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;De mon coté, je continue mon petit projet que je documenterai via de nouveaux articles d'ici peu.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Rester à l'écoute ;-)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-6276760851247024337?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=IrBWZeUco18:bfPksK9PXjk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=IrBWZeUco18:bfPksK9PXjk:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=IrBWZeUco18:bfPksK9PXjk:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/6276760851247024337/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/01/ouverture-dun-compte-github.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/6276760851247024337?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/6276760851247024337?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/01/ouverture-dun-compte-github.html" title="Ouverture d'un compte GitHub" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_XLL8sJPQ97g/TUW89rVpt-I/AAAAAAAAAUM/iuvXdlFSGAE/s72-c/github.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkUBRXs4cCp7ImA9Wx9bEk8.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-6608184884355944862</id><published>2011-01-23T12:31:00.003+01:00</published><updated>2011-02-20T18:50:54.538+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-20T18:50:54.538+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jmx" /><title>Petites astuces avec JMX</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TTr8YAhjHqI/AAAAAAAAAUA/nx8ug8MDDNA/s1600/jmx02.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" height="226" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TTr8YAhjHqI/AAAAAAAAAUA/nx8ug8MDDNA/s320/jmx02.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ce rapide article fournit un petit retour d'expérience de quelques galères que j'ai pu avoir avec JMX (&lt;i&gt;Java Management eXtension&lt;/i&gt;), galères certes stupides mais qui pourront peut être servir à d'autres... ;-)&lt;br /&gt;
Sera donc abordé deux points :&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Erreur lors de l'arrêt de tomcat configuré avec JMX&lt;/li&gt;
&lt;li&gt;Impossibilité de se connecter à l'agent JMX&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;h1&gt;Message d'erreur lors de l'arrêt d'Apache Tomcat?&lt;/h1&gt;&lt;h2&gt;Cas d'usage&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Les options permettant d'activer JMX sur la JVM ont été passées via la variable JAVA_OPTS ou autre (via le catalina.sh par exemple).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Le démarrage de Tomcat s'effectue sans problème mais lors de son arrêt, une erreur&amp;nbsp;apparaît&amp;nbsp;et tomcat refuse de s'arrêter c'est-à-dire que son processus tourne toujours en tâche de fond.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Exemple de variable JAVA_OPTS :&lt;/div&gt;&lt;pre class="brush: bash"&gt;export JAVA_OPTS="$JAVA_OPTS \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=18080 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false"&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Message affiché sur la console lors du démarrage de Tomcat :&lt;/div&gt;&lt;pre class="brush: bash"&gt;khanh@khanh-vaio:/opt/apache-tomcat-6.0.20/bin$ ./startup.sh
Using CATALINA_BASE:   /opt/apache-tomcat-6.0.20
Using CATALINA_TMPDIR:  /opt/apache-tomcat-6.0.20
Using CATALINA_HOME:  /opt/apache-tomcat-6.0.20/temp
Using JRE_HOME:     /usr/lib/jvm/java-6-sun/jre&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Message affiché sur la console lors de l'arrêt de Tomcat :&lt;/div&gt;&lt;pre class="brush: bash"&gt;khanh@khanh-vaio:/opt/apache-tomcat-6.0.20/bin$ ./shutdown.sh
Using CATALINA_BASE:   /opt/apache-tomcat-6.0.20
Using CATALINA_TMPDIR:  /opt/apache-tomcat-6.0.20
Using CATALINA_HOME:   /opt/apache-tomcat-6.0.20/temp
Using JRE_HOME:     /usr/lib/jvm/java-6-sun/jre
Erreur: Exception envoyée par l'agent : java.rmi.server.ExportException: Port already in use: 18080; nested exception is: 
        java.net.BindException: Address already in use
&lt;/pre&gt;&lt;h2&gt;Explication&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;En fait, cette erreur se produit lors de l'arrêt de Tomcat car le script shutdown.sh (ou catalina.sh stop) relance un processus java qui tente alors de démarrer un serveur RMI qui est utilisé par JMX. Bien sûr, ce port étant déjà utilisé par le processus java que l'on tente d'arrêter, cela échoue.&lt;/div&gt;&lt;h2&gt;Proposition pour résoudre le problème&lt;/h2&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;s&gt;Ne pas positionner les options pour activer JMX sur la variable système JAVA_OPTS au risque de ne pas pouvoir démarrer plusieurs processus Java.&lt;/s&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;s&gt;Si c'est le script catalina.sh qui positionne la variable JAVA_OPTS, ne pas la positionner dans tous les cas mais seulement dans le cas où l'argument start est passé au script.&lt;/s&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;s&gt;Positionner la variable JAVA_OPTS dans le script startup.sh.&lt;/s&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Utiliser la variable CATALINA_OPTS qui n'est utilisée que quand les options run et start sont passées"&lt;/li&gt;
&lt;/ul&gt;&lt;blockquote&gt;&lt;blockquote&gt;CATALINA_OPTS &amp;nbsp; (Optional) Java runtime options used when the "start", &amp;nbsp;or "run" command is executed.&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;h1&gt;Problème de connexion?&lt;/h1&gt;&lt;h2&gt;Cas d'usage&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Une jconsole ou une jvisualvm qui n'arrive pas à se connecter à un programme ou une connexion au connecteur d'un agent JMX qui échoue avec une exception.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Chose d'autant plus étonnante qu'avec une connexion réseau, il n'y a pas de problèmes alors qu'en mode hors-ligne, impossible d'avoir accès à l'agent JMX.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Exemple d'exception lors de la tentative de connexion à l'agent JMX distant :&lt;/div&gt;&lt;pre class="brush: bash"&gt;java.lang.NullPointerException
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:281)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:227)
at com.blogspot.jetoile.jgroups.connector.ConnectorStubListener.update(ConnectorStubListener.java:47)
at com.blogspot.jetoile.jgroups.connector.ConnectorStubManager.put(ConnectorStubManager.java:46)
[...]
at com.blogspot.jetoile.jgroups.connector.TestJMXServerTest.main(TestJMXServerTest.java:34)
&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Fenêtre d'erreur de la jconsole :&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TTsrkOibDDI/AAAAAAAAAUE/qpX-1nw0OOA/s1600/error02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="333" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TTsrkOibDDI/AAAAAAAAAUE/qpX-1nw0OOA/s400/error02.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Fenêtre d'erreur de jvisualvm : "&lt;i&gt;Data not available because JMX connection to the JMX agent could not be established.&lt;/i&gt;" :&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TTsroeTxKoI/AAAAAAAAAUI/0aUghCdjv0w/s1600/error01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="243" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TTsroeTxKoI/AAAAAAAAAUI/0aUghCdjv0w/s400/error01.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h2&gt;Analyse&lt;/h2&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Après de multiples tentatives pour comprendre, j'ai tenté un changement de jre pour voir si cela ne pouvait pas venir d'une anomalie (si j'avais un problème de connexion en mode hors-ligne, ce n'était pas pour rien puisque j'étais effectivement hors-ligne et, par conséquent, je devais me débrouiller par moi-même... ;-) ).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, en passant d'une jre hotspot vers une openjdk, j'ai obtenu une stacktrace beaucoup plus complète puisqu'elle m'a clairement indiquée la source du problème :&lt;/div&gt;&lt;br /&gt;
&lt;pre class="brush: bash"&gt;ERROR c.b.j.j.c.ConnectorStubListener - ConnectorStubListener update: {}
java.rmi.ConnectIOException: Exception creating connection to: 192.168.xxx.xxx; nested exception is:
java.net.NoRouteToHostException: Network is unreachable
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:632) ~[na:1.6.0_20]
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216) ~[na:1.6.0_20]
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202) ~[na:1.6.0_20]
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:128) ~[na:1.6.0_20]
at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source) ~[na:1.6.0_20]
at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2343) ~[na:1.6.0_20]
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:296) ~[na:1.6.0_20]
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:244) ~[na:1.6.0_20]
at com.blogspot.jetoile.jgroups.connector.ConnectorStubListener.update(ConnectorStubListener.java:47) ~[classes/:na]
at com.blogspot.jetoile.jgroups.connector.ConnectorStubManager.put(ConnectorStubManager.java:46) [classes/:na]
...
at com.blogspot.jetoile.jgroups.connector.JMXServer.start(JMXServer.java:152) [classes/:na]
at com.blogspot.jetoile.jgroups.connector.TestJMXServerTest2.main(TestJMXServerTest2.java:34) [test-classes/:na]


Caused by: java.net.NoRouteToHostException: Network is unreachable
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.6.0_20]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:310) ~[na:1.6.0_20]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:176) ~[na:1.6.0_20]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:163) ~[na:1.6.0_20]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384) ~[na:1.6.0_20]
at java.net.Socket.connect(Socket.java:546) ~[na:1.6.0_20]
at java.net.Socket.connect(Socket.java:495) ~[na:1.6.0_20]
at java.net.Socket.&lt;init&gt;(Socket.java:392) ~[na:1.6.0_20]&lt;/init&gt;
at java.net.Socket.&lt;init&gt;(Socket.java:206) ~[na:1.6.0_20]&lt;/init&gt;
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40) ~[na:1.6.0_20]
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146) ~[na:1.6.0_20]
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613) ~[na:1.6.0_20]
... 34 common frames omitted
&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;Explication&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;En fait, mon problème venait du fait que mon fichier &lt;i&gt;hosts&lt;/i&gt; était incorrect (je vous avais prévenu que c'était une erreur stupide : n'importe qui aurait pensé à vérifier sa configuration réseau... ! ;-) ).&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En effet, la couche logicielle gérant mes connexions réseaux sur mon ordinateur a tendance à ajouter dans mon fichier /etc/hosts mon adresse réseau. Cependant, lorsque je coupe mon wifi, mon ordinateur passe en mode hors-ligne sans modifier mon fichier &lt;i&gt;hosts&lt;/i&gt;, ce qui corrompt ma configuration réseau.&lt;/div&gt;&lt;h2&gt;Proposition pour résoudre le problème&lt;/h2&gt;&lt;div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Corriger son fichier &lt;i&gt;hosts&lt;/i&gt; et vérifier sa configuration réseau&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;A noter que dans mon cas, le fait d'avoir changer de jre m'a permis d'obtenir une stacktrace beaucoup plus complète et précise. Aussi, dans un moment de désespoir et en dernier recours, il peut être intéressant de changer de jre ;-).&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-6608184884355944862?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=pdetmTp8diM:FJ0LMx6ByMw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=pdetmTp8diM:FJ0LMx6ByMw:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=pdetmTp8diM:FJ0LMx6ByMw:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/6608184884355944862/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2011/01/petites-astuces-avec-jmx.html#comment-form" title="2 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/6608184884355944862?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/6608184884355944862?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2011/01/petites-astuces-avec-jmx.html" title="Petites astuces avec JMX" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_XLL8sJPQ97g/TTr8YAhjHqI/AAAAAAAAAUA/nx8ug8MDDNA/s72-c/jmx02.png" height="72" width="72" /><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;Dk8HRno8eip7ImA9Wx9bEk8.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-7877601280471708447</id><published>2010-12-28T17:05:00.006+01:00</published><updated>2011-02-20T19:00:37.472+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-20T19:00:37.472+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jgroups" /><title>JGroups : tour d'horizon</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XLL8sJPQ97g/TRtn71JxZPI/AAAAAAAAATI/0vNqJjOXKlY/s1600/jgroups_logo_450px.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="113" src="http://2.bp.blogspot.com/_XLL8sJPQ97g/TRtn71JxZPI/AAAAAAAAATI/0vNqJjOXKlY/s320/jgroups_logo_450px.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Actuellement, le besoin de rendre les systèmes ou les applications interopérables est indéniable. Pour ce faire, de nombreuses technologies ont vues le jour. Il peut s'agir des MOM (&lt;i&gt;Message-Oriented Middleware&lt;/i&gt;), des protocoles de communication entre les applications clientes et serveurs (REST, Soap, RMI, ...), de solutions propriétaires utilisées pour permettre la communication entre les serveurs pour des problématiques de réplication ou de synchronisation ou même de solutions basées sur le paradigme NoSQL.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cependant, il est important de ne pas oublier que nos couches basses restent les protocoles TCP ou UDP et que répondre par un grand concept tel que MOM, réplication de serveurs ou cache distribué sur une problématique ne permet pas de savoir ce qui se trame derrière...&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Un produit souvent méconnu est utilisé en interne pour les problématiques de communication entre serveurs et même si, à ce jour, je ne connais pas d'implémentations de MOM qui l'utilise, il pourrait être un très bon candidat pour ces dernières en interne. Il s'agit de JGroups.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Aussi, cet article va tenter de donner un rapide tour d'horizon sur &lt;a href="http://www.jgroups.org/"&gt;JGroups&lt;/a&gt; en présentant ses concepts. Il s'appuiera sur sa version stable courante, à savoir la version 2.11.0.&lt;br /&gt;
A noter que ce tour d'horizon s'appuie très fortement sur le manuel de référence de JGroups.&lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;Cet article suivra le plan suivant :&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#histoire"&gt;Un peu d'histoire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#concepts"&gt;Présentation des concepts&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#canal"&gt;Canal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#bloc"&gt;Bloc de construction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#pile"&gt;Pile de protocoles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#entete"&gt;Entête&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#evenement"&gt;Evénement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#api"&gt;Présentation des APIs de JGroups&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#interface"&gt;Les interfaces&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#messagelistener"&gt;MessageListener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#membershiplistener"&gt;MembershipListener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#channellistener"&gt;ChannelListener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#receiver"&gt;Receiver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#receiveradapter"&gt;ReceiverAdapter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#address"&gt;L'interface Address&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#message"&gt;La classe Message&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#view"&gt;La classe View&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#viewid"&gt;La classe ViewId&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#mergeview"&gt;La classe MergeView&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#jchannel"&gt;La classe JChannel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#blocs"&gt;Les blocs de construction&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#messagedispatcher"&gt;MessageDispatcher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#rpcdispatcher"&gt;RpcDispatcher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#replicatedhashmap"&gt;ReplicatedHashMap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#notificationbus"&gt;NotificationBus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#protocoles"&gt;Liste des protocoles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="histoire"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1&gt;Un peu d'histoire...&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Créé par Bela Ban, JGroups a vu le jour suite à son travail universitaire dans les équipe de Ken Birman sur le framework &lt;i&gt;Ensemble&lt;/i&gt; qui, en 1998-1999, était un prototype pour la troisième génération de communication de groupes. &lt;i&gt;Ensemble&lt;/i&gt; faisait suite à &lt;i&gt;Horus&lt;/i&gt; (écrit par Robbert VanRenesse) qui faisait lui-même suite à &lt;i&gt;ISIS&lt;/i&gt; (écrit par Keb Birman) et était écrit en OCaml. &lt;i&gt;Ensemble&lt;/i&gt; proposant une interface pour s'interfacer avec Java mais s'appuyant sur son coeur, cela a été le début de JGroups (enfin pour être plus précis le début de &lt;i&gt;JChannel&lt;/i&gt; puis de la partie &lt;i&gt;ProtocolStack&lt;/i&gt;) qui avait pour objectif de fournir une solution full Java de &lt;i&gt;Ensemble&lt;/i&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, JGroups a pris son&amp;nbsp;essor&amp;nbsp;en 2000 avec le départ de Bela Ban du pôle de recherche de l'université de Cornell pour enfin être utilisé par JBoss dès 2002 avec, entre autre &lt;i&gt;JBossCache&lt;/i&gt;.&amp;nbsp;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="concepts"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1&gt;Présentation des concepts&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;La communication entre groupes utilise les termes de&amp;nbsp;groupes et de&amp;nbsp;membres qui font partis intégrantes des groupes. En fait, un membre peut être vu comme un noeud et un groupe comme un cluster.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En fait, un noeud est un processus qui réside sur une machine hôte et un cluster est constitué d'un ou de plusieurs noeuds, sachant que plusieurs noeuds peuvent résider sur le même hôte et qu'ils peuvent appartenir à un ou plusieurs clusters.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;JGroups est un framework permettant la communication fiable entre groupes et permets aux processus :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;de rejoindre un groupe,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;d'envoyer des messages à tout ou partie des membres du groupe,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;et de recevoir les messages des membres du groupe.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;En outre, JGroups permet de garder de notifier les membres de chaque groupe lors de l'arrivé d'un nouveau membre ou d'un départ ou arrêt brutal de l'un d'eux.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Un &lt;b&gt;groupe&lt;/b&gt; est identifié par son nom et n'a pas besoin d'être créé explicitement puisqu'il est créé automatiquement.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En fait, l'architecture de JGroups s'articule autour de trois points :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;les canaux (&lt;b&gt;channel&lt;/b&gt;) utilisés par les applications pour leurs permettre de prendre part au groupe de communication fiable,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;les blocs de construction (&lt;b&gt;building blocks&lt;/b&gt;) qui sont des couches au dessus des canaux qui permettent d'abstraire ces derniers de la pile de protocoles à utiliser,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;la pile de protocoles qui implémentent les propriétés d'un canal donné. &amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;En fait, un canal est connecté à une pile (&lt;i&gt;stack&lt;/i&gt;) de protocoles et lorsqu'une application émet un message, le canal le transmet au travers de cette pile pour effectuer séquentiellement des traitements jusqu'à la couche réseau. De manière similaire, pour qu'une application reçoive un message, ce dernier doit repasser dans cette pile de protocole (dans l'ordre inverse des traitements qu'il a subi lors de son émission) jusqu'à arriver à canal qui gère la file des messages jusqu'à leurs consommations par l'application.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Il est à noter que lorsqu'une application se connecte à un canal, la pile de protocole est démarrée et que lorsqu'elle se déconnecte, cette même pile est arrêtée. Quand le canal est fermé, la pile est détruite permettant ainsi de libérer ses ressources.&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="canal"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Canal (&lt;i&gt;Channel&lt;/i&gt;)&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Pour joindre un groupe et émettre des messages, un processus doit créer un canal et s'y connecter en utilisant le nom du groupe puisque tous les canaux qui possèdent le même nom forment un même groupe.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Une fois connecté, un membre peut émettre (resp. recevoir) des messages aux (resp. des) autres membres du groupe.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Il quitte le groupe en se déconnectant du canal permettant ainsi sa réutilisation. Cependant, un canal ne gère qu'un seul client simultanément.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Le client a également la possibilité de signaler qu'il ne désire plus utiliser un canal en le fermant. Dans ce cas, le canal ne peut plus être utilisé.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Chaque canal dispose d'une adresse unique et est toujours connu des autres membres de son groupe : une liste d'adresse des membres peut être récupérée d'un canal et est appelé vue (&lt;i&gt;view&lt;/i&gt;).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Un processus peut alors sélectionner une adresse dans cette liste et émettre un message à destination de l'unique membre associé à cette adresse (mais également à lui-même puisqu'il appartient à la vue) ou émettre un message à tous les membre de la vue (et donc au groupe).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour gérer les vues :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;lorsqu'un membre rejoint le groupe ou qu'il s'arrête (déconnexion ou détection de crash), JGroups envoie une nouvelle vue à tous les membres du groupes.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;lorsqu'un membre est suspecté comme ayant potentiellement crashé, un message de suspicion est émis à destination de tous les membres non fautif.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Ainsi, un canal peut recevoir trois types de messages ;&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;les messages normaux (ie. un message émis par une application),&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;les messages de vues lors de l'ajout ou du retrait d'un de ses membres,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;les messages de suspicion. &amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Bien sûr, un client peut choisir s'il accepte de recevoir les messages de types vue ou suspicion.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En fait, les canaux sont similaires à des sockets BSD ; les messages sont stockés dans le canal jusqu'à temps qu'ils soient consommés par un client (approche pull). Dans le cas où il n'y a pas de messages, le client est bloqué. Cependant, JGroups propose également la notion de &lt;i&gt;push&lt;/i&gt; pour recevoir les messages en se basant sur la notion de &lt;i&gt;callback&lt;/i&gt; (ou, du point de vue client, de &lt;i&gt;Listener&lt;/i&gt;). Il est à noter que le fonctionnement en mode &lt;i&gt;pull&lt;/i&gt; tend à être supprimé en version 3 de JGroups : il est donc déconseillé de l'utiliser.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Afin de positionner les propriétés sur un canal, JGroups s'appuie sur une configuration XML.&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="bloc"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Bloc de construction (&lt;i&gt;Building Blocks&lt;/i&gt;)&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Le canal est un concept simple qui permet de fournir la fonctionnalité basique d'un groupe de communication en proposant une douzaine de méthodes qui permettent la communication entre applications via la transmission de messages asynchrones sur le même modèle que UDP. Ainsi, par exemple, le canal de base ne gère pas l'ordonnancement des messages et il est alors à la charge de l'application de réordonnancer les messages. En outre, le fonctionnement en mode &lt;i&gt;pull&lt;/i&gt; nécessite généralement au client d'avoir à gérer un thread pour éviter de bloquer l'application lorsqu'il attend un message.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, JGroups propose la notion de blocs de construction (&lt;i&gt;Building Blocks&lt;/i&gt;) qui offre une API plus sophistiquée et qui s'appuie, en interne, sur les canaux.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cela permet aux applications de communiquer en utilisant ces derniers en offrant une plus grande facilité d'utilisation du groupe de communication (par exemple, certains blocks permettent de gérer nativement les identifiants des corrélations).&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="pile"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Pile de protocoles (&lt;i&gt;Protocol Stack&lt;/i&gt;)&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;La pile de protocoles contient de nombreuses couches de protocoles qui sont bidirectionnels. Tous les messages émis et reçus par le canal doivent passer à travers ces protocoles qui peuvent :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;modifier,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;réordonnancer,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;supprimer ou laisser passer un message,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;ajouter un entête au message,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;découper le message en messages plus petit,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;réaggréger un ensemble de messages,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;...&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;La composition de la pile de protocoles (ie. ses couches) est déterminée par le créateur du canal via un fichier XML qui définit et paramètres les différentes couches à utiliser en lui associant un nom.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cette séparation des concepts permet ainsi d'abstraire l'application, qui utilise un canal, de comment le message est émis et reçu.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Si aucune pile de protocoles n'est fournie lors de la création du canal, alors c'est sa configuration par défaut qui est utilisé.&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="entete"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Entête (&lt;i&gt;Header&lt;/i&gt;)&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Un entête (&lt;i&gt;Header&lt;/i&gt;) est un ensemble d'informations personnalisables qui peut être ajouté à chaque message.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Il est à noter que JGroups utilise cette fonctionnalité dans de nombreux cas de figures comme, par exemple, pour savoir connaitre l'ordonnancement d'envoi des messages (via les entêtes &lt;i&gt;NAKACK&lt;/i&gt; et &lt;i&gt;UNICAST&lt;/i&gt;).&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="evenement"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Evénement (&lt;i&gt;Event&lt;/i&gt;)&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Les&amp;nbsp;évènements&amp;nbsp;(&lt;i&gt;Event&lt;/i&gt;) permettent à JGroups de savoir quels protocoles peuvent communiquer avec quel autre. Ainsi, contrairement aux messages qui transitent au travers du réseau entre les membres d'un groupe, les évènements transitent au travers la pile.&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="api"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1&gt;Présentation générale des APIs de JGroups&lt;/h1&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="interface"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Les interfaces&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;JGroups propose un certain nombre d'interfaces principales sur lesquelles s'appuient les différentes implémentations :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;i&gt;MessageListener&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;MembershipListener&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;ChannelListener&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;Receiver&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;ReceiverAdapter&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="messagelistener"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;MessageListener&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;L'interface &lt;i&gt;MessageListener&lt;/i&gt; permet d'être notifier lors de la réception d'un message&amp;nbsp;lorsque le mode de fonctionnement est de type &lt;i&gt;push&lt;/i&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour ce faire, la méthode &lt;i&gt;receive(Message msg)&lt;/i&gt; est invoquée. Les méthodes &lt;i&gt;getState()&lt;/i&gt; et &lt;i&gt;setState()&lt;/i&gt; permettent, quant à elles, de récupérer l'état du groupe.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ4yCVvoq6I/AAAAAAAAAQ8/P05famfiSL4/s1600/jgroups01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ4yCVvoq6I/AAAAAAAAAQ8/P05famfiSL4/s1600/jgroups01.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="membershiplistener"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;MembershipListener&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;L'interface &lt;i&gt;MembershipListener&lt;/i&gt; permet d'être notifiée lorsqu'une nouvelle vue, un message de suspicion ou un évènement de bloc est reçu.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Dans la plupart des cas, c'est la méthode &lt;i&gt;viewAccepted()&lt;/i&gt; qui est invoquée puisqu'elle notifie lorsqu'un nouveau membre a rejoint le groupe ou que l'un d'entre eux s'est déconnecté ou s'est arrêté brutalement. La méthode &lt;i&gt;suspect()&lt;/i&gt; permet d'être informé lorsqu'un membre du groupe est suspecté de s'être arrêté brutalement mais qu'il n'a pas encore été exclu. La méthode &lt;i&gt;block()&lt;/i&gt; est invoquée pour indiqué que le membre courant est sur le point d'être d'être exclu des membres qui ont le droit d'émettre des messages.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TQ4yKn49KiI/AAAAAAAAARA/w8UlwBfI1lc/s1600/jgroups02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TQ4yKn49KiI/AAAAAAAAARA/w8UlwBfI1lc/s1600/jgroups02.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="channellistener"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;ChannelListener&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;L'interface &lt;i&gt;ChannelListener&lt;/i&gt; est utilisée comme interface de &lt;i&gt;callback&lt;/i&gt; lorsque l'application souhaite recevoir des informations sur les changements d'état du canal (fermeture, déconnexion ou ouverture).&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ4ydDBkt5I/AAAAAAAAARE/kEWjYvTnDFs/s1600/jgroups03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ4ydDBkt5I/AAAAAAAAARE/kEWjYvTnDFs/s1600/jgroups03.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="receiver"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;Receiver&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;L'interface &lt;i&gt;Receiver&lt;/i&gt; peut être utilisée pour recevoir des messages et les changements de vue dans le mode &lt;i&gt;push&lt;/i&gt;. A noter que cette interface est marquée comme dépréciée et sera supprimé en version 3. L'utilisation de &lt;i&gt;MessageListener&lt;/i&gt; et &lt;i&gt;MembershipListener&lt;/i&gt; est préconisée.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TRoGqAZ288I/AAAAAAAAASg/EshWFLsfHjA/s1600/jgroups04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TRoGqAZ288I/AAAAAAAAASg/EshWFLsfHjA/s400/jgroups04.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="receiveradapter"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;ReceiverAdapter&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;Cette classe permet de fournir une implémentation par défaut de l'interface &lt;i&gt;Receiver&lt;/i&gt; en ne permettant d'avoir à implémenter que les méthodes nécessaires (dont la méthode &lt;i&gt;receive()&lt;/i&gt;).&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XLL8sJPQ97g/TRoG6cQ9F5I/AAAAAAAAASk/orJ7pVnADug/s1600/jgroups05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="293" src="http://2.bp.blogspot.com/_XLL8sJPQ97g/TRoG6cQ9F5I/AAAAAAAAASk/orJ7pVnADug/s400/jgroups05.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="address"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;L'interface Address&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Chaque membre d'un groupe dispose d'une adresse qui l'identifie de manière unique. Cette adresse est représentée par l'interface &lt;i&gt;Address&lt;/i&gt; qui require une implémentation concrète afin de fournir ses méthodes de comparaison, de trie et afin de permettre de différencier une adresse de type multicast.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cependant, une implémentation de l'interface &lt;i&gt;Address&lt;/i&gt; ne doit jamais être utilisée directement et l'interface &lt;i&gt;Address&lt;/i&gt; doit être vue comme une couche d'abstraction lui permettant d'identifier le noeud dans le cluster. Ses implémentations sont généralement générées par la couche la plus basse du protocole (ie. UDP ou TCP).&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Puisque l'adresse identifie de manière unique un canal et plus précisément un membre du groupe, elle peut être utilisée pour émettre des message.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, par exemple, dans le cas de &lt;i&gt;JChannel&lt;/i&gt;, l'adresse, qui est implémentée par la classe &lt;i&gt;IpAddress&lt;/i&gt;, correspond à l'IP de l'hôte sur laquelle se trouve le membre et de son port sur lequel sont reçus les messages.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TRoHFjviIMI/AAAAAAAAASo/nsGhSwGXwzw/s1600/jgroups06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="118" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TRoHFjviIMI/AAAAAAAAASo/nsGhSwGXwzw/s400/jgroups06.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="message"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;La classe Message&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Les échanges de données émis entre les membres se fait au travers de messages qui sont représentés par la classe &lt;i&gt;Message&lt;/i&gt;. Un message peut être émis, par un membre, aussi bien à un membre ou à tous les membres du groupe du canal.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Il est composé de cinq parties :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;L'adresse de destination : si elle vaut &lt;i&gt;null&lt;/i&gt;, le message est émis à tous les membre du groupe courant.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;L'adresse de l'émetteur : ce champ est optionnel mais sera renseigné par le protocole de transport avant que le message n'atteigne la couche réseau.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Les drapeaux (&lt;i&gt;flags&lt;/i&gt;) qui est codé sur un octet et qui peut valoir l'une des valeurs suivantes :&amp;nbsp;&lt;i&gt;OOB&lt;/i&gt;, &lt;i&gt;LOW_PRIO&lt;/i&gt; ou &lt;i&gt;HIGH_PRIO&lt;/i&gt;.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Le contenu (&lt;i&gt;payload&lt;/i&gt;) : codé sous forme de buffers d'octets, la classe &lt;i&gt;Message&lt;/i&gt; doit contenir les méthodes permettant de sérialiser et désérialiser l'information transmise.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Les entêtes (&lt;i&gt;headers&lt;/i&gt;) qui représentent les informations additionnelles au contenu.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ4y5ZcL1RI/AAAAAAAAARU/3ayXiOTHOIY/s1600/jgroups07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ4y5ZcL1RI/AAAAAAAAARU/3ayXiOTHOIY/s400/jgroups07.png" width="145" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="view"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;&amp;nbsp;La classe View&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Une vue représente la liste des membres d'un groupe à un instant donné. Elle consiste en un objet de type &lt;i&gt;ViewId&lt;/i&gt; qui représente de manière unique la vue ainsi que la liste de ses membres.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Les vues sont gérées automatiquement par la couche de protocoles lorsqu'un nouveau membre rejoint le groupe ou qu'un membre le quitte. Tous les membres d'un groupe voient la même séquence de vues qui sont ordonnées.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, généralement, le premier membre d'une vue est le coordinateur (son rôle consiste à émettre les nouvelles vues aux autres membres du groupe). Cela permet, si les membres du groupes changent, de déduire le coordinateur facilement sans avoir à contacter les autres membres du groupe.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A noter que lorsqu'une application est notifiée que le groupe a changé (ie. qu'une nouvelle vue a été reçue), la vue est déjà à sa disposition dans le canal.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TRoHVP9nFLI/AAAAAAAAASs/bdb-orAyhxo/s1600/jgroups08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="396" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TRoHVP9nFLI/AAAAAAAAASs/bdb-orAyhxo/s400/jgroups08.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="viewid"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;La classe ViewId&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;La classe &lt;i&gt;ViewId&lt;/i&gt; est utilisée pour numéroter les vues et consiste en l'adresse du créateur de la vue et en son numéro de séquence.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TRoHeWcBzbI/AAAAAAAAASw/aSNJllb0Q3o/s1600/jgroups09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="258" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TRoHeWcBzbI/AAAAAAAAASw/aSNJllb0Q3o/s400/jgroups09.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="mergeview"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;La classe MergeView&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;Lorsqu'un groupe se retrouve découpé en sous-groupe (par exemple, lors d'un partitionnement du réseau puis de son ré-aggrégement), les vues peuvent nécessiter un merge.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Dans ce cas, un objet de type &lt;i&gt;MergeView&lt;/i&gt; qui étend la classe &lt;i&gt;View&lt;/i&gt; est reçu par l'application. Cette classe contient, en plus de &lt;i&gt;View&lt;/i&gt;, la liste des vues qui ont été mergés.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, par exemple, si un groupe est décrit par la vue &lt;i&gt;V1:(p,q,r,s,t)&lt;/i&gt;, qu'il subit un découpage en deux sous-groupe &lt;i&gt;V2:(p,q,r)&lt;/i&gt; et &lt;i&gt;V2:(s,t)&lt;/i&gt;, et que sa vue mergée est &lt;i&gt;v3:(p,q,r,s,t)&lt;/i&gt;, alors l'objet &lt;i&gt;MergegView&lt;/i&gt; contiendra la liste des deux vues suivantes : &lt;i&gt;v2:(p,q,r)&lt;/i&gt; et &lt;i&gt;v2:(s,t)&lt;/i&gt;.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ4zP2h5POI/AAAAAAAAARg/SUrNkuEtuR8/s1600/jgroups10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ4zP2h5POI/AAAAAAAAARg/SUrNkuEtuR8/s400/jgroups10.png" width="235" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="jchannel"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;&amp;nbsp;La classe JChannel&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Afin de pouvoir joindre un groupe et émettre des messages (ou en recevoir), un processus doit créer un canal. Un canal peut s'assimiler à une Socket. Quand le client se connecte à un canal, il doit donner le nom du groupe qu'il veut rejoindre. En effet, un canal est (dans son mode connecté) toujours associé à un groupe donné. La pile de protocoles a alors à sa charge de vérifier que le canal se joint au groupe du même nom, résultant un nouvelle vue à installer sur chaque membre du groupe.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Si aucun membre existe, le groupe est créé.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A noter que lors de sa création, un canal est dans un état déconnecté. Pour qu'il puisse commencer à traiter des opérations, il doit être dans un état connecté.&lt;br /&gt;
&lt;table&gt;&lt;tbody&gt;
&lt;tr&gt; &lt;td&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ40li7dxMI/AAAAAAAAARs/0kqgw2nAHfs/s1600/jgroups12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ40li7dxMI/AAAAAAAAARs/0kqgw2nAHfs/s400/jgroups12.png" width="127" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ40pwT73BI/AAAAAAAAARw/JbgnSQwnk2g/s1600/jgroups11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ40pwT73BI/AAAAAAAAARw/JbgnSQwnk2g/s400/jgroups11.png" width="91" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="blocs"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1&gt;Les blocs de construction (&lt;i&gt;Building blocks&lt;/i&gt;)&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Les blocs de construction sont les couches qui se trouvent au dessus des canaux. La plupart ne nécessite pas d'un canal mais seulement d'implémenter l'interface &lt;i&gt;Transport&lt;/i&gt; (qui est également implémentée par la classe &lt;i&gt;Channel&lt;/i&gt;). Cela leurs permet de fonctionner pour n'importe quel type de transport qui implémente cette interface. Les blocs de construction peuvent donc être utilisés à la place des canaux si cela est nécessaire. Ainsi, alors que les canaux peuvent être vus comme des sortes de sockets, les blocs de construction peuvent bénéficier d'une interface beaucoup plus sophistiquée.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Dans la suite, seuls les blocs de construction les plus importants seront décrits (à noter que le bloc de construction &lt;i&gt;PushPullAdapter&lt;/i&gt; étant déprécié, il ne sera pas non plus décrit).&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="messagedispatcher"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;MessageDispatcher&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;Les canaux sont de simple patron pour émettre et recevoir des messages de manière asynchrone. Cependant, il peut être nécessaire de disposer d'un moyen de communiquer de manière synchrone.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Le &lt;i&gt;MessageDispatcher&lt;/i&gt; offre cette possibilité en fournissant la possibilité d'émettre un message (ou requête) en positionnant un identifiant de corrélation afin de pouvoir associer la réponse avec la requête.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Il offre également la possibilité de recevoir un message en mode push.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour l'utiliser, il doit être créé associé avec un canal et peut être utilisé coté émetteur ou récepteur.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;S'il est utilisé du coté serveur, alors à chaque requête reçu, la méthode &lt;i&gt;handle()&lt;/i&gt; provenant de l'interface&amp;nbsp;&lt;i&gt;RequestHandler&lt;/i&gt;&amp;nbsp;est invoquée.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cette méthode retourne le message (qui doit être sérialisable) ou lève une exception qui sont transmises au client.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ43hC993TI/AAAAAAAAASE/2mgpujE4eL0/s1600/jgroups14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ43hC993TI/AAAAAAAAASE/2mgpujE4eL0/s400/jgroups14.png" width="303" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;S'il est utilisé du coté client, il est possible d'utiliser deux méthodes :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;i&gt;castMessage()&lt;/i&gt; qui permet de requêter un ensemble de destinataires (dans ce cas, si le destinataire est positionné sur l'entête du message, il sera écrasé) et qui renvoie un objet de type &lt;i&gt;RspList&lt;/i&gt; (qui implémente l'interface &lt;i&gt;Map&lt;/i&gt;)&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;sendMessage()&lt;/i&gt; qui permet de requêter un seul destinataire (dans ce cas, le destinataire doit être positionné sur l'entête du message)&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Ces deux méthodes peuvent positionner un certain nombre d'options lors de l'émission du message encapsuler dans un objet de type &lt;i&gt;RequestOptions&lt;/i&gt; tels que :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;un timeout qui permet d'indiquer le temps qu'il faut attendre la réponse.&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;le type de requête à émettre :&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;dès qu'une réponse arrive, la méthode &lt;i&gt;castMessage()&lt;/i&gt; rend la main au programme (&lt;i&gt;GroupRequest.GET_FIRST&lt;/i&gt;)&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;attend la réponse de chaque destinataire avant de rendre la main au programme (&lt;i&gt;GroupRequest.GET_ALL&lt;/i&gt;)&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;attend la majorité des réponses (&lt;i&gt;GroupRequest.GET_MAJORITY&lt;/i&gt;)&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;attend la majorité absolue des réponses (&lt;i&gt;GroupRequest.GET_ABS_MAJORITY&lt;/i&gt;)&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;n'attend aucune réponse (&lt;i&gt;GroupRequest.GET_NONE&lt;/i&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;li style="text-align: justify;"&gt;un filtre pour les réponses attendues à l'aide d'un objet de type &lt;i&gt;RspFilter&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TRoHzicdvtI/AAAAAAAAAS0/OjoJmHdwLHU/s1600/jgroups13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TRoHzicdvtI/AAAAAAAAAS0/OjoJmHdwLHU/s1600/jgroups13.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;A noter que si un membre destinataire se déconnecte du canal (dans le cas d'un arrêt brutal par exemple), alors l'objet &lt;i&gt;RspList&lt;/i&gt; retourner par la méthode &lt;i&gt;castMessage()&lt;/i&gt; contiendra une réponse indiquée comme en échec.&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="rpcdispatcher"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;RpcDispatcher&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;La classe &lt;i&gt;RpcDispatcher&lt;/i&gt; est dérivée de &lt;i&gt;MessageDispatcher&lt;/i&gt; et permet donc au programmeur d'invoquer des méthodes distantes sur un ou tous les membres du groupe et, optionnellement, attendre leurs réponses. Cependant, contrairement à l'utilisation d'un &lt;i&gt;MessageDispatcher&lt;/i&gt;, l'utilisation d'un &lt;i&gt;RpcDispatcher&lt;/i&gt; est plus simple pour un besoin de type requête/réponse puisqu'il ne nécessite pas d'avoir à implémenter l'interface &lt;i&gt;RequestHandler&lt;/i&gt; (et donc la méthode &lt;i&gt;handle()&lt;/i&gt;).&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XLL8sJPQ97g/TQ42co-e7II/AAAAAAAAASA/arjovzck9cY/s1600/jgroups15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/_XLL8sJPQ97g/TQ42co-e7II/AAAAAAAAASA/arjovzck9cY/s400/jgroups15.png" width="285" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En effet, il est possible d'indiquer lors de l'émission des requêtes (qui se fait à l'aide des méthodes &lt;i&gt;callRemoteMethod()&lt;/i&gt; et &lt;i&gt;callRemoteMethods()&lt;/i&gt;) quelles seront les méthodes (ainsi que leurs paramètres) qui seront invoqués lors de la réception des réponses.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Les autres paramètres de ces méthodes sont similaires à la méthode &lt;i&gt;castMessage()&lt;/i&gt; de la classe &lt;i&gt;MessageDispatcher&lt;/i&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;De plus, il est à noter qu'il est possible d'utiliser les méthodes &lt;i&gt;callRemoteMethodWithFuture()&lt;/i&gt; et &lt;i&gt;callRemoteMethodsWithFuture()&lt;/i&gt; qui, comme leur nom l'indique, permettent de ne pas bloquer l'application lors de l'appel à des méthodes.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ44DbehK6I/AAAAAAAAASM/SEJXTcIvnZY/s1600/jgroups16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="210" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ44DbehK6I/AAAAAAAAASM/SEJXTcIvnZY/s320/jgroups16.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="replicatedhashmap"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;ReplicatedHashMap&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;La classe &lt;i&gt;ReplicatedHashMap&lt;/i&gt; a été écrite comme une classe de démonstration afin de montrer comme les états pouvaient être partagés entre les différents noeuds du cluster. Aussi, elle n'a pas été entièrement testée et n'a pas pour objectif d'être utilisée en production.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Une &lt;i&gt;ReplicatedHashMap&lt;/i&gt; utilise une &lt;i&gt;HashMap&lt;/i&gt; concurrente en interne et permet de créer différentes instances d'objets de type &lt;i&gt;HashMap&lt;/i&gt; dans différents processus. Toutes ces instances possèdent exactement le même état. Lorsqu'une instance de &lt;i&gt;ReplicatedHashMap&lt;/i&gt; est créée, un nom de groupe permet de déterminer quel groupe de &lt;i&gt;ReplicatedHashMap&lt;/i&gt; est rejoint et la nouvelle instance interroge alors les autres membres existants pour connaitre l'état courant, le met à jour et se démarre.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Les modifications de la &lt;i&gt;ReplicatedHashMap&lt;/i&gt; (méthodes &lt;i&gt;put()&lt;/i&gt;, &lt;i&gt;clear()&lt;/i&gt; ou &lt;i&gt;remove()&lt;/i&gt;) sont propagées de manière ordonné dans tout le groupe alors que les lectures (méthode &lt;i&gt;get()&lt;/i&gt;) sont faites sur la copie locale.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XLL8sJPQ97g/TQ438y8jKhI/AAAAAAAAASI/QUvyWEKXEXY/s1600/jgroups17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="98" src="http://2.bp.blogspot.com/_XLL8sJPQ97g/TQ438y8jKhI/AAAAAAAAASI/QUvyWEKXEXY/s400/jgroups17.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TQ44U-8aDBI/AAAAAAAAASQ/8P6jK1PT8j8/s1600/jgroups18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TQ44U-8aDBI/AAAAAAAAASQ/8P6jK1PT8j8/s400/jgroups18.png" width="137" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="notificationbus"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;NotificationBus&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;La classe &lt;i&gt;NotificationBus&lt;/i&gt; permet d'émettre et de recevoir des notifications. Ainsi, cela permet à une application de maintenir un cache local répliqué avec toutes les autres instances. La classe &lt;i&gt;NotificationBus&lt;/i&gt; s'appuie sur un canal en interne.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En fait, le bloc de construction &lt;i&gt;NotificationBus&lt;/i&gt; s'apparente à JMS dans son mode &lt;i&gt;publish/subscribe&lt;/i&gt;. Cependant, il peut également être utilisé pour faire du point à point en précisant l'adresse du destinataire.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ44eSOwW3I/AAAAAAAAASU/l8hNwFLTXYU/s1600/jgroups19.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TQ44eSOwW3I/AAAAAAAAASU/l8hNwFLTXYU/s400/jgroups19.png" width="252" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="protocoles"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1&gt;Liste des protocoles&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Ce paragraphe fournit à titre indicatif une liste non exhaustive de protocoles fournies par JGroups. Pour plus d'informations sur la configuration de chacun, il est conseillé de se référer à la documentation &lt;a href="http://www.jgroups.org/ug.html"&gt;officielle&lt;/a&gt; et/ou au &lt;a href="http://community.jboss.org/wiki/JGroups"&gt;wiki&lt;/a&gt; dont est issu ce paragraphe.&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;th&gt;Catégorie&lt;/th&gt; &lt;th&gt;Nom&lt;/th&gt; &lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Transport&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;UDP&lt;/span&gt;&lt;/td&gt;&lt;td&gt;UDP utilise le protocole multicast IP pour émettre des messages à tous les membres du groupe et des datagrams UDP pour les messages unicast (ie. à destination de membres particuliers). Quand il et démarré, il ouvre un socket multicast et unicast : le socket unicast est utilisé pour émettre et recevoir les messages unicast alors que le socket multicast pour les messages multicast. L'adresse du canal est l'adresse et le port du socket unicast.&lt;br /&gt;
Une pile de protocoles &amp;nbsp;utilisant UDP comme protocole de transport est généralement utilisé avec les groupes dont les membres s'exécute sur le même hôte ou de manière distribué sur le LAN. Il est nécessaire de s'assurer que le multicast IP est supporté entre les sous-réseau, ce qui n'est souvent pas le cas. Dans ce dernier cas de figure, il est préférable d'utiliser le protocole de transport TCP.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;TCP&lt;/span&gt;&lt;/td&gt;&lt;td&gt;TCP permet d'indiquer à JGroups qu'il doit s'appuyer sur le protocole de transport TCP pour émettre des messages à travers les membres du groupe. Dans ce cas, les membres du groupe créé un réseau de connexions TCP.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;TCP_NIO&lt;/span&gt;&lt;/td&gt;&lt;td&gt;TCP_NIO est une implémentation de TCP ne bloquant pas les I/O. Cependant, il n'est pas conseillé de l'utiliser en production mais d'utiliser plutôt le protocole TCP.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;TUNNEL&lt;/span&gt;&lt;/td&gt;&lt;td&gt;TUNNEL est un protocole de transport qui fonctionne en ouvrant une connexion TCP sur un routeur de message (tel que le Gossip Router). Tous les membres d'un groupe utilisant le protocole TUNNEL doivent être connectés au même routeur qui a pour rôle de transmettre les messages.&lt;br /&gt;
Il peut être utilisé dans le cas où des firewalls sont en place.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Découverte&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;PING&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole PING permet de récupérer les membres du groupe. Il est utilisé pour détecter le coordinateur (le membre le plus vieux) soit en utilisant une requête PING multicast à l'adresse IP MCAST, soit en se connectant au GossipRouteur : chaque membre du groupe répond alors avec un paquet {C, A} où C est l'adresse du coordinateur et A est sa propre adresse. Cela permet de déterminer le coordinateur en fonction des réponses, permettant ainsi d'émettre une requête de type JOIN au coordinateur.&lt;br /&gt;
Si personne ne répond alors on considère qu'il s'agit du premier membre du groupe.&lt;br /&gt;
A noter que, contrairement à TCPPING, PING permet une découverte dynamique et n'a donc pas besoin d'avoir la connaissance des autres membres du groupe.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;TCPPING&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole TCPPING permet de récupérer les membres initiaux du groupe en contactant directement (ie. en point-à-point) les autres membres du groupe suite à la réception d'un message de type FIND_INITIAL_MBRS émit par le protocole GSM. Les réponses permettent de déterminer qui est le coordinateur du groupe.&lt;br /&gt;
A noter que, si le noeud courant est le serveur (ie. après avoir reçu un message de type BECOME_SERVER), alors il répondra aux requêtes de type TCPPING avec un message de type TCPPING.&lt;br /&gt;
TCPPING requière une configuration statique qui permet de savoir à l'avance où trouver les autres membre du groupe.&lt;br /&gt;
Pour permettre une découverte dynamique des autres membres avec une pile de protocole qui s'appuie sur TCP, il est possible d'utiliser soit le protocole MPING (qui utilise un découverte multicast), soit le protocole TCPGOSSIP (qui contacte le GossipRouteur pour obtenir les membres initiaux).&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;TCPGOSSIP&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole TCPGOSSIP permet de récupérer les membres initiaux du groupe (utilisé par le protocole GMS et initié lors de la réception d'un message de type FIND_INITIAL_MBRS).&lt;br /&gt;
Cela s'effectue en contactant le ou les GossipRouteur qui doivent se trouver à des adresses/ports connus. Les réponses reçues doivent permettre de déterminer le coordinateur qui doit être contacté dans le cas où le noeud courant souhaite rejoindre le groupe.&lt;br /&gt;
A noter que, si le noeud courant est le serveur (ie. après avoir reçu un message de type BECOME_SERVER), alors il répondra aux requêtes de type TCPGOSSIP avec un message de type TCPGOSSIP.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;MPING&lt;/span&gt;&lt;/td&gt;&lt;td&gt;MPING (pour Multicast PING) utilise les IP multicast pour&amp;nbsp;déterminer&amp;nbsp;les membres initiaux du groupe. Il peut être utilisé avec tous les types de transport mais il s'applique plus généralement avec le protocole TCP.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;S3_PING&lt;/span&gt;&lt;/td&gt;&lt;td&gt;S3_PING utilise le protocole S3 d'Amazon pour déterminer les membres du groupe. Il a été conçu spécialement pour les membres qui s'exécute sur Amazon EC2 qui ne supporte pas les échanges multicast.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Merge&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;MERGE2&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Les protocoles MERGE et MERGE2 permettent, dans le cas d'une scission du groupe (par exemple dans le cas d'un partitionnement réseau), de fusionner les sous-groupes en un seul. Il est seulement exécuté par le coordinateur du groupe (ie. le membre le plus ancien du groupe) qui rappelle périodiquement sa présence par un message muticast. Si un autre coordinateur du même groupe reçoit le message émis par un autre coordinateur, cela signifie qu'il doit engager un processus de fusion.&lt;br /&gt;
A noter que si une fusion des sous-groupe {A, B} et {C, D, E} a lieu et donne {A, B, C, D, E}, l'état n'est pas fusionner mais laisse à l'application le soin de le faire.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Détection d'échec&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;FD&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole FD (pour &lt;em&gt;Failure Detection&lt;/em&gt;) s'appuie sur des messages de heartbeat. Si aucune réponse n'est reçu dans un délai imparti, le membre est déclaré comme suspect et sera exclu par le protocole GSM.&lt;br /&gt;
Si le protocole FD_SOCK est utilisé, alors aucun message de heartbeat n'est émis mais un socket TCP est créé et un membre est déclaré mort quand le socket est fermé.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;FD_ALL&lt;/span&gt;&lt;/td&gt;&lt;td&gt;FD_ALL permet la détection d'échec en s'appuyant sur un simple protocole de heartbeat : chaque membre diffuse (multicast) périodiquement un message de type heartbeat. Chaque membre devant maintenir la table de tous les membres, dès qu'un message n'est pas reçu d'un des membres dans un délai imparti, il est considéré comme suspect.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;FD_PING&lt;/span&gt;&lt;/td&gt;&lt;td&gt;FD_PING utilise un script ou une commande qui reçoit comme paramètre l'hôte à &lt;em&gt;pinger&lt;/em&gt; et qui doit renvoyer l'entier 0 en cas de succès et 1 sinon.&lt;br /&gt;
A noter que la commande par défaut est /sbin/ping (resp. ping.exe).&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;FD_ICMPL&lt;/span&gt;&lt;/td&gt;&lt;td&gt;FD_ICMPL utilise en interne la méthode&amp;nbsp;InetAddress.isReachable() afin de déterminer si l'hôte donné est présent ou pas.&lt;br /&gt;
A noter qu'il est préférable, avant d'utiliser ce protocole, de s'assurer au préalable du mode de fonctionnement de cette méthode pour le système d'exploitation cible.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;FD_SOCK&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole FD_SOCK s'appuie sur une topologie en anneau au niveau des sockets TCP créé entre les membres du groupe.&lt;br /&gt;
Ainsi, par exemple, le membre B est suspecté par son voisin A s'il observe une fermeture du socket TCP. Par contre, c'est au membre B de prévenir son voisin dans le cas d'un départ du groupe volontaire.&lt;br /&gt;
Cependant, dans le cas de l'interruption d'un serveur et/ou arrêt brutal d'un switch (et donc une non fermeture du socket TCP), ce protocole est inefficace. Aussi, il est conseillé de l'utiliser conjointement avec le protocole de FD (qui s'appuie sur un fonctionnement en heartbeat).&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;VERIFY_SUSPECT&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole VERIFY_SUSPECT vérifie l'état d'un membre suspect en lui envoyant un ping.&lt;br /&gt;
A noter qu'il doit être utilisé entre les couches FD et GMS sur la pile de protocole.&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Messages fiables&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;pbcast.NAKACK&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole pbcast.NAKACK permet de s'assurer de la fiabilité de réception des messages en utilisant une file de message de type FIFO conjointement à des ack.&lt;br /&gt;
Ainsi, par exemple, si le noeud a reçu les messages P:1, P:3, P:4, alors il demandera une retransmission du message 2.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;pbcast.STABLE&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole pbcast.STABLE permet de calculer les messages émis qui sont dans un état stable, c'est-à-dire qui ont été reçus par tous les membres. Cela permet au protocole NAKACK de supprimer les messages qui sont considérés comme ayant été reçu par tous les membres du groupe.&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;UNICAST&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole UNICAST fournit un protocole unicast&amp;nbsp;fiable&amp;nbsp;d'émission en mode FIFO.&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Fragmentation&amp;nbsp;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;FRAG&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole FRAG permet de fragmenter les messages trop gros lors de l'émission et de les ré-assembler lors de la réception.&lt;br /&gt;
Ce protocole fonctionne aussi bien pour les messages émis en multicast ou en unicast.&lt;br /&gt;
Il sérialise chaque message afin de le morceler, et cela, quel que soit son type (même s'il s'agit d'octets) afin de pouvoir prendre en compte avec précision la taille de l'entête et les propriétés du message.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;FRAG2&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole FRAG2 permet, tout comme le protocole FRAG, de fragmenter les messages.&lt;br /&gt;
Cependant, il offre un autre algorithme lui permettant de ne pas avoir à sérialiser les messages pour les découper.&lt;br /&gt;
A noter que le protocole FRAG2 est préférable au protocole FRAG.&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Gestion des membres du groupe&amp;nbsp;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;pbcast.GMS&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole pbcast.GMS permet de gérer le départ ou l'enregistrement des membres dans le groupe. Il a également à sa charge de gérer les membres suspects et de les exclure du groupe. En fait, c'est lui qui émet les vues à tous les autres membres du groupe quand un changement se produit.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;VIEW_SYNC&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole VIEW_SYNC permet aux membres du groupe de s'échanger périodiquement leurs vues et, si une incohérence entre vue est constatée, alors cela permet au protocole pbcast.GMS de mettre à jour la vue "officielle".&amp;nbsp;En fait, ce protocole est le pendant du coordinateur mais au niveau des noeuds et garanti, en cas d'anomalie sur le coordinateur pendant une dissémination des vues, une consistance des vues.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Contrôle de flux&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;FC&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole FC (&lt;em&gt;Flow Control&lt;/em&gt;) permet de gérer le flux des messages. En effet, si l'émetteur émet plus vite que les destinataires ne peuvent consommer les messages, alors il y a risque de contension et c'est pourquoi les émetteurs ne doivent pas émettre les messages plus vite que leur capacité à être absorbés par le système.&lt;br /&gt;
Pour ce faire, un émetteur possède N crédits pour chaque membres. Quand il émet un message, il décrémente le nombre d'octets émis au crédit du récepteur. Quand le crédit d'un récepteur est inférieur que ce que requière le message à émettre, l"émetteur se bloque et attend que l'émetteur dispose de plus de crédits.&lt;br /&gt;
Le récepteur décrémente également le nombre d'octets reçu et émet son nombre de crédit à l'émetteur quand il est en dessous d'un certain seuil.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;SFC&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole SFC correspond à une version simplifiée du protocole FC qui peut&amp;nbsp;entraîner&amp;nbsp;une surconsommation chez le récepteur lorsqu'il existe de la latence dans la couche de transport.&lt;br /&gt;
En fait, ce protocole s'appuie sur un nombre d'octet maximal de crédits (configurable) qui est vérifié coté émetteur et récepteur. Il se marrie très bien avec le protocole pbcast.STABLE qui permet de "nettoyer" les messages déjà traités.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Transfert d'état&amp;nbsp;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;pbcast&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;.STATE_TRANSFER&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole pbcast.STATE_TRANSFER permet à un nouveau membre de récupérer l'état du groupe du coordinateur.&lt;br /&gt;
Il fonctionne comme suit :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;le nouveau membre demande au coordinateur l'état&lt;/li&gt;
&lt;li&gt;Le coordinateur vérifie deux choses : un digest et l'état de l'application, le digest étant un vecteur contenant le plus haut et le plus bas numéro de séquence des messages reçu pour chaque membre&lt;/li&gt;
&lt;li&gt;Les messages dans le digest font déjà parti de l'état du groupe et ne doivent pas être reçus&lt;/li&gt;
&lt;li&gt;Le coordinateur émet l'état et le digest au membre arrivant&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Le membre arrivant positionne son état et positionne son digest avec celui reçu permettant ainsi de savoir les messages qui n'ont pas encore été reçu&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;pbcast&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;.STREAMING&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;_STATE_TRANSFER&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole pbcast.STREAMING_STATE_TRANSFER permet de pallier aux problèmes de gros messages non traités par le protocole pbcast.STATE_TRANSFER.&lt;br /&gt;
Il permet de gérer des états de plus d'un gigaoctet.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Synchronisation virtuelle&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;pbcast.FLUSH&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole FLUSH, comme son nom l'indique, force les membres du groupe à &lt;em&gt;flusher&lt;/em&gt; leurs messages en cours plutôt que de les bloquer.&lt;br /&gt;
Il peut être utilisé dans les cas suivants :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Transfert d'état ; quand un membre demande l'état, le coordinateur indique à tous les membres d'arrêter d'émettre des message et attends leur réponse. Lorsque le nouveau membre a reçu toutes les informations requises, le coordinateur indique alors à tous les membres qu'ils peuvent reprendre leurs activités&lt;/li&gt;
&lt;li&gt;Changement du vue (c'est-à-dire opération de join) : avant d'installer une nouvelle vue, l'opération de flush permet de s'assurer que tous les messages émis dans la vue précédente ont été traités&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Authentification et cryptage&amp;nbsp;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;AUTH&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole AUTH est utilisé pour le couche d'authentification de JGroups en permettant de déterminer si un noeud est autorisé à rejoindre un groupe. AUTH s'appuie sur le protocole GMS et écoute les messages de type JOIN REQUEST : quand un message de type JOIN REQUEST est reçu, il cherche l'objet &lt;em&gt;AuthHeader&lt;/em&gt; dans lequel doit se trouver une implémentation de la classe &lt;em&gt;AuthToken&lt;/em&gt;.&lt;br /&gt;
&lt;em&gt;AuthToken&lt;/em&gt; est une classe abstraite dont les implémentations doivent fournir le mécanisme d'authentification. JGroups fournit des implémentations basiques telles que :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;SimpleToken,&lt;/li&gt;
&lt;li&gt;MD5Token&lt;/li&gt;
&lt;li&gt;et X50Token.&lt;/li&gt;
&lt;/ul&gt;Ces implémentations encrypte un chaîne de caractère se trouvant dans la configuration de JGroups et la passe au message JOIN REQUEST.&lt;br /&gt;
Quand l'authentification est réussie, le message est passé à la pile qui s'occupe du protocole GMS, sinon, un message de type JOIN RESPONSE contenant un message d'erreur est renvoyé au noeud. Le client lève alors une exception de type &lt;em&gt;SecurityException&lt;/em&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;ENCRYPT&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole ENCRYPT permet de crypter les messages. Par défaut, il n'encrypte que le corps du message (ie. que tous les entêtes, les adresses des destinataires et de la source ne sont pas cryptés par défaut).&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Synchronisation&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;BARRIER&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Le protocole BARRIER peut être utilisé pour suspendre les messages à émettre.&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4495310291235200788&amp;amp;postID=7877601280471708447" name="conclusion"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;div style="text-align: justify;"&gt;Comme nous avons pu le voir, JGroups présente une API pour le développeur qui est très agréable à utiliser.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Cependant, la configuration des canaux peut s'avérer très ardue car elle est demande une bonne connaissance de la couche réseau mais aussi de ce qui est ciblé :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Est-il acceptable de faire du multicast IP sur notre réseau? A défaut, l'utilisation de TCP est-elle suffisante?&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Faut-il crypter les messages?&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Faut-il que les messages émis sur le canal X soient ordonnancés?&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Comment veut-on s'assurer que les messages soient bien transmis?&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;...&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Pour moi, c'est ce type de questions qu'il est important de se poser afin de configurer les différents canaux de JGroups. En outre, par défaut, JGroups peut s'avérer très bavard (notion de ping, signalisation en interne sur un merge, ...) et, là encore, plutôt que de faire hurler votre administrateur réseau, essayer de voir avec lui ce qui est acceptable.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi JGroups s'adresse aux personnes qui veulent avoir la main sur les couches basses (contrairement à JMS qui a tendance à être plus abstrait sur les couches basses puisque cela dépend du provider choisi).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;h1&gt;Pour aller plus loin...&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Site officiel de JGroups&lt;/b&gt; :&amp;nbsp;&lt;a href="http://www.jgroups.org/"&gt;http://www.jgroups.org/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;b&gt;Wiki de JGroups&lt;/b&gt; :&amp;nbsp;&lt;a href="http://community.jboss.org/wiki/JGroups"&gt;http://community.jboss.org/wiki/JGroups&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-7877601280471708447?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=rMgzQuhHFYE:v8yArMYvTsM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=rMgzQuhHFYE:v8yArMYvTsM:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=rMgzQuhHFYE:v8yArMYvTsM:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/7877601280471708447/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/7877601280471708447?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/7877601280471708447?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2010/12/jgroups-tour-d.html" title="JGroups : tour d&amp;#39;horizon" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_XLL8sJPQ97g/TRtn71JxZPI/AAAAAAAAATI/0vNqJjOXKlY/s72-c/jgroups_logo_450px.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0UMSH85fCp7ImA9WhRUEEw.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-5087162426029133641</id><published>2010-12-20T08:00:00.005+01:00</published><updated>2012-01-19T23:14:49.124+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-19T23:14:49.124+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jmx" /><title>JMX pour les nuls... - Les connecteurs - Partie 8</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s1600/jmx-cover.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" height="200" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s200/jmx-cover.png" width="171" /&gt;&lt;/a&gt;&lt;/div&gt;Ce huitième et dernier article sur JMX&amp;nbsp;clôture&amp;nbsp;cette petite série de posts sur JMX (cf. &lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-introduction.html"&gt;introduction&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html"&gt;partie 1 portant sur les généralités&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html"&gt;partie 2 portant sur les différents MBeans et le concept de Notification&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html"&gt;partie 3 sur les agents JMX&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html"&gt;partie 4 sur les classes de base&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html"&gt;partie 5 sur le MBeanServer&lt;/a&gt;,&amp;nbsp;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html"&gt;partie 6 sur le chargement dynamique des MBeans&lt;/a&gt;&amp;nbsp;et &lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html"&gt;partie 7 sur les services JMX&lt;/a&gt;). Il abordera&amp;nbsp;succinctement&amp;nbsp;la notion de connecteur.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;Table des matières&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html"&gt;JMX, qu'est ce que c'est?&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#generalite"&gt;Généralités&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#architecture"&gt;Architecture JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#instrumentation"&gt;Niveau instrumentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#agent"&gt;Niveau agent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#distribue"&gt;Niveau service distribué&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#composant"&gt;Composants JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#mbean"&gt;MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#notification"&gt;Modèle de notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#metadonnee"&gt;Classe de métadonnées de MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#serveur"&gt;Serveur de MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#services"&gt;Service d'agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Spécifications&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html"&gt;JMX Instrumentation&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean"&gt;MBean&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_standard"&gt;MBean Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_dynamic"&gt;Dynamic MBean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#notification"&gt;Notification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_open"&gt;Open MBean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_model"&gt;Model MBean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html#agent"&gt;Agent JMX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html"&gt;Concepts&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#objectname"&gt;ObjectName&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#objectinstance"&gt;ObjectInstance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#attribute"&gt;Attribute et AttributeList&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#exception"&gt;Les Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html"&gt;MBean Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html"&gt;Chargement dynamique des MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html"&gt;Les services JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#monitoring"&gt;Service Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#timer"&gt;Service Timer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#relation"&gt;Service Relation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#securite"&gt;Service Sécurité&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-connecteurs.html"&gt;Les Connecteurs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;La spécification JMX défnit la notion de connecteurs : un connecteur est attaché à l'API JMX d'un MBean Server et le rend accessible de clients Java distants, le connecteur client possèdant une interface similaire à celle du MBean Server.&lt;/div&gt;&lt;div&gt;Un connecteur est donc constitué d'une partie cliente et d'une partie serveur :&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Le connecteur serveur est attaché au MBean Server et écoute les requêtes de connexion des clients&lt;/li&gt;
&lt;li&gt;Le connecteur client a pour rôle de trouver le server et d'étable une connexion avec ce dernier. Un connecteur client se trouve généralement dans une JVM différente du connecteur serveur et s'exécutera même généralement sur une machine différente.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Il est à noter que contrairement à un connecteur serveur, le connecteur client ne pourra se connecter qu'à un et un seul connecteur serveur (mais une application cliente pourra posséder plusieurs connecteurs clients).&lt;/div&gt;&lt;div&gt;JMX permet d'avoir de multiples connecteurs qui peuvent s'appuyer sur différents protocoles de communication entre le client et le serveur. Cependant, il définit le protocole standard et obligatoire sur tous serveurs JMX s'appuyant sur RMI (&lt;em&gt;Remote Method Invocation&lt;/em&gt;) et le protocole optionel s'appuyant sur des sockets TCP et appelé JMXMP (&lt;em&gt;JMX Messaging Protocol&lt;/em&gt;).&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Les connecteurs distinguent deux notions distinctes qui sont la &lt;strong&gt;session&lt;/strong&gt; et la &lt;strong&gt;connexion&lt;/strong&gt;. Un connecteur client voit une session qui peut, tout au long de son cycle de vie de la session, avoir plusieurs connexions successives à un connecteur serveur. Il est à noter que, dans certains cas, il est possible d'avoir une connexion par requête (comme cela peut être le cas avec le protocole UDP ou JMS).&lt;/div&gt;&lt;div&gt;Une session possède un état sur le client mais pas nécessairement sur le connecteur serveur. Un connecteur, ne possède, quant à lui, pas forcément d'état.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Pour se connecter au connecteur serveur, le connecteur client peut utiliser une adresse du type "&lt;em&gt;service:jmx:jmxmp://host1:9876&lt;/em&gt;". Si la requête de connexion aboutie, le point d'accès client du connecteur client est retourné en réponse.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XLL8sJPQ97g/TQ0JWJXGzAI/AAAAAAAAAQo/b1hs_49t0Ys/s1600/jmx75.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/_XLL8sJPQ97g/TQ0JWJXGzAI/AAAAAAAAAQo/b1hs_49t0Ys/s400/jmx75.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Du point de vue de la connexion cliente, le code de l'utilisateur peut obtenir un objet qui implémente l'interface &lt;em&gt;MBeanServerConnection&lt;/em&gt;. Cette interface étant similaire à l'interface &lt;em&gt;MBeanServer&lt;/em&gt;, il devient transparent pour le code de l'application cliente d'interagir avec un MBean Server ne se trouvant pas dans la même JVM.&amp;nbsp;&lt;/div&gt;&lt;div&gt;En fait, l'interface &lt;em&gt;MBeanServerConnection&lt;/em&gt; est étendue par l'interface &lt;em&gt;MBeanServer&lt;/em&gt; et contient donc toutes les méthodes principales sauf celles qui n'ont de sens que pour une utilisation locale.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ0Js7mndfI/AAAAAAAAAQs/puPa9Bkgz1Y/s1600/jmx68.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="286" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ0Js7mndfI/AAAAAAAAAQs/puPa9Bkgz1Y/s320/jmx68.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Lors de l'enregistrement d'un écouteur auprès du &lt;em&gt;MBeanServerConnection&lt;/em&gt;, le connecteur s'assure de la transmission de la notification de la partie serveur du connecteur à la partie cliente, puis à l'écouteur.&lt;br /&gt;
Les détails de la mise en œuvre de la transmission de la notification sont dépendants du protocole.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Lors de l'utilisation d'un filtre de notifications, le filtrage des notifications reçues peut être effectué soit par la partie cliente du connecteur, soit par le MBean Server suite à la transmission du filtre.&lt;br /&gt;
Il est, bien sûr, à noter que le filtrage des notifications coté serveur évite la transmission des notifications sur le réseau.&lt;br /&gt;
Cependant, il est conseillé de rendre les filtres indépendants de leur lieu d'exécution (pour rappel, l'interface &lt;em&gt;NotificationFilter&lt;/em&gt; étend l'interface &lt;em&gt;Serializable&lt;/em&gt;).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Toutes les implémentations des connecteurs coté serveur doivent posséder un buffer de notifications qui correspond à la liste de toutes notifications émises par les MBeans à destination du MBean Server. Il est à noter que les connecteurs doivent supporter les requêtes concurrentes pour des raisons évidentes. Concernant l'adresse du serveur connecteur, il est conseillé, pour la générer, de passer par la classe &lt;em&gt;JMXServiceURL&lt;/em&gt;. &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TQ0J6oZ__RI/AAAAAAAAAQw/HbReQRkRJtk/s1600/jmx69.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TQ0J6oZ__RI/AAAAAAAAAQw/HbReQRkRJtk/s320/jmx69.png" width="224" /&gt;&lt;/a&gt;&lt;/div&gt;Afin de créer la partie cliente d'un connecteur, il existe deux possibilités : &lt;ul&gt;&lt;li&gt;si l'adresse du serveur est connue, la méthode &lt;em&gt;connect(JMXServiceURL)&lt;/em&gt; de la classe statique &lt;em&gt;JMXConnectorFactory&lt;/em&gt; peut être utilisée,&lt;/li&gt;
&lt;li&gt;sinon, il est possible d'interroger le serveur pour obtenir un stub de &lt;em&gt;JMXConnector&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;Du point de vue de la connexion serveur, la connexion serveur est représentée par une sous-classe de &lt;em&gt;JMXConnectorServer&lt;/em&gt; qui peut être obtenue : &lt;ul&gt;&lt;li&gt;soit à l'aide de &amp;nbsp;la classe statique &lt;em&gt;JMXConnectorServerFactory&lt;/em&gt; en lui indiquant le paramètre de type &lt;em&gt;JMXServiceURL&lt;/em&gt; qui lui permet de connaitre les classes à instancier,&lt;/li&gt;
&lt;li&gt;soit en instanciant directement la sous-classe de &lt;em&gt;JMXConnectorServer&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;Le connecteur serveur doit être attaché à un MBean Server (ce qui ne signifie pas qu'il doit s'enregistré en son sein) et doit être actif pour être utilisable. Il peut être attaché auprès du MBean Server de deux manières : &lt;ul&gt;&lt;li&gt;Le MBean Server auquel est attaché le connecteur serveur lui est spécifié lors de sa construction&lt;/li&gt;
&lt;li&gt;Le connecteur serveur est enregistré auprès du MBean Server comme s'il s'agissait d'un MBean&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XLL8sJPQ97g/TQ0KE210zHI/AAAAAAAAAQ0/uN68yvrtjr4/s1600/jmx71.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="281" src="http://2.bp.blogspot.com/_XLL8sJPQ97g/TQ0KE210zHI/AAAAAAAAAQ0/uN68yvrtjr4/s400/jmx71.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ0KUwpcisI/AAAAAAAAAQ4/oWKoFdTIM4k/s1600/jmx70.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="39" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TQ0KUwpcisI/AAAAAAAAAQ4/oWKoFdTIM4k/s320/jmx70.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;Exemple de création et d'attachement d'un connecteur serveur auprès d'un MBean Server&lt;/div&gt;&lt;div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;MBeanServer mbs = MBeanServerFactory.createMBeanServer();
JMXServiceURL addr = new JMXServiceURL("jmxmp", null, 0);
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(addr, null, mbs);
cs.start();
&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;Exemple de création et d'enregistrement d'un connecteur serveur dans un MBean Server&lt;/div&gt;&lt;div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;MBeanServer mbs = MBeanServerFactory.createMBeanServer();
JMXServiceURL addr = new JMXServiceURL("jmxmp", null, 0);
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(addr, null, null);
ObjectName csName = new ObjectName(":type=cserver,name=mycserver");
mbs.registerMBean(cs, csName);
cs.start();
&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;JMX définit également comment un agent peut publier son serveur de connexion dans une infrastructure de recherche et de découverte ; ce qui permet à l'API cliente distante de savoir où trouver un serveur et ainsi de pouvoir si connecter. Cela couvre :&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;SLP (&lt;em&gt;Service Location Protocol&lt;/em&gt;) en décrivant comme un agent enregistre le service URL d'un connecteur serveur avec SLP&lt;/li&gt;
&lt;li&gt;Jini en décrivant comment un agent enregistre un stub du connecteur serveur dans le service de recherche Jini&lt;/li&gt;
&lt;li&gt;JNDI (&lt;em&gt;Java Naming and Directory Interface&lt;/em&gt;) en décrivant un agent enregistre le service URL d'un connecteur dans un annuaire LDAP&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Un connecteur client peut spécifier un class loader par défaut lorsqu'il effectue sa connexion au serveur. Ce class loader est alors utilisé lors de la déserialisation des objets reçus du serveur que ce soit les valeurs retournées, les exceptions ou les notifications.&lt;br /&gt;
Le class loader par défaut est positionné par la valeur de l'attribut &lt;em&gt;jmx.remote.default.class.loader&lt;/em&gt; définie par l'environnement &lt;em&gt;JMXConnector&lt;/em&gt;, sinon, il s'agit du class loader du contexte.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Le class loader utilisé par le connecteur serveur pour déserialiser les paramètres reçus par le connecteur client est dépendant de l'opération : en effet, parfois, il peut s'agir de celui du MBean cible (si les types de paramètres ne sont pas définis par l'API JMX), parfois, de celui configuré pendant la création du connecteur server (s'il est prévu de l'utiliser dans une application de gestion particulière qui peut définir ses propres sous classes de types de paramètres de MBean ou &lt;em&gt;NotificationFilter&lt;/em&gt;).&lt;br /&gt;
Le connecteur serveur possède un class loader par défaut qui est déterminé lors de son démarrage comme suit :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Si l'attribut &lt;em&gt;jmx.remote.default.class.loader&lt;/em&gt; de l'environnement existe, sa valeur détermine le class loader à utiliser&lt;/li&gt;
&lt;li&gt;Si l'attribut &lt;em&gt;jmx.remote.default.class.loader.name&lt;/em&gt; de l'environnement existe, sa valeur détermine l'ObjectName du MBean à utiliser comme class loader par défaut. Cette fonctionnalité permet à un connecteur serveur d'être créé avec un class loader qui est un m-let dans le même MBean Server&lt;/li&gt;
&lt;li&gt;Sinon, c'est le class loader du thread contextuel qui est utilisé&lt;/li&gt;
&lt;/ul&gt;Pour plus d'informations sur l'utilisation de class loader étendu, il est recommandé de se référer au chapitre 13.11 Class Loading de la spécification JMX.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Afin d'éviter les difficultés avec le fonctionnement des class loader Java, il est conseillé de n'utiliser que les types standards Java ou fournis par l'API JMX ou les Open MBeans qui permettent des structures plus complexes. De même, pour les notifications, il est préconisé de n'utiliser que les notifcations suivantes :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;em&gt;NotificationFilterSupport&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;MBeanServerNotificationFilter&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;AttributeChangeNotificationFilter&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Le connecteur serveur est, en outre, capable d'authentifier le client distant. Par exemple, pour le connecteur RMI, cela est fait fournissant une implémentation de l'interface &lt;em&gt;JMXAuthenticator&lt;/em&gt; lors de la création du connecteur serveur. Dans le cas du connecteur JMXMP, cela est fait via SASL. Dans ces deux cas, le résultat de l'authentification renvoie un Subject JAAS qui représente l'identité authentifiée. Les requêtes alors reçues du client sont exécutées en utilisant cette identité. Avec JAAS, il est possible de définir les permissions liées à une identité. En particulié, il est possible de restreindre l'accès aux opérations du MBean Server en utilisant la classe &lt;em&gt;MBeanPermission&lt;/em&gt;. Bien sûr, pour que cela fonctionne, il est nécessaire d'avoir un &lt;em&gt;SecurityManager&lt;/em&gt;. Dans le cas où le connecteur serveur ne supporte pas l'authentification ou qu'il n'est pas configuré, les requêtes clientes sont exécutées en utilisant la même identité que celle qui a été créée avec le connecteur serveur. Comme alternative à JAAS, il est possible de controler l'accès aux opérations du MBean Server en utilisant un &lt;em&gt;MBeanServerForwarder&lt;/em&gt;. Cet objet est une implémentation de l'interface &lt;em&gt;MBeanServer&lt;/em&gt; et transmet les méthodes à un autre objet &lt;em&gt;MBeanServer&lt;/em&gt; mais en ajoutant des opérations avant et après la transmission. Cela permet, en l'occurrence d'y faire des controles d'accès. Pour ajouter un &lt;em&gt;MBeanServerForwarder&lt;/em&gt;, la méthode &lt;em&gt;setMBeanServerForwarder&lt;/em&gt; peut être utilisée. De plus, pour chaque connexion à un connecteur serveur, au moins un &lt;em&gt;Subject&lt;/em&gt; authentifié est néccessaire. Cela signifie que si un client effectue des opérations qui nécessitent plusieurs identités, des connexions différentes doivent être établies. Cependant, il est possible aux connecteurs (tels que les connecteurs RMI et JMXMP) d'utiliser la notion de délégation de &lt;em&gt;Subject&lt;/em&gt;. Pour ce faire, avec chaque requête, le client spécifie un &lt;em&gt;Subject&lt;/em&gt;. La requête est alors exécutée en utilisant une identité pour chaque requête si cela est possible. La permission a utilisé doit alors être de type &lt;em&gt;SubjectDelegationPermission&lt;/em&gt;. Dans ce cas, pour chaque Subject délégué, le client obtient un &lt;em&gt;MBeanServerConnection&lt;/em&gt; du &lt;em&gt;JMXConnector&lt;/em&gt; pour un &lt;em&gt;Subject&lt;/em&gt; authentifié. Les requêtes utilisées par le &lt;em&gt;MBeanServerConnection&lt;/em&gt; sont émises avec un &lt;em&gt;Subject&lt;/em&gt; délégué. Il est, de plus, à noter que ces objets de type &lt;em&gt;MBeanServerConnection&lt;/em&gt; peuvent être obtenus du même &lt;em&gt;JMXConnector&lt;/em&gt; et peuvent être utilisés simultanément. Ainsi, pour résumer, il est possible de configurer les permissions d'un connecteur serveur de deux manières : &lt;ul&gt;&lt;li&gt;toutes les permissions pour les opérations de chaque client distant doivent être configurées,&lt;/li&gt;
&lt;li&gt;un &lt;em&gt;SubjectDelegationPermission&lt;/em&gt; pour chaque &lt;em&gt;Principal&lt;/em&gt; utilisé par les clients distants doit être configuré.&lt;/li&gt;
&lt;/ul&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Le connecteur RMI est le seul connecteur qui doit être présent dans les implémentations de JMX. Il utilise l'infrastructure RMI (Remote Method Invocation) pour la communication entre le client et le serveur.&lt;br /&gt;
RMI définit deux couches de transport standard :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;em&gt;Java Remote Method Protocol&lt;/em&gt; (JRMP) qui est le protocole de transport par défaut&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Internet Inter-ORB Protocol&lt;/em&gt; (IIOP) qui est le protocole défini par CORBA et qui permet l'interopérabilité avec un autre langage de programmation&lt;/li&gt;
&lt;/ul&gt;Pour chaque serveur de connexion RMI, un objet distant implémentant l'interface distante RMIServer existe. Un client voulant communiquer avec le connecteur serveur doit obtenir une référence distante (ou stub) connecté à cet objet distant. Via RMI, chaque méthode appelée sur un stub sera transféré à l'objet distant. Ainsi, le client possédant un stub sur l'objet &lt;em&gt;RMIServer&lt;/em&gt; pourra appeler obtenir le même résultat que s'il avait appelé l'objet du serveur.&lt;br /&gt;
De plus, il existe un objet distant pour chaque connexion cliente qui permet de créer un nouvel objet distant qui implémente l'interface distante &lt;em&gt;RMIConnection&lt;/em&gt;.&lt;br /&gt;
Enfin, il est à noter que le code de l'utilisateur n'interagit généralement pas directement avec les objets du &lt;em&gt;RMIServer&lt;/em&gt; ou du &lt;em&gt;RMIConnection&lt;/em&gt; : en général, le stub &lt;em&gt;RMIServer&lt;/em&gt; est obtenu au travers d'un objet &lt;em&gt;RMIConnector&lt;/em&gt; qui implémente l'interface &lt;em&gt;JMXConnector&lt;/em&gt;.&lt;br /&gt;
L'obtention de cet objet &lt;em&gt;RMIConnector&lt;/em&gt; peut être fait de trois manières :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;En fournissant un &lt;em&gt;JMXServiceURL&lt;/em&gt; au &lt;em&gt;JMXConnectorFactory&lt;/em&gt; qui spécifie le protocol RMI ou IIOP.&lt;/li&gt;
&lt;li&gt;En obtenant le stub &lt;em&gt;JMXConnector&lt;/em&gt; de " quelque part " (annuaire LDAP, Service de lookup JNDI, …).&lt;/li&gt;
&lt;li&gt;En obtenant un stub &lt;em&gt;RMIServer&lt;/em&gt; de " quelque part " et qui peut être utilisé comme paramètre du constructeur de &lt;em&gt;RMIConnector&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;Les notions de sécurité et de versionnement sont également décrites dans le spécification JMX (et plus particulièrement la JSR160). Cependant, ce document n'abordera pas ces points.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;La spécification JMX (et plus précisément la JSR160) décrit comment implémenter un connecteur générique en précisant comment configurer par plugin son protocole de transport ainsi que la manière dont il encapsule les objets transitant du client au serveur et plus particulièrement sa gestion du classloader du MBean cible.&lt;br /&gt;
Cependant, ce document n'abordera pas ces points. Aussi, pour plus d'informations, il est conseillé de se référer à la JSR160 ou aux chapitres 15 -&amp;nbsp;&lt;em&gt;Generic Connector&lt;/em&gt; et 16 -&amp;nbsp;&lt;em&gt;Defining a new transport&lt;/em&gt; des spécifications agrégées JMX.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Le connecteur JMXMP est une configuration particulière du connecteur générique où le protocole de transport s’appuie sur TCP et l’encapsulation des objets est la sérialisation native Java.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;La spécification JMX ne spécifie pas comment trouver l'adresse d'un serveur de connecteurs attaché à un agent connu ou comment découvrir les agents présents dans le système ainsi que ce qu'ils proposent. Cependant, la JSR160 propose trois infrastructures permettant de répondre à ces besoins :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;SLP (&lt;em&gt;Service Location Protocol&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;JINI&lt;/li&gt;
&lt;li&gt;JNDI (&lt;em&gt;Java Naming and Discovery Interface&lt;/em&gt;) utilisé au travers un annuaire LDAP&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Bien sûr, les APIs pour utiliser ces différentes technologies diffèrent cependant, les principes généraux restent identiques :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;L'agent créé un ou plusieurs serveurs de connecteurs&lt;/li&gt;
&lt;li&gt;Pour chacun des connecteurs à exposer, il expose soit le &lt;em&gt;JMXServiceURL&lt;/em&gt; (dans le cas de SLP ou JNDI), soit le stub &lt;em&gt;JMXConnector&lt;/em&gt; (dans le cas de JINI ou JNDI) qu'il enregistre dans le service de recherche (en spécifiant au besoin d'autres méta-données)&lt;/li&gt;
&lt;li&gt;Le client interroge le service de recherche pour obtenir un ou plusieurs &lt;em&gt;JMXServiceURL&lt;/em&gt; ou stub &lt;em&gt;JMXConnector&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Le client utilise soit le factory &lt;em&gt;JMXConnectorFactory&lt;/em&gt; pour obtenir un &lt;em&gt;JMXConnector&lt;/em&gt; connecté au serveur s'il possède un &lt;em&gt;JMXServiceURL&lt;/em&gt;, soit se connecte directement au serveur en utilisant le stub &lt;em&gt;JMXConnector&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;Ce document ne fournira pas plus d'informations sur ces points. Aussi, pour plus d'informations, il est conseillé de se référer à la JSR160 ou au chapitres 17 -&lt;em&gt;&amp;nbsp;Bindings to lookup services&lt;/em&gt; des spécifications agrégées JMX.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;ol style="text-align: justify;"&gt;&lt;li&gt;Le mot de la fin&lt;/li&gt;
&lt;/ol&gt;&lt;div style="text-align: justify;"&gt;Voilà, ce dernier article met fin à cette série. Si vous avez réussi à tenir jusque là et à tout lire, félicitation! Maintenant, vous devriez avoir (enfin, j'espère) une vision plus précise sur ce que contiennent les spécifications JMX. Bien sûr, cette série n'était qu'un condensée (qui vaut ce qu'il vaut) permettant de comprendre les concepts sans pour autant lire les 290 pages de spécification et ne se veut pas être suffisante pour tout&amp;nbsp;maîtriser.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-5087162426029133641?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=-98_TeYOywQ:qD4CiP_INS4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=-98_TeYOywQ:qD4CiP_INS4:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=-98_TeYOywQ:qD4CiP_INS4:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/5087162426029133641/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-connecteurs.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/5087162426029133641?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/5087162426029133641?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-connecteurs.html" title="JMX pour les nuls... - Les connecteurs - Partie 8" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s72-c/jmx-cover.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0YGRX47eip7ImA9WhRUEEw.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-1995550387799645066</id><published>2010-12-13T08:00:00.005+01:00</published><updated>2012-01-19T23:12:04.002+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-19T23:12:04.002+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jmx" /><title>JMX pour les nuls... - Les services JMX - Partie 7</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s1600/jmx-cover.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s200/jmx-cover.png" width="171" /&gt;&lt;/a&gt;&lt;/div&gt;Ce septième et avant dernier&amp;nbsp;article sur JMX (cf. &lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-introduction.html"&gt;introduction&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html"&gt;partie 1 portant sur les généralités&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html"&gt;partie 2 portant sur les différents MBeans et le concept de Notification&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html"&gt;partie 3 sur les agents JMX&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html"&gt;partie 4 sur les classes de base&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html"&gt;partie 5 sur le MBeanServer&lt;/a&gt; et &lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html"&gt;partie 6 sur le chargement dynamique des MBeans&lt;/a&gt;) abordera les différents types de services JMX.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;Table des matières&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html"&gt;JMX, qu'est ce que c'est?&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#generalite"&gt;Généralités&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#architecture"&gt;Architecture JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#instrumentation"&gt;Niveau instrumentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#agent"&gt;Niveau agent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#distribue"&gt;Niveau service distribué&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#composant"&gt;Composants JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#mbean"&gt;MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#notification"&gt;Modèle de notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#metadonnee"&gt;Classe de métadonnées de MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#serveur"&gt;Serveur de MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#services"&gt;Service d'agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Spécifications&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html"&gt;JMX Instrumentation&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean"&gt;MBean&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_standard"&gt;MBean Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_dynamic"&gt;Dynamic MBean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#notification"&gt;Notification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_open"&gt;Open MBean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_model"&gt;Model MBean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html#agent"&gt;Agent JMX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html"&gt;Concepts&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#objectname"&gt;ObjectName&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#objectinstance"&gt;ObjectInstance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#attribute"&gt;Attribute et AttributeList&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#exception"&gt;Les Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html"&gt;MBean Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html"&gt;Chargement dynamique des MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html"&gt;Les services JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#monitoring"&gt;Service Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#timer"&gt;Service Timer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#relation"&gt;Service Relation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#securite"&gt;Service Sécurité&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-connecteurs.html"&gt;Les Connecteurs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;Le MBean Server propose, par défaut, un ensemble de fonctionnalités qui se présente sous forme de services JMX (ie. de MBeans), à savoir : &lt;ul&gt;&lt;li style="text-align: justify;"&gt;Service Monitoring&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Service Timer&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Service de relation&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Service de sécurité&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;a name="monitoring"&gt;&lt;/a&gt; &lt;h2&gt;Service Monitoring&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Il existe une famille de MBeans de monitoring qui se présentent qui permettent de scrupter les variations au cours du temps de la valeur des attributs des autres MBeans et qui permet d'émettre des notifications à intervalle régulier. Ils sont aussi classifiés comme des services de monitoring.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;En fait, un service de monitoring (et donc un MBean de monitoring) permet d'observer la valeur d'un attribut donné présent dans un ou plusieurs MBeans (on dit qu'il s'agit alors du &lt;b&gt;MBean observé&lt;/b&gt;) à un intervalle à régulier. Cette valeur peut être indifféremment la valeur d'un attribut ou la valeur contenue dans la valeur d'un attribut s'il est de type complexe. Pour chaque MBean observé, le moniteur interpole une seconde valeur qui est appelé le &lt;b&gt;pas dérivé&lt;/b&gt; (&lt;i&gt;derived gauge&lt;/i&gt;) et qui correspond, soit à la valeur observée, soit à la différence entre deux valeurs numériques obtenues consécutivement.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Un type de notification spécifique est alors émis à chaque service de monitoring lorsque le pas dérivé répond à un ou un ensemble de conditions (ou lorsque certaines erreurs se produisent) qui peuvent être initialisées lors de l'initialisation du moniteur ou dynamiquement au travers de l'interface d'administration du MBean moniteur.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Il existe trois types de moniteurs :&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;b&gt;CounterMonitor&lt;/b&gt; qui permet de scrupter des valeurs de type entier (&lt;i&gt;Byte&lt;/i&gt;, &lt;i&gt;Integer&lt;/i&gt;, &lt;i&gt;Short&lt;/i&gt;, &lt;i&gt;Long&lt;/i&gt;) et qui se comporte comme un compteur :&lt;/li&gt;
&lt;ul&gt;&lt;li style="text-align: justify;"&gt;les valeurs ne peuvent être inférieures strictement à 0,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;les valeurs ne peuvent qu'être incrémentées,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;les valeurs peuvent être tournantes (dans ce cas un modulo doit être défini).&lt;/li&gt;
&lt;/ul&gt;&lt;li style="text-align: justify;"&gt;&lt;b&gt;GaugeMonitor&lt;/b&gt; qui permet de scrupter des valeurs de types entier ou flottantes (&lt;i&gt;Float&lt;/i&gt;, &lt;i&gt;Double&lt;/i&gt;) et qui se comporte comme un pas&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;b&gt;StringMonitor&lt;/b&gt; qui permet de scrupter des valeurs de type &lt;i&gt;String&lt;/i&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Tous ces moniteurs doivent étendre la classe abstraite &lt;i&gt;Monitor&lt;/i&gt; alors que les types des valeurs surveillées doivent être supportés par le type de moniteur utilisé. Cependant, il est à noter que le moniteur vérifie le type de la valeur de l'instance retournée et non le te type de l'attribué déclaré dans les méta-données du MBean observé.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKLxHRkZAI/AAAAAAAAAP4/eZfErdqRqWE/s1600/jmx58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKLxHRkZAI/AAAAAAAAAP4/eZfErdqRqWE/s400/jmx58.png" width="262" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TPKMExdR2sI/AAAAAAAAAP8/LvN1aDxsNIc/s1600/jmx59.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TPKMExdR2sI/AAAAAAAAAP8/LvN1aDxsNIc/s400/jmx59.png" width="323" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TPKMQ5MDK8I/AAAAAAAAAQA/sszqSpNWdeM/s1600/jmx60.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="387" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TPKMQ5MDK8I/AAAAAAAAAQA/sszqSpNWdeM/s400/jmx60.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TPKNgMBobwI/AAAAAAAAAQI/NyLwm_9d4oc/s1600/jmx76.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="295" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TPKNgMBobwI/AAAAAAAAAQI/NyLwm_9d4oc/s400/jmx76.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;Pour les notifications, une sous classe spécifique de &lt;i&gt;Notification&lt;/i&gt; est définie pour être utilisée par tous les services de monitoring. Il s'agit de la classe &lt;i&gt;MonitorNotification&lt;/i&gt;.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;Ainsi, elle est utilisée pour rapporter les cas suivants :&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Une condition de déclenchement d'un moniteur est détectée (par exemple, si le seuil d'une valeur est atteinte)&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Une erreur s'est produite durant la scrutation d'un attribut (par exemple, si un MBean est désenregistré)&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TPKOjDQNWDI/AAAAAAAAAQM/qL7w59mPIcM/s1600/jmx77.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TPKOjDQNWDI/AAAAAAAAAQM/qL7w59mPIcM/s400/jmx77.png" width="312" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;La figure suivante représente tous les types de notifications qui peuvent être générées par un service Monitor.&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TPKO0P3FAEI/AAAAAAAAAQQ/FSwyMlB4ryI/s1600/jmx57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="222" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TPKO0P3FAEI/AAAAAAAAAQQ/FSwyMlB4ryI/s400/jmx57.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;a name="timer"&gt;&lt;/a&gt; &lt;h2&gt;Service&amp;nbsp;Timer&lt;/h2&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: justify;"&gt;Le service Timer permet de déclencher des notifications à des dates et heures spécifiques ou à intervalles réguliers. Les notifications sont émises à tous les objets déclarés comme étant interessés par les notifications émises par le timer (patron &lt;i&gt;Observer&lt;/i&gt;).&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: justify;"&gt;Le service Timer est un MBean qui peut être managé en permettant, entre autre, aux applications de modifier la configuration de son ordonnanceur (&lt;i&gt;scheduler&lt;/i&gt;).&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: justify;"&gt;En fait, la classe Timer gère une liste de notifications datées qui sont émises quand leur date et heure arrivent. Les méthodes de cette classe permettent d'ajouter et de supprimer des notifications de sa liste. En fait, les types de notifications sont fournis par l'utilisateur avec la date et optionnellement la fréquence et le nombre de répétitions.&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKPT0nrpwI/AAAAAAAAAQU/_P4QW-Dln5I/s1600/jmx64.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKPT0nrpwI/AAAAAAAAAQU/_P4QW-Dln5I/s400/jmx64.png" width="330" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: justify;"&gt;Pour les notifications, une sous classe spécifique de &lt;i&gt;Notification&lt;/i&gt; est définie pour être utilisée par le service Timer. Il s'agit de la classe &lt;i&gt;TimerNotification&lt;/i&gt;.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: justify;"&gt;Ainsi, elle est utilisée pour rapporter les cas suivants :&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Les notifications ne sont déclenchées qu'une seule fois&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Les notifications sont répétées à une période définie et/ou un nombre d'occurrences&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: justify;"&gt;Ces paramètres sont définis lorsque la notification est ajoutée à la liste de notifications du timer. En outre, à chacune des notifications émises est associée un identifiant unique.&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XLL8sJPQ97g/TPKPwGfdiTI/AAAAAAAAAQY/YNQBbw48Vsw/s1600/jmx61.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/_XLL8sJPQ97g/TPKPwGfdiTI/AAAAAAAAAQY/YNQBbw48Vsw/s400/jmx61.png" width="237" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TPKO0P3FAEI/AAAAAAAAAQQ/FSwyMlB4ryI/s1600/jmx57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;/a&gt; &lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;Si la notification ajoutée au service Timer possède une date antérieure à la date courante, alors la méthode &lt;i&gt;addNotification&lt;/i&gt; se comporte comme si la date indiquée était la date courante.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;Si la date d'émission d'une notification est mise à jour alors qu'elle est déjà existante, alors aucune notification de mise à jour n'est émise.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Le service Timer MBean est un émetteur standard de notifications (qui possèdent un type et une date définis dans la liste de notifications ajoutées à l'aide de la méthode &lt;i&gt;addNotification()&lt;/i&gt;). Tous les écouteurs d'un MBean Timer donnés reçoivent toutes les notifications. Les écouteurs interessés par un type de notifications Timer particulier doivent spécifier un objet filtre lors de leur enregistrement.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Lorsqu'un timer est actif et que la date d'une notification de type Timer arrive à son terme, le service Timer émet cette notification en fournissant son type, message, données utilisateurs ainsi que l'identifiant de la notification. S'il s'agit d'une notification périodique disposant d'un nombre d'occurrence, il est décrémenté.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enfin, si la notification n'a plus besoin d'être émise (notification non récurente ou notification périodique disposant d'un nombre d'émission prédéfini), elle est supprimée de la liste des notifications.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;Si une notification dispose d'une date d'émission antérieure à son démarrage, il est possible de l'émettre ou de l'ignorer à l'aide de la méthode &lt;i&gt;sendPastNotification()&lt;/i&gt;. Par défaut, la valeur de cet attribut est mise à &lt;i&gt;false&lt;/i&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;a name="relation"&gt;&lt;/a&gt; &lt;h2&gt;Service Relation&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;JMX définit un modèle de relation entre les MBeans. Une relation est définie par l'utilisateur et se présente comme une association n-aire entre les MBeans.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Pour ce faire, JMX propose un ensemble de classes à utiliser pour décrire les relations, ainsi qu'un service qui permet de centraliser toutes les opérations de mise en relation.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Toutes les relations permettent d'associer un type de relations (qui fournit des informations sur les rôles qu'il contient comme la multiplicité) avec le nom de classe du MBean qui satisfait le rôle.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Le service de relations permet également de chercher un MBean au travers de ses relations.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Il est garant de la consistance des relations en vérifiant les opérations et le désenregistrement des MBean afin de s'assurer que les relations sont toujours conformes. Si une relation n'est plus valide, elle est supprimée du service de relations même si ses MBeans membres restent présents.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Une relation est composée de rôles nommés qui disposent d'une liste de MBeans associés à ce rôle. Cette liste doit être consistante avec les informations de multiplicité ainsi qu'avec les classes des MBean qui représentent ce rôle.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Un ensemble de définition de rôles constitue un type de relation.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Un type de relation est un patron pour toutes les instances de relations qui associent les MBeans représentant ses rôles.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Par la suite, le terme de relation signifiera une instance spécique d'une relation associant des MBeans existants aux rôles dans un type de relations défini.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Le tableau ci-dessous décrit les concepts nécessaires à la compréhension du modèle de relations défini par JMX :&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;th align="center"&gt;Concept&lt;/th&gt; &lt;th align="center"&gt;Description&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Role information&lt;/td&gt; &lt;td&gt;Décrit un des rôles dans une relation. L'information sur un rôle est composée du nom du rôle, de sa multiplicité, du nom de la classe qui participe à ce rôle, d'une propriété en lecture-seule sur les permissions et d'une description.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Relation type&lt;/td&gt; &lt;td&gt;Méta-donnée d'une relation, composée d'un ensemble de Role information. Permet de décrire les rôles qu'une relation satisfait et permet de servir de patron pour créer et maintenir des relations.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Relation&lt;/td&gt; &lt;td&gt;Association courante entre des MBeans qui satisfont une relation donnéee. Une relation peut avoir des propriétés et méthodes qui ne s'appliquent qu'à ses MBeans.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Role Value&lt;/td&gt; &lt;td&gt;Liste de MBeans qui satisfont un rôle donné dans une relation.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Unresolved Role&lt;/td&gt; &lt;td&gt;Résultat d'un accès illégal d'une opération sur un rôle. Contient la raison du refus de l'opération.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Support Classes&lt;/td&gt; &lt;td&gt;Classes internes utilisées pour représenter des types de relations et des instances de relations.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Relation Service&lt;/td&gt; &lt;td&gt;&lt;span style="font-family: Tahoma, sans-serif; font-size: 10pt;"&gt;MBean qui peut accéder et maintenir la consistance de tous les types de relations et toutes les instances de relations dans un agent JMX. Fournit des opérations pour trouver un MBean et ses rôles dans une relation.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;En JMX, le type de relation est un ensemble statique de rôles. Les types de relations peuvent être définis à l'exécution mais, une fois défini, ces rôles et informations sur les rôles ne peuvent être modifiés.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;u&gt;Exemple de relations :&lt;/u&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Dans cet exemple, des livres (&lt;i&gt;Books&lt;/i&gt;) et les propriétaires (&lt;i&gt;Owner&lt;/i&gt;) représente des rôles :&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;i&gt;Books&lt;/i&gt; représente le nombre de livres que possède la classe d'un MBean donnée.&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;Owner&lt;/i&gt; représente un propriétaire de livres d'une autre classe d'un MBean.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Un type de relations (&lt;i&gt;Personal Library&lt;/i&gt;) peut être défini comme étant la notion d'appartenance de livres.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XLL8sJPQ97g/TPKRennmH-I/AAAAAAAAAQg/l79ynOUIw8k/s1600/jmx65.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="160" src="http://2.bp.blogspot.com/_XLL8sJPQ97g/TPKRennmH-I/AAAAAAAAAQg/l79ynOUIw8k/s400/jmx65.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;En fait, le service de relations empêche la création de types de relations invalides, de relations invalides ou la modifiation de valeurs de rôles invalides.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Quand une relation est supprimée du service de relations, ses MBeans membres ne sont pas impactés.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Quand un type de relation est supprimé, toutes les relations référencées sont au préalable supprimées. Cependant, c'est à l'appelant de gérer la consistance lors de la suppression d'un type de relations.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;En outre, puisque les relations ne sont définies qu'au niveau des MBeans enregistrés, en supprimer un de l'annuaire est susceptible de modifier la relation. Le service de relations écoute, pour tous les MBean, le server de notifications qui indique quand un membre d'une relation est désenregistré. Le MBean correspondant est alors supprimé de tous rôles où il se trouve. Dans le cas où la nouvelle cardinalité du rôle n'est pas consistante avec son type de relation, alors la relation est supprimée du service de relation.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Le service de relations émet des notifications après l'exécution d'opérations qui modifient une instance de relations (création, mise à jour ou suppression). Cette notification fournit des informations sur la modification comme l'identifiant de la relation et la nouvelle valeur d'un rôle.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;De plus, il est à noter qu'il existe deux types de relations et relations :&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Les types de relations et relations internes : les types de relations et leurs instances sont créés par le service de relations et ne sont accessibles qu'aux travers ses opéraitons.&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Les types de relations et relations externes : les types de relations et leurs instances sont instanciés en dehors du service de relations puis lui sont ajoutés. Dans ce cas, ils peuvent être accessibles directement et, en l'occurrence, peuvent être enregistré comme des MBeans. Il est cependant à noter que ces types de relation sont immuables et qu'elles ne doivent pas être modifiées une fois enregistré dans le service de relation.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;En raison de la complexité de ce service, pour plus d'informations, il est préférable de se référer aux chapitres &lt;i&gt;11.2 Relation Service Classes&lt;/i&gt;, &lt;i&gt;11.3 Interfaces and Support Classes&lt;/i&gt; et &lt;i&gt;11.4 Role Description Classes&lt;/i&gt; des spécifications agrégées JMX.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;&lt;a name="securite"&gt;&lt;/a&gt; &lt;h2&gt;Service Securité&lt;/h2&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Un MBean Server JMX peut avoir accès à des informations sensibles et peut être susceptible d'exposer des opérations sensibles. Pour ce faire, JMX propose un mécanisme d'accès à de telles opérations en s'appuyant sur le modèle de sécurité de Java : il est possible de définir des permissions qui permettent de&amp;nbsp;contrôler&amp;nbsp;l'accès au MBean Server et à ses opérations.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;La sécurisation du MBean Server s'appuyant sur le modèle standard de sécurité Java, il est nécessaire de disposer du gestionnaire de sécurité Java (&lt;i&gt;security manager&lt;/i&gt;). La méthode statique &lt;i&gt;System.getSecurityManager()&lt;/i&gt; permet de le vérifier.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;Pour rappel, le modèle de sécurité de Java s'appuie sur le principe de permissions : pour qu'une opération soit invocable, l'appelant doit posséder la/les permissions.&lt;br /&gt;
En effet, à un point donné de l'exécution d'un programme correspond un ensemble de permissions appliqué à l'exécution d'un thread. &lt;br /&gt;
En fait, une opération est autorisée si le thread qui l'invoque dispose des permissions nécessaires.&lt;br /&gt;
&lt;br /&gt;
Les permissions sont des objets java qui étendent la classe &lt;i&gt;Permission&lt;/i&gt;.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKS5FhDvOI/AAAAAAAAAQk/QbB4KTZsUXA/s1600/jmx66.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="263" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKS5FhDvOI/AAAAAAAAAQk/QbB4KTZsUXA/s320/jmx66.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;En fait, JMX défini, par défaut, sa propre permission &lt;i&gt;MBeanServerPermission&lt;/i&gt; qui peut être configurée comme suit :&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;i&gt;MBeanServerPermission&lt;/i&gt; qui prend en paramètre de son constructeur une chaine de caractère représentant la liste des opérations autorisées sur le MBeanServer (ex : &lt;i&gt;MBeanServerPermission("createMBeanServer")&lt;/i&gt; qui permet de controler l'accès aux méthodes &lt;i&gt;MBeanServerFactory.createMBeanServer&lt;/i&gt; )&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;MBeanPermission&lt;/i&gt; qui prend en paramètre deux chaines de caractères :&lt;/li&gt;
&lt;ul&gt;&lt;li style="text-align: justify;"&gt;la première représente la cible et peut être composée du nom canonique de la classe ou d'une expression régulière, du membre (c'est-à-dire le nom de l'attribut ou de l'opération qui doit être accédé), et de l'ObjetName du MBean cible.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;&lt;u&gt;Exemples de cible :&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false" style="text-align: justify;"&gt;com.example.Resource#Name[com.example.main:type=resource]
com.example.Resource#*[com.example.main:type=resource]
*#Name[com.example.main:type=resource]&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;ul&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;la &amp;nbsp;deuxième représente l'action une ou plusieurs méthodes du MBean Server parmi les suivantes :&lt;/li&gt;
&lt;ul&gt;&lt;li style="text-align: justify;"&gt;&lt;i&gt;addNotificationListener&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;getAttribute&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;getClassLoader&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;getClassLoaderFor&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;getClassLoaderRepository&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;getMBeanInfo&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;getObjectInstance&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;instantiate&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;invoke&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;isInstanceOf&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;queryMBeans&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;queryNames&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;registerMBean&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;removeNotificationListener&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;setAttribute&lt;/i&gt;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;&lt;i&gt;unregisterMBean&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: justify;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;Les opérations suivantes ne sont pas soumises à la sécurisation du MBean Server :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;i&gt;isRegistered&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;getMBeanCount&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;getDefaultDomain&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;De plus, JMX propose la permission &lt;i&gt;MBeanTrustPermission&lt;/i&gt; qui permet de faire confiance à un certain utilisateur ou code source signé. Si le signataire ou le code source possède cette permission, le MBean est considéré comme étant de confiance. Seuls les MBeans de confiance peuvent alors être enregistrés dans le MBean Server.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Une permission &lt;i&gt;MBeanTrustPermission&lt;/i&gt; est configurée soit avec la valeur "&lt;i&gt;register&lt;/i&gt;", soit avec la valeur &amp;nbsp;"&lt;i&gt;*&lt;/i&gt;" qui signifient toutes deux la même chose dans la version courante de la version JMX.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, utilisé en complément de la permission &lt;i&gt;MBeanPermission&lt;/i&gt;, la permission &lt;i&gt;MBeanTrustPermission&lt;/i&gt; permet une gestion de la sécurité plus fine sur l'enregistrement des MBeans : la permission &lt;i&gt;MBeanPermission&lt;/i&gt; vérifie qui enregistre alors que la permission &lt;i&gt;MBeanTrustPermission&lt;/i&gt; vérifie ce qui est enregistré.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;u&gt;Exemples de fichier de policy :&lt;/u&gt;&lt;/div&gt;&lt;pre class="brush:java; wrap-lines: false; auto-links: false"&gt;grant {
    permission javax.management.MBeanPermission "*", "*";
};

grant codeBase "file:${user.dir}${/}appl1.jar" {
    permission javax.management.MBeanPermission "", "getClassLoaderRepository";
};

grant codeBase "file:${user.dir}${/}appl2.jar" {
    permission javax.management.MBeanPermission "[d1:*]", "isInstanceOf, getObjectInstance";
};

grant codeBase "file:${user.dir}${/}appl3.jar" {
    permission javax.management.MBeanServerPermission "findMBeanServer";
    permission javax.management.MBeanPermission "JMImplementation:*", "queryNames";
};

grant {
    permission javax.management.MBeanTrustPermission "register";
};

grant signedBy "Gorey" {
    permission javax.management.MBeanTrustPermission "register";
};

&lt;/pre&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-1995550387799645066?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=swLIqSZBWu4:HeJpvOchPqo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=swLIqSZBWu4:HeJpvOchPqo:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=swLIqSZBWu4:HeJpvOchPqo:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/1995550387799645066/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/1995550387799645066?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/1995550387799645066?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html" title="JMX pour les nuls... - Les services JMX - Partie 7" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s72-c/jmx-cover.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0UBRXsycSp7ImA9Wx9bEk8.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-628604457742299639</id><published>2010-12-06T08:00:00.004+01:00</published><updated>2011-02-20T19:07:34.599+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-20T19:07:34.599+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jmx" /><title>JMX pour les nuls... - Chargement dynamique de MBeans - Partie 6</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s1600/jmx-cover.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s200/jmx-cover.png" width="171" /&gt;&lt;/a&gt;&lt;/div&gt;Cet article toujours dans la lignée de ma petite série d'articles sur JMX (cf. &lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-introduction.html"&gt;introduction&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html"&gt;partie 1 portant sur les généralités&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html"&gt;partie 2 portant sur les différents MBeans et le concept de Notification&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html"&gt;partie 3 sur les agents JMX&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html"&gt;partie 4 sur les classes de base&lt;/a&gt;&amp;nbsp;et &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html"&gt;partie 5 sur le MBeanServer&lt;/a&gt;) sera plus accès sur les capacités de chargement dynamique des MBeans. Cependant, il n'abordera que succinctement cette partie car il est nécessaire &amp;nbsp;d'avoir une très bonne connaissance du fonctionnement du classloader et qu'un simple article ne saurait l'aborder comme il se doit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;Table des matières&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html"&gt;JMX, qu'est ce que c'est?&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#generalite"&gt;Généralités&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#architecture"&gt;Architecture JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#instrumentation"&gt;Niveau instrumentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#agent"&gt;Niveau agent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#distribue"&gt;Niveau service distribué&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#composant"&gt;Composants JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#mbean"&gt;MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#notification"&gt;Modèle de notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#metadonnee"&gt;Classe de métadonnées de MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#serveur"&gt;Serveur de MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#services"&gt;Service d'agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Spécifications&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html"&gt;JMX Instrumentation&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean"&gt;MBean&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_standard"&gt;MBean Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_dynamic"&gt;Dynamic MBean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#notification"&gt;Notification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_open"&gt;Open MBean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_model"&gt;Model MBean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html#agent"&gt;Agent JMX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html"&gt;Concepts&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#objectname"&gt;ObjectName&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#objectinstance"&gt;ObjectInstance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#attribute"&gt;Attribute et AttributeList&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#exception"&gt;Les Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html"&gt;MBean Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html"&gt;Chargement dynamique des MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html"&gt;Les services JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#monitoring"&gt;Service Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#timer"&gt;Service Timer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#relation"&gt;Service Relation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#securite"&gt;Service Sécurité&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-connecteurs.html"&gt;Les Connecteurs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;JMX propose un service de chargement dynamique de MBeans qui s'appuie sur les fonctionnalités du classloader Java pour récupérer et instancier les MBeans qui peuvent utilisés indifféremment des classes Java ou des librairies natives. Cette fonctionnalité existe car lorsque le serveur JMX est démarré, il peut ne pas avoir connaissance de tous les MBeans et devoir en télécharger. Pour ce faire, un service particulier chargé de gérer des applets de management (m-let) est utilisé pour instancier les MBeans obtenus d'une URL distante sur le réseau.  En fait, le service de m-let permet d'instancier et d'enregistrer des MBeans dans le MBean Server en chargeant un fichier texte, dont la localisation est spécifiée par une URL, qui contient les informations des MBeans à obtenir. Quand ce fichier texte est chargé, toutes les classes spécifiés par le tag MLET sont téléchargées et une instance de chaque MBean spécifié est crée et enregistré.  Le service de m-let étant lui-même un MBean enregistré dans le MBean Server, il peut être utilisé par d'autres MBeans, par d'autres applications ou par d'autres applications d'administration et de supervision distantes. &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKDftVvX6I/AAAAAAAAAPw/3wQmopnzDw0/s1600/jmx74.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="252" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKDftVvX6I/AAAAAAAAAPw/3wQmopnzDw0/s400/jmx74.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;Le fonctionnement des m-let est similaire à celui de Java Web Start.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKEiiLkb-I/AAAAAAAAAP0/xpRHd_cDe80/s1600/jmx56.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TPKEiiLkb-I/AAAAAAAAAP0/xpRHd_cDe80/s400/jmx56.png" width="388" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;La classe &lt;i&gt;MLet&lt;/i&gt; étend la classe &lt;i&gt;URLClassLoader&lt;/i&gt;, ce qui implique qu'il s'agit également d'un classe loader.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;Dans le cas générique, l'appel à la méthode &lt;i&gt;getMBeansFromURL()&lt;/i&gt; du service de m-let permet de :&lt;/div&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li style="text-align: justify;"&gt;télécharger le fichier texte contenant le descriptif des MBeans (un MBean par tag MLET),&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;télécharger les classes nécessaires,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;charger les classes dans le classe loader du MBean Server,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;instancier les MBeans,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;enregistrer les MBeans instanciés préalablement,&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;renvoyer les instances des MBeans.&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;Dans le cas où le MBean contient de méthodes natives et que des librairies natives sont chargées en utilisant la méthode &lt;i&gt;System.loadLibrary&lt;/i&gt;, alors la méthode &lt;i&gt;findLibrary&lt;/i&gt; du classe loader du m-let est appelé pour trouver la librairie. Cette méthode surcharge celle de la classe &lt;i&gt;ClassLoader&lt;/i&gt; et, si la librairie est trouvée, copie cette dernière à l'emplacement retourné par la méthode &lt;i&gt;getLibraryDirectory&lt;/i&gt; de la classe &lt;i&gt;MLet&lt;/i&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;Le MBean Server maintient une liste de classe loader dans le repository de classe loader (aussi appelé &lt;i&gt;default loader Repository&lt;/i&gt;). &lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ce classe loader &lt;i&gt;Repository&lt;/i&gt; est utilisé dans les méthodes createMBean et instantiate de l'interface MBean Server : le repository loader repository est utilisé pour trouver et charger les classes.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Si un m-let ne trouve pas les classe à l'URL, il essaie de chargeer les classes du classe loader repository.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;Dans le cas où plusieurs MBean Server sont présent dans une même JVM, ils disposent chacun de leurs propres classe loader repository qui sont indépendants les uns des autres.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;L'ordre des classes loader dans le repository est important : quand une classe est chargée dans le repository, chaque classe loader est interrogé pour charger la classe. Si un loader réussi à charger la classe alors la recherche s'arrête, sinon (s'il lève une exception &lt;i&gt;ClassNotFoundException&lt;/i&gt;) la recherche continue jusqu'à ce qu'il n'y en ait plus (dans ce cas l'exception &lt;i&gt;ClassNotFoundException&lt;/i&gt; est levée).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Le premier loader dans la classe loader repository est celui qui a chargé l'implémentation du MBean Server. Se trouve ensuite les loaders des MBeans, l'ordre des loaders étant celui du chargement des MBeans.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Ainsi, on aura, par exemple : &lt;/div&gt;&lt;div style="text-align: justify;"&gt;Un MBean m1 apparait avant le MBean m2 si la méthode &lt;i&gt;createMBean&lt;/i&gt; ou  &lt;i&gt;registerMBean&lt;/i&gt; qui a enregistrée m1 s'est terminé avant le démarrage de l'opération qui a enregistré m2. Si la méthode d'enregistrement de m2 a démarré avant la fin de la méthode d'enregistrement de m1, alors l'ordre des loaders est indéterminé.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;Un m-let est un classe loader et, comme l'indique le comportement d'un classe loader standard, il charge une classe en utilisant la méthode &lt;i&gt;loadClass&lt;/i&gt; :&lt;/div&gt;&lt;div style="text-align: justify;"&gt;En premier lieu, il envoie une requête au classe loader parent pour charger la classe (le classe loader parent est celui spécifié lors le m-let est créé (par défaut le classe loader système)), puis, dans un second temps, si le classe loader parent n'a pas pu charger la classe, le m-let tente de la charger dans sa liste d'URL. Enfin, si ces deux essais se soldent par un échec, le m-let tente de charger la classe dans le classe loader repository (dans ce cas, il est dit qu'il délègue au classe loader repository).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Si ces trois tentatives échouent, l'exception &lt;i&gt;ClassNotFoundException&lt;/i&gt; est levée.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Pour avoir d'autres informations sur le chargement de classe ainsi que sur les problèmes qui peuvent apparaitre, voir les chapitres &lt;i&gt;8.4 The Class Loader Repository&lt;/i&gt; et &lt;i&gt;8.5 Using the Correct Class Loader for Parameters&lt;/i&gt; des spécifications JMX.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4495310291235200788-628604457742299639?l=jetoile.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=S-GB0YJbWtg:C-JX5uOonYQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jetoile?a=S-GB0YJbWtg:C-JX5uOonYQ:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jetoile?i=S-GB0YJbWtg:C-JX5uOonYQ:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jetoile.blogspot.com/feeds/628604457742299639/comments/default" title="Publier les commentaires" /><link rel="replies" type="text/html" href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html#comment-form" title="0 commentaires" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/628604457742299639?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4495310291235200788/posts/default/628604457742299639?v=2" /><link rel="alternate" type="text/html" href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html" title="JMX pour les nuls... - Chargement dynamique de MBeans - Partie 6" /><author><name>Khanh</name><uri>http://www.blogger.com/profile/16483007168280298995</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s72-c/jmx-cover.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0QFSH0zcSp7ImA9Wx9bEk8.&quot;"><id>tag:blogger.com,1999:blog-4495310291235200788.post-6449799586531789986</id><published>2010-11-29T08:00:00.018+01:00</published><updated>2011-02-20T19:08:39.389+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-20T19:08:39.389+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="jmx" /><title>JMX pour les nuls... - Le MBean Server - Partie 5</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s1600/jmx-cover.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/_XLL8sJPQ97g/TMdPuTpRY8I/AAAAAAAAALQ/R_w0PiLpvwo/s200/jmx-cover.png" width="171" /&gt;&lt;/a&gt;&lt;/div&gt;Cet article reste dans la lignée de ma petite série d'articles sur JMX (cf. &lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-introduction.html"&gt;introduction&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html"&gt;partie 1 portant sur les généralités&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html"&gt;partie 2 portant sur les différents MBeans et le concept de Notification&lt;/a&gt;, &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html"&gt;partie 3 sur les agents JMX&lt;/a&gt; et &lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html"&gt;partie 4 sur les classes de base&lt;/a&gt;) et portera sur le MBean Server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;Table des matières&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html"&gt;JMX, qu'est ce que c'est?&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#generalite"&gt;Généralités&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#architecture"&gt;Architecture JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#instrumentation"&gt;Niveau instrumentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#agent"&gt;Niveau agent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#distribue"&gt;Niveau service distribué&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#composant"&gt;Composants JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#mbean"&gt;MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#notification"&gt;Modèle de notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#metadonnee"&gt;Classe de métadonnées de MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#serveur"&gt;Serveur de MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/10/jmx-pour-les-nuls-les-concepts-partie-1.html#services"&gt;Service d'agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Spécifications&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html"&gt;JMX Instrumentation&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean"&gt;MBean&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_standard"&gt;MBean Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_dynamic"&gt;Dynamic MBean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#notification"&gt;Notification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_open"&gt;Open MBean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-differents-mbeans.html#mbean_model"&gt;Model MBean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-agents-jmx-partie.html#agent"&gt;Agent JMX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html"&gt;Concepts&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#objectname"&gt;ObjectName&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#objectinstance"&gt;ObjectInstance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#attribute"&gt;Attribute et AttributeList&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-les-classes-de-base.html#exception"&gt;Les Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/11/jmx-pour-les-nuls-le-mbean-server.html"&gt;MBean Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-chargement-dynamique.html"&gt;Chargement dynamique des MBeans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html"&gt;Les services JMX&lt;/a&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#monitoring"&gt;Service Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#timer"&gt;Service Timer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#relation"&gt;Service Relation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-services-jmx.html#securite"&gt;Service Sécurité&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;a href="http://jetoile.blogspot.com/2010/12/jmx-pour-les-nuls-les-connecteurs.html"&gt;Les Connecteurs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Le MBean Server est un annuaire de MBeans se trouvant dans l'agent JMX. Il permet de fournir les services que manipulent les MBeans et toutes les opérations d'administration et de supervision, qui sont fournies par le MBean, le sont au travers de l'interface &lt;i&gt;MBeanServer&lt;/i&gt; :&lt;/div&gt;&lt;ul style="text-align: justify;"&gt;&lt;li&gt;Les MBeans qui représentent une ressource managée qui peuvent être n'importe quelle application, des ressources système ou réseaux tant qu'elles sont représentés par une interface Java ou un wrappeur Java.&lt;/li&gt;
&lt;li&gt;Les MBeans qui ajoutent des fonctionnalités de management qui peuvent être génériques (par exemple, des fonctionnalités de journalisation ou de monitoring) ou plus spécifique à une technologie ou à un domaine d'application.&lt;/li&gt;
&lt;li&gt;Les composants de l'infrastructure comme les serveurs de connecteurs et les adaptateurs de protocole.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Pour ce faire, l'agent JMX propose une classe factory pour trouver ou créer un MBean Server qui peut ne pas êre unique dans un agent JMX.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;L'interface &lt;i&gt;MBeanServer&lt;/i&gt; définie les opérations accessible sur un agent JMX.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TOlMH2RYqlI/AAAAAAAAAOY/rcYE9XfKwrQ/s1600/jmx43.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TOlMH2RYqlI/AAAAAAAAAOY/rcYE9XfKwrQ/s640/jmx43.png" width="283" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;La classe &lt;i&gt;MBeanServerFactory&lt;/i&gt; dispose de méthodes statiques permettant de retourner une instance de l'implémentation de l'interface &lt;i&gt;MBeanServer&lt;/i&gt;. &lt;/div&gt;&lt;div style="text-align: justify;"&gt;Lorsque l'implémentation du MBean Server est créée, il est possible d'indiquer le nom du domaine par défaut utilisé dans l'agent JMX qu'il représente. Ce sont ces méthodes qui sont également utilisées par l'agent JMX pour créer un ou plusieurs MBean Server.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Dans le cas où ce sont des méthodes de recherche et de récupération du MBean Server déjà créé dans l'agent JMX, les classes chargées dans la JVM peuvent accéder aux MBean Server déjà existant sans avoir à connaitre l'agent JMX.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div style="text-align: justify;"&gt;Depuis Java 5, toute application Java possède un MBean Server qui peut être obtenu via la méthode &lt;i&gt;java.lang.management.ManagementFactory.&lt;/i&gt;&lt;/div&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; getPlatformMBeanServer()&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TOlM8DBItVI/AAAAAAAAAOc/GK-kgJY2Hos/s1600/jmx46.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="254" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TOlM8DBItVI/AAAAAAAAAOc/GK-kgJY2Hos/s320/jmx46.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;L'accès aux méthodes statiques de la classe &lt;i&gt;MBeanServerFactory&lt;/i&gt; est controlé par la classe &lt;i&gt;MBeanServerPermission&lt;/i&gt;. Cette classe étend les classes de permissions basiques de Java et permet l'accès aux opérations suivantes :&lt;/div&gt;&lt;ul style="text-align: justify;"&gt;&lt;li&gt;&lt;i&gt;createMBeanServer&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;findMBeanServer&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;newMBeanServer&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;releaseMBeanServer&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_XLL8sJPQ97g/TOlQlzvrRwI/AAAAAAAAAPM/6MVsoLxzkxM/s1600/jmx47.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/_XLL8sJPQ97g/TOlQlzvrRwI/AAAAAAAAAPM/6MVsoLxzkxM/s640/jmx47.png" width="310" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;L'enregistrement des MBeans au sein du MBean Server peut être fait soit via l'agent JMX, soit via un autre MBean. Pour ce faire, l'interface &lt;i&gt;MBeanServer&lt;/i&gt; propose deux types d'enregistrement :&lt;/div&gt;&lt;ul style="text-align: justify;"&gt;&lt;li&gt;l'instanciation d'un nouveau MBean et son enregistrement en une seule opération. Dans ce cas, le chargement de la classe Java du MBean peut être fait en utilisant le classe loader par défaut ou en en explicitant un,&lt;/li&gt;
&lt;li&gt;l'enregistrement d'un MBean déjà existant.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Dans ces deux cas, un &lt;i&gt;ObjectName&lt;/i&gt; doit être associé au MBean lors de son enregistrement afin de l'identifier de manière unique au sein du contexte du MBean Server.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Le développeur du MBean peut, de plus, avoir la main sur l'enregistrement et le désenregistrement du MBean au sein du MBean Server en implémentant l'interface &lt;i&gt;MBeanRegistration&lt;/i&gt;. Pour ce faire, le MBean Server vérifie dynamiquement avant (resp. après) l'exécution de ces opérations si le MBean implémente l'interface &lt;i&gt;MBeanRegistration&lt;/i&gt;. Si c'est le cas, alors les opérations de callbacks adéquates sont invoquées.&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" style="margin-left: 0px; margin-right: 0px; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class="Apple-style-span"&gt;&lt;a href="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_XLL8sJPQ97g/TNCS7qzv19I/AAAAAAAAAL4/6qkEYy4pX6o/s1600/remarque.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/td&gt; &lt;td style="text-align: justify;"&gt;L'implémentation de l'interface &lt;i&gt;MBeanRegistration&lt;/i&gt; est la seule manière de renseigner le MBean sur son environnement et plus particulièrement de lui fournir des informations sur le MBean Server au sein duquel il est enregistré. Cela lui permet, entre autre, d'obtenir des informations sur les autres MBean présent dans le MBean Server.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbo
