<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2frenchfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Blog d’Ippon Technologies</title>
	
	<link>http://blog.ippon.fr</link>
	<description>Les experts Java EE, Portail et SOA</description>
	<lastBuildDate>Mon, 14 May 2012 14:18:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/LeBlogDesExpertsJ2ee" /><feedburner:info uri="leblogdesexpertsj2ee" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/content?lg=fr&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/bn/intatm_fr_1.gif">Subscribe with Mon Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/LeBlogDesExpertsJ2ee" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item>
		<title>Java est-il trop “serré” ?</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/CEfqQseQXXc/</link>
		<comments>http://blog.ippon.fr/2012/05/14/java-est-il-trop-serre/#comments</comments>
		<pubDate>Mon, 14 May 2012 11:16:33 +0000</pubDate>
		<dc:creator>Thomas ESCOLAN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[opinion]]></category>
		<category><![CDATA[troll]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5642</guid>
		<description><![CDATA[<p></p> <p>Récemment, une énième discussion a enflammé les esprits sur les forums techniques. Vous savez bien, c&#8217;est une discussion qui démarre sur l&#8217;état de l&#8217;art et qui se termine en considérations sans fins sur les qualités comparées avec un &#8220;vieux langage&#8221; que-sur-des-cas-précis-il-ne-sera-jamais-dépassé&#8230;</p> <p>C&#8217;est un fait que l&#8217;écosphère Java souffre actuellement d&#8217;une offre pléthorique (Struts/Stripes, Tapestry, <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/05/14/java-est-il-trop-serre/">Java est-il trop &#8220;serré&#8221; ?</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="  alignleft" title="Java est-il trop serré ?" src="http://www.epicerie-fine-lepleindepices.com/uploads/Medias/37/85/G_pim_82_1204109217.jpg" alt="" width="156" height="124" /></p>
<p>Récemment, une <a href="http://www.developpez.net/forums/showthread.php?t=1051348&amp;referrerid=374273 " target="_blank">énième discussion</a> a enflammé les esprits sur les forums techniques. Vous savez bien, c&#8217;est une discussion qui démarre sur l&#8217;état de l&#8217;art et qui se termine en considérations sans fins sur les qualités comparées avec un &#8220;vieux langage&#8221; que-sur-des-cas-précis-il-ne-sera-jamais-dépassé&#8230;</p>
<p>C&#8217;est un fait que l&#8217;écosphère Java <span style="text-decoration: underline;">souffre</span> actuellement d&#8217;une offre pléthorique (Struts/Stripes, Tapestry, JSF, Spring MVC, GWT, JavaFX&#8230; j&#8217;ai la tête qui tourne) et redondante (cf. débats actuels Java EE 6 vs. Spring 3.x ou la foule des portails, GED ou ESB apparus). Il est vrai aussi que :</p>
<ol>
<li>les débutants sont mal formés, notamment sur les paradigmes OOP, AOP et SOA</li>
<li>les développeurs expérimentés s&#8217;épuisent à passer d&#8217;un <em>framework</em> à l&#8217;autre</li>
<li>les architectes n&#8217;ont pas le temps d&#8217;évaluer les versions qui sortent en permanence</li>
</ol>
<p>Sans parler des projets tellement évolutifs qu&#8217;ils embarquent plusieurs technologies Web Services en même temps ou pâtissent de toutes sortes de dettes techniques, faute de recevoir une maintenance planifiée&#8230;</p>
<p>Mais <em>a contrario</em>, en Java les <strong>standards</strong> évoluent tellement lentement qu&#8217;on leur préfère des <strong>solutions alternatives</strong> à forte obsolescence. On en est là. Avouez que c&#8217;est quand même dommage de faire preuve d&#8217;immaturité à cet âge ! De mon temps (hum) les bonnes idées étaient simplement reprises et transcendées au sein de la &#8220;meilleure&#8221; <strong>communauté</strong> créée.</p>
<p>Mais aujourd&#8217;hui il semblerait que notre industrie soit en <span style="text-decoration: underline;">guerre</span>. jBoss vs Spring, Adobe vs Google, Hudson vs Jenkins&#8230; Faut-il pour autant prêcher la dictature comme remède à l&#8217;anarchie ? Nous ne voulons pas devenir .Net, si ? Bref, j&#8217;exagère (à peine).</p>
<h2>Pourquoi le monde Java en est-il arrivé là ?</h2>
<p>Selon moi, c&#8217;est à cause de son succès, justement. Le niveau d&#8217;activité de la communauté me semble tout à fait remarquable, notamment dans l&#8217;Open Source, mais pas que. Le revers de la médaille, c&#8217;est qu&#8217;un si grand nombre d&#8217;intervenants implique le ralentissement des prises de décision, favorisant ainsi l&#8217;adoption de solutions spécifiques ou inachevées.</p>
<p>Avant, c&#8217;était mieux (n&#8217;est-ce pas ?). Un serveur d&#8217;application Tomcat et quelques <em>spin-off</em>, un peu d&#8217;injection et de bonnes pratiques ORM et c&#8217;est parti pour le <em>framework</em> léger. Un IDE sympa, avec quelques <em>plugins</em> utiles. En plus, tout ça gratos ! Et l’enthousiasme du fait main se répandait dans les entreprises à la faveur des SCM. Ajoutez à cela les annotations, et l&#8217;on a pu croire un temps que nous serions productifs.</p>
<p>Bon&#8230; ça n&#8217;a pas vraiment suffit. N&#8217;est-ce pas ? Alors il y a eu Maven, l&#8217;intégration continue et même l&#8217;agilité. Et BOUM ; peut-être que ça marche <em>trop bien</em>, finalement : tout le monde s&#8217;est mis à parler/publier en même temps, la tête dans le guidon. Une vraie course à la nouvelle version.</p>
<h2>Mais alors qu&#8217;est-ce qu&#8217;on va FAIRE (Mon Dieu) ?</h2>
<p>Nous avons une responsabilité, en tant que communauté et en tant que professionnels. Cette responsabilité est de suivre un cap réfléchi pour assurer à nos utilisateurs et à nos clients une certaine forme de pérennité. Je ne parle pas de 10 ou 15 ans, bien sûr. En technologies de l&#8217;information et de la communication (comme on dit), c&#8217;est l&#8217;éternité ! Et c&#8217;est enfoncer une porte ouverte que de proposer un socle commun stable. Nous SAVONS ce qu&#8217;il nous faut. La question est COMMENT l&#8217;obtenir.</p>
<p>Et bien je pense personnellement que la <strong>République des Experts</strong>, c&#8217;est fini. Il nous faut une <strong>Démocratie Participative</strong> (notez les majuscules, je vous prie). Nous vivons actuellement une période transitoire qui pourrait très bien aboutir à un verrouillage par quelques grands acteurs (parmi Adobe, Google, jBoss ou d&#8217;autres), au détriment de la créativité et de la réactivité. Pour éviter cela, je pense que les développeurs devraient pouvoir influer sur les orientations du marché pas seulement par plébiscite, <em>a posteriori</em>, mais aussi en amont sur la base d&#8217;une information éclairante.</p>
<p><em>The Apache Software Foundation</em> nous a montré la <a href="http://www.apache.org/foundation/how-it-works.html" target="_blank">voie</a> (par le truchement de l&#8217;incubation et d&#8217;un processus électif). Mais la méritocratie (qui a dit bureaucratie ?) n&#8217;est pas suffisante. Avez-vous compté le nombre de projets que la fondation héberge, récemment ? Là aussi, le débordement fait plus que nous guetter : il nous attend au tournant. Certaines idées méritent plus qu&#8217;un avis technique, il leur faut un coup de pouce (comme dans l&#8217;expression &#8220;Je poussoies&#8221;, bien sûr) afin de leur assurer l&#8217;effort requis. Et chacun, comme pour une primaire politique, devrait pouvoir donner sa voix sur la teneur des projets à privilégier.</p>
<p>Nous n&#8217;avons pas besoin d&#8217;une dizaine de bases NoSQL ; nous avons besoin d&#8217;une (aller, deux) solutions qui fonctionnent et garantissent une réponse à une problématique réelle (mais je garde pour moi mon opinion, concernant cet exemple précis). Les outils existent, je regarde vers GitHub (en tant que plateforme collaborative, peu importe que le support soit Git ou SVN, au fond). Nous savons fédérer la <strong>motivation</strong> ; mais il nous reste à exprimer l&#8217;<strong>intérêt</strong> plus tôt au cours du processus de développement afin d&#8217;éviter le gâchis actuel qui consiste à jeter nos forces dans des projets concurrents, parfois complètement équivalents, mais dont personne ne veut abandonner la paternité.</p>
<p>Un processus démocratique, ouvert, devrait permettre aux solutions d&#8217;avenir de recevoir suffisamment de moyens pour percer, prendre le temps de se stabiliser, et enfin s&#8217;imposer. Non pas sur <span style="text-decoration: underline;">une mode</span> qui aurait duré, mais sur la qualité d&#8217;une réalisation ayant reçu toute l&#8217;attention nécessaire.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/CEfqQseQXXc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/05/14/java-est-il-trop-serre/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/05/14/java-est-il-trop-serre/</feedburner:origLink></item>
		<item>
		<title>Ippevent Cassandra le 23 mai prochain</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/4Z6gs5pBDLI/</link>
		<comments>http://blog.ippon.fr/2012/05/11/ippevent-cassandra-le-23-mai-prochain/#comments</comments>
		<pubDate>Fri, 11 May 2012 13:37:07 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5665</guid>
		<description><![CDATA[<p></p> <p>Au royaume du NoSQL, Apache Cassandra tient une place de choix</p> <p>Apache Cassandra est une base de donnée distribuée conçue pour géer de larges volumes de données sur des grappes de serveurs d&#8217;entrée de gamme. Son architecture complètement distribuée lui permet de jouir d&#8217;une scalabilité horizontale linéaire et d&#8217;une forte tolérance aux pannes (&#8216;high <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/05/11/ippevent-cassandra-le-23-mai-prochain/">Ippevent Cassandra le 23 mai prochain</a></span>]]></description>
			<content:encoded><![CDATA[<p><img style="float: left;" src="http://socialtimes.com/files/2010/03/cassandra.jpg" alt="cassandra logo" width="100" height="95" /></p>
<p>Au royaume du NoSQL, Apache Cassandra tient une place de choix</p>
<p>Apache Cassandra est une base de donnée distribuée conçue pour géer de larges volumes de données sur des grappes de serveurs d&#8217;entrée de gamme. Son architecture complètement distribuée lui permet de jouir d&#8217;une scalabilité horizontale linéaire et d&#8217;une forte tolérance aux pannes (&#8216;high availability&#8217;).</p>
<p>Lors de cet Ippevent, deux intervanant viendront nous parler de cet outil génial.</p>
<p>Tout d&#8217;abord Nicolas Romanetti de Jaxio qui nous fera un retour d&#8217;expérience sur ses mises en oeuvre de Cassandra, puis Sylvain Lebresne de Datastax éditeur spécialisé sur Cassandra viendra nous parler de l&#8217;architecture et des évolutions futures de la solution</p>
<p>Pour vous inscrire il vous suffit de cliquer sur le bouton ci-dessous</p>
<div style="width: 100%; text-align: left;"><iframe frameborder="0" height="192" marginheight="5" marginwidth="5" scrolling="auto" src="http://www.eventbrite.fr/tickets-external?eid=3532442631&amp;ref=etckt" width="100%"></iframe></p>
<div style="font-family: Helvetica, Arial; font-size: 10px; padding: 5px 0 5px; margin: 2px; width: 100%; text-align: left;"><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.fr/r/etckt" target="_blank">Billeterie en ligne</a><span style="color: #ddd;"> pour </span><a style="color: #ddd; text-decoration: none;" href="http://http://ippeventcassandra.eventbrite.fr?ref=etckt" target="_blank">Ippevent Cassandra</a> <span style="color: #ddd;">géré par</span> <a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.fr?ref=etckt" target="_blank">Eventbrite</a></div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/4Z6gs5pBDLI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/05/11/ippevent-cassandra-le-23-mai-prochain/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/05/11/ippevent-cassandra-le-23-mai-prochain/</feedburner:origLink></item>
		<item>
		<title>Participez à une formation JSF2/PrimeFaces avec Çağatay Çivici, le fondateur de PrimeFaces !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/SWeSsuSVBew/</link>
		<comments>http://blog.ippon.fr/2012/05/09/participez-a-une-formation-jsf2primefaces-avec-cagatay-civici-le-fondateur-de-primefaces/#comments</comments>
		<pubDate>Wed, 09 May 2012 07:30:39 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Formation]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[PrimeFaces]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5658</guid>
		<description><![CDATA[<p>Dans le cadre de son partenariat avec PrimeFaces , Ippon Technologies organise les 20, 21 et 22 juin une formation exceptionnelle dans ses locaux, avec Çağatay Çivici !</p> <p>Çağatay est membre de l’expert group JSF, fondateur et développeur principal de PrimeFaces, et membre du comité de management d’Apache MyFaces. Il a animé de nombreuses conférences <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/05/09/participez-a-une-formation-jsf2primefaces-avec-cagatay-civici-le-fondateur-de-primefaces/">Participez à une formation JSF2/PrimeFaces avec Çağatay Çivici, le fondateur de PrimeFaces !</a></span>]]></description>
			<content:encoded><![CDATA[<p>Dans le cadre de son partenariat avec <a href="http://www.primefaces.org/" target="_blank">PrimeFaces</a> , Ippon Technologies organise les 20, 21 et 22 juin une formation exceptionnelle dans ses locaux, avec Çağatay Çivici !</p>
<p>Çağatay est membre de l’expert group JSF, fondateur et développeur principal de PrimeFaces, et membre du comité de management d’Apache MyFaces. Il a animé de nombreuses conférences à travers le monde, en particulier Jax, W-Jax, SpringOne, Jazoon, JSFDays, JSFSummit, ainsi que de nombreux JUGs. Il est également auteur et relecteur technique de plusieurs livres traitants du développement d’applications Web avec Java et JSF. En tant que formateur, Çağatay a formé plus de 300 développeurs sur les technologies Java EE, et tout particulièrement JSF.</p>
<p>Le descriptif détaillé de la formation est disponible sur le site d’Ippon Technologies : <a href="http://www.ippon.fr/formation/primefaces" target="_blank">http://www.ippon.fr/formation/primefaces</a></p>
<p>Concernant les détails pratiques :</p>
<ul>
<li>Le lieu : la formation aura lieu dans <a href="http://www.ippon.fr/paris" target="_blank">les locaux d’Ippon Technologies à Levallois-Perret</a>. Nous sommes équipés de iMacs dernière génération, mais vous pouvez venir également avec votre propre matériel (<a href="http://en.wikipedia.org/wiki/Bring_your_own_device" target="_blank">BYOD</a>).</li>
<li>Le prix : 1650 Euros HT pour les 3 jours, incluant les repas de midi</li>
</ul>
<p>Pour vous inscrire à cette formation, ou pour obtenir de plus amples informations, n’hésitez pas à nous envoyer un e-mail à <a href="mailto:formation@ippon.fr">formation@ippon.fr</a> ou à nous téléphoner au + 33 (0)1 46 12 48 48 .</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/SWeSsuSVBew" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/05/09/participez-a-une-formation-jsf2primefaces-avec-cagatay-civici-le-fondateur-de-primefaces/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/05/09/participez-a-une-formation-jsf2primefaces-avec-cagatay-civici-le-fondateur-de-primefaces/</feedburner:origLink></item>
		<item>
		<title>De Flex à HTML5 (2) ?</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/8naBEDn5aP8/</link>
		<comments>http://blog.ippon.fr/2012/05/04/de-flex-a-html5-2/#comments</comments>
		<pubDate>Fri, 04 May 2012 08:00:18 +0000</pubDate>
		<dc:creator>Thomas ESCOLAN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[RIA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5334</guid>
		<description><![CDATA[<p>Maintenant que nous connaissons un peu l&#8217;historique de HTML5 et de Flex (voir l&#8217;article précédent, publié hier), intéressons-nous à leur productivité. La productivité, c&#8217;est la capacité pour un ou plusieurs développeurs de produire un logiciel utilisable dans un temps donné. La productivité peut s&#8217;appuyer sur différents aspects du développement : d&#8217;abord l&#8217;environnement de programmation lui-même, mais <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/05/04/de-flex-a-html5-2/">De Flex à HTML5 (2) ?</a></span>]]></description>
			<content:encoded><![CDATA[<p>Maintenant que nous connaissons un peu l&#8217;historique de HTML5 et de Flex (voir l&#8217;article précédent, publié hier), intéressons-nous à leur productivité. La <strong>productivité</strong>, c&#8217;est la capacité pour un ou plusieurs développeurs de produire un logiciel utilisable dans un temps donné. La productivité peut s&#8217;appuyer sur différents aspects du développement : d&#8217;abord l&#8217;environnement de programmation lui-même, mais aussi la structure du langage ainsi que la présence éventuelle de <em>frameworks</em> (SDK) dédiés.</p>
<h1>Les IDEs</h1>
<p>Les éditeurs de code dont vous vous serviez auparavant pour programmer en HTML4 et JavaScript peuvent tout à fait être utilisés pour HTML5, la prise en compte des nouveautés est bien entendu un plus en termes d&#8217;auto-complétion. Il y a pas mal de nouveaux produits, y compris des <em>plugins</em> (Aptana, etc.) permettant de travailler sous Eclipse, pour ceux qui utilisent ce produit par ailleurs. Des éditeurs WYSIWYG sont disponibles (Maquetta, BlueGriffon, Mercury, etc.).</p>
<p>De son côté, nous l&#8217;avons déjà dit, Adobe propose un IDE qui, à ma connaissance, n&#8217;a pas d&#8217;équivalent. Il existe sous deux formes : <em>standalone</em> ou <em>plugin</em> ; les deux solutions s&#8217;appuient sur Eclipse, quoi qu&#8217;il en soit. Cette solution propose la création de projets (Flash, AIR, mobile), le montage WYSIWYG des interfaces, le débogage et prend en charge la compilation avec les SDKs disponibles.</p>
<p>Les aspects purement rédactionnels sont assez difficiles à départager. Mais bien sûr, le WYSIWYG est très important. Or, je ne crois pas qu&#8217;en HTML il soit jamais possible de garantir à 100% la conformité entre les différents navigateurs. Vous devrez effectuer « à la main » les tests de compatibilité à la fois de rendu et de comportement. S&#8217;appuyant sur une machine virtuelle, Flex prends la main.</p>
<h1>Les langages</h1>
<p>HTML5 s&#8217;appuie sur trois langages : <strong>X-HTML 1</strong><strong>.x</strong> qui est le langage de description des documents Web, <strong>JavaScript</strong> qui est un langage objet permettant d&#8217;intervenir sur la structure DOM de ces documents ou d&#8217;intercepter les actions de l&#8217;utilisateur sur son navigateur, et <strong>CSS 3</strong> qui prend en charge l&#8217;apparence éventuellement contextuelle des pages. Actuellement, la partie JavaScript est le plus souvent étendue par la librairie JavaScript <strong>jQuery</strong> qui permet de faire le lien entre les trois langages<sup><a name="sdfootnote1anc" href="#sdfootnote1sym"></a></sup><sup>1</sup> de manière très efficace, tout en prenant en charge une grande partie des disparités entre navigateurs. Par ailleurs, ce module léger peut se voir adjoindre un nombre sans cesse croissant de <em>plugins</em> adressant toutes sortes de particularités, notamment <strong>jQuery UI</strong> et <strong>jQuery Mobile</strong>. Le transfert de données s&#8217;appuie le plus souvent sur le format JSON. Mais les APIs <strong>Node.js</strong> et <strong>Sencha</strong> semblent aussi proposer des choses intéressantes.</p>
<p>Afin de combler le retard de HTML4 et JavaScript sur la question du RIA, HTML5 propose de nouvelles fonctionnalités fort pratiques : history, Drag &amp; Drop, Web Forms, Local &amp; Session Storage, <strong>Ajax</strong> natif amélioré, support des WebSockets<a name="sdfootnote2anc" href="#sdfootnote2sym"></a><sup>2</sup>, extensions media et canvas (SVG), etc.</p>
<p>Flex, quant à lui, s&#8217;appuie sur deux autres langages : <strong>ActionScript</strong> qui est un langage de script orienté objet, et <strong>MXML</strong> qui est un langage de description des IHM, avec la particularité qu&#8217;il est possible qu&#8217;un « script » MXML étende (au sens de l&#8217;héritage objet) une classe AcionScript (afin d&#8217;obtenir une meilleure séparation vue/comportement et une meilleure réutilisation). En fait, MXML est optionnel, étant donné que tout ce qui peut être décrit avec peut l&#8217;être également en ActionScript. Il propose cependant une syntaxe beaucoup plus concise et claire dont vous ne voudrez certainement pas vous passer.</p>
<p>Toujours au rayon du langage, on note d&#8217;autres points importants concernant Flex : notamment le mécanisme de <em>binding</em> (simple ou double sens) qui permet de lier la valeur d&#8217;une variable à son affichage et éventuellement sa saisie. Flex propose également la notion d&#8217;états de pages ; ils peuvent permettre d&#8217;influer sur leur aspect et leur comportement à partir de valeurs symboliques, limitant ainsi au minimum le code nécessaire aux changements cosmétiques dans les traitements métier. Ces concepts sont très puissants et font toute la différence en termes d&#8217;architecture orientée composants.</p>
<p>Flex dispose en plus de cadres de développement (<strong>Cairngorm</strong>, <strong>Parsley</strong>, etc.) ainsi que de façades permettant de transférer les données applicatives entre le serveur et le client (format <strong>AMF<a name="sdfootnote3anc" href="#sdfootnote3sym"></a><sup>3</sup></strong>, <strong>GraniteDS</strong>, <strong>BlazeDS</strong>, etc.). Pour HTML5 et CSS3, les <em>frameworks</em> <strong>Less</strong> (feuilles de style dynamiques et/ou <em>grid</em> <em>layouts</em>), <strong>PhoneGap</strong> (pour encapsuler les applications mobiles &#8211; qui fut un temps entre les mains d&#8217;Adobe, d&#8217;ailleurs, et s&#8217;appelle maintenant <strong>Apache Cordova</strong>), <strong>Gravity</strong> (feuilles de style Sass, CoffeeScript) ou encore <strong>Boilerplate</strong> (qui supporte la technologie Flash !) et <strong>Perkins</strong> commencent à se faire une place sans que l&#8217;on sache vraiment lequel s&#8217;imposerait éventuellement. Je ne peux pas prétendre les avoir testés, tout avis est donc bienvenu. Concernant la partie mobile, il apparaît dores et déjà que le développement <em>hybride</em> a toutefois des limites intrinsèques assez fortes (<a title="PPDC" href="http://fr.wikipedia.org/wiki/Portabilit%C3%A9_(informatique)#Plus_petit_d.C3.A9nominateur_commun">PPDC</a>), sachant par exemple que la norme JavaScript <a href="http://en.wikipedia.org/wiki/Web_worker">WebWorkers</a> n&#8217;est pas supportée par Android.</p>
<h2>Le rendu</h2>
<p>Avec HTML, le rendu est avantageusement assuré par la partie CSS qui est en elle-même une compétence à part. Son usage peut se révéler abscons, et intervenir dans son code sans de solides connaissances réserve parfois de mauvaises surprises. Mais cela permet de séparer en activités séparées la structuration des documents du rendu final. Les développeurs fonctionnels d&#8217;un côté, les infographistes de l&#8217;autre.</p>
<p>Flex propose un modèle d&#8217;affichage plus simple à la base, mais avec la possibilité de l&#8217;étendre&#8230; en CSS ! Mais comme la plupart des options de rendu et des effets sont disponibles depuis MXML, il est plus rapide d&#8217;obtenir un rendu efficace sans faire appel à des notions trop poussées. C&#8217;est-à-dire qu&#8217;avec Flex on aboutit à un produit fini, standardisé, beaucoup plus facilement.</p>
<p>Bien sûr, l&#8217;écosystème HTML5 évolue très rapidement et on s&#8217;appuiera avec profit sur une API comme <strong>Twitter Bootstrap</strong> ; cependant, aucune standardisation ne vous est garantie quant au rendu sur différentes plateformes (épreuves personnelles à l&#8217;appui). [mauvaise-foi ON force="légère"]Par ailleurs, il reste difficile de localiser et d&#8217;évaluer ces nouveaux outils[mauvaise-foi OFF comment="mais quand même..."].</p>
<p>En face, l&#8217;application <strong>TourDeFlex</strong> permet de « visiter » l&#8217;ensemble des composants internes de Flex en situation réelle, c&#8217;est une aide précieuse au <em>design</em> des applications. De nombreuses librairies additionnelles de composants sont disponibles pour Flex (Spark, Hero<a name="sdfootnote4anc" href="#sdfootnote4sym"></a><sup>4</sup>, flexlib, Eskimo, etc.), et Adobe a très vite pris au sérieux la nécessité de proposer rapidement une plateforme de développement pour les mobiles. Après une hésitation quant au choix du mode de distribution pour les mobiles (plugin Flash contre VM AIR), les outils (FlashBuilder 4.5) et les composants dédiés (FlashBuilder 4.6) ont très vite été mis à la disposition du public.</p>
<h2>L&#8217;architecture</h2>
<p>Bref, les deux techniques sont orientées événements mais là où HTML5 propose une séparation nette des compétences de programmation (X-HTML et JavaScript d&#8217;un côté, CSS de l&#8217;autre), Flex s&#8217;appuie essentiellement sur une architecture composants, ce qui à mon avis fait toute la différence&#8230;</p>
<p>HTML5 permet l&#8217;inclusion dynamique de fragments de code HTML. Votre interface peut donc être découpée dans des fichiers différents réutilisables. Seulement les fichiers HTML ne sont pas des classes, ils n&#8217;ont pas d&#8217;état. Par ailleurs, et c&#8217;est un « problème » plus inquiétant, les fragments HTML ne peuvent pas embarquer, à ma connaissance, de comportement qui leur soit propre (c&#8217;est-à-dire de scripts internes) ; un fragment n&#8217;est pas interprété lors de son chargement dans un document, il est simplement injecté dans l&#8217;arborescence DOM. Pour animer la structure d&#8217;un fragment, vous devrez donc charger à part les scripts lui afférant &#8211; éventuellement dans une partie distincte du document parent, ce qui peut poser un problème de maintenance.</p>
<p>Concernant l&#8217;accès aux données, AMF, BlazeDS et GraniteDS fournissent un ensemble de solutions largement exploitées du côté de Flex. Cependant il s&#8217;agit d&#8217;invocations distantes (<em>RemoteObject</em>) et, en ce qui me concerne, je crois que les architectures SOA(P) et notamment le protocole <strong>REST</strong> ont plus d&#8217;avenir. Elles permettent, justement, de s&#8217;affranchir de solutions spécifiques aux technologies RIA elles-mêmes. Sur la technologie REST encore plus que sur les services web, HTML5 et jQuery prennent la main avec une facilité déconcertante, via Ajax et le format <strong>JSON</strong> ; c&#8217;est un fait. Pour Flex, il semblerait que <em>HTTPService</em> ait encore un peu de chemin à faire, en particulier pour supporter l&#8217;ensemble des « verbes » CRUD HTTP s&#8217;appliquant à REST. Mais cela reste exploitable et évolutif (par exemple avec <em>RestHttpService<a name="sdfootnote5anc" href="#sdfootnote5sym"></a><sup>5</sup></em>). Match nul donc, en ce qui me concerne, sur cette question liée aux évolutions du web.</p>
<h1>Comment structurer ses applications ?</h1>
<p>Alors bien sûr, une API comme jQuery, nous l&#8217;avons dit, permet le développement de <em>plugins</em>. C&#8217;est-à-dire qu&#8217;elle laisse aux développeurs la possibilité de l&#8217;étendre. Mais <strong>étendre</strong> une API n&#8217;est pas la même chose que de <strong>modulariser</strong> son code. Premièrement en étendant un produit tiers, vous vous rendez dépendant de ce produit. Et deuxièmement, surtout, vous vous rendez dépendant de la version du produit disponible au moment de vos développements. En imaginant que vous ayez développé un certain nombre de <em>plugins</em> jQuery pour répondre à vos besoins de réutilisation liés au métier de l&#8217;application ; vous n&#8217;aurez peut-être pas la possibilité de bénéficier des avancées de ce <em>framework</em> dans deux ans, lorsque vos besoins fonctionnels auront évolué. Il s&#8217;agit-là d&#8217;un cas typique de création de dette technique.</p>
<p>Les composants, eux, disposent d&#8217;un état (<em>stateful</em>) et sont autonomes<sup><a name="sdfootnote6anc" href="#sdfootnote6sym"></a></sup><sup>6</sup>. Tout en pouvant s&#8217;appuyer sur les APIs disponibles, ils encapsulent à la fois un état et un comportement avec un couplage faible. Figurons-nous qu&#8217;un <em>plugin</em> (une fiche électrique, littéralement) est fait pour correspondre à une « prise électrique » (une interface d&#8217;injection dans l&#8217;hôte), il s&#8217;agit d&#8217;une contrainte imposée au développement, tandis qu&#8217;un composant reste un utilisateur ; c&#8217;est toute la différence qu&#8217;il y a en conception entre l&#8217;<strong>héritage</strong> et la <strong>composition</strong>.</p>
<p>Or, là ou Flex conserve un avantage non négligeable, de ce point de vue, c&#8217;est dans l&#8217;imbrication d&#8217;ActionScript et de MXML. Il est possible de créer des <em>widgets</em> en JavaScript (cf. jQuery UI), mais les éléments doivent être instanciés « à la main », si j&#8217;ose dire. On y perd grandement en lisibilité, et donc en productivité. Par ailleurs, cette technologie est prévue pour faire des composants graphiques, ce qui peut ne pas être adapté à l&#8217;élaboration de composants métier évolutifs.</p>
<h1>Comment tester ses développements ?</h1>
<p>Si les fonctionnalités de débogage de Flash Builder et <strong>FlexUnit</strong> pour les tests unitaires ne vous suffisaient pas, l&#8217;outil <strong>Web Monkey</strong> permet des tests d&#8217;intégration très complets.</p>
<p>Pour HTML5, plusieurs outils « web », non spécifiques, sont disponibles. Par exemple <strong>Selenium</strong>. Mais il s&#8217;agit là de tests d&#8217;intégration. Pour le JavaScript lui-même, les APIs <strong>jsUnit</strong> (apparemment délaissée, mais disposant d&#8217;un <em>plugin</em> pour Eclipse), <strong>RhinoUnit</strong> et <strong>qUnit</strong> peuvent rendre pas mal de services limités à cet aspect technologique. Mais il n’existe pas actuellement de norme aboutie de protocole de débogage distant de page Web (HTML + CSS + JavaScript) ; c&#8217;est un chantier certes actif mais balbutiant. N&#8217;oublions, pas quand même, que les navigateurs permettent l&#8217;inspection des pages, ce qui reste utile mais pas forcément pratique.</p>
<p>Pour moi, l&#8217;avantage va à Flex, cette fois encore, pace que les solutions sont complètes et centralisées. Cet aspect des développements est tout à fait primordial. Aucune application professionnelle ne peut aujourd&#8217;hui se passer d&#8217;un minimum de tests de non-régression. Cette contrainte est chronophage et doit donc bénéficier des outils les plus productifs possibles. Pour cela, ils doivent être intégrés (faciles à manipuler), standardisés (faciles à reprendre par de nouveaux équipiers) et intégrables à un processus d&#8217;intégration continue (pour pouvoir superviser le niveau de qualité du logiciel).</p>
<h1>Flex gagne le match ; quel avenir pour Flex ?</h1>
<p>La force principale de Flex est donc sa préséance (voir première partie). Adobe a beaucoup investi depuis longtemps sur cette technologie et sa communauté est très active. Malgré le poids de ses organismes de standardisation, HTML5 est donc bien le challenger, dans cette histoire. Les développeurs JavaScript et CSS le savent bien, le standard n&#8217;implique pas l&#8217;uniformité en matière de Web. Pour s&#8217;imposer, HTML5 devra pouvoir s&#8217;appuyer soit sur un parfait support de la part des navigateurs du marché ; et nous avons déjà remarqué combien ils sont nombreux. Soit sur un cadre de développement HTML5 proposant une prise en compte exhaustive des différences entre eux. Ceci reste une gageure, soulignons-le, et ce strictement pour les mêmes raisons !</p>
<p>Flex, de son côté, va profiter de cette inertie pour conquérir toujours plus de marchés, et donc consolider sa position de standard <em>de facto</em>. Par ailleurs, l&#8217;implication dans le projet confié à la fondation Apache promise par Adobe permet d&#8217;espérer que Flex pourra continuer à bénéficier d&#8217;orientations solides et d&#8217;une forte cohésion. Ces deux atouts pourraient constamment creuser l&#8217;écart, en termes d&#8217;adoption professionnelle, aussi longtemps qu&#8217;une version complètement supportée (et finalisée) de HTML5 se fera désirer. La plus grande peur de la communauté étant que la division DreamWeaver chez Adobe ne prenne le pas sur celle de Flex&#8230;</p>
<p>Pourquoi <strong>choisir Flex aujourd&#8217;hui</strong>, donc ? Si vous avez déjà du Flex, si vous ne pouvez ou ne voulez pas attendre, ou si vous pensez qu&#8217;HTML5 ne rattrapera jamais (à l&#8217;échelle industrielle) son retard ; vous le ferez. Si, au contraire, vous voulez construire un produit dont le socle technique sera encore vivant dans dix ans, et que vous pourrez toujours faire évoluer, alors&#8230; vous attendrez !</p>
<div id="sdfootnote1">
<p><a name="sdfootnote1sym" href="#sdfootnote1anc"></a>1. jQuery propose d&#8217;accéder au DOM via des sélecteurs CSS (entre autres), pour le modifier ou lui greffer des comportements dynamiques consolidés.</p>
</div>
<div id="sdfootnote2">
<p><a name="sdfootnote2sym" href="#sdfootnote2anc"></a>2. Elles-mêmes très peu/mal supportées par les serveurs, en tout cas pour l&#8217;instant.</p>
</div>
<div id="sdfootnote3">
<p><a name="sdfootnote3sym" href="#sdfootnote3anc"></a>3. Format binaire inspiré de SOAP</p>
</div>
<div id="sdfootnote4">
<p><a name="sdfootnote4sym" href="#sdfootnote4anc"></a>4. Toutes deux intégrées à TourDeFlex</p>
</div>
<div id="sdfootnote5">
<p><a name="sdfootnote5sym" href="#sdfootnote5anc"></a>5. http://code.google.com/p/resthttpservice/</p>
</div>
<div id="sdfootnote6">
<p><a name="sdfootnote6sym" href="#sdfootnote6anc"></a>6. cf. single responsibility principle</p>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/8naBEDn5aP8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/05/04/de-flex-a-html5-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/05/04/de-flex-a-html5-2/</feedburner:origLink></item>
		<item>
		<title>De Flex à HTML5 (1) ?</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/hU7o5l_j-Lc/</link>
		<comments>http://blog.ippon.fr/2012/05/03/de-flex-a-html5-1/#comments</comments>
		<pubDate>Thu, 03 May 2012 08:00:29 +0000</pubDate>
		<dc:creator>Thomas ESCOLAN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5332</guid>
		<description><![CDATA[<p align="JUSTIFY">L&#8217;actualité récente du RIA (Rich Internet Application) a connu des remous (cf. La mort annoncée de Flex ?), et cela n&#8217;est pas probablement pas terminé. Ce marché s&#8217;appuie sur l&#8217;émergence de nouveaux langages et cadres de développements innovants autant que sur celle de nouveaux supports très hétérogènes (smart phones, tablettes, etc.) dont les capacités ne <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/05/03/de-flex-a-html5-1/">De Flex à HTML5 (1) ?</a></span>]]></description>
			<content:encoded><![CDATA[<p align="JUSTIFY">L&#8217;actualité récente du RIA (Rich Internet Application) a connu des remous (cf. La mort annoncée de Flex ?), et cela n&#8217;est pas probablement pas terminé. Ce marché s&#8217;appuie sur l&#8217;émergence de nouveaux langages et cadres de développements innovants autant que sur celle de nouveaux supports très hétérogènes (smart phones, tablettes, etc.) dont les capacités ne cessent de progresser. C&#8217;est tout l&#8217;enjeu des technologies qui proposent de l&#8217;adresser. Aujourd&#8217;hui, même si certaines plateformes ont pris ou prennent le dessus (Flex, SilverLight<a name="sdfootnote1anc" href="#sdfootnote1sym"></a><sup>1</sup>, etc.) d&#8217;autres ont l&#8217;ambition de les remplacer (HTML5, JavaFX).</p>
<h1>Introduction aux RIAs</h1>
<p align="JUSTIFY">D&#8217;abord, définissons rapidement ce qu&#8217;est une RIA. Il s&#8217;agit, comme son nom le laisse présager, d&#8217;une application <em>Web</em>. La particularité étant que son interface et son expérience utilisateur ainsi que ses performances se rapprochent des applications de bureau locales. Pour cela, un certain nombre de fonctionnalités sont attendues, comme le mode <em>off line</em> ou la possibilité de rafraîchir uniquement les parties actives des écrans sans avoir à les recharger à chaque manipulation.</p>
<p align="JUSTIFY">Mais la particularité principale du RIA est de proposer littéralement l&#8217;exécution des applications sur le poste client, au contraire des applications Web « traditionnelles » dont le fonctionnement implique principalement un traitement sur le serveur au travers d&#8217;un dialogue permanent avec lui. Par ailleurs, s&#8217;exécutant localement, l&#8217;application RIA voudra naturellement s&#8217;affranchir de tout navigateur Internet, afin entre autres de pouvoir même redémarrer sans qu&#8217;une connexion ne soit disponible. Une fois le produit installé, il pourra garder une relation forte avec son origine distribuée, lui permettant notamment de se mettre à jour ou d&#8217;accéder à des services partagés, à distance.</p>
<p align="JUSTIFY">Par rapport aux applications <em>Web</em>, les applications RIA ont un paradigme inversé. Dans le premier cas, le serveur reçoit une requête (HTTP ou autre) et construit en réponse une page à afficher, en fonction des paramètres renseignés et des données internes stockées. L&#8217;application RIA est aussi une sorte de page, mais qui va s&#8217;adresser (<em>pull</em>) à un ou plusieurs (pourquoi pas) serveurs pour collecter les informations (le contenu) nécessaires à son affichage qu&#8217;elle va elle-même, par un traitement local, agencer. Certaines technologies peuvent également ouvrir des canaux de communication avec un serveur pour lui permettre de signaler des événements à ses clients (<em>push</em>). Cette architecture s&#8217;appuie idéalement sur une forte orientation dite <em>services</em>, elle promouvra donc la création de multiples clients.</p>
<p align="JUSTIFY">Cette approche implique de nouvelles contraintes, notamment en termes de sécurité. Vous ne voudriez pas que n&#8217;importe quel produit téléchargé sur le <em>Web</em> puisse démarrer à distance et accéder à toutes les ressources de votre ordinateur personnel&#8230; si ? Non !</p>
<p align="JUSTIFY">Les solutions existantes de développement adressent tout ou partie de ces besoins en donnant plus ou moins la priorité à certains d&#8217;entre eux. La problématique principale étant de proposer une IHM (Interface Homme-Machine, GUI en anglais) qui soit la même sur toutes les plateformes d&#8217;exécution. En effet, quoi de plus désagréable que de pouvoir ouvrir sont application favorite depuis n&#8217;importe où&#8230; mais sans pouvoir la reconnaître ? C&#8217;est tout l&#8217;enjeu, au fond, du RIA.</p>
<h1>Qu&#8217;est-ce que HTML5 ?</h1>
<p align="JUSTIFY">À tout seigneur, tout honneur, HTML (pour HyperText Markup Language) est le langage historique du <em>Web</em> (il date de 1989). L&#8217;organisme qui le contrôle est le <strong>W3C</strong>. Il permet la mise en forme et, surtout, la mise en relations de pages au travers du réseau internet. Au départ prévu pour des contenus statiques (textes, images, sons enregistrés à la rigueur), il a rapidement été complété à la fois par des langages de script permettant de modifier le comportement (JavaScript, etc.) et l&#8217;apparence (CSS) des pages une fois chargées sur le poste client ; mais également par de nombreuses technologies destinées à construire dynamiquement les pages depuis leur serveur <em>Web</em> (PHP, JSP, etc.) en se basant sur les paramètres des liens <em>hypertext</em>, ou le contenu des formulaires de saisie, appelés requêtes.</p>
<p align="JUSTIFY">Entre temps, une nouvelle forme de structuration des contenus textuels est apparue. Le XML (pour eXtended Markup Language). À côté HTML faisait figure de patois, tant il était possible d&#8217;omettre de symboles sans heurter la sensibilité des plus anciens navigateurs comme des plus récents. Mais le ver était dans le fruit ; la structuration forte de XML permettant de solides contrôles (DTD, XML Schema) et de nombreux traitements (XSLT, etc.) en chaîne, son adoption n&#8217;a pas tardé. Ainsi est né X-HTML (pour, heu&#8230; je vous laisse deviner) ; c&#8217;était en 2006-2007, à peu près.</p>
<p align="JUSTIFY">Par ailleurs, les nouveaux besoins multimédia suscités par l&#8217;amélioration des performances à la fois des réseaux et des postes clients ont mécaniquement amené la communauté à envisager une évolution du vénérable langage. En effet, le nombre croissant de navigateurs disponibles et, surtout, de variantes possibles dans le développement des sites ont exponentiellement augmenté le risque pour les utilisateurs de se retrouver tôt ou tard confrontés à une incompatibilité quelconque ou, pire, à toutes sortes de failles de sécurité. <strong>Internet AIME les standards</strong>, qu&#8217;on se le dise !</p>
<p align="JUSTIFY">HTML5 est l&#8217;aboutissement de ce cheminement. Souhaitant influer sur les travaux du consortium, les éditeurs de navigateurs Web créèrent le Web Hypertext Application Technology Working Group (WHATWG ; standard ouvert). Ils mirent leur nez dans la spécification de X-HTML et donnèrent l&#8217;impulsion pour une nouvelle refonte, HTML5, destinée à intégrer les nouvelles pratiques de l&#8217;Internet, et en particulier le RIA, au tout début de 2008 (<em>Working Draft</em>). Aujourd&#8217;hui, en 2012, HTML5 est toujours en développement<sup><a name="sdfootnote2anc" href="#sdfootnote2sym"></a></sup><sup>2</sup>.</p>
<h2>Tour (rapide) des frameworks en vogue</h2>
<p lang="en-US" align="JUSTIFY">jQuery, jQuery Mobile, Twitter Bootstrap, Node.js, Lime.js, PhoneGap, Less&#8230;</p>
<h1>Qu&#8217;est-ce que Flex ?</h1>
<p align="JUSTIFY">À l&#8217;origine (1996), la société <strong>Macromedia</strong> a racheté puis développé une technologie capable de mettre en ligne des composants Web animés, un peu comme des dessins animés (les nostalgiques s’en souviendront) qui ont permis de donner un peu de vie aux tristes écrans statiques de l&#8217;ère 1.0 du <em>Web</em>. Outre son dynamisme visuel, Flash incorpore un mécanisme d&#8217;interactivité avec les éléments affichés, leur permettant de réagir aux actions des utilisateurs. Rapidement, nombre d&#8217;artistes et d&#8217;informaticiens (parfois les deux) ont proposé des jeux en ligne. Il suffisait d&#8217;installer dans son navigateur fétiche (il y en avait alors relativement peu de différents) le <em>plugin</em> de Macromedia pour pouvoir afficher, et donc interagir, avec toutes sortes de concepts excitants sans aucune autre installation locale.</p>
<p align="JUSTIFY">Très vite, des agences Web ont proposé à leurs clients de tirer partie à la fois de ces innovations et, surtout, de la fulgurante prolifération du <em>plugin</em> Flash<sup><a name="sdfootnote3anc" href="#sdfootnote3sym"></a></sup><sup>3</sup> sur le parc des ordinateurs connectés. Moins lourde à télécharger qu&#8217;une vidéo, l&#8217;animation Flash s&#8217;est révélée idéale à la diffusion de messages publicitaires ou de films informatifs efficaces. De plus, la possibilité d&#8217;incrustation dans les pages HTML permettent bien des clins d’œil d&#8217;infographistes.</p>
<p align="JUSTIFY">Mais bien vite également, les programmeurs ont eu l&#8217;idée de s&#8217;appuyer sur l&#8217;interactivité avec les éléments, pour développer des interfaces de saisie avec effets graphiques divers et variés. Las, les problèmes ont commencé ! Prévus pour l&#8217;animation, les outils d&#8217;édition de Flash sont basés sur un modèle de <em>timeline</em>, avec la possibilité d&#8217;avances et retours rapides, pas sur un modèle événementiel souple et dont les redirections seraient centralisés (type MVC 2). de nombreuses difficultés (des <em>bugs</em>, quoi) sont apparues aussi bien dans les jeux que dans les interfaces de saisie dont les ambitions ont très vite dues être revues&#8230; à la baisse.</p>
<p align="JUSTIFY">En 2004, Macromedia réagit et crée Flex. Cette plateforme orientée composants propose enfin un cadre événementiel de développement de « modules » Flash (appelés par les initiés des « swiff », comme c&#8217;est charmant). Ouf ! En 2006, <strong>Adobe</strong> (prononcez « Adobi », pour être dans le coup) rachète Macromedia et continue à investir dans Flex en le dotant d&#8217;un environnement complet de développement, en maintenant les librairies de composants, et en encourageant la diffusion de nouveaux composants évolués en permettant notamment leur commercialisation.</p>
<p align="JUSTIFY">Les applications Flex peuvent prendre deux formes : <em>Web</em> ou <em>Desktop</em>. Dans le premier cas, elles sont exécutées au sein du <em>plugin</em> Flash du navigateur utilisé (au sein de son <em>bac à</em> <em>sable</em><sup><a name="sdfootnote4anc" href="#sdfootnote4sym"></a></sup><sup>4</sup>), tandis que dans le second elles sont exécutées dans une machine virtuelle appelée <strong>AIR</strong> qui permet de faire résider les applications distribuées sur le bureau du poste client et d&#8217;accéder à certaines ressources du système.</p>
<h2 align="JUSTIFY">Tour des frameworks en vogue</h2>
<p align="JUSTIFY">Cairngorm, Parsley, Spark components, BlazeDS, GraniteDS&#8230;</p>
<h1><a name="__RefHeading__30814_210933834"></a>La mort annoncée de Flex ?</h1>
<p align="JUSTIFY">Bref, tout cela est bel et beau. Mais pourquoi opposer HTML5 et Flex ?</p>
<p align="JUSTIFY">Fin 2011, Adobe a proposé de remettre le SDK, la spécification, le compilateur Flex ainsi que BlazeDS<sup><a name="sdfootnote5anc" href="#sdfootnote5sym"></a></sup><sup>5</sup> sous licence Open Source (MPL) aux bons soins de la Fondation Apache, tout en gardant le contrôle du Flash Player et de FlashBuilder (l&#8217;IDE dédié à Flex, basé sur Eclipse). La raison invoquée ? À terme, l&#8217;essentiel des efforts d&#8217;Adobe vont se porter sur HTML5 ! Victime de son succès, Flex est devenu trop lourd à porter pour Adobe seul, qui espère qu&#8217;en élargissant sa base de contribution la feuille de route pourra être respectée. Parallèlement Adobe a annoncé travailler sur des outils de migration de Flex vers HTML5&#8230; « A long terme, nous croyons que HTML5 sera la meilleure technologie pour concevoir des applications d&#8217;entreprise »<sup><a name="sdfootnote6anc" href="#sdfootnote6sym"></a></sup><sup>6</sup>, sans compter son activité autour de DreamWeaver.</p>
<p align="JUSTIFY">Dans la foulée, Adobe a mis sur le marché la version 4.5 de Flex, très rapidement suivie de sa version 4.6, qui se concentrent sur les aspects mobile. Il est désormais possible de publier une même application sur plusieurs plateformes mobiles (iOS &amp; Android principalement, mais pas que) simultanément, tout en bénéficiant d&#8217;un environnement <strong>WYSIWYG</strong> complet (smart phone, tablet) et d&#8217;habillages contextuels des composants qui s’adapteront donc à leur hôte. MAIS Adobe abandonne les <em>plugins</em> sur les platesformes mobiles, notamment à l&#8217;issue d&#8217;un refus sans concessions de la part d&#8217;<strong>Apple</strong> de l&#8217;autoriser sur l&#8217;iOS, prédominant. Dorénavant, les applications Flex/Flash sur mobile seront uniquement autonomes sur un socle AIR permettant (si vous avez suivi) de s&#8217;affranchir des navigateurs <em>Web</em>.</p>
<p align="JUSTIFY">Il y a de quoi rester perplexe, n&#8217;est-il pas ? La question se pose donc bien, pour les développeurs Flex, de considérer la possibilité de migrer leur compétences vers HTML5&#8230; à terme, bien sûr ! À condition que l&#8217;ensemble des fonctionnalités de Flex puissent être reproduites entièrement, ce dont même Adobe semble douter, soit dit en passant<sup><a name="sdfootnote7anc" href="#sdfootnote7sym"></a></sup><sup>7</sup>. Voici donc le débat qui est posé. Après cette (longue, mais nécessaire) introduction, nous entrerons dans le vif du sujet pour essayer de définir les caractéristiques de Flex et de HTML5 et tenter de les comparer.</p>
<p align="JUSTIFY">La suite de ce post demain, toujours sur le blog d&#8217;Ippon !</p>
<div id="sdfootnote1">
<p><a name="sdfootnote1sym" href="#sdfootnote1anc"></a>1. Certains le disent déjà mort&#8230; Oh mon Dieu : un zombie !</p>
</div>
<div id="sdfootnote2">
<p><a name="sdfootnote2sym" href="#sdfootnote2anc"></a>2. Pour le détail des changements : http://www.w3.org/TR/html5-diff/</p>
</div>
<div id="sdfootnote3">
<p><a name="sdfootnote3sym" href="#sdfootnote3anc"></a>3. cf. http://www.adobe.com/products/flashplatformruntimes/statistics.html</p>
</div>
<div id="sdfootnote4">
<p><a name="sdfootnote4sym" href="#sdfootnote4anc"></a>4. Ou <em>sandbox</em>, en anglais</p>
</div>
<div id="sdfootnote5">
<p><a name="sdfootnote5sym" href="#sdfootnote5anc"></a>5. Transfert des données entre une application Flex et un serveur Java EE.</p>
</div>
<div id="sdfootnote6">
<p><a name="sdfootnote6sym" href="#sdfootnote6anc"></a>6. cf. http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html</p>
</div>
<div id="sdfootnote7">
<p><a name="sdfootnote7sym" href="#sdfootnote7anc"></a>7. Même référence que ci-dessus (UPDATE – 11/15/11 ; « Will Adobe provide migration tools to enable existing Flex applications to be converted to HTML/JavaScript? »).</p>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/hU7o5l_j-Lc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/05/03/de-flex-a-html5-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/05/03/de-flex-a-html5-1/</feedburner:origLink></item>
		<item>
		<title>Scrum Breakfast : l’Agilité chez Google</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/nPTt_dK5A88/</link>
		<comments>http://blog.ippon.fr/2012/04/25/scrum-breakfast-lagilite-chez-google/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 08:00:07 +0000</pubDate>
		<dc:creator>Anne GABRILLAGUES</dc:creator>
				<category><![CDATA[Agilité]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[Scrum User Group]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5481</guid>
		<description><![CDATA[<p>Google et le French Scrum User Group nous ont accueilli mardi 17 Avril matin dans les locaux de Google Paris pour une matinée consacrée à l&#8217;Agilité, incluant une présentation de la mise en pratique de l&#8217;Agilité chez Google par Petra Cross. L&#8217;événement a fait salle plus que comble, et a été l&#8217;occasion de  présentations faites par des <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/04/25/scrum-breakfast-lagilite-chez-google/">Scrum Breakfast : l&#8217;Agilité chez Google</a></span>]]></description>
			<content:encoded><![CDATA[<p>Google et le French Scrum User Group nous ont accueilli mardi 17 Avril matin dans les locaux de Google Paris pour une matinée consacrée à l&#8217;Agilité, incluant une présentation de la mise en pratique de l&#8217;Agilité chez Google par Petra Cross. L&#8217;événement a fait salle plus que comble, et a été l&#8217;occasion de  présentations faites par des intervenants de Google :</p>
<ul>
<li>&#8220;Human Ressource Management Handbook for Software Development Team&#8221;, par Martin Görner,</li>
<li>&#8220;Behind the Scenes of Day-To-Day Software Development at Google&#8221;, par <a href="http://gmailblog.blogspot.fr/2011/04/faces-of-gmail-petra-cross.html" target="_blank">Petra Cross</a>.</li>
</ul>
<div>La suite du billet est le résultat de ma prise de note, et où j&#8217;ai essayé de retranscrire au mieux l&#8217;ensemble des éléments présentés à cette occasion.</div>
<div></div>
<hr style="width: 500px;" width="500" />
<p><strong>&#8220;Human Ressource Management Handbook for Software Development Team&#8221;, par Martin Görner </strong></p>
<p><img class="alignright" src="http://blog.ippon.fr/wp-content/uploads/2012/04/shutterstock_82563007.jpg" alt="" width="152" height="139" /></p>
<p>Martin a présenté une typologie des membres d&#8217;une équipe de développement basée sur un rapprochement avec les personnae classiques de l&#8217;heroic fantasy (libellés librement traduits de l&#8217;anglais). Or tous les archétypes n&#8217;ont pas leur place dans une équipe qui se veut efficace !</p>
<ul>
<li><em>le Barbare</em> : le développeur / expert technique, doté de compétences de haut niveau</li>
<li><em>le Clerc</em> : le détenteur de la la connaissance, ayant comme mission d&#8217;en assurer la diffusion au sein de l&#8217;équipe</li>
<li><em>le Mage</em> : le solutionneur de problème, détenteur de techniques très puissantes mais secrètes. Or c&#8217;est justement cet aspect &#8220;secret&#8221; qui est gênant au niveau d&#8217;une équipe, a fortiori d&#8217;une équipe de développement. Au final la présence d&#8217;un Mage n&#8217;est pas si souhaitable que cela, surtout si vous pouvez recruter à la place &#8230;</li>
<li><em>le Maître</em> : l&#8217;équivalent du Mage, mais ayant en plus un vrai talent pour le partage de connaissances, ayant à coeur de faire évoluer les autres aventuriers du groupe</li>
<li><em>l&#8217;Amazone</em> : l&#8217;incontournable élément féminin d&#8217;une équipe performante, dotée de réelles aptitudes faisant d&#8217;elle l&#8217;égal des autres aventuriers. Martin a insisté sur l&#8217;importance d&#8217;une certaine mixité dans les équipes de développement, ce qui d&#8217;après son expérience en augmente l&#8217;efficacité.</li>
<li><em>la Bête issue de la 27ème dimension</em> : le membre de l&#8217;équipe adepte (fanatique ?) des dernières nouveautés, qui vous proposera / imposera une solution technique combinant tout ce qui se fait / s&#8217;est fait / se fera &#8220;de mieux&#8221;, en gros un empilement de technologies et langages disparates. Au final votre aventure risque bien de se transformer en combat sans fin contre un monstre tentaculaire suite aux agissements de ce compagnon. Autant éviter de partir à l&#8217;aventure avec lui, cela risque fort de mal se terminer.</li>
<li><em>l&#8217;Eclaireur</em> : celui qui apporte l&#8217;espoir au reste de l&#8217;équipe, le vrai &#8220;team player&#8221;</li>
<li><em>le Chevaucheur de Dragon / Chevalier Dragon (&#8220;Dragon Rider&#8221;)</em> : le seul membre de l&#8217;équipe apte à dompter le dragon, la personne disposant des compétences métiers nécessaires à un projet portant sur un contexte métier très spécifique (par exemple : projet fortement lié à l&#8217;industrie nucléaire).</li>
</ul>
<div></div>
<div>
<hr style="width: 500px;" width="500" />
</div>
<p><strong>&#8220;Behind the Scenes of Day-To-Day Software Development at Google&#8221;, par Petra Cross</strong></p>
<p>Après une rapide présentation de son parcours et de ses centres d&#8217;intérêts, Petra a introduit sa conférence en présentant / rappelant la devise de Google, par rapport à laquelle tout est évalué :</p>
<p style="text-align: center;"><em>&#8220;Google’s mission is to organize the world’s information and make it universally accessible and useful.&#8221;</em></p>
<p>Petra a ensuite fait un point sur les gaspillages monumentaux commis par l&#8217;industrie informatique aux Etats-Unis, illustrés par des chiffres qui mettent en avant l&#8217;ampleur des dégâts : 70 milliards de dollars &#8220;investis&#8221; chaque année sur des projets qui seront abandonnés en cours de route, chiffre ne tenant pas compte des projets qui une fois mis en production se révéleront être des échecs. Les causes en sont multiples et sont globalement liés à un problème général de gestion des projets : vision déconnectée des besoins des utilisateurs, cycle projet très / trop long, etc.</p>
<p><em><strong>Equipes et rôles</strong></em></p>
<p>La taille et l&#8217;organisation de Google sont des paramètres à prendre en compte impérativement pour comprendre les contraintes et enjeux :</p>
<ul>
<li>plus de 10 000 développeurs répartis sur plus de 40 pays</li>
<li>50% du code existant change tous les mois</li>
<li>plus de 20 modifications sont décomptées par minute</li>
</ul>
<p>Petra a présenté rapidement les rôles identifiés dans les équipes Google :</p>
<ul>
<li>Engineering Director : en charge de la traduction des besoins business en exigences techniques</li>
<li>Product Manager : détenteur de la vision produit et en charge de la définition des exigences produit</li>
<li>Engineering Manager / Project Manager : responsable du projet, alloue les ressources et élimine les points de blocage non techniques</li>
<li>Software Engineer / Tech Leader : responsable de la partie technique du projet, priorise les fonctionnalités en accord avec le &#8220;product manager&#8221; et élimine les points de blocage techniques</li>
<li>Software Developper : développe les produits, crée et gère les tests unitaires</li>
<li>Software Engineer in test : définit les stratégies de test</li>
<li>Software Tester : crée et gère les tests</li>
</ul>
<p>Equipes :</p>
<ul>
<li>hiérarchie plate, typiquement 2 ou 3 niveaux maximum</li>
<li>taille réduite, de 3 à 5 personnes (&#8220;size of a family&#8221;), incluant des personnes jouant des rôles différents</li>
<li>espace de travail ouvert, du type &#8220;open space&#8221; finalement assez classique en France (par opposition aux traditionnels cubicles et autres bureaux fermés), permettant à toute personne de l&#8217;équipe de voir les autres membres.</li>
</ul>
<p><em><strong>Processus général de développement</strong></em></p>
<p>Les fonctionnalités sont gérées via une file d&#8217;attente  :</p>
<p><img src="http://blog.ippon.fr/wp-content/uploads/2012/04/Capture-d’écran-2012-04-18-à-17.46.02.png" alt="" width="822" height="91" /></p>
<p>Petra a très rapidement présenté les différentes étapes, en indiquant notamment que :</p>
<ul>
<li>chaque développeur est responsable de la bonne exécution des tests sur le code produit. Cette responsabilité est aussi bien morale (cela fait partie des bonnes pratiques et du cadre méthodologique que tout développeur s&#8217;est engagé à respecter) que technique (le code doit être revu par deux autres personnes avant de pouvoir être versé dans le référentiel de livraison).</li>
<li>les livraisons sont gérées par une équipe dédiée de &#8220;release engineers&#8221;, qui sélectionnent les changements à livrer, génèrent une version &#8220;snapshot&#8221; et la livrent en mode &#8220;beta live / canary&#8221; auprès d&#8217;une petite partie des utilisateurs (environ 2% de la population totale)</li>
</ul>
<p>Le but des équipes Google est triple :</p>
<ul>
<li>développer rapidement</li>
<li>développer uniquement ce qui est nécessaire</li>
<li>réduire voire éliminer les gaspillages</li>
</ul>
<p>Petra présente ensuite rapidement les différentes familles de méthodologies projet :</p>
<ul>
<li>Cycle en V / &#8220;waterfall&#8221; (que l&#8217;on ne présente plus),</li>
<li>le modèle en spirale, caractérisé par des itérations longues (plus de 6 mois), basées sur le prototypage et qui conduisent donc à la production de multiples prototypes,</li>
<li>l&#8217;approche Agile, et plus particulièrement Lean. Au quotidien les équipes Google utilisent une combinaison de pratiques issues de XP, Scrum et Kanban et appliquent au maximum les principes exposés via la liste &#8220;<a href="http://www.google.com/about/company/philosophy/" target="_blank">Ten things we know to be true</a>&#8220;.</li>
</ul>
<div>
<p>Les tâches de développement doivent impérativement inclure la description des tests d&#8217;acceptation correspondant. Une tâche est réputée terminée à partir du moment où les tests d&#8217;acceptation passent avec succès. Le but étant de fournir le minimum d&#8217;effort pour être conforme aux critères d&#8217;acceptation, les Product Managers apprennent rapidement à être très précis dans la formulation de leurs demandes.</p>
<div>
<p><strong><em><br />
Gestion des tâches</em></strong></p>
</div>
<div>Les fonctionnalités et tâches sont réparties en 4 sous groupes, qui correspondent globalement aux principaux états de traitement :</div>
</div>
<div>
<ul>
<li>&#8220;icebox&#8221; : nouvelles idées et demandes d&#8217;évolution non qualifiées, en attente de prise en charge. Toutes ne seront pas forcément traitées, c&#8217;est une sorte de &#8220;boîte à idées&#8221;.</li>
<li>&#8220;backlog&#8221; : la seule liste utilisée par les équipes pour alimenter le flux de travaux, contenant environ 2 semaines de travail pour les équipes</li>
<li>&#8220;current / working on&#8221; : tâches en cours</li>
<li>&#8220;done and verified&#8221; : tâches terminées, fonctionnalités prêtes à être livrées.</li>
</ul>
<div>Le backlog est généralement géré via fichier de type tableur (Google spreadsheet) comportant 2 onglets :</div>
<div>
<ul>
<li>un onglet listant les user stories : géré uniquement par les Product Managers</li>
<li>un onglet listant les tâches : sous la responsabilité de l&#8217;équipe de développement</li>
</ul>
</div>
<div>Les tâches en cours sont gérées plus finement via un tableau comportant plusieurs couloirs (&#8220;swimlanes&#8221;), par exemple :</div>
<div>
<ul>
<li>tâches prévues (&#8220;scheduled&#8221;)</li>
<li>tâches en développement (&#8220;working on&#8221;)</li>
<li>tâches en revue (&#8220;in review&#8221;)</li>
<li>etc.</li>
</ul>
<div>
<p>Le tableau utilisé n&#8217;est donc pas un tableau Scrum, et comporte autant de couloirs que nécessaires pour donner un maximum de visibilité sur les travaux en cours sur l&#8217;itération. Les personnes en charge des tâches sont identifiés par des stickers portant leur photo, collés sur les post-it du tableau.</p>
<div>
<p><strong><em><br />
Planning et réunions</em></strong></p>
</div>
<div>Exemple de planning hebdomadaire :</div>
</div>
</div>
</div>
<div>
<ul>
<li>Lundi : stand up meeting</li>
<li>Mardi : stand up meeting</li>
<li>Mercredi : démo + rétrospective + planning</li>
<li>Jeudi : stand up meeting</li>
<li>Vendredi : stand up meeting</li>
</ul>
</div>
<div>La rétrospective est courte : de 15 mn environ pour une rétro hebdo à 1h pour une rétro mensuelle.</div>
<div>La rétrospective et la réunion de planification se déroulent sans participation du Product Manager : la rétrospective est centrée sur le fonctionnement de l&#8217;équipe, et la réunion de planification se fait sur la base du découpage des fonctionnalités en tâches réalisé en amont par le Tech Lead et le Product Manager.</div>
<div>
<p>Dans certaines équipes le stand up meeting a été supprimé car jugé inutile / inefficace : toutes les informations nécessaires sont affichées à la vue de tous sur les  tableaux de suivi des projets et les gens sont plus qu&#8217;encouragés à discuter en face à face pour tout complément d&#8217;information.</p>
<div>
<p><strong><em><br />
Estimations</em></strong></p>
</div>
<div>La réunion d&#8217;estimation est conduite selon les principes suivants :</div>
</div>
<div>
<ul>
<li>Les estimations doivent représenter la taille des tâches, et surtout pas le temps de travail correspondant.</li>
<li>le facilitateur traite les items du backlog selon leur priorité</li>
<li>il en lit la description à l&#8217;équipe</li>
<li>il fait un décompte et au signal les membres de l&#8217;équipe montrent à tous la carte représentant leur estimation (principe du planning poker)</li>
<li>si la majorité n&#8217;est pas atteinte le facilitateur demande aux personnes ayant fournis les estimations inférieure et supérieur d&#8217;expliquer leur choix en indiquant précisément les travaux à réaliser pour traiter la tâche en question. Afin d&#8217;être efficaces ces échanges ne doivent comporter ni discussion multi-directionnelle ni émotion. Une fois les arguments exposés le facilitateur organise une nouvelle estimation et recommence tant que la majorité n&#8217;est pas atteinte.</li>
<li>les membres de l&#8217;équipe ne doivent jamais utiliser des phrases du type &#8220;c&#8217;est facile&#8221; : ils doivent impérativement expliquer leur évaluation en utilisant une phrase du type &#8220;pour faire X il faut faire a, b, c &#8230;&#8221;</li>
<li>si la description d&#8217;une tâche n&#8217;est pas suffisamment claire, il faut la réécrire afin qu&#8217;il ne subsiste aucune ambiguïté, tant au niveau de la tâche que des exigences associées.</li>
</ul>
<p>Une réunion d&#8217;estimation efficace n&#8217;a pas forcément besoin d&#8217;être faite avec tous les membres de l&#8217;équipe : une réunion de 4 personnes est en général suffisamment satisfaisante.</p>
<p>Concernant le découpage des tâches fait en amont, il n&#8217;est pas toujours fait par le Tech Lead : il peut aussi être pris en charge par un des développeurs, avec rotation au sein de l&#8217;équipe.</p>
<div>
<p><strong><em><br />
Réalisation des travaux</em></strong></p>
</div>
<div>Les développeurs prennent les tâches en charge selon leur ordre de priorité. Quand un développeur est bloqué, il sélectionne la tâche à traiter ayant la priorité la plus élevée dans la backlog. Le but est d&#8217;éviter la spécialisation : une tâche est prise par un développeur même s&#8217;il ne sait pas exactement comment la traiter. Dans ce cas là il trouvera les informations nécessaires en discutant avec les autres membres de l&#8217;équipe.</div>
</div>
<div></div>
<div>
<p>Il n&#8217;y a pas d&#8217;équipe dédiée de type QA : les tests et les revues sont placés sous la responsabilité des développeurs, à charge pour eux d&#8217;intégrer ces travaux dans le flux de traitement des tâches. Petra cite par exemple le cas de tâches restées bloquées en attente de revue lors d&#8217;une itération. Lors de la revue suivante l&#8217;équipe a acté que la revue des développement devait avoir la priorité absolue et qu&#8217;elle devait être traitée dès que possible (par ex au retour de la pause déjeuner dans le cas d&#8217;une tâche passant au statut &#8220;en attente de revue&#8221; au cours de la matinée). Une revue est donc prioritaire par rapport au fait de terminer un développement en cours et un développeur bloqué ne doit pas hésiter à relancer les personnes en charge de la revue, quitte à ce que la revue soit réaffectée à une personne disponible si besoin.</p>
</div>
<div></div>
<div>
<div style="text-align: center;"><em>&#8220;Unblocking your peers is the best thing you can do for your team&#8221;</em></div>
<div></div>
<div>
<p>Une itération a généralement une durée de 2 semaines, et est alimentée par une backlog comportant environ 3 semaines de travaux afin de toujours avoir une liste de tâches à traiter, même en cas d&#8217;évaluations trop pessimistes.</p>
</div>
<div></div>
<div>
<p>Le Product Manager ne participe pas aux standup meetings ni à la réunion de planification, mais reste disponible au quotidien pour échanger avec les équipes, que ce soit pour des demandes de précisions ou pour évaluer les propositions faites spontanément par les développeurs.</p>
</div>
<div></div>
<div>
<div>
<p><strong><em>Rétrospective</em></strong></p>
</div>
<div>Comme indiqué précédemment, la rétrospective est courte et centrée sur l&#8217;équipe. En ce qui concerne son déroulement, les éléments présentés par Petra sont classiques. Elle a par exemple mentionné le fait de noter sur 3 post it différents les éléments à partager avec le reste de l&#8217;équipe (&#8220;mad/sad/glad&#8221;).</div>
<div></div>
<div>
<p>L&#8217;absence du Product Manager a par contre soulevé un certain nombre de questions dans l&#8217;assistance, notamment en ce qui concerne le feedback utilisateurs. Petra a indiqué que les échanges avec les utilisateurs sont gérés par une équipe spécialisée (&#8220;Consumer Operations&#8221;) et que ces informations sont remontées aux équipes par d&#8217;autres canaux.</p>
</div>
<div>
<div></div>
<div>
<p><strong><em>Ce que j&#8217;ai retenu de cette présentation</em></strong></p>
</div>
<div>
<ul>
<li>L&#8217;approche Google est plus centrée sur Lean que sur Scrum, mais reste très pragmatique : les équipes ont toute latitude pour piocher dans la boite à outils agile afin de trouver le mode de fonctionnement le plus efficace possible</li>
<li>Les réunions sont identifiées comme ayant un fort potentiel de gaspillage : elles sont donc réduites au minimum</li>
<li>La présence de l&#8217;équipe complète n&#8217;est pas nécessaire pour la phase d&#8217;estimation : 4 personnes suffisent</li>
<li>Une équipe ne traite pas l&#8217;ensemble d&#8217;un projet mais juste une macro-fonctionnalité (par exemple la gestion des dossiers sous GMail). Elles sont donc loin d&#8217;être stables dans le temps.</li>
<li>Le pair programming n&#8217;est globalement pas mis en place car cette pratique est généralement mal perçue par les équipes. Google favorise à la place la revue par les pairs, ce qui fonctionne a priori bien grâce au niveau technique élevé des développeurs.</li>
<li>Les fameux 20% de temps alloué aux employés Google pour travailler sur tout sujet de leur choix (un minimum lié à l&#8217;entreprise) ne sont pas une légende urbaine : Petra a justement présenté cette session dans ce cadre.</li>
</ul>
<div>
<div></div>
<div>
<p><strong><em>Ce que j&#8217;aurais aimé savoir à l&#8217;issu de cette présentation</em></strong></p>
</div>
<div>
<ul>
<li>comment est-ce que le Product Manager communique la vision du produit à l&#8217;équipe ?</li>
<li>jusqu&#8217;à quel niveau l&#8217;équipe s&#8217;engage t&#8217;elle ? A priori il n&#8217;y a pas d&#8217;engagement de réalisation sur l&#8217;itération &#8230;</li>
<li>comment est-ce que le retour des utilisateurs est communiqué / exploité par les équipes ?</li>
<li>comment est-ce que la &#8220;ice box&#8221; est gérée ? Est-ce que les éléments très anciens sont purgés ? Comment se passe la sélection et le transfert des éléments de la &#8220;ice box&#8221; vers la backlog ?</li>
</ul>
</div>
<div></div>
</div>
</div>
</div>
<div></div>
</div>
<hr style="width: 500px;" width="500" />
<div></div>
<div></div>
<div>Malheureusement les supports de ces présentations ne sont pas disponibles en ligne et je n&#8217;ai pas réussi à prendre de photo correcte. Cependant Pierre Merlin a filmé la session et devrait bientôt publier la video correspondante. La présentation de Petra sera de plus a priori filmée dans le cadre de Devoxx puis diffusée ultérieurement. Une <a href="http://www.youtube.com/watch?v=3DfZi3ooyfE" target="_blank">vidéo d&#8217;une précédente version de cette présentation</a>, faite en 2011 en Tchécoslovaquie est disponible en ligne. <a href="http://www.meetup.com/frenchsug/photos/7525862/#111373312">Quelques photos</a> prises pendant la présentation ont été publiées sur le site MeetUp du SUG.</div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/nPTt_dK5A88" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/04/25/scrum-breakfast-lagilite-chez-google/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/04/25/scrum-breakfast-lagilite-chez-google/</feedburner:origLink></item>
		<item>
		<title>Les présentations Ippon à Devoxx France 2012 sont disponibles</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/iCCxy2ZGfxA/</link>
		<comments>http://blog.ippon.fr/2012/04/23/les-presentations-ippon-a-devoxx-france-2012-sont-disponibles/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 13:24:43 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring MVC]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5623</guid>
		<description><![CDATA[<p>Les consultants Ippon Technologies ont animées 3 sessions à Devoxx France, dont un atelier pratique et 2 conférences. Les présentations de ces deux conférences sont disponibles dès maintenant sur notre compte slideshare :</p> CDI par la pratique (slides), qui était une &#8220;université&#8221; de 3 heures, présentée par Antoine Sabot-Durand (Ippon Technologies) et Mathieu Ancelin (Serli), <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/04/23/les-presentations-ippon-a-devoxx-france-2012-sont-disponibles/">Les présentations Ippon à Devoxx France 2012 sont disponibles</a></span>]]></description>
			<content:encoded><![CDATA[<p>Les consultants Ippon Technologies ont animées 3 sessions à Devoxx France, dont un atelier pratique et 2 conférences. Les présentations de ces deux conférences sont disponibles dès maintenant sur <a href="http://www.slideshare.net/ippontech/" target="_blank">notre compte slideshare</a> :</p>
<ul>
<li><a href="http://www.devoxx.fr/display/FR12/CDI+mis+en+pratique+avec+travers+Seam+Social+et+Weld+OSGI" target="_blank">CDI par la pratique</a> (<a href="http://www.slideshare.net/ippontech/cdi-par-la-pratique-12652483" target="_blank">slides</a>), qui était une &#8220;université&#8221; de 3 heures, présentée par Antoine Sabot-Durand (Ippon Technologies) et Mathieu Ancelin (Serli), et qui proposait une exploration pratique des fonctionnalités de CDI à travers le module Seam Social (solution d&#8217;interconnexion aux réseaux sociaux) et Weld OSGi (solution de modularization pour CDI).</li>
<li><a href="http://www.devoxx.fr/display/FR12/Nouveau+look+pour+une+nouvelle+vie++Spring%2C+JQuery+et+HTML5" target="_blank">&#8220;Nouveau look pour une nouvelle vie&#8221;</a> (<a href="http://www.slideshare.net/ippontech/nouveau-look-pour-une-nouvelle-vie-html5-spring-nosql-et-mobile" target="_blank">slides</a>), une conférence d&#8217;1 heure animée par Julien Dubois, et qui proposait d&#8217;étudier la réalisation d&#8217;une application Web moderne, basée sur HTML5, Spring et NoSQL (Cassandra), et proposant une interface Web mobile.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/iCCxy2ZGfxA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/04/23/les-presentations-ippon-a-devoxx-france-2012-sont-disponibles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/04/23/les-presentations-ippon-a-devoxx-france-2012-sont-disponibles/</feedburner:origLink></item>
		<item>
		<title>Le DDD à Devoxx France 2012</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/R2AaxyrOBFE/</link>
		<comments>http://blog.ippon.fr/2012/04/22/le-ddd-a-devoxxfr-2012/#comments</comments>
		<pubDate>Sun, 22 Apr 2012 17:14:25 +0000</pubDate>
		<dc:creator>Thomas ESCOLAN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5566</guid>
		<description><![CDATA[<p>Il y a beaucoup de choses dont j&#8217;aurais éventuellement envie de parler, suite à ma visite à Devoxx 2012 (Nota: un jour, c&#8217;est trop court ; penser à demander plus l&#8217;an prochain Mais il est une conférence, parmi celles auxquelles j&#8217;ai assisté, où les réactions ont été les plus vives ; pendant le speech, au <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/04/22/le-ddd-a-devoxxfr-2012/">Le DDD à Devoxx France 2012</a></span>]]></description>
			<content:encoded><![CDATA[<p>Il y a beaucoup de choses dont j&#8217;aurais éventuellement envie de parler, suite à ma visite à Devoxx 2012 (Nota: un jour, c&#8217;est trop court ; penser à demander plus l&#8217;an prochain <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  Mais il est une conférence, parmi celles auxquelles j&#8217;ai assisté, où les réactions ont été les plus vives ; pendant le <em>speech</em>, au moment des questions, et même après. En effet, notre petit groupe d&#8217;internes était très animé sur le chemin de la présentation suivante.</p>
<p>Cette <a title="Il n'y a pas de bon Modèle Métier" href="http://devoxx.fr/display/FR12/Il+n%27y+a+pas+de+bon+Modele+Metier" target="_blank">conférence</a>, donnée par <strong>Grégory Weinbach</strong> (Objet Direct) est basée en grande partie sur la lecture du célèbre ouvrage d&#8217;Eric Evans (<a title="Quickie : Domain-Driven Design vite fait" href="http://blog.infosaurus.fr/public/docs/DDDViteFait.pdf" target="_blank">Domain-Driven Design</a> &#8211; 2003). Elle ne visait pas seulement, à mon avis, qu&#8217;à exposer les concepts du DDD mais plutôt à bousculer quelques notions confortables (?) d&#8217;une manière que j&#8217;ai trouvée assez futée.</p>
<h2>Démonstration</h2>
<p>L&#8217;orateur commence par le postulat désormais <a title="Manifeste Agile" href="http://agilemanifesto.org/" target="_blank">banal</a> que notre métier d&#8217;informaticiens consiste à répondre aux besoins des <strong>utilisateurs</strong>. Lesquels <strong>besoins</strong> sont certes souvent complexes, voire mal exprimés. Nous devrions donc nous attacher à ce qu&#8217;est l&#8217;utilisateur en priorité, afin de comprendre non pas ce que VEUT notre utilisateur mais POURQUOI il le demande ; c&#8217;est-à-dire son <strong>objectif métier</strong> (le domaine).</p>
<p>Selon le DDD, le modèle et le code partagent un langage commun : le modèle objet, qui rassemble les données et le comportement du système d&#8217;informations. Afin de l&#8217;organiser, ce dernier est organisé en couches dont les dépendances sont hiérarchiques :</p>
<p><a href="http://blog.ippon.fr/2012/04/22/le-ddd-a-devoxxfr-2012/ddd1/" rel="attachment wp-att-5575"><img class="aligncenter size-medium wp-image-5575" title="Dépendances logiques entre les couches d'un SI" src="http://blog.ippon.fr/wp-content/uploads/2012/04/DDD1-300x40.png" alt="" width="300" height="40" /></a>On constate dans le schéma ci-dessus que le modèle métier (constitué par les entités du système) est la source centrale des dépendances des autres couches qui s&#8217;appuient dessus. Il s&#8217;agit de <strong>dépendances logiques</strong>. Cette couche impose des contraintes aux autres couches, donc, et d&#8217;ailleurs la couche de données peut ne se résumer qu&#8217;à une transcription (MDE) triviale, mécanique, sous une forme de persistance ou une autre.</p>
<p>Puisqu&#8217;il est si important (ce modèle), l&#8217;architecte concepteur devra donc se demander COMMENT bien construire le modèle métier. L&#8217;approche classique consiste à interroger l&#8217;utilisateur afin de déterminer à quels <strong>concepts</strong> son métier peut se réduire, des entités modélisables. Ici, l&#8217;on se représente tout à fait le dictionnaire de données, dans les règles de l&#8217;art de la franchouillarde (sans offense) méthode <a title="Merise" href="http://fr.wikipedia.org/wiki/Merise_%28informatique%29" target="_blank">Merise</a>, et on aboutit à un diagramme de classes tentaculaire le plus complet <em>possible</em>. Pour y arriver, il faut découvrir quelles sont les <strong>abstractions</strong> des concepts métiers pour CHAQUE utilisateur. On apprendra plus  loin, dans un <a title="dictionnaire philosophique" href="http://fr.wikipedia.org/wiki/Dictionnaire_philosophique" target="_blank">dictionnaire philosophique</a> datant de plusieurs siècles, que l&#8217;abstraction permet de se concentrer sur certaines propriétés et non l&#8217;ensemble. Le modèle est donc contextuel, il s&#8217;agit d&#8217;un point de vue. Certaines informations seront communes à toutes les projections du concept, mais en général très peu. Pour passer d&#8217;un modèle à l&#8217;autre, on aura donc recours le cas échéant à des <span style="text-decoration: underline;">transcodifications</span>.</p>
<p>En fait, le DDD constate que la pression des dépendances logiques s&#8217;applique d&#8217;abord dans le sens de la descente (<em>top-down</em>). En particulier, j&#8217;imagine, dans un environnement de production tendu (le fameux &#8220;time to market&#8221;). L&#8217;idée, si j&#8217;ai bien compris, est que si le besoin est simple, l&#8217;interface (la perspective) de l&#8217;utilisateur doit aussi être simple ; et il n&#8217;y a donc aucune raison que le modèle métier ne le soit pas quant à lui. Le Domaine du DDD ne se rapportera qu&#8217;au seul <strong>contexte</strong> du <em>use case</em> :</p>
<p><a href="http://blog.ippon.fr/2012/04/22/le-ddd-a-devoxxfr-2012/ddd2/" rel="attachment wp-att-5588"><img class="aligncenter size-medium wp-image-5588" title="Dépendances logiques entre les couches d'un SI (bis)" src="http://blog.ippon.fr/wp-content/uploads/2012/04/DDD2-300x42.png" alt="Le TDD considère en priorité les dépendances descendantes" width="300" height="42" /></a>Pour modéliser un concept, il conviendrait donc de <em>choisir</em> le contexte afin de s&#8217;intéresser au coeur du domaine&#8230; le <strong>client</strong> (en fait, l&#8217;acteur) ! Or, en DDD, c&#8217;est l&#8217;<strong>usage</strong> via le logiciel qui détermine le modèle métier. Celui-ci reste une projection de la réalité et n&#8217;a en aucune manière vocation à être exhaustif ; ce qui est considéré comme improductif (c&#8217;est moi qui rajoute). On travaille donc sur la base de cas d&#8217;utilisation (les intéractions), ce qui aboutit à une organisation différente. Le vocabulaire reste pourtant le même, mais le modèle n&#8217;est pas issu des besoins logiciels. <a title="Oh My God" href="http://fr.wikipedia.org/wiki/Omfg#Argot" target="_blank">OMG</a> !</p>
<h2>Premières critiques</h2>
<p>Modèle contextuel, voire partiel ; transcodification&#8230;</p>
<p>En DDD, on peut avoir plusieurs modèles qui cohabitent dans une application. Ceux-ci peuvent être redondants (<a title="Oh My F...g God - t'as compris, quoi" href="http://fr.wikipedia.org/wiki/Omfg#Argot" target="_blank">OMFG</a> !) ; et, pire que tout, on ne s&#8217;inquiète pas de la façon dont les entités seraient au final le <em>mieux</em> persistées (<a title="Ok, c'est lourd, là" href="http://fr.wikipedia.org/wiki/Omfg#Argot" target="_blank">WTF</a> !!!). Selon moi, on devra par conséquent probablement fournir un <strong>effort caché</strong> futur (et cacher les coûts au client fort chéri, c&#8217;est mal), lorsqu&#8217;il s&#8217;avèrera nécessaire de réconcillier les modèles pour des besoins transversaux : &#8220;Il conviendra de communiquer sur ce point ; cet effort sera traité <em>alors</em> en tant que nouveau use case (<a title="transcodification" href="http://fr.wikipedia.org/wiki/Extract_Transform_Load">ETL</a>)&#8221; m&#8217;a-t-on répondu en substance.</p>
<p>L&#8217;un des participants s&#8217;est violemment élevé contre le fait de ne pas s&#8217;attacher à consolider la couche de données. Selon lui, les données constituent la <strong>valeur</strong> la plus importante de l&#8217;entreprise. Peu important la méthode de collecte ou de saisie. Les logiciels passent mais les données restent, en somme. Petit flottement ; je comprends soudain pourquoi Grégory Weinbach a gardé tant de temps pour les questions&#8230; Les réactions sont vives, c&#8217;est bien normal et c&#8217;est bon signe : c&#8217;est la preuve qu&#8217;un point sensible est touché.</p>
<p>Bon, après j&#8217;ai pas tout compris aux interventions du public, j&#8217;avoue. Il fut question de DSL (j&#8217;accroche à peu près), de modèles adaptatifs (à éviter, selon l&#8217;orateur &#8220;le besoin virtuel n&#8217;est pas prouvé&#8221; &#8211; j&#8217;attends une autre présentation). Bref, passons.</p>
<h2>Prise de recul</h2>
<p>Parlons franchement. Une grande part de la valeur de l&#8217;architecte logiciel et de sa légitimité vient de sa capacité à produire de bons gros diagrammes de classes &#8220;bien formé&#8221;, de préférence en UML. Non ? La fierté du concepteur, c&#8217;est sa capacité à anticiper toutes les évolutions possibles et <em>imaginables</em>. Ce qui n&#8217;arrive JAMAIS, nous le savons bien. Il y a donc là matière à un débat sans fin, probablement teinté de mauvaise foi et de personnalisation à <a title="private joke" href="http://www.linternaute.com/ville/erreur/aucunresultat.html">outrance</a>.</p>
<p>Mais, à bien y réfléchir, qu&#8217;est-ce qu&#8217;une architecture SOA ? L&#8217;architecture SOA consiste à mettre en relation des systèmes potentiellement hétérogènes au travers de contrats et de protocoles communs&#8230; des transcodifications ? Si les <strong>outils</strong> du TDD peuvent permettre d&#8217;adresser cette complexité, nous devons les envisager pour résoudre ce genre de problématiques. Pensez aussi aux systèmes concurrents que vous avez peut-être eu à fusionner au prix de longs (et coûteux) efforts en un seul système centralisé&#8230; Quels gains, en termes d&#8217;objectifs métier, ont-ils été réalisés <em>in fine</em>, pour l&#8217;utilisateur final ?..</p>
<p>Je vous invite à donner votre avis et à partager vos témoignages sur ces questions ouvertes. Merci.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/R2AaxyrOBFE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/04/22/le-ddd-a-devoxxfr-2012/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/04/22/le-ddd-a-devoxxfr-2012/</feedburner:origLink></item>
		<item>
		<title>Résultat du concours “Tatami” pour Devoxx France</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/HGBexIrZt-Q/</link>
		<comments>http://blog.ippon.fr/2012/04/11/resultat-du-concours-tatami-pour-devoxx-france/#comments</comments>
		<pubDate>Wed, 11 Apr 2012 06:00:33 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippon]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Concours]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Ippon Technologies]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[jquerymobile]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5440</guid>
		<description><![CDATA[<p>Ippon Technologies a lancé il y a 3 semaines un grand concours de code, portant sur l&#8217;application Tatami.</p> <p>Ce concours consistait à finaliser et à débugger une application complète, basée sur HTML5+Spring+Cassandra. Du vrai code, disponible sur GitHub, pour une vraie application !</p> <p>Cette application a été spécialement développée par votre humble serviteur, ainsi que <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/04/11/resultat-du-concours-tatami-pour-devoxx-france/">Résultat du concours &#8220;Tatami&#8221; pour Devoxx France</a></span>]]></description>
			<content:encoded><![CDATA[<p>Ippon Technologies a lancé il y a 3 semaines un <a href="http://blog.ippon.fr/2012/03/19/bienvenue-sur-le-tatami-ippon-lance-un-grand-concours-de-code-pour-devoxx-france/" target="_blank">grand concours de code</a>, portant sur l&#8217;application <a href="https://github.com/ippontech/tatami" target="_blank">Tatami</a>.</p>
<p>Ce concours consistait à finaliser et à débugger une application complète, basée sur HTML5+Spring+Cassandra. Du vrai code, disponible sur GitHub, pour une vraie application !</p>
<p>Cette application a été spécialement développée par <a href="https://twitter.com/#!/juliendubois" target="_blank">votre humble serviteur</a>, ainsi que par mon collègue Thomas Escolan, que je tiens à vivement remercier pour son travail sur la partie HTML5.</p>
<p>Le jeu s’est terminé ce matin, il est donc temps de faire un bilan et d’annoncer les vainqueurs !</p>
<h1>Bilan du jeu</h1>
<p>Sur Github, nous avons eu 60 “watchers”, 46 “forks” et 18 “pull requests” : il est évident que ce jeu a été pour nous un grand succès.</p>
<p>Au final, nous avons eu une dizaine de participations intéressantes (que nous allons détailler ci-après), dont certaines étaient particulièrement avancées et créatives.</p>
<p>L’application a évolué de manière très notable, même s’il est parfois compliqué de pouvoir fusionner des modifications provenant de tous ces forks différentes.</p>
<p>L’un de nos objectifs futurs est de pouvoir terminer l’application, afin qu’elle soit rééllement utilisable, sachant qu’il n’existe pas de solution Open Source équivalente (à notre connaissance, le système qui s’en approche le plus est <a href="https://www.yammer.com/" target="_blank">Yammer</a>, qui bien entendu est un logiciel commercial).</p>
<h1>Participations marquantes</h1>
<h2>Un fork “full Java EE”</h2>
<p><a href="https://twitter.com/#!/rmannibucau" target="_blank">Romain Manni-Bucau</a>, commiter <a href="http://openejb.apache.org/apache-tomee.html" target="_blank">TomEE</a> et OpenEJB, a fait un fork supprimant totalement Spring de l’application :</p>
<p><a href="https://github.com/rmannibucau/tatami" target="_blank">https://github.com/rmannibucau/tatami</a></p>
<p>Le code final fonctionne donc correctement sur <a href="http://openejb.apache.org/apache-tomee.html" target="_blank">TomEE</a>, à quelques nuances près (en particulier la sécurité, qui en Java EE doit être configurée dans le serveur d’applications et non dans l’application, ainsi que le cache, qui a dû être codé spécifiquement), et cela nous a permis de faire des tests de performance très intéressants, entre deux stacks concurrentes :</p>
<ul>
<li>Jetty + Spring + Spring MVC REST</li>
<li>Tomcat + OpenEJB + CXF</li>
</ul>
<p>Le résultat initial étant très lié au serveur d’applications (Jetty faisant du NIO par défaut, il tenait nettement mieux la charge), après un peu de tuning Romain est arrivé aux statistiques suivantes, avec pour 1000 utilisateurs concurrents, sur une petite machine de bureau :</p>
<ul>
<li>Spring : 196.6 requêtes par seconde</li>
<li>TomEE : 182.3 requêtes par seconde</li>
</ul>
<p>Sachant que les serveurs et JMeter étaient tous sur la même machine, ces résultats sont bien entendu à prendre avec une pincée de sel&#8230;</p>
<p>Mais quoiqu’il en soit, nous pouvons en tirer les conclusions suivantes :</p>
<ul>
<li>Spring et TomEE tiennent la chargent de manière équivalente</li>
<li>L’application tient facilement 3000 utilisateurs concurrents, avant que JMeter ne crashe : nous tenons donc extrêmement bien la charge, essentiellement grâce à Cassandra et au système de cache</li>
<li>L’ajout d’un cache nous fait gagner environ 20% de requêtes/seconde, car on n’a plus à faire un accès réseau (local) vers Cassandra, et à sérialiser/déserialiser les données : Cassandra seul peut donc largement suffire en tant que cache distribué</li>
</ul>
<p>Si vous voulez faire ces tests vous-mêmes, le jeu de test est <a href="https://github.com/ippontech/tatami/tree/master/src/test/jmeter" target="_blank">disponible sur GitHub</a>. Attention cependant, la version Spring a depuis pas mal évolué, l’ajout de nouvelles fonctionnalités devraient logiquement la faire ralentir un peu.</p>
<p>Enfin, pour ce qui est de la productivité et de la qualité des développements Spring vs Java EE, je vous laisse juges en lisant le code source :</p>
<ul>
<li>Le code Spring est nécessairement plus concis, car Spring propose plus de fonctionnalités en standard (c’est normal d’ailleurs, Spring s’appuyant sur Java EE pour l’améliorer)</li>
<li>Le code “full Java EE” est plus standard (pas d’annotations Spring), en particulier sur la partie REST (pour l’injection de dépendances les deux codes utilisent le standard @Inject, les différences restent donc minimes)</li>
</ul>
<h2>Ajout de tests unitaires avec cassandra-unit</h2>
<p><a href="https://twitter.com/#!/jsevellec" target="_blank">Jérémy Sevellec</a>, l’auteur de <a href="https://github.com/jsevellec/cassandra-unit" target="_blank">cassandra-unit</a>, a ajouté une suite complète de tests d’intégration utilisant (évidemment) <a href="https://github.com/jsevellec/cassandra-unit" target="_blank">cassandra-unit</a>. C’est sans doute la contribution qui a le plus aidé à la qualité du code.</p>
<p>Jérémy a également fait preuve d’un excellent esprit de participation (ce qui compte au Judo !), vous pouvez donc voir ce travail dans cette pull request qui a été ajoutée au code du projet :</p>
<p><a href="https://github.com/ippontech/tatami/pull/32" target="_blank">https://github.com/ippontech/tatami/pull/32</a></p>
<h2>Utilisation d’un configuration Spring avec 0 ligne de XML</h2>
<p><a href="https://twitter.com/#!/gcuisinier" target="_blank">Gildas Cuisinier</a>, bien connu des amateurs de Spring, nous a proposé une configuration Spring “0 XML”. La mode actuelle est de faire le moins de XML possible, mais d’un point de vue purement personnel je vous avoue trouver cette configuration moins lisible que son homologue XML.</p>
<p>Vous pouvez étudier son travail via cette pull request, elle aussi acceptée dans le projet :</p>
<p><a href="https://github.com/ippontech/tatami/pull/36" target="_blank">https://github.com/ippontech/tatami/pull/36</a></p>
<p>Cependant, ce code s’est révélé relativement lent au démarrage, car il forçait l’application à scanner tout son classpath. <a href="https://twitter.com/#!/farrault" target="_blank">Fabien Arrault</a> (Ippon Technologies) nous a donc proposé cette pull request, qui réintroduit quelques lignes de XML et nous redonne les performances d’origine :</p>
<p><a href="https://github.com/ippontech/tatami/pull/38" target="_blank">https://github.com/ippontech/tatami/pull/38</a></p>
<h2>Utilisation de Spring Mobile et JQuery Mobile</h2>
<p>L’une des amélioration à réaliser était de réaliser une interface “mobile” de l’application. Plusieurs personnes ont démarré cette fonctionnalité, en utilisant toutes :</p>
<ul>
<li><a href="http://www.springsource.org/spring-mobile" target="_blank">Spring Mobile</a> pour savoir si l’utilisateur utilisait (ou non) un téléphone ou une tablette</li>
<li>Les fonctionnalités de Spring MVC pour rediriger ensuite l’utilisateur vers une vue “standard” ou une vue “mobile”</li>
</ul>
<p><a href="https://twitter.com/#!/gcuisinier" target="_blank">Gildas Cuisinier</a> en a proposé une première version qui a été intégrée dans le projet principal :</p>
<p><a href="https://github.com/ippontech/tatami/pull/46" target="_blank">https://github.com/ippontech/tatami/pull/46</a></p>
<h2>Utilisation de Spring Social</h2>
<p><a href="http://www.springsource.org/spring-social" target="_blank">Spring Social</a> est un sous-projet Spring permettant d’utiliser simplement les APIs des différents réseaus sociaux tels que Twitter, Facebook, etc&#8230;</p>
<p>L’un des objectifs du jeu était de connecter l’application à ces réseaux, à priori en utilisant Spring Social : malheureusement, c’est l’un des seuls objectifs qui n’a pas été entièrement finalisé.</p>
<p><a href="https://twitter.com/#!/samklr" target="_blank">Sam Bessalah</a> en a certainement fait la version la plus aboutie, mais il ne l’a pas livrée à temps pour la date finale du jeu :</p>
<p><a href="https://github.com/samklr/tatami" target="_blank">https://github.com/samklr/tatami</a></p>
<h1>Gagnants</h1>
<h2>2ème place : François Descamps</h2>
<p><a href="https://twitter.com/#!/descampsf" target="_blank">François Descamps</a> a contribué un nombre de pull requests impressionnant. Il gagne donc haut la main le trophée du fair play, car il a très régulièrement soumis son code pour qu&#8217;il soit intégré dans l&#8217;application d&#8217;origine.</p>
<p>En particulier (et de manière non exhaustive), il a :</p>
<ul>
<li>Refactoré le code JavaScript (mais précisons que ce refactoring ne fait pas l’unanimité du jury)</li>
<li>Mis en place <a href="http://www.elasticsearch.org/" target="_blank">Elastic Search</a> avec l’aide de <a href="https://twitter.com/#!/TweetingFroggy" target="_blank">David Martin</a> (Ippon Technologies), pour pouvoir rechercher des utilisateurs et des tweets</li>
<li>Ajouté une protection contre les attaques XSS avec <a href="http://jsoup.org/" target="_blank">JSoup</a> et Bean Validation</li>
<li>Et proposé de nombreux commits pour améliorer l’interface graphique et l’utilisabilité&#8230;</li>
</ul>
<p>François gagne donc une place de 2 jours à Devoxx France !</p>
<h2>1ère place : DuyHai Doan</h2>
<p><a href="http://doanduyhai.wordpress.com/" target="_blank">DuyHai Doan</a> a fait un fork particulièrement impressionnant. Le seul défaut de sa contribution étant qu’elle soit dans un fork tellement éloigné du master qu’il nous sera difficile de réintégrer ses modifications dans le code principal.</p>
<p>Mais à part cela, il a développé un très grand nombre de fonctionnalités, ce qui fait de son fork une version de l’application plus avancée que l’originale, malgré les commits de nombreux concurrents différents.</p>
<p>En particulier, il a :</p>
<ul>
<li>utilisé <a href="https://github.com/rantav/hector/wiki/Hector-Object-Mapper-(HOM)" target="_blank">Hector Object Mapper</a> pour améliorer la qualité de la couche repository (en utilisant au maximum JPA)</li>
<li>utilisé Cassandra de manière intelligente pour proposer une recherche des utilisateurs sans utiliser Elastic Search (ou Lucene). Cependant, il n’a pas implémenté la recherche des Tweets (impossible à faire avec Cassandra), il a donc une solution plus simple que celle utilisant Elastic Search, mais moins complète</li>
<li>mis en place <a href="https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API" target="_blank">ESAPI</a> et Bean Validation pour protéger l’application des attaques XSS</li>
<li>ajouté la librairie <a href="http://www.thymeleaf.org/" target="_blank">Thymeleaf</a> comme moteur de templates HTML5</li>
<li>codé une interface graphique riche en utilisant <a href="http://lesscss.org/" target="_blank">LESS CSS</a>, en ajoutant de nombreuses nouvelles fonctionnalités (les profils utilisateurs), ainsi qu’en améliorant le design général de l’application</li>
<li>réalisé une excellente couverture de tests en utilisant <a href="http://testng.org/doc/index.html" target="_blank">TestNG</a></li>
<li>développé une version mobile très complète de l&#8217;application, avec <a href="http://www.springsource.org/spring-mobile" target="_blank">Spring Mobile</a>, <a href="http://lesscss.org/" target="_blank">LESS CSS</a>, <a href="http://jackson.codehaus.org/" target="_blank">Jackson</a>, HTML5. C&#8217;est le point principal qui a fait gagner DuyHai</li>
</ul>
<p>DuyHai gagne donc une place de 2 jours à Devoxx France, ainsi qu’un Galaxy Tab !</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/HGBexIrZt-Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/04/11/resultat-du-concours-tatami-pour-devoxx-france/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/04/11/resultat-du-concours-tatami-pour-devoxx-france/</feedburner:origLink></item>
		<item>
		<title>jQueryMobile et PhoneGap : un duo gagnant pour vos applications mobiles ?</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/Q6yvitzJ-TQ/</link>
		<comments>http://blog.ippon.fr/2012/04/10/jquerymobile-et-phonegap-un-duo-gagnant-pour-vos-applications-mobiles/#comments</comments>
		<pubDate>Tue, 10 Apr 2012 07:51:00 +0000</pubDate>
		<dc:creator>Damien RAUDE-MORVAN</dc:creator>
				<category><![CDATA[Mobilité]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[jquerymobile]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[phonegap]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5349</guid>
		<description><![CDATA[<p>Le succès des smartphones, tablettes, et autres mobile devices ne semble, malgré la crise, subir aucun ralentissement : sur 2011 on observe une augmentation des ventes de smartphones de 74% et un total de 63 millions de tablettes vendues. Pour nos clients, cela déclenche une remise en perspective de leur stratégie : &#8220;comment proposer mes services <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/04/10/jquerymobile-et-phonegap-un-duo-gagnant-pour-vos-applications-mobiles/">jQueryMobile et PhoneGap : un duo gagnant pour vos applications mobiles ?</a></span>]]></description>
			<content:encoded><![CDATA[<p>Le succès des <em>smartphones</em>, tablettes, et autres <em>mobile devices</em> ne semble, malgré la crise, subir aucun ralentissement : sur 2011 on observe une <a href="http://www.lemonde.fr/technologies/article/2011/08/12/les-ventes-mondiales-de-smartphones-en-hausse-de-74_1558812_651865.html" target="_blank">augmentation des ventes de smartphones de 74%</a> et un total de <a href="http://www.journaldunet.com/solutions/systemes-reseaux/ventes-de-tablettes-en-2011.shtml">63 millions de tablettes vendues</a>. Pour nos clients, cela déclenche une remise en perspective de leur stratégie : &#8220;comment proposer mes services mobiles à la population la plus large possible&#8221;, &#8220;comment m&#8217;adapter aux nouveaux canaux de diffusion que sont les App Store et Google Play&#8221; ou encore &#8220;puis-je maitriser mes coûts de développement et de maintenance sur ces X plateformes&#8221;.</p>
<p>Dans cet article, je vais essayer de vous présenter l&#8217;approche que j&#8217;ai utilisé pour un client. Je ne peux malheureusement pas rentrer dans les détails de ce projet mais sachez cependant que l&#8217;approche de développement &#8220;hybride&#8221; retenue (i.e. application mixte native / web) était un pré-requis du client&#8230; Étant plutôt un habitué des développements natifs, j&#8217;ai profité de ce projet pour essayer de me forger ma propre opinion. Je vous propose donc dans cet article d&#8217;évaluer ce que propose les technologies web pour l&#8217;implémentation d&#8217;application mobile et bien sûr, leurs limites.</p>
<h2>jQueryMobile, les composants graphiques</h2>
<p><a href="http://blog.ippon.fr/2012/04/10/jquerymobile-et-phonegap-un-duo-gagnant-pour-vos-applications-mobiles/jquery-mobile-logo/" rel="attachment wp-att-5380"><img class="alignleft" title="jquery-mobile-logo" src="http://blog.ippon.fr/wp-content/uploads/2012/04/jquery-mobile-logo.png" alt="" width="186" height="57" /></a><a href="http://jquerymobile.com/">jQueryMobile</a> est un framework qui permet, à partir de pages HTML5/CSS3, d&#8217;obtenir des écrans et des composants graphiques adaptés au rendu sur un écran de <em>smartphone</em> ou tablette.</p>
<p>Il s&#8217;agit d&#8217;un framework qui se base, évidemment, sur jQuery mais utilise plus particulièrement son cousin jQuery UI pour l&#8217;implémentation des composants graphiques (<em>widgets</em>). Il est conçu pour fonctionner sur un grand nombre de navigateurs et de plateformes différentes : chaque plateforme est classée suivant son niveau de support ainsi il est possible de &#8220;dégrader&#8221; correctement l&#8217;application sur un ancien téléphone. Dans la même philosophie que jQuery, il essaye d’être le moins intrusif possible : les pages HTML5 contiennent seulement des <a href="http://html5doctor.com/html5-custom-data-attributes/">attributs HTML5 “data”</a> qui permettent de déclencher le rendu des <em>widgets</em> (la page est alors dite “augmentée”).</p>
<h3>Exemple “quick &amp; dirty”</h3>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot;&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p&gt;
      [...]
    &lt;/p&gt;
    &lt;div data-role=&quot;page&quot; data-theme=&quot;b&quot; id=&quot;page1&quot;&gt;
      &lt;div data-role=&quot;header&quot;&gt;
        &lt;h3&gt;
          Application XXX
        &lt;/h3&gt;
      &lt;/div&gt;
      &lt;div data-role=&quot;content&quot;&gt;
        &lt;h2&gt;
          Page 1
        &lt;/h2&gt;
        &lt;ul data-role=&quot;listview&quot; data-divider-theme=&quot;a&quot; data-inset=&quot;true&quot;&gt;
          &lt;li data-role=&quot;list-divider&quot; role=&quot;heading&quot;&gt;Menu
          &lt;/li&gt;
          &lt;li data-theme=&quot;c&quot;&gt;
            &lt;a href=&quot;#page2&quot; data-transition=&quot;slide&quot;&gt;Vers Page 2&lt;/a&gt;
          &lt;/li&gt;
          &lt;li data-theme=&quot;c&quot;&gt;
            &lt;a href=&quot;#page3&quot; data-transition=&quot;slide&quot;&gt;Vers Page 3&lt;/a&gt;
          &lt;/li&gt;
          &lt;li data-theme=&quot;c&quot;&gt;
            &lt;a href=&quot;#page4&quot; data-transition=&quot;slide&quot;&gt;Vers Page 4&lt;/a&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div data-role=&quot;page&quot; data-theme=&quot;b&quot; id=&quot;page2&quot;&gt;
      &lt;div data-role=&quot;header&quot;&gt;
        &lt;a data-role=&quot;button&quot; data-direction=&quot;reverse&quot; data-rel=&quot;back&quot; data-transition=&quot;fade&quot; href=&quot;#page1&quot; data-icon=&quot;arrow-l&quot; data-iconpos=&quot;left&quot;&gt;Retour&lt;/a&gt;
        &lt;h3&gt;
          Application XXX
        &lt;/h3&gt;
      &lt;/div&gt;
      &lt;div data-role=&quot;content&quot;&gt;
        &lt;h2&gt;
          Page 2
        &lt;/h2&gt;&lt;img src=&quot;https://maps.googleapis.com/maps/api/staticmap&quot;&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p><a href="http://blog.ippon.fr/2012/04/10/jquerymobile-et-phonegap-un-duo-gagnant-pour-vos-applications-mobiles/example/" rel="attachment wp-att-5383"><img class="alignright size-full wp-image-5383" title="example" src="http://blog.ippon.fr/wp-content/uploads/2012/04/example-e1333618657831.png" alt="" width="214" height="598" /></a><br />
Comme on peut le voir dans le code ci-dessus, deux DIV portent des attributs “data” qui sont découverts par jQueryMobile. &#8220;<em>data-role=page</em>&#8221; permet d&#8217;indiquer qu&#8217;il s&#8217;agit d&#8217;un écran et &#8220;<em>data-theme=b</em>&#8221; permet de choisir la charte graphique à utiliser (sachant qu&#8217;il dispose de <a href="http://jquerymobile.com/demos/1.0.1/docs/api/themes.html" target="_blank">5 thèmes par défaut</a>). Chaque écran peut-être composé de trois zones : <em>header, content, footer</em> (attribut <em>data-role</em> également) dans lesquels on ajoute ses composants graphiques. Pour ajouter une liste ? Il suffit d&#8217;utiliser le tag HTML &lt;<em>ul/&gt;</em> avec un attribut &#8220;<em>data-role=listview</em>&#8220;.</p>
<h3>Cinématique des écrans</h3>
<p>Ce framework est conçu pour être utilisé à la fois sur des sites web mobiles (ou finalement jQueryMobile peut-être vu comme une couche de rendu spécifique) mais également sur des applications hybrides (c-a-d installées sur le <em>smartphone</em>). Les pages HTML sont alors être distribuées avec l’application (on parle de pages <em>locales</em>) ou bien téléchargées via AJAX (pages <em>distantes</em>).</p>
<p>Afin de gérer les liens et les formulaires, jQM utilise une approche <a href="http://en.wikipedia.org/wiki/Hijax" target="_blank">Hijax</a> : il va ajouter, si cela est possible, un appel Ajax sur l&#8217;ensemble des liens <em>&lt;a href/&gt;</em> pour charger le fragment de page et l&#8217;injecter de façon dynamique dans l’arbre DOM. Il déclenche des animations CSS3 afin de proposer une transition adaptée.</p>
<p>Il est également possible de capturer des événements “spécifiques mobile” : <em>swipe, orientationchange, tap, taphold, scroll</em>, etc&#8230;</p>
<h3>Retour d’expérience</h3>
<p>Les points forts sont :</p>
<ul>
<li>Le développement utilise des standards HTML5/CSS3 (et demande donc des compétences plus faciles à trouver sur le marché du travail)</li>
<li>Cela s&#8217;intègre très bien dans un développement MVC classique : il suffit que le serveur génère directement les pages dans le bon format HTML5 et ca marche tout seul</li>
<li>Les composants graphiques par défaut sont plutôt étoffés (tableau, formulaire, liste dépliables, boutons, icône, layout grid)</li>
<li>Le système de thèmes et l&#8217;outil <a href="http://jquerymobile.com/themeroller/index.php" target="_blank">Theme Roller</a> permettent de créer facilement une charte graphique sans &#8211; presque &#8211; faire de CSS</li>
<li>Un développeur connaissant jQuery UI pourra assez facilement faire ses propres composants graphiques</li>
</ul>
<p>Les points faibles (qui ne sont pas tous spécifique à jQM, mais plutôt à l&#8217;approche HTML5) :</p>
<ul>
<li>L&#8217;expérience utilisateur (&#8220;User eXperience&#8221; comme on dit) est vraiment pauvre par rapport à ce qu&#8217;on peut obtenir avec une application native</li>
<li>Les performances sont mauvaises, notamment sur <a href="http://jquerymobile.com/blog/2012/02/28/announcing-jquery-mobile-1-1-0-rc1/#features" target="_blank">les transitions entre écrans sur Android</a></li>
<li>On subit les bugs des différentes versions de WebKit (nous avons eu des problèmes avec Android 2.1 par exemple) et finalement on retrouve les mêmes problématiques qu&#8217;avec un développement web classique : debug pas spécialement évident, même s&#8217;il existe <a href="http://phonegap.github.com/weinre/" target="_blank">des outils</a></li>
</ul>
<h2>PhoneGap et sa galaxie</h2>
<p><a href="http://blog.ippon.fr/2012/04/10/jquerymobile-et-phonegap-un-duo-gagnant-pour-vos-applications-mobiles/phonedap-logo/" rel="attachment wp-att-5378"><img class="alignleft size-thumbnail wp-image-5378" title="phonedap-logo" src="http://blog.ippon.fr/wp-content/uploads/2012/04/phonedap-logo-150x150.png" alt="" width="150" height="150" /></a><a href="http://phonegap.com/" target="_blank">PhoneGap</a> est un framework qui permet d&#8217;encapsuler (on parle aussi de &#8220;wrapper&#8221;) une application HTML/CSS dans une application native (c-a-d disponible sur les différents Store/Market et visible dans le menu du téléphone). L’application native n&#8217;est alors qu&#8217;une coquille vide qui permet juste de masquer à l’utilisateur qu’il s&#8217;agit de simple pages web.</p>
<p>Suite au rachat de Nitobi (société à l&#8217;origine de PhoneGap) par Adobe, le code source de PhoneGap a été reversé à la fondation Apache via le <a href="http://incubator.apache.org/cordova/" target="_blank">projet <del>Callback</del> Cordova</a>. Après quelques petits accrochages avec le PMC de la fondation sur l&#8217;utilisation de Git (PhoneGap étant utilisateur de Git, le projet ne souhaitait pas revenir à SVN <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> , il semblerait que l&#8217;incubation du projet soit sur les rails pour une acceptation comme &#8220;<em>Top Level Project</em>&#8220;.</p>
<p>Concrètement, il utilise les composants navigateurs (appelé « WebView ») disponibles sur chaque <em>OS mobile</em> et expose &#8211; dans ce composant navigateur &#8211; un certain nombre de passerelles vers les éléments natifs du téléphone. Évidemment, ces passerelles sont accessibles via le langage Javascript (et plus particulièrement via des flux JSON). Il devient ainsi possible depuis son application HTML/CSS/JS de piloter les éléments physiques du téléphone : caméra, fichiers, liste des contacts.</p>
<p>Contrairement à jQueryMobile, je ne vous ferais pas l&#8217;affront de vous présenter un projet d&#8217;exemple : la <a href="http://phonegap.com/start/#android">page Get Started du site de PhoneGap</a> est très claire et permet de créer un projet en quelques secondes.</p>
<h3>Plug-in : JS/Natif</h3>
<p><a href="http://blog.ippon.fr/2012/04/10/jquerymobile-et-phonegap-un-duo-gagnant-pour-vos-applications-mobiles/phonegap_plugins1/" rel="attachment wp-att-5404"><img class="alignright size-full wp-image-5404" title="phonegap_plugins1" src="http://blog.ippon.fr/wp-content/uploads/2012/04/phonegap_plugins1.png" alt="" width="364" height="300" /></a>Tous les plugins PhoneGap sont constitués d&#8217;une classe Javascript qui expose la fonctionnalité dans l&#8217;application HTML/JS (boîte rouge dans la figure ci-contre). La classe JavaScript (boîte verte dans la figure ci-contre) communique à la couche native grâce à la classe de base en utilisant PhoneGap <em>PhoneGap.exec</em>(). La passerelle native de PhoneGap invoque ensuite le code natif du plugin (boîte de violet dans la figure ci-contre).</p>
<p><a href="http://docs.phonegap.com/en/1.5.0/">La liste des plugins fournit dans le paquet par défaut de PhoneGap</a> est la suivante :</p>
<ul>
<li>Accelerometer : écouter le capteur de mouvement</li>
<li>Camera : capturer une photo via l&#8217;application dédiée</li>
<li>Capture : capturer les flux son/image/vidéo du téléphone</li>
<li>Compass : orientation magnétique (N/S/E/O) de l&#8217;appareil</li>
<li>Connection : informations sur la connectivité DATA</li>
<li>Contacts : accès à la base de contacts</li>
<li>Device : identifiant du smartphone</li>
<li>Events : accès aux événements natifs (batterylow, volumeupbutton)</li>
<li>File : lecture / écriture de fichiers</li>
<li>Geolocation : réception des coordonnées géographiques</li>
<li>Media : lecture de fichier audio</li>
<li>Notification : notifications visuelles, sonores et tactiles</li>
<li>Storage : accès à une base de données SQL</li>
</ul>
<p>En plus des plugins gérés directement par le projet PhoneGap, il existe un certain nombre de plugins développés par la communauté sur <a href="https://github.com/phonegap/phonegap-plugins">le site GitHub dédié</a>.</p>
<h3>Retour d’expérience</h3>
<p>Les points forts de PhoneGap sont :</p>
<ul>
<li>Bonne intégration avec jQueryMobile</li>
<li>Permet de rapidement obtenir une application fonctionnelle et déployable sur les Market. Il existe même un <a href="https://build.phonegap.com/">système de build automatisé</a> qui permet d&#8217;obtenir son application packagée pour les différents OS sans installer un seul SDK (c&#8217;est une offre payante proposée par Nitobi)</li>
<li>Les plugins fournis en standard permettent de répondre à 80% du besoin pour des applications catalogues/consultation</li>
</ul>
<p>Les points faibles :</p>
<ul>
<li>Il ne s&#8217;agit &#8220;que&#8221; d&#8217;une API Javascript : l&#8217;implémentation des méthodes de callback est une charge non-négligeable</li>
<li>Il faut bien prendre en compte que si on développe des plugins spécifiques PhoneGap il faudra effectuer ce développement sur chaque plateforme cible (pour la partie native ET la partie Javascript). Seule “l’API” exposée par les méthodes Javascript reste stable entre plateformes, non pas le coeur de PhoneGap.</li>
<li>Le niveau de qualité des plugins, notamment de la communauté, est très hétérogène</li>
<li>Assez compliqué de faire une application vraiment &#8220;offline&#8221; : il faut alors utiliser manuellement le localStorage HTML5 + gérer de la synchronisation avec le serveur ensuite + traiter les erreurs JSON/Ajax. Je n&#8217;ai pas eu le temps de tester des outils <a href="http://code.google.com/p/openmobster/wiki/PhoneGapGetStarted">comme OpenMobster pour gérer la synchronisation</a>, mais cela s&#8217;annonce prometteur.</li>
</ul>
<h2>Pour quels projets ?</h2>
<p>Cette approche “un seul code pour l’ensemble de plateformes” limite le support des fonctionnalités au plus petit dénominateur commun. Il faut donc que le client soit conscient d&#8217;obtenir une application juste &#8220;moyenne&#8221; sur plusieurs plateformes (ie. au total sept OS sont supportés par PhoneGap) plutôt qu’une &#8220;très bonne&#8221; sur un périmètre plus réduit comme Android et iOS (quand même 70% de part de marché à eux deux). Ce n&#8217;est pas un drame mais il ne faut surtout pas s&#8217;imaginer que cela répond à 100% des besoins (ou faire imaginer cela au client <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Je prendrais juste trois exemples pour illustrer quelques limites :</p>
<ul>
<li>L&#8217;avantage évident des solutions hybride est de réduire les coûts de développement mais il ne faut pas oublier les coûts de maintenance : le développement hybride ne permet pas de réduire le périmètre de tests. D&#8217;autre part, le code étant partagé, une correction de bug devra être testée sur toutes les plateformes pour s&#8217;assurer de l&#8217;absence de régression</li>
<li>La comparaison entre les <a href="http://developer.android.com/design/index.html">Android Design Guidelines</a> et les <a href="http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/Introduction/Introduction.html)">iOS Mobile HIG Guidelines</a> permet d&#8217;identifier que les approches proposées par ces deux plateformes différents parfois radicalement. Proposer une IHM identique pour ses deux plateformes ne pourra logiquement se solder que par un écart entre l&#8217;ergonomie de l&#8217;application &#8220;hydride&#8221; et des autres applications de l&#8217;OS</li>
<li>Il n&#8217;est pas possible d&#8217;utiliser des services en tache de fond : une fois le composant navigateur fermé, l&#8217;application n&#8217;existe simplement plus. Il est donc impossible de proposer du push, de synchronisation en tache de fond ou des traitements en parallèles. La norme JavaScript <a href="http://en.wikipedia.org/wiki/Web_worker">WebWorkers</a> permet théoriquement de lancer plusieurs traitements en parallèle, mais n&#8217;est pas supportée par Android</li>
</ul>
<p>Il faut donc le dire clairement, l’approche proposée par le couple jQueryMobile / PhoneGap même si elle semble sexy n&#8217;est pas applicable à n&#8217;importe quel projet mobile et il faudra réfléchir au cas par cas pour s&#8217;assurer que la technologie employée permet de répondre dans le temps et le budget envisagé par le client.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/Q6yvitzJ-TQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/04/10/jquerymobile-et-phonegap-un-duo-gagnant-pour-vos-applications-mobiles/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/04/10/jquerymobile-et-phonegap-un-duo-gagnant-pour-vos-applications-mobiles/</feedburner:origLink></item>
		<item>
		<title>GWT et Spring Security : c’est possible</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/XlA579SW_H8/</link>
		<comments>http://blog.ippon.fr/2012/04/05/gwt-et-spring-security-cest-possible/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 12:15:46 +0000</pubDate>
		<dc:creator>David MARTIN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Tutoriel]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[gwt-rpc]]></category>
		<category><![CDATA[request factory]]></category>
		<category><![CDATA[sécurité]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[spring security]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5264</guid>
		<description><![CDATA[<p>Beaucoup d’applications nécessitent la mise en oeuvre de règles de sécurité dans tout ou partie de leurs fonctionnalités. Lorsque GWT est utilisé comme framework de présentation, les choses ne sont pas aussi simples qu’avec un framework plus traditionnel, où la nature des échanges client-serveur est plus claire et contrôlée.</p> <p>Avant toute chose, commençons par définir <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/04/05/gwt-et-spring-security-cest-possible/">GWT et Spring Security : c&#8217;est possible</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.gwtcontractor.com/img/logo-185x175.png" alt="GWT" width="148" height="140" /><img class="alignright" src="http://www.javasimples.com.br/wp-content/uploads/2010/09/spring_security_login1.jpg" alt="Spring Security" width="216" height="125" />Beaucoup d’applications nécessitent la mise en oeuvre de règles de sécurité dans tout ou partie de leurs fonctionnalités. Lorsque GWT est utilisé comme framework de présentation, les choses ne sont pas aussi simples qu’avec un framework plus traditionnel, où la nature des échanges client-serveur est plus claire et contrôlée.</p>
<p>Avant toute chose, commençons par définir ce qui sera présenté sous la notion de sécurité. L&#8217;objet du billet est de proposer à une application GWT la possibilité de gérer l’authentification des utilisateurs et le contrôle des droits sur les fonctionnalités exposées par le serveur. Ne sont donc pas présentés les aspects relatifs à la protection contre des attaques (XSS, CSRF, injections&#8230;).</p>
<h2>Particularités de GWT</h2>
<p><a href="http://blog.ippon.fr/2012/04/05/gwt-et-spring-security-cest-possible/gwt_security_spring/" rel="attachment wp-att-5273"><img class="alignright size-medium wp-image-5273" title="gwt_security_spring" src="http://blog.ippon.fr/wp-content/uploads/2012/03/gwt_security_spring-300x200.jpg" alt="Securité" width="300" height="200" /></a>Les mécanismes de communication client-serveur proposés par GWT sont multiples. Historiquement, GWT propose une approche bas niveau : le <a title="RequestBuilder" href="http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/http/client/RequestBuilder.html" target="_blank">RequestBuilder</a> ainsi qu’une approche plus haut niveau, orientée RPC, et justement nommée <a title="GWT-RPC" href="http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html" target="_blank">GWT-RPC</a>. Plus récemment, soit depuis GWT 2.1, un nouveau protocole d’échange, toujours basé sur http, est apparu, souvent désigné par son interface phare : <a title="RequestFactory" href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html" target="_blank">RequestFactory</a>. C&#8217;est un protocole orienté donnée, mais toujours de type RPC.<br />
Alors que <a title="RequestBuilder" href="http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/http/client/RequestBuilder.html" target="_blank">RequestBuilder</a> permet d’avoir accès aux caractéristiques des requêtes et réponses http (ajout de headers http, choix du verbe http à utiliser, …), les deux autres approches que sont <a title="GWT-RPC" href="http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html" target="_blank">GWT-RPC</a> et <a title="RequestFactory" href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html" target="_blank">RequestFactory</a> se positionnent à un niveau d’abstraction plus élevé et masquent ou bloquent l’usage de toutes ces possibilités.<br />
<a title="RequestBuilder" href="http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/http/client/RequestBuilder.html" target="_blank">RequestBuilder</a> reste une approche assez technique, souvent réservée à des besoins ponctuels précis, mais rarement répandue comme mécanisme global de communication avec les services exposés par le serveur. <a title="GWT-RPC" href="http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html" target="_blank">GWT-RPC</a> et <a title="RequestFactory" href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html" target="_blank">RequestFactory</a> apportent une bien meilleure productivité (non sans autres coûts cependant&#8230;).</p>
<p>La partie sécurité illustrée dans ce billet va s’appuyer sur Spring Security pour implémenter les règles de sécurité. Le framework va apporter les facilités de gestion des droits, mode de connexion, déconnexion, … Les principes présentés resteraient les mêmes pour un autre framework de sécurité (Apache Shiro (<a href="http://shiro.apache.org/">http://shiro.apache.org/</a>) par exemple) mais nécessiteraient bien sûr une adaptation du code.</p>
<p>Voici les fonctions importantes qu’il convient de traiter dans le cadre de la sécurisation d’une application :</p>
<ul>
<li>Authentification : quel type et à quel niveau ?</li>
<li>Validation des droits de l’utilisateur : vérification des droits et prise en charge des refus d’accès</li>
<li>Mécanisme de déconnexion, remember-me, &#8230;</li>
</ul>
<p>Avant d’aborder ces points, il convient de se pencher sur le coeur du problème : qu’est ce qui rend une application GWT différente d’une application plus classique dans la gestion de la sécurité ?</p>
<p>La première différence notable est la sensibilité aux données retournées lors des appels aux services, principalement dans les cas d’utilisation reposant sur <a title="GWT-RPC" href="http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html" target="_blank">GWT-RPC</a> ou <a title="RequestFactory" href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html" target="_blank">RequestFactory</a>. En effet, ces protocoles ne vont pas savoir interpréter les réponses classiques de Spring Security dans le cas d’une authentification nécessaire (traité classiquement par une redirection vers une page HTML contenant le formulaire de connexion) ou d’un refus d’accès à une ressource (redirection vers une page d’erreur 403 par exemple). Afin que ces protocoles soient éventuellement en mesure d&#8217;interpréter des messages correspondant à ces cas de figure, il leur faudra recevoir une réponse adaptée à leur format d’échange.<br />
Il va donc être nécessaire au serveur de différencier une requête issue d’un composant GWT de toute autre requête, afin d’adapter sa réponse au besoin spécifique.</p>
<p>Un autre point important, qui concerne autant <a title="GWT-RPC" href="http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html" target="_blank">GWT-RPC</a> que <a title="RequestFactory" href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html" target="_blank">RequestFactory</a> est la nature &#8220;RPC&#8221; de ces protocoles. Les URL qui seront appelées ne pourront pas (sauf effort supplémentaire coûteux et peu élégant) laisser présumer de l’action souhaitée coté serveur. Cette information appartient au “payload” de la requête. Et à moins de le décrypter (toujours possible, mais un peu coûteux) afin d’aller chercher cette information, il n’est pas possible d’appliquer une politique de sécurité basée uniquement sur un simple filtrage d’URL.</p>
<h2>Mécanismes de Spring Security</h2>
<p>Pour comprendre la proposition d’implémentation ci-après, il convient d’avoir à l’esprit quelques grands principes de fonctionnement de Spring Security.<br />
Le framework Spring Security fonctionne par application d’un filtre (au sens Filter de la spécification Java Servlet) sur les requêtes reçues par l’application. Ce filtre gère en fait une chaîne ordonnée de sous filtres (au sens Spring Security cette fois), et agit donc comme une sorte de point d’entrée vers un ensemble de contrôles séquentiels appliqués aux requêtes. Chacun de ces contrôles est dédié à une vérification ou action particulière.</p>
<p>Autre point important concernant Spring Security : les différentes façons de définir et contrôler les droits. Spring Security propose une première approche basée sur des règles de filtre d’URL : il est possible d’associer à des patterns d’URL des privilèges requis pour y accéder (ex. : “/admin/**” -&gt; “ROLE_ADMIN”).<br />
Par ailleurs, en substitution ou en complément selon les cas, il est aussi possible d&#8217;utiliser une autre approche, par instrumentation des classes de l&#8217;application afin de leur appliquer des restrictions d’usage. Par configuration XML ou par annotation (beaucoup plus simple), un service pourra alors voir ses méthodes décorées de notions de droits d’accès (ex. : <em>@Secured(&#8220;ROLE_ADMIN&#8221;)</em> sur une méthode <em>public boolean delete(MyResource resource)</em>);</p>
<p>Ces deux notions (fonctionnement par application d’une chaîne de filtres sur les requêtes ainsi que les deux modes de déclaration des contraintes de sécurité par patterns sur des URL d&#8217;une part ou instrumentation d&#8217;autre part) vont vous permettre de mieux comprendre ce qui suit.</p>
<p>Commençons maintenant le tour d’horizon des cas d’utilisation relatifs à la sécurité.</p>
<h2>La toolbox</h2>
<p>Afin de simplifier la création de la couche de sécurité, l’approche décrite ci-après s’appuie sur une petite librairie et une application “sample”, que vous trouverez ici : <a href="https://github.com/dmartinpro/gwt-security/">https://github.com/dmartinpro/gwt-security/</a></p>
<h2>L’authentification</h2>
<p>Comme vous le savez sûrement, l’authentification peut être réalisée de plusieurs façons. La plus courante consiste à utiliser un formulaire HTML afin de collecter dans la plupart des cas un identifiant accompagné d’un mot de passe. Le tout en général transite via une connexion sécurisée vers le serveur (SSL). Une autre approche, plus souvent utilisée pour sécuriser des services “techniques” (web service, API http), utilise l’authentification de type BASIC, toujours de façon sécurisée (clarté des informations oblige avec BASIC&#8230;). Il existe par ailleurs d’autres types (DIGEST, par certificat, indirecte par SSO, custom).<br />
Le mode d&#8217;authentification le plus ergonomique pour un utilisateur est celui par formulaire. Il permet d’offrir une présentation personnalisée, intégrée graphiquement à l’application, … des qualités qu’une popup pour une authentification BASIC ne propose pas.<br />
Dans le cas d’une application dont la couche de présentation est écrite en GWT, deux choix s’offrent alors : le formulaire d’authentification est-il aussi écrit avec GWT ou bien est-il proposé séparément sur une page dédiée ?</p>
<p>Illustrons le cas le plus intéressant : le formulaire est codé avec GWT (et donc mieux intégré au sein de l’application). Ce formulaire va être accédé de deux façons :</p>
<ul>
<li>Volontaire : l’utilisateur affiche le formulaire pour y saisir les informations</li>
<li>Involontaire : l’utilisateur tente d’accéder à une ressource protégée mais n’est pas encore connecté : il est redirigé vers le formulaire.</li>
</ul>
<p>Dans les deux cas, il devra poster les informations saisies vers un “service” particulier (un filtre au sens Spring Security : <a title="UsernamePasswordAuthenticationFilter" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.html" target="_blank">UsernamePasswordAuthenticationFilter</a>). Le code GWT lié au formulaire pourra s’appuyer sur <a title="RequestBuilder" href="http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/http/client/RequestBuilder.html" target="_blank">RequestBuilder</a> (voir <a title="com.gwtsecurity.client.LoginHandler" href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-pack/src/main/java/com/gwtsecurity/client/LoginHandler.java" target="_blank">com.gwtsecurity.client.LoginHandler</a>) pour cela.<br />
Le filtre <a title="UsernamePasswordAuthenticationFilter" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.html" target="_blank">UsernamePasswordAuthenticationFilter</a> délègue à deux objets le soin de gérer les cas d’authentification réussie et en échec. Il est important d’ores et déjà de savoir répondre au composant GWT sous une forme intelligible spécifique, distincte du cas nominal d’un formulaire traditionnel.<br />
Afin de répondre à ce besoin particulier, deux classes sont donc créées :<br />
<a title="GwtSavedRequestAwareAuthenticationSuccessHandler" href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-pack/src/main/java/com/gwtsecurity/server/GwtSavedRequestAwareAuthenticationSuccessHandler.java" target="_blank">GwtSavedRequestAwareAuthenticationSuccessHandler</a> et <a title="GwtSavedRequestAwareAuthenticationFailureHandler" href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-pack/src/main/java/com/gwtsecurity/server/GwtSavedRequestAwareAuthenticationFailureHandler.java" target="_blank">GwtSavedRequestAwareAuthenticationFailureHandler</a><br />
L’identification des requêtes GWT doit se faire sur un discriminant simple. L&#8217;approche proposée est de s&#8217;appuyer sur un header http spécifique. <a title="RequestBuilder" href="http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/http/client/RequestBuilder.html" target="_blank">RequestBuilder</a> va donc ajouter à la signature de la requête le header “X-GWT-Secured=true”.<br />
Dans le cas d’une requête http issue du composant <a title="RequestBuilder" href="http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/http/client/RequestBuilder.html" target="_blank">RequestBuilder</a> ainsi configuré, les deux classes pourront ainsi adapter leur réponse en retournant des structures simples à interpréter (une simple chaîne JSONdans un cas, et une réponse avec un “status code” explicite dans l’autre).</p>
<p>Dans le cas d’un accès dit “involontaire”, il convient de venir se greffer sur la classe <a title="ExceptionTranslationFilter" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/access/ExceptionTranslationFilter.html" target="_blank">ExceptionTranslationFilter</a> de Spring Security. Cette classe s’appuie sur un “<a title="AuthenticationEntryPoint" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/AuthenticationEntryPoint.html" target="_blank">AuthenticationEntryPoint</a>” pour proposer l’ “accès” à la méthode d’authentification requise. Dans le cas d’un formulaire, c’est <a title="LoginUrlAuthenticationEntryPoint" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPoint.html" target="_blank">LoginUrlAuthenticationEntryPoint</a> qui se charge d’effectuer une redirection vers la page du formulaire.<br />
Une telle redirection vers une page HTML contenant le formulaire d&#8217;authentification ne serait pas comprise par le composant GWT appelant et sera difficilement exploitable.<br />
Aussi, un nouvel objet de type <a title="AuthenticationEntryPoint" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/AuthenticationEntryPoint.html" target="_blank">AuthenticationEntryPoint</a> va devoir savoir lui aussi faire la distinction entre une requête issue d&#8217;un composant GWT et une requête autre et répondre dans le cas d’une requête issue de GWT quelque chose d’interpretable.<br />
C’est le rôle que va jouer la classe <a title="GwtAwareAuthenticationEntryPoint" href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-pack/src/main/java/com/gwtsecurity/server/GwtAwareAuthenticationEntryPoint.java" target="_blank">GwtAwareAuthenticationEntryPoint</a> en produisant une réponse JSON à toute requête reconnue comme issue de GWT. Le cas échéant, elle déléguera à <a title="LoginUrlAuthenticationEntryPoint" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPoint.html" target="_blank">LoginUrlAuthenticationEntryPoint</a>.<br />
La classe <a title="ExceptionTranslationFilter" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/access/ExceptionTranslationFilter.html" target="_blank">ExceptionTranslationFilter</a> gérant aussi les exceptions de type <a title="AccessDeniedException" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/access/AccessDeniedException.html" target="_blank">AccessDeniedException</a>, nous avons ainsi aussi la matière pour prendre en compte les cas de privilèges insuffisants du paragraphe suivant.</p>
<h2>Contrôle des droits d’accès</h2>
<p>Comme évoqué plus haut, le contrôle des droits d’accès ne peut pas se faire sur la simple base d’un filtre sur les URL. A ce niveau, seule une sécurité très macroscopique peut éventuellement trouver place (exemple : “il faut être connecté pour accéder à cette ressource”). Dès lors qu’on souhaite avoir un contrôle plus fin, du type : la suppression de la ressource X requiert un privilège “DELETE_RESOURCE” alors que sa consultation ne requiert que “GET_RESOURCE”, il convient de trouver une approche alternative plus fine.<br />
Spring Security propose deux façons de procéder pour définir et contrôler les droits. Comme évoqué, l’approche par simple application d’un filtre sur l’URL est insuffisante sur des appels de type RPC. Par contre une sécurisation des services par instrumentation du code permet de répondre à ce problème d’ “obfuscation” de l’action demandée.</p>
<p>Comme vu précédemment, en se greffant sur <a title="ExceptionTranslationFilter" href="http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/web/access/ExceptionTranslationFilter.html" target="_blank">ExceptionTranslationFilter</a>, il est simple de prendre en compte le cas d’un accès refusé pour manque de privilège (réalisé aussi par la classe <a title="GwtAwareAuthenticationEntryPoint" href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-pack/src/main/java/com/gwtsecurity/server/GwtAwareAuthenticationEntryPoint.java" target="_blank">GwtAwareAuthenticationEntryPoint</a>).<br />
Ce qui reste à présenter maintenant, c’est la mécanique d’interception de ces réponses dans le code GWT, que cela soit dans le cas d’un appel <a title="GWT-RPC" href="http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html" target="_blank">GWT-RPC</a> ou dans le cas d’un appel via <a title="RequestFactory" href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html" target="_blank">RequestFactory</a>.<br />
Les deux approches partagent le même concept : un callback spécialisé va prendre en charge l&#8217;interprétation de ces réponses. Dans le cas de <a title="GWT-RPC" href="http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html" target="_blank">GWT-RPC</a>, c’est la classe <a title="SecuredAsyncCallback" href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-pack/src/main/java/com/gwtsecurity/client/SecuredAsyncCallback.java" target="_blank">SecuredAsyncCallback</a> qui va s’en charger, et <a href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-pack/src/main/java/com/gwtsecurity/client/SecuredReceiver.java" target="_blank">SecuredReceiver</a> pour <a title="RequestFactory" href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html" target="_blank">RequestFactory</a>.<br />
Dans les deux cas, les méthodes <em>onFailure()</em> vont traquer une réponse liée à la sécurité et la gérer, sinon déléguer le traitement de l’erreur à une nouvelle méthode <em>onServiceFailure()</em> qui remplace le <em>onFailure()</em> par défaut.<br />
Le code, pour un appel <a title="GWT-RPC" href="http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html" target="_blank">GWT-RPC</a>, devient alors :</p>
<pre class="brush: java; title: ; notranslate">

@UiHandler(&quot;gwtRPCButton&quot;)
public void onRpcButtonClick(ClickEvent e) {
 ApplicationResourcesFactory.getSimpleService().getData(new SecuredAsyncCallback&lt;String&gt;() {
   public void onServiceFailure(Throwable caught) {
     // Show the RPC error message to the user
     DialogBox dialogBox = new DialogBox();
     dialogBox.center();
     dialogBox.setModal(true);
     dialogBox.setGlassEnabled(true);
     dialogBox.setAutoHideEnabled(true);
     dialogBox.setText(&quot;Remote Procedure Call - Failure&quot;);
     dialogBox.show();
   }
   public void onSuccess(String result) {
     DialogBox dialogBox = new DialogBox();
     dialogBox.center();
     dialogBox.setModal(true);
     dialogBox.setGlassEnabled(true);
     dialogBox.setAutoHideEnabled(true);
     dialogBox.setText(result);
     dialogBox.show();
   }
 });
}
</pre>
<h2>Autres fonctionnalités</h2>
<p>Parmi les autres fonctionnalités, on peut ne peut pas oublier la déconnexion. Elle est tout aussi utile que la connexion et ne pas la proposer est une potentielle faille.<br />
Spring Security propose un filtre simple pour répondre à ce besoin. Il suffit d’appeler une URL particulière, au besoin personnalisable, pour détruire le contexte de sécurité. Cela fonctionne très bien avec une authentification par formulaire ou par cookie (remember me). Par contre, une authentification de type BASIC (par exemple) sera automatiquement récréée à la prochaine requête et seule une fermeture du navigateur, en plus de ce mécanisme (à cause du potentiel cookie du remember me), peut avoir raison de l’authentification (à noter qu’il existe une autre approche moins radicale, mais aussi moins officielle, que la fermeture du navigateur, que je ne documenterai pas ici).<br />
Afin de supporter cette fonction de déconnexion, il convient donc de créer un composant GWT dont la responsabilité est la création d’une requête http pointant sur cette URL de déconnexion.<br />
Rien de plus simple avec <a title="RequestBuilder" href="http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/http/client/RequestBuilder.html" target="_blank">RequestBuilder</a>.Voir pour cela le code de la classe <a href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-pack/src/main/java/com/gwtsecurity/client/ui/LogoutButton.java" target="_blank">com.gwtsecurity.client.ui.LogoutButton</a>.</p>
<p>L’option souvent associée à l’authentification “classique” est la fonctionnalité de “remember me”. Cette option permet de stocker dans un cookie une information qui va permettre lors d’une visite ultérieure, et même après une expiration de session sur le serveur (c&#8217;est l&#8217;intérêt d&#8217;ailleurs), de restaurer un contexte de sécurité. Cette option est très intéressante, d’autant plus avec les applications GWT qui favorisent le travail déconnecté (la richesse locale de l&#8217;application permet de travailler sans interagir forcement avec le serveur).<br />
Bonne nouvelle : il n’y a rien à faire de spécifique pour supporter cette fonctionnalité avec GWT, alors autant en faire usage. Il s&#8217;agit donc d&#8217;ajouter la configuration nécessaire à Spring Security pour activer cette fonctionnalité.</p>
<h2>Assemblage du tout</h2>
<p>Cette configuration globale de la sécurité pour GWT nécessite quelques ajustements coté Spring Security. La configuration par défaut proposée par le namespace Spring Security ne peut plus suffire et il faut donc déclarer “à l’ancienne” la sécurité. Rien de compliqué lorsqu’on a cerné les responsabilités de chaque composant et le fonctionnement global, mais cela peut donner quelques mots de tête au démarrage. La configuration illustrée dans l’application d’exemple peut servir de base : <a title="applicationContext-security.xml" href="https://github.com/dmartinpro/gwt-security/blob/master/gwt-security-sample/src/main/resources/META-INF/spring/applicationContext-security.xml" target="_blank">/gwt-security-sample/src/main/resources/META-INF/spring/applicationContext-security.xml</a></p>
<h2>Conclusion</h2>
<p>La solution présentée mérite sûrement des améliorations ou adaptations (je vous invite à forker le projet), mais elle pose quelques bases qui pourront vous aider rapidement à mettre en place les composants nécessaires à la sécurisation de votre application.</p>
<p>Par ailleurs, si vous souhaitez approfondir le domaine de la sécurité dans les applications Java, je vous invite à (re)consulter le livre blanc sur le sujet : <a href="http://www.ippon.fr/livres-blancs">http://www.ippon.fr/livres-blancs</a>.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/XlA579SW_H8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/04/05/gwt-et-spring-security-cest-possible/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/04/05/gwt-et-spring-security-cest-possible/</feedburner:origLink></item>
		<item>
		<title>Google fait les cartes, Spring fait le REST</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/Pvyr3OwNqH4/</link>
		<comments>http://blog.ippon.fr/2012/04/04/google-fait-les-cartes-spring-fait-le-rest/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 20:13:55 +0000</pubDate>
		<dc:creator>Bertrand PINEL</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Tutoriel]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[JAXB]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4707</guid>
		<description><![CDATA[<p>La cartographie est maintenant utilisée communément sur le Web. On ne peut plus consulter un site marchand sans pouvoir calculer son itinéraire jusqu&#8217;au point de vente, se renseigner sur un pays sans pouvoir explorer sa géographie, parfois même faire une sortie jogging ou vélo sans consulter ultérieurement son parcours sur une carte&#8230;</p> <p>Les deux grands <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/04/04/google-fait-les-cartes-spring-fait-le-rest/">Google fait les cartes, Spring fait le REST</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.gizmocrazed.com/wp-content/uploads/2011/11/google-maps-logo.png" alt="Logo google maps" width="124" height="137" />La cartographie est maintenant utilisée communément sur le Web. On ne peut plus consulter un site marchand sans pouvoir calculer son itinéraire jusqu&#8217;au point de vente, se renseigner sur un pays sans pouvoir explorer sa géographie, parfois même faire une sortie jogging ou vélo sans consulter ultérieurement son parcours sur une carte&#8230;</p>
<p>Les deux grands fournisseurs de cartographie sont actuellement Google avec sa <a title="Google Maps API" href="http://code.google.com/intl/fr-FR/apis/maps/index.html" target="_blank">Google Maps API</a> et Microsoft avec <a title="Bing Maps" href="http://www.microsoft.com/maps/" target="_blank">Bing Maps</a>. La plupart du temps, leur utilisation passe par du code Javascript exécuté côté client. Pourtant, il est parfois nécessaire de faire des traitements de géolocalisation côté serveur. Pour cela, les deux fournisseurs ont prévu une API de type REST. La suite de cet article ne s&#8217;intéressera plus qu&#8217;au monde &#8220;Google&#8221; et à son <a title="API" href="http://code.google.com/intl/fr-FR/apis/maps/documentation/webservices/index.html">API</a>, capable de générer une réponse de type XML ou JSON.</p>
<h2><span id="more-4707"></span>Be API avec le REST de Google !</h2>
<h3>Les principes de base</h3>
<p>Pas de grosse surprise pour effectuer une requête géographique : on reste sur des principes REST classiques, avec une requête pour effectuer une géolocalisation inversée (à partir d&#8217;une adresse postale) du type :</p>
<p style="text-align: center;">http://maps.googleapis.com/maps/api/geocode/xml?address=90+rue+Baudin+92300+Levallois+Perret&amp;sensor=false</p>
<p>Cette requête, qui peut être jouée directement sur un navigateur, permet de récupérer un message XML du type :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;GeocodeResponse&gt;
  &lt;status&gt;OK&lt;/status&gt;
  &lt;result&gt;
    &lt;type&gt;street_address&lt;/type&gt;
    &lt;formatted_address&gt;90 Rue Baudin, 92300 Levallois-Perret, France&lt;/formatted_address&gt;
    &lt;address_component&gt;
      &lt;long_name&gt;90&lt;/long_name&gt;
      &lt;short_name&gt;90&lt;/short_name&gt;
      &lt;type&gt;street_number&lt;/type&gt;
    &lt;/address_component&gt;
    &lt;address_component&gt;
      &lt;long_name&gt;Rue Baudin&lt;/long_name&gt;
      &lt;short_name&gt;Rue Baudin&lt;/short_name&gt;
      &lt;type&gt;route&lt;/type&gt;
    &lt;/address_component&gt;
    &lt;address_component&gt;
      &lt;long_name&gt;Levallois-Perret&lt;/long_name&gt;
      &lt;short_name&gt;Levallois-Perret&lt;/short_name&gt;
      &lt;type&gt;locality&lt;/type&gt;
      &lt;type&gt;political&lt;/type&gt;
    &lt;/address_component&gt;
    &lt;address_component&gt;
      &lt;long_name&gt;Hauts-de-Seine&lt;/long_name&gt;
      &lt;short_name&gt;92&lt;/short_name&gt;
      &lt;type&gt;administrative_area_level_2&lt;/type&gt;
      &lt;type&gt;political&lt;/type&gt;
    &lt;/address_component&gt;
    &lt;address_component&gt;
      &lt;long_name&gt;&amp;#xCE;le-de-France&lt;/long_name&gt;
      &lt;short_name&gt;IdF&lt;/short_name&gt;
      &lt;type&gt;administrative_area_level_1&lt;/type&gt;
      &lt;type&gt;political&lt;/type&gt;
    &lt;/address_component&gt;
    &lt;address_component&gt;
      &lt;long_name&gt;France&lt;/long_name&gt;
      &lt;short_name&gt;FR&lt;/short_name&gt;
      &lt;type&gt;country&lt;/type&gt;
      &lt;type&gt;political&lt;/type&gt;
    &lt;/address_component&gt;
    &lt;address_component&gt;
      &lt;long_name&gt;92300&lt;/long_name&gt;
      &lt;short_name&gt;92300&lt;/short_name&gt;
      &lt;type&gt;postal_code&lt;/type&gt;
    &lt;/address_component&gt;
    &lt;geometry&gt;
      &lt;location&gt;
        &lt;lat&gt;48.8989222&lt;/lat&gt;
        &lt;lng&gt;2.2877605&lt;/lng&gt;
      &lt;/location&gt;
      &lt;location_type&gt;RANGE_INTERPOLATED&lt;/location_type&gt;
      &lt;viewport&gt;
        &lt;southwest&gt;
          &lt;lat&gt;48.8975800&lt;/lat&gt;
          &lt;lng&gt;2.2864066&lt;/lng&gt;
        &lt;/southwest&gt;
        &lt;northeast&gt;
          &lt;lat&gt;48.9002780&lt;/lat&gt;
          &lt;lng&gt;2.2891046&lt;/lng&gt;
        &lt;/northeast&gt;
      &lt;/viewport&gt;
      &lt;bounds&gt;
        &lt;southwest&gt;
          &lt;lat&gt;48.8989222&lt;/lat&gt;
          &lt;lng&gt;2.2877507&lt;/lng&gt;
        &lt;/southwest&gt;
        &lt;northeast&gt;
          &lt;lat&gt;48.8989358&lt;/lat&gt;
          &lt;lng&gt;2.2877605&lt;/lng&gt;
        &lt;/northeast&gt;
      &lt;/bounds&gt;
    &lt;/geometry&gt;
  &lt;/result&gt;
&lt;/GeocodeResponse&gt;
</pre>
<p>Le message résultat est immédiatement compréhensive à un esprit humain. C&#8217;est sans doute pour cela qu&#8217;il n&#8217;est absolument pas documenté par Google, qui ne fournit pas même un XSD&#8230;  <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </p>
<h3>REST ou JSON ?</h3>
<p>Google préconise plutôt l&#8217;utilisation du service JSON.</p>
<p>JSON est clairement une notation beaucoup plus compacte que le verbeux XML et donc plus efficace. Cependant, elle n&#8217;offre pas tout l&#8217;attirail de XML, notamment en ce qui concerne la description des signatures de service et le contrôle des formats des messages. J&#8217;ai toujours tendance à privilégier XML pour les échanges de serveur à serveur et JSON pour les interactions internes à un système (interrogation AJAX d&#8217;un client web sur son serveur par exemple).</p>
<p>On est ici sur des échanges serveur à serveur, donc va pour le XML !</p>
<h2>Comment conjuguer REST et Spring</h2>
<h3>La classe RestTemplate</h3>
<p>Spring fournit la classe RestTemplate, qui elle-même fournit des méthodes de haut niveau pour invoquer les 6 méthodes principales du protocole HTTP. Elle simplifie énormément la programmation de la partie cliente d&#8217;un appel REST en gérant toute la plomberie habituelle liée à l&#8217;utilisation du protocole HTTP et la conversion des objets Java.</p>
<p>La lecture de la doc Spring conduit vite à la constatation que l&#8217;appel du service Google maps précédent peut se faire sous la forme :</p>
<pre class="brush: java; light: true; title: ; notranslate">
	restTemplate.getForObject(
		&quot;http://maps.googleapis.com/maps/api/geocode/xml?address={address}&amp;sensor=false&quot;,
		String.class,&quot;90 rue Baudin, 92300 Levallois Perret&quot;);
</pre>
<h3>L&#8217;encapsulation de JAXB 2</h3>
<p>Le code suivant est simple et de bon aloi, mais ne résout pas la problématique du mapping du résultat (ici un flux XML) vers le graphe d&#8217;objets Java.</p>
<p>Heureusement, et c&#8217;est là qu&#8217;entre la magie du RESTTemplate, il peut être configuré à l&#8217;aide d&#8217;un marshaller fourni par Spring :</p>
<pre class="brush: java; light: true; title: ; notranslate">
org.springframework.oxm.jaxb.Jaxb2Marshaller
</pre>
<p>Rien de plus à ajouter que de référencer cette classe, à la fois comme marshaller et comme unmarshaller pour retrouver son modèle métier directement mappé sur le flux XML ! C&#8217;est de la pure magie, mais c&#8217;est bon !</p>
<h2>Un petit projet vaut mieux qu&#8217;un long post de blog&#8230;</h2>
<h3>La Mise en place Maven</h3>
<p>Il n&#8217;existe pas à ma connaissance d&#8217;archetype tout prêt pour faire du Spring. Pour notre exemple, nous partirons donc d&#8217;un archetype simple, en tapant la commande suivante :</p>
<pre class="brush: bash; light: true; title: ; notranslate">
 mvn archetype:generate \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DgroupId=fr.ippon.gmap \
  -DartifactId=restgmap \
  -Dversion=1.0-SNAPSHOT
</pre>
<p>On obtient ainsi un projet restgmap, dans lequel nous allons nous empresser de modifer le fichier pom.xml pour notamment ajouter les dépendances à Spring :</p>
<pre class="brush: xml; title: ; notranslate">
  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;junit&lt;/groupId&gt;
      &lt;artifactId&gt;junit&lt;/artifactId&gt;
      &lt;version&gt;4.10&lt;/version&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.apache.log4j&lt;/groupId&gt;
      &lt;artifactId&gt;com.springsource.org.apache.log4j&lt;/artifactId&gt;
      &lt;version&gt;1.2.15&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.apache.commons&lt;/groupId&gt;
      &lt;artifactId&gt;com.springsource.org.apache.commons.logging&lt;/artifactId&gt;
      &lt;version&gt;1.1.1&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.springframework&lt;/groupId&gt;
      &lt;artifactId&gt;org.springframework.core&lt;/artifactId&gt;
      &lt;version&gt;${spring.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.springframework&lt;/groupId&gt;
      &lt;artifactId&gt;org.springframework.test&lt;/artifactId&gt;
      &lt;version&gt;${spring.version}&lt;/version&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.springframework&lt;/groupId&gt;
      &lt;artifactId&gt;org.springframework.context&lt;/artifactId&gt;
      &lt;version&gt;${spring.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.springframework&lt;/groupId&gt;
      &lt;artifactId&gt;spring-oxm&lt;/artifactId&gt;
      &lt;version&gt;${spring.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.springframework&lt;/groupId&gt;
      &lt;artifactId&gt;org.springframework.web&lt;/artifactId&gt;
      &lt;version&gt;${spring.version}&lt;/version&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;
  &lt;properties&gt;
    &lt;spring.version&gt;3.0.5.RELEASE&lt;/spring.version&gt;
  &lt;/properties&gt;
  &lt;repositories&gt;
    &lt;repository&gt;
      &lt;id&gt;com.springsource.repository.bundles.release&lt;/id&gt;
      &lt;name&gt;SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases&lt;/name&gt;
      &lt;url&gt;http://repository.springsource.com/maven/bundles/release&lt;/url&gt;
    &lt;/repository&gt;
    &lt;repository&gt;
      &lt;id&gt;com.springsource.repository.bundles.external&lt;/id&gt;
      &lt;name&gt;SpringSource Enterprise Bundle Repository - External Bundle Releases&lt;/name&gt;
      &lt;url&gt;http://repository.springsource.com/maven/bundles/external&lt;/url&gt;
    &lt;/repository&gt;
  &lt;/repositories&gt;
</pre>
<h3>La création du modèle</h3>
<p>L&#8217;analyse de la réponse fournie lors d&#8217;une interrogation du service de géolocalisation permet assez facilement de construire un modèle objet comme suit :</p>
<p><img title="Modèle de géolocalisation" src="http://blog.ippon.fr/wp-content/uploads/2012/01/gmap-model.png" alt="Modèle de géolocalisation" width="672" height="567" /></p>
<p>Ce modèle en poche, les annotations JAXB se font très facilement même s&#8217;il aurait été plus simple de faire tout cela à partir d&#8217;une XSD, directement fournie par Google&#8230;</p>
<p>On a par exemple la classe <em><strong>Geometry</strong></em> comme suit :</p>
<pre class="brush: java; title: ; notranslate">
package fr.ippon.gmap.model.gmap;

import javax.xml.bind.annotation.XmlElement;

public class Geometry {
    @XmlElement
    private GeoPosition location;
    @XmlElement
    private Viewport viewport;
    @XmlElement
    private Viewport bounds;

    public GeoPosition getLocation() {
        return location;
    }
}
</pre>
<p>Pour avoir toutes les informations sur les classes annotées, vous pouvez vous référerez au code qui est disponible sur GitHub à l&#8217;adresse : <a title="github.com/bpinel/restgmap" href="https://github.com/bpinel/restgmap">https://github.com/bpinel/restgmap</a></p>
<h3>Le service et son test unitaire</h3>
<p>Le reste du code est tout ce qu&#8217;il y a de plus standard. Et je vous laisse découvrir le service et les tests unitaires dans le projet git.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/Pvyr3OwNqH4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/04/04/google-fait-les-cartes-spring-fait-le-rest/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/04/04/google-fait-les-cartes-spring-fait-le-rest/</feedburner:origLink></item>
		<item>
		<title>Ippon Technologies est partenaire PrimeFaces</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/fbSgsHduSYQ/</link>
		<comments>http://blog.ippon.fr/2012/04/02/ippon-technologies-est-partenaire-primefaces/#comments</comments>
		<pubDate>Mon, 02 Apr 2012 13:29:36 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippon]]></category>
		<category><![CDATA[Ippon Technologies]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[PrimeFaces]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5341</guid>
		<description><![CDATA[<p>Chez Ippon Technologies, nous aimons les solutions standards, efficaces et Open Source. C&#8217;est donc tout naturellement que nous avons fait le choix de PrimeFaces comme librairie de composants JSF chez plusieurs de nos clients.</p> <p>Depuis son apparition, PrimeFaces est dans la pratique en train de supplanter les autres bibliothèques de composants JSF, grâce à sa simplicité <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/04/02/ippon-technologies-est-partenaire-primefaces/">Ippon Technologies est partenaire PrimeFaces</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://cagataycivici.files.wordpress.com/2011/05/logo.png" alt="" width="288" height="84" />Chez Ippon Technologies, nous aimons les solutions standards, efficaces et Open Source. C&#8217;est donc tout naturellement que nous avons fait le choix de <a href="http://www.primefaces.org/" target="_blank">PrimeFaces</a> comme librairie de composants JSF chez plusieurs de nos clients.</p>
<p>Depuis son apparition, PrimeFaces est dans la pratique en train de supplanter les autres bibliothèques de composants JSF, grâce à sa simplicité et à ses performances. <a href="http://www.google.com/trends/?q=richfaces,+icefaces,+primefaces" target="_blank">Cette recherche Google Trends en est la meilleure illustration</a>.</p>
<p>Nous apprécions en particulier :</p>
<ul>
<li>La légèreté et la performance de l&#8217;interface graphique</li>
<li>Le fait d&#8217;utiliser JQuery, ce qui permet facilement de personnaliser l&#8217;interface</li>
<li>La rapidité des développements, grâce à des jeux de composants très bien conçus</li>
<li>Son excellente intégration avec Spring Web Flow, ce qui permet de réaliser des applications complexes (utilisant en particulier un persistence context étendu afin de gérer les conversations)</li>
<li>Sa communauté très dynamique</li>
<li>Le respect des standards, qui reste une garantie de pérennité pour nos clients</li>
</ul>
<p>Par conséquent, nous avons décidé de nouer un partenariat avec <a href="http://www.prime.com.tr/" target="_blank">Prime Technoloji</a>, la société développant PrimeFaces. Comme vous pouvez le constater, aussi bien sur la <a href="http://www.ippon.fr/prime-technology" target="_blank">page partenaire d&#8217;Ippon Technologies</a> que sur la <a href="http://www.primefaces.org/partners.html" target="_blank">page partenaire de PrimeFaces</a>, Ippon Technologies est aujourd&#8217;hui la seule société en France proposant :</p>
<ul>
<li><a href="http://www.ippon.fr/formation/primefaces" target="_blank">Les formations officielles et certifiantes PrimeFaces</a>, conçues par Çağatay Çivici en personne!</li>
<li>Le support officiel PrimeFaces</li>
</ul>
<p>Et bien entendu nous proposons toujours nos services de conseil et d&#8217;architecture autour de Java EE, JSF et donc PrimeFaces !</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/fbSgsHduSYQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/04/02/ippon-technologies-est-partenaire-primefaces/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/04/02/ippon-technologies-est-partenaire-primefaces/</feedburner:origLink></item>
		<item>
		<title>Livre blanc Ippon : Grilles de données mémoire</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/WtgzFBdNNEg/</link>
		<comments>http://blog.ippon.fr/2012/03/27/livre-blanc-ippon-grilles-de-donnees-memoire/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 08:00:21 +0000</pubDate>
		<dc:creator>Christophe PARAGEAUD</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Livre Blanc]]></category>
		<category><![CDATA[Coherence]]></category>
		<category><![CDATA[Gemfire]]></category>
		<category><![CDATA[IMDG]]></category>
		<category><![CDATA[Infinispan]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5309</guid>
		<description><![CDATA[<p>Plus que de simples caches, pas tout à fait des solutions NoSQL, surtout pas des bases de données mémoire, la définition des In memory Data Grids (IMDG) n&#8217;est pas simple.</p> <p>Les IMDG font partie du paysage depuis quelques temps mais on les imagine réservés aux applications complexes telles que celles que l&#8217;on rencontre dans la <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/03/27/livre-blanc-ippon-grilles-de-donnees-memoire/">Livre blanc Ippon : Grilles de données mémoire</a></span>]]></description>
			<content:encoded><![CDATA[<p><span style="font-family: Arial, sans-serif; font-size: small;"><span style="color: #000000;">Plus que de simples caches, pas tout à fait des solutions NoSQL, surtout pas des bases de données mémoire, la définition des In memory Data Grids (IMDG) n&#8217;est pas simple.</span></span></p>
<p><span style="font-family: Arial, sans-serif; font-size: small;"><span style="color: #000000;">Les IMDG font partie du paysage depuis quelques temps mais on les imagine réservés aux applications complexes telles que celles que l&#8217;on rencontre dans la finance, ou alors réservés à des traitements de masse.</span></span></p>
<p><span style="font-family: Arial, sans-serif; font-size: small;"><span style="color: #000000;">Or ce n&#8217;est pas vraiment le cas lorsque l&#8217;on regarde les cas d&#8217;application les plus courants, en effet elles peuvent répondre aux besoins suivants :</span></span></p>
<ul style="list-style-type: circle;">
<li><span style="font-family: Arial, sans-serif; font-size: small;"><span style="color: #000000;">Performances (améliorer les performances des accès aux données, </span></span><span style="font-family: Arial, sans-serif; font-size: small;">soulager une source de données).</span></li>
<li><span style="font-family: Arial, sans-serif; font-size: small;"><span style="color: #000000;">Disponibilité (augmenter la disponibilité d&#8217;une application).</span></span></li>
<li><span style="font-family: Arial, sans-serif; font-size: small;"><span style="color: #000000;">Scalabilité (assurer une scalabilité horizontale).</span></span></li>
</ul>
<p><span style="color: #000000; font-size: small;"><span style="font-family: Arial, sans-serif;">Ce livre blanc sur les IMDG Java en donne une définition ainsi que leurs principales caractéristiques. Il présente les cas d&#8217;utilisation les plus courants, les bonnes pratiques ainsi que les écueils que l&#8217;on peut rencontrer lors de la mise en œuvre de ce type de solution.</span></span></p>
<p><span style="color: #000000; font-size: small;"><span style="font-family: Arial, sans-serif;">De plus il présente une étude de trois produits les plus répandus du marché :</span></span></p>
<ul style="list-style-type: circle;">
<li><span style="color: #000000; font-size: small;"><span style="font-family: Arial, sans-serif;"><a href="http://www.oracle.com/fr/products/middleware/coherence/index.html">Oracle Coherence</a></span></span></li>
<li><span style="color: #000000; font-size: small;"><span style="font-family: Arial, sans-serif;"><a href="http://www.jboss.org/infinispan">JBoss Infinispan</a></span></span></li>
<li><span style="font-family: Arial, sans-serif; font-size: small;"><span style="color: #000000;"><a href="http://www.vmware.com/products/application-platform/vfabric-gemfire/overview.html">VMWare Gemfire</a></span></span></li>
</ul>
<p><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: Arial, sans-serif;">Si vous souhaitez approfondir le sujet ou tout simplement le (re)découvrir, vous pouvez </span></span><a href="http://www.ippon.fr/livres-blancs"><span style="color: #9d000e;"><span style="font-family: Arial, sans-serif;">télécharger le livre blanc dans la rubrique dédiée sur le site d’Ippon Technologies</span></span></a><span style="color: #000000;"><span style="font-family: Arial, sans-serif;">.</span></span></span></p>
<p><span style="font-family: Arial, sans-serif; font-size: small;"><span style="color: #000000;">Et bien évidement ce blog est un lieu d&#8217;échanges, j’attends donc avec impatience vos remarques et réactions suite à votre lecture.</span></span></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/WtgzFBdNNEg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/03/27/livre-blanc-ippon-grilles-de-donnees-memoire/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/03/27/livre-blanc-ippon-grilles-de-donnees-memoire/</feedburner:origLink></item>
		<item>
		<title>Scrum Day : J – 7 !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/deGyeb828Qo/</link>
		<comments>http://blog.ippon.fr/2012/03/20/scrum-day-j-7/#comments</comments>
		<pubDate>Tue, 20 Mar 2012 07:24:03 +0000</pubDate>
		<dc:creator>Anne GABRILLAGUES</dc:creator>
				<category><![CDATA[Agilité]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[Scrumday]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5262</guid>
		<description><![CDATA[<p></p> <p>La date fatidique approchant, nous sommes en train de préparer activement nos interventions :</p> <p> &#8211; rodage de l&#8217;Agile Game &#8220;Lego4Scrum&#8221; dans nos agences de Paris/ Levallois et Nantes (dont notamment une session à 30 personnes animée sur Nantes par Alvin, qui sera notre maître de cérémonie le jour dit). Nous remercions d&#8217;ailleurs les participants <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/03/20/scrum-day-j-7/">Scrum Day : J &#8211; 7 !</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://blog.ippon.fr/wp-content/uploads/2012/03/IMG_20120313_200354-001.jpg" alt="" width="302" height="207" /></p>
<p>La date fatidique approchant, nous sommes en train de préparer activement nos interventions :</p>
<p> &#8211; rodage de l&#8217;Agile Game &#8220;Lego4Scrum&#8221; dans nos agences de Paris/ Levallois et Nantes (dont notamment une session à 30 personnes animée sur Nantes par Alvin, qui sera notre maître de cérémonie le jour dit). Nous remercions d&#8217;ailleurs les participants à ces sessions, en espérant qu&#8217;ils auront passé un moment riche en bonne humeur et en agilité.</p>
<p> &#8211; répétition de la présentation &#8220;Mise en application de Scrum sur le projet BusinessCenter de PagesJaunes&#8221; par  Raphael, Scrum Master du projet.</p>
<p>Rejoignez-nous le 27 Mars au <a href="http://scrumday.fr/">Scrum Day</a> !</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/deGyeb828Qo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/03/20/scrum-day-j-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/03/20/scrum-day-j-7/</feedburner:origLink></item>
		<item>
		<title>Bienvenue sur le tatami : Ippon lance un grand concours de code pour Devoxx France !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/sqstYchAUTw/</link>
		<comments>http://blog.ippon.fr/2012/03/19/bienvenue-sur-le-tatami-ippon-lance-un-grand-concours-de-code-pour-devoxx-france/#comments</comments>
		<pubDate>Mon, 19 Mar 2012 12:52:14 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippon]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Concours]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Ippon Technologies]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5248</guid>
		<description><![CDATA[<p>A gagner : 1 Galaxy Tab et deux places de 2 jours pour Devoxx France</p> Le jeu en quelques phrases <p>A l’occasion de Devoxx France, nous avons décidé de lancer un grand concours de code : attention, ce n’est pas un simple kata de code, l’objectif est de développer une vraie application !</p> <p>Notre projet <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/03/19/bienvenue-sur-le-tatami-ippon-lance-un-grand-concours-de-code-pour-devoxx-france/">Bienvenue sur le tatami : Ippon lance un grand concours de code pour Devoxx France !</a></span>]]></description>
			<content:encoded><![CDATA[<p><em><strong>A gagner : 1 Galaxy Tab et deux places de 2 jours pour Devoxx France</strong></em></p>
<h2>Le jeu en quelques phrases</h2>
<p>A l’occasion de <a href="http://www.devoxx.fr/">Devoxx France</a>, nous avons décidé de lancer un grand concours de code : attention, ce n’est pas un simple kata de code, l’objectif est de développer une vraie application !</p>
<p>Notre projet se nomme Tatami. Il s’agit d’un clone de Twitter orienté entreprise : il sera utilisable au sein d’une même entreprise (en l&#8217;occurrence Ippon Technologies) afin de permettre à ses salariés d’avoir leur propre plate-forme de microblogging interne et privée.<br />
Le code est disponible ici : <a href="https://github.com/ippontech/tatami">https://github.com/ippontech/tatami</a></p>
<p>Tatami est l’application qui sera utilisée à Devoxx France pour la session “<a href="http://www.devoxx.fr/display/FR12/Nouveau+look+pour+une+nouvelle+vie++Spring%2C+JQuery+et+HTML5">Nouveau look pour une nouvelle vie: Spring, JQuery et HTML5</a>”, le code que vous proposerez dans le cadre du concours pourra donc être montré dans cette session.</p>
<p>Le fonctionnement du concours est simple :</p>
<ul>
<li>Vous forkez notre repo Github</li>
<li>Vous développez de nouvelles fonctionnalités, améliorez le code, etc&#8230;</li>
<li>Au bout de 3 semaines de code, vous pushez votre code et nous sélectionnons le “meilleur” fork</li>
</ul>
<h2>Les technologies actuellement utilisées</h2>
<p>Tatami est une application utilisant une base de données NoSQL (<a href="http://cassandra.apache.org/">Cassandra</a>) et le framework <a href="http://www.springsource.org/">Spring</a>. La couche de présentation est codée en HTML5, utilisant <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a> et <a href="http://jquery.com/">JQuery</a>, afin de faire des requêtes REST sur le backend codé avec Spring MVC REST.</p>
<p>L’utilisation de ces technologies est certainement améliorable, en termes de qualité du code proposé comme en termes de performances.</p>
<p>Dans le cadre du concours, vous pouvez bien entendu ajouter de nouvelles technologies (par exemple Lucene pour pouvoir rechercher des Tweets) ou même en remplacer si cela a un sens (amélioration des perfs ou de la qualité du code).</p>
<h2>Ce qui a déjà été développé</h2>
<p>L’application actuelle permet déjà de poster des tweets, suivre d’autres utilisateurs, lire des tweets, etc&#8230;</p>
<p>Par contre de nombreuses fonctionnalités sont manquantes, le code a été écrit de manière relativement rapide, et sans aucun test (méthodologie <a href="http://programming-motherfucker.com/">http://programming-motherfucker.com/</a>, qui n’est peut-être pas idéale&#8230;.).</p>
<h2>Les fonctionnalités manquantes et les bugs</h2>
<p>Nous listons les fonctionnalités manquantes et les bugs sur le tracker de Github, avec le label “Concours” :</p>
<p><a href="https://github.com/ippontech/tatami/issues?labels=Concours&amp;sort=created&amp;direction=desc&amp;state=open&amp;page=1">https://github.com/ippontech/tatami/issues?labels=Concours&amp;sort=created&amp;direction=desc&amp;state=open&amp;page=1</a></p>
<p>Cette liste est là pour vous donner des idées sur ce que vous pouvez réaliser sur l’application : elle n’est pas à suivre de manière obligatoire, elle est juste là pour vous aider.</p>
<p>Au fur et à mesure du jeu nous ajouterons certainement de nouvelles idées dans cette liste.</p>
<p>Si vous trouvez un bug dans le code actuel, vous pouvez nous envoyer une “pull request” que nous intégrerons alors dans le projet principal :</p>
<ul>
<li>Il est donc possible que le code du projet principal évolue légèrement pendant le jeu (ce qui impacte donc tous les concurrents)</li>
<li>Corriger ce type de bug montre votre fair play dans le jeu, et vous donne donc des “points bonus”</li>
</ul>
<h2>Comment gagner ?</h2>
<p>Les gagnants seront élus par Ippon Technologies en fonction des critères suivants :</p>
<ul>
<li>Nouvelles fonctionnalités développées</li>
<li>Design graphique</li>
<li>Qualité du code</li>
<li>Performance et scalabilité de l’application</li>
<li>Bugs corrigés</li>
</ul>
<p>Afin de nous aider à mieux comprendre votre travail, vous devrez :</p>
<ul>
<li>Nous fournir un document décrivant ce que vous avez fait, et pourquoi vous l’avez fait de cette manière</li>
<li>Si vous avez réalisé des améliorations de performance, un test démontrant ces améliorations sera nécessaire</li>
<li>Si vous avez ajouté des tests unitaires ou des tests d’intégration, un rapport de couverture de code sera également nécessaire (pour que nous puissions départager deux concurrents ayant fait la même chose)</li>
</ul>
<p><strong>Le jeu se terminera le Mardi 10 Avril à 8:00, ce qui vous laisse donc 3 semaines !</strong></p>
<h2>Quels sont les lots ?</h2>
<p><strong>Lot n°1:</strong> 1 Galaxy Tab et une place pour 2 jours à Devoxx France<br />
<strong>Lot n°2:</strong> 1 place pour 2 jours à Devoxx France</p>
<h2>Comment s’inscrire ?</h2>
<p>Contactez-nous (jdubois chez ippon point fr) pour nous tenir au courant de votre participation, et forkez <a href="https://github.com/ippontech/tatami">notre repository Github</a> pour commencer à jouer.</p>
<p><em>Hajime !</em></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/sqstYchAUTw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/03/19/bienvenue-sur-le-tatami-ippon-lance-un-grand-concours-de-code-pour-devoxx-france/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/03/19/bienvenue-sur-le-tatami-ippon-lance-un-grand-concours-de-code-pour-devoxx-france/</feedburner:origLink></item>
		<item>
		<title>ScrumDay 2012 : 2 présentations Ippon retenues</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/iYbEx2Gzz3I/</link>
		<comments>http://blog.ippon.fr/2012/02/29/scrumday-2012-2-presentations-ippon-retenues/#comments</comments>
		<pubDate>Wed, 29 Feb 2012 11:02:45 +0000</pubDate>
		<dc:creator>Anne GABRILLAGUES</dc:creator>
				<category><![CDATA[Agilité]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[Scrumday]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5214</guid>
		<description><![CDATA[<p></p> <p>Le programme définitif du Scrum Day 2012 vient d&#8217;être annoncé et c&#8217;est maintenant officiel : les 2 présentations proposées par Ippon sont retenues !</p> <p>Nous sommes donc heureux de vous présenter à cette occasion :</p> un REX &#8220;3 ans de retours d’expérience sur la conduite en Scrum du projet BusinessCenter de PagesJaunes&#8221; . Le projet BusinessCenter <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/29/scrumday-2012-2-presentations-ippon-retenues/">ScrumDay 2012 : 2 présentations Ippon retenues</a></span>]]></description>
			<content:encoded><![CDATA[<p><img style="float: left; margin-left: 10px; margin-right: 10px;" title="Logo French SUG" src="http://www.frenchsug.org/download/attachments/131074/global.logo?version=2" alt="" width="177" height="60" /></p>
<p>Le programme définitif du Scrum Day 2012 vient d&#8217;être <a href="http://www.scrumday.fr/?page_id=317">annoncé</a> et c&#8217;est maintenant officiel : les 2 présentations proposées par Ippon sont retenues !</p>
<p>Nous sommes donc heureux de vous présenter à cette occasion :</p>
<ul>
<li>un REX &#8220;<strong>3 ans de retours d’expérience sur la conduite en Scrum du projet BusinessCenter de PagesJaunes</strong>&#8221; . Le projet BusinessCenter est un Portail de services à destination de tous les clients de PagesJaunes. Cette présentation sera menée en compagnie du responsable de projet PagesJaunes, qui présentera dans un premier temps l’historique, l’organisation et les différentes étapes qui font, aujourd’hui, de BusinessCenter, un projet Scrum très mature. Raphaël (ScrumMaster Ippon) présentera ensuite la manière dont les grands principes Scrum sont appliqués, les estimations de complexité des US, le déroulement des sprints, l’intégration de nouveaux collaborateurs, les routines au quotidien, les outils, les interactions MOE/MOA.</li>
</ul>
<ul>
<li>un atelier &#8220;Agile Games&#8221; : <strong>Lego4Scrum</strong>, une mise en pratique de l&#8217;ensemble de la méthode Scrum par le biais de la plus stimulante des API : les LEGO ! Par équipe, les participants entreront de plein pied dans la réalisation d’un projet intense et ambitieux, qui n’aura que pour but de mieux révéler les comportements favorisant ou freinant le bon fonctionnement d’une méthode SCRUM.</li>
</ul>
<p>Le Scrum Day est un événement annuel organisé par le French User Group. Cette série de présentations est un des événements majeurs de la communauté Agile en France. Pour vous inscrire à l&#8217;événement c&#8217;est <a href="http://ec2-176-34-210-51.eu-west-1.compute.amazonaws.com/wordpress/?page_id=57">ici</a>.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/iYbEx2Gzz3I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/29/scrumday-2012-2-presentations-ippon-retenues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/29/scrumday-2012-2-presentations-ippon-retenues/</feedburner:origLink></item>
		<item>
		<title>Ippevent ETL et Talend : Le Seigneur des Données</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/1y6hjAl88KI/</link>
		<comments>http://blog.ippon.fr/2012/02/27/ippevent-etl-et-talend-le-seigneur-des-donnees/#comments</comments>
		<pubDate>Mon, 27 Feb 2012 15:23:25 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[ETL]]></category>
		<category><![CDATA[Talend]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5202</guid>
		<description><![CDATA[<p>EDIT : ATTENTION l&#8217;IPPEVENT TALEND EST REPORTE AU 22 MARS</p> <p>Il n&#8217;y a pas que le code dans la vie d&#8217;un développeur : il y a aussi les données.</p> <p>Vous avez des données que vous devez filtrer, agréger, transformer ou autre ? Talend va devenir votre ami. Venez découvrir lors de cet Ippevent les possibilités <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/27/ippevent-etl-et-talend-le-seigneur-des-donnees/">Ippevent ETL et Talend : Le Seigneur des Données</a></span>]]></description>
			<content:encoded><![CDATA[<p><strong>EDIT</strong> : ATTENTION l&#8217;IPPEVENT TALEND EST REPORTE AU 22 MARS</p>
<p><img style="float: left;" src="http://www.talend.com/img/style/logo_talend-open-integration-solution.jpg" alt="" width="179" height="67" />Il n&#8217;y a pas que le code dans la vie d&#8217;un développeur : il y a aussi les données.</p>
<p>Vous avez des données que vous devez filtrer, agréger, transformer ou autre ? Talend va devenir votre ami. Venez découvrir lors de cet Ippevent les possibilités de cet outil et vous familiariser avec les notions liées à l&#8217;ETL.</p>
<p>Jérémy Beucler, consultant Ippon, vous présentera le produit, un retour d&#8217;expérience et une démonstration de Talend.</p>
<p>Alors si vous voulez voir du concret sur la manipulation de données n&#8217;hésitez pas à vous inscrire via notre <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/">page Ippevent</a> ou cliquant sur le bouton ci-dessous :</p>
<div style="width: 100%; text-align: left;">
<p><iframe frameborder="0" height="192" marginheight="5" marginwidth="5" scrolling="auto" src="http://www.eventbrite.com/tickets-external?eid=3036864343&amp;ref=etckt" width="100%"></iframe></p>
<div style="font-family: Helvetica, Arial; font-size: 10px; padding: 5px 0 5px; margin: 2px; width: 100%; text-align: left;"><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/r/etckt" target="_blank">Billetterie en ligne</a><span style="color: #ddd;"> pour </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/event/3036864343?ref=etckt" target="_blank">Ippevent ETL &amp; Talend : Le Seigneur des Données.</a><span style="color: #ddd;"> produit par </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com?ref=etckt" target="_blank">Eventbrite</a></div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/1y6hjAl88KI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/27/ippevent-etl-et-talend-le-seigneur-des-donnees/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/27/ippevent-etl-et-talend-le-seigneur-des-donnees/</feedburner:origLink></item>
		<item>
		<title>Optimiser ses resources web statiques avec wro4j</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/5QQaVIhEXOM/</link>
		<comments>http://blog.ippon.fr/2012/02/27/optimiser-ses-resources-web-statiques-avec-wro4j/#comments</comments>
		<pubDate>Mon, 27 Feb 2012 08:00:52 +0000</pubDate>
		<dc:creator>Kévin VASSEURE</dc:creator>
				<category><![CDATA[Outils]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[optimisation]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5119</guid>
		<description><![CDATA[<p></p> <p>La rapidité de chargement d&#8217;une page web dépend essentiellement du temps qu&#8217;il faut au navigateur pour en télécharger les données (c.f. la très bonne collection d&#8217;articles d&#8217;optimisation de yahoo);  La manière la plus efficace et évidente d’optimiser le chargement d’une page est de réduire au maximum les requêtes vers les ressources statiques : css, <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/27/optimiser-ses-resources-web-statiques-avec-wro4j/">Optimiser ses resources web statiques avec wro4j</a></span>]]></description>
			<content:encoded><![CDATA[<p><strong></strong><strong><img class="alignleft" title="wro4j" src="http://code.google.com/p/wro4j/logo?cct=1326057876" alt="" width="79" height="55" /></strong></p>
<p>La rapidité de chargement d&#8217;une page web dépend essentiellement du temps qu&#8217;il faut au navigateur pour en télécharger les données (c.f. la très bonne collection d&#8217;articles d&#8217;optimisation de <a href="http://developer.yahoo.com/performance/rules.html" target="_blank">yahoo</a>);  La manière la plus efficace et évidente d’optimiser le chargement d’une page est de réduire au maximum les requêtes vers les ressources statiques : css, javascript, et images. Pour les images, la solution de la feuille de sprite reste la plus valable pour des raison de compatibilité (pour ce faire, je recommande <a href="http://www.spritecow.com/">spritecow</a>) mais il y a une alternative plus &#8220;moderne&#8221; que j&#8217;évoquerai plus tard.  Pour les feuilles de style et les script, la problématique est un peu plus complexe&#8230;</p>
<h2>l&#8217;optimisation du chargement des scripts et des feuilles de style.</h2>
<p>Il y a 2 axes principaux d’optimisation. Le premier est la compression des scripts pour en réduire la taille et ainsi en accélérer le chargement, le second, est de limiter le nombre de requêtes en fusionnant les ressources. Un moyen simple de vérifier si vos appels de scripts et de css sont optimisés, est de lancer un diagnostique à l’aide de l’outil de développement de chrome (onglet “audit”, puis “run”), ou encore à l&#8217;aide de <a href="http://developer.yahoo.com/yslow/">YSlow</a>.</p>
<p>La compression des javascripts et css se résume en fait à la suppression des espaces et retours à la ligne inutiles ainsi que des commentaires. Pour ce faire, il existe de nombreux scripts connus de compression : YUI compressor, Google Closure, JSMin, Csslint&#8230; Mais tous ne se chargent pas de fusionner les fichier ensemble. On peut alors faire en plus appel à des script de merge comme JMerge. Bien évidemment, une fois compressé et fusionné, les .css et .js deviennent illisibles.</p>
<p>La meilleure pratique dans un projet est donc de conserver ces éléments décompressés dans ses sources pour pouvoir développer sereinement, et se charger de la compression lors du build. Et c’est là que le bat blesse. Avec les outils cités précédemment il faut soit compresser son code “manuellement”, soit lancer un script d&#8217;exécution lors du build, en shell ou via son outil de build (maven). Rien d’insurmontable, mais pas la panacée en terme de maintenabilité et de stabilité. Si l’on ajoute à cela l’utilisation d’extensions commes Sass ou Coffeescript, cela peut vite devenir un casse tête. C&#8217;est là qu&#8217;intervient wro4j.</p>
<h2>Wro4j : une solution java intégrée.</h2>
<h3>Présentation</h3>
<p>C’est en cherchant une manière facile d’integrer les fusions et compressions de ces ressources à mon build maven que je suis tombé sur le projet java <a href="http://code.google.com/p/wro4j/">wro4j</a>. Il se charge, soit à l’exécution via un Filter, soit au build via un plugin Maven, de compresser et fusionner vos ressources. En plus d’offrir la possibilité d’utiliser les algorithmes de compression de votre choix (YUI compressor, Google Closure, JSMin, JSlint&#8230;), il est très facilement extensible et configurable.</p>
<p>Wro4j opère de la manière suivante : vous définissez des groupes de fichier js et css, et au lieu d&#8217;appeler directement les ressources, vous appeler le nom du groupe. A l&#8217;exécution le Filter va se charger de constituer vos ressources compressé, et vous renvoyer une seule ressource compacte. Si l’on choisit de faire cela au build, les ressources compressées sont bien évidemment pré générées. Notez que la définition de groupes vous force, à organiser vos resources.</p>
<h3>Utilisation</h3>
<p>Je peux donc au choix mettre en place wro4j via un filter dans mon web.xml</p>
<pre class="brush: xml; title: ; notranslate">&lt;filter&gt;
    &lt;filter-name&gt;WebResourceOptimizer&lt;/filter-name&gt;
    &lt;filter-class&gt;ro.isdc.wro.http.WroFilter&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
    &lt;filter-name&gt;WebResourceOptimizer&lt;/filter-name&gt;
    &lt;url-pattern&gt;/wro/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;</pre>
<p>Ou en mode build maven dans mon pom.xml</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugins&gt;
    &lt;plugin&gt;
        &lt;groupId&gt;ro.isdc.wro4j&lt;/groupId&gt;
        &lt;artifactId&gt;wro4j-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;${wro4j.version}&lt;/version&gt;
        &lt;executions&gt;
                &lt;execution&gt;
                &lt;phase&gt;compile&lt;/phase&gt;
                &lt;goals&gt;
                    &lt;goal&gt;run&lt;/goal&gt;
                &lt;/goals&gt;
             &lt;/execution&gt;
        &lt;/executions&gt;
        &lt;configuration&gt;
            &lt;targetGroups&gt;all&lt;/targetGroups&gt;
            &lt;destinationFolder&gt;${basedir}/src/main/webapp/wro/&lt;/destinationFolder&gt;
            &lt;contextFolder&gt;${basedir}/src/main/webapp/&lt;/contextFolder&gt;
        &lt;/configuration&gt;
    &lt;/plugin&gt;
&lt;/plugins&gt;</pre>
<p>Maintenant admettons que j&#8217;utilise un moteur de template pour mon application web et que le template principal contienne les inclusions suivantes :</p>
<pre class="brush: xml; title: ; notranslate">&lt;!-- début de page --&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/static/css/style.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/static/css/global/picto.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/static/css/global/header.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/static/css/global/footer.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/static/css/global/divers.css&quot; /&gt;
&lt;!-- fin de page --&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/static/js/jquery/jquery.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/static/js/jquery/jquery.ui.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/static/js/common.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/static/js/mustache.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/static/js/iCanHaz.js&quot;&gt;&lt;/script&gt;
</pre>
<p>Comme ces inclusions sont à priori communes à toutes les pages du site, l&#8217;idéal serait donc de regrouper ces fichiers. Pour cela  je définis le groupe de ressources suivant en xml dans un fichier que je fourni à wro4j (par défaut /WEB-INF/wro.xml) :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;groups xmlns=&quot;http://www.isdc.ro/wro&quot;&gt;
    &lt;group name=&quot;common&quot;&gt;
        &lt;css&gt;/static/css/style.css&lt;/css&gt;
        &lt;css&gt;/static/css/global/*.css&lt;/css&gt;
        &lt;js&gt;/static/js/jquery/jquery.js&lt;/js&gt;
        &lt;js&gt;/static/js/jquery/jquery.ui.js&lt;/js&gt;
        &lt;js&gt;/static/js/**&lt;/js&gt;
    &lt;/group&gt;
&lt;/groups&gt;
</pre>
<p><em>NB : vous remarquerez la possibilité d&#8217;utiliser des wildcards.</em></p>
<p>Wro4j se charge ensuite de compresser et de fusionner les fichiers en fonction des groupes que l&#8217;on a défini, au build, ou à la volée si l&#8217;on utilise le filter. Pour appeler les ressources du groupe &#8220;common&#8221; définit précédemment dans nos pages web :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/wro/common.css&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/wro/common.js&quot;&gt;&lt;/script&gt;
</pre>
<h3>Mode opératoire</h3>
<p>La classe centrale de wro4j est WroManager. Elle offre un ensemble de possibilités de personnalisation simple. Le WroManager opère de la manière suivante : (cf : <a title="schema explicatif fonctionnement wro4j" href="http://wro4j.googlecode.com/svn/wiki/img/wro4j-process.png">http://wro4j.googlecode.com/svn/wiki/img/wro4j-process.png</a>)</p>
<h4>1) Construire le modèle de données</h4>
<p>Le WroModel contient les informations de regroupement des fichiers, et va permettre leur fusion par la suite. Il est construit par une WroModelFactory, capable de lire ces information sous forme :</p>
<ul>
<li>de xml (cf l&#8217;exemple précédent)</li>
<li>de groovy</li>
<li>de json</li>
</ul>
<p>Par défaut, la SmartWroModelFactory est appelée. Elle va essayer de trouver les informations sous ces 3 formats successivement. Il est également très simple de faire sa propre WroModelFactory.</p>
<h4>2) Localisation des ressources à traiter à l’aide d’une classe Locator</h4>
<h4>3) Pre-traitement des ressources.</h4>
<p>Par exemple compilation de coffeescript, ou Sass, mais surtout réécriture des urls des images dans le css, et la minification des ressources.</p>
<h4>4) Fusion des ressources.</h4>
<h4>5) Post-traitement des ressources.</h4>
<p>Les classes et interfaces utilisées pour la construction du modèle et la localisation des ressources sont facilement extensible/implémentable, comme nous le verrons dans l&#8217;exemple suivant. Pour les étapes de pre et post-processing, wro4j offre une configuration par défaut, mais il existe de nombreux <a href="http://code.google.com/p/wro4j/wiki/AvailableProcessors" target="_blank">processors</a> disponibles. A noter que ces processors sont également utilisables de manière autonome.</p>
<h3>Un exemple de &#8220;customisation&#8221;</h3>
<p>A titre d’exemple, je vais vous faire un retour d&#8217;expérience :  j’ai souhaité faire la déclaration des groupes wro4j directement dans un fichier freemarker &#8211; le framework de templating que j’utilisais alors. Le fichier de templating contenant les informations de groupe freemarker, cela lui permet de construire du html appelant soit les ressources décompressées et non fusionnées, soit les ressources assemblées par wro4j (au gré d&#8217;un flag dans la configuration du serveur par exemple).</p>
<p>Comme on ne va pas dupliquer ces informations, il faut permettre à wro4j de les lire.</p>
<p>Pour cela, Il m’a suffit d’implémenter une WroModelFactory (cf étape 1), qui construit le modèle de groupes wro4j (WroModel) à partir des données stockées dans le fichier freemarker :</p>
<pre class="brush: java; title: ; notranslate">
public class CustomWroModelFactory implements WroModelFactory {
    private static final String PACK_EXT = &quot;.pack&quot;;
    /**
     * method create, appelée par le framework wro4j
     * renvoie un model wro.
     */
    @Override
    public WroModel create() {
        ParsedResourceContainer container = parseModel();
        WroModel model = new WroModel();
        for (CustomWroModelFactory.ParsedResourcesGroups rgroup : container.resources_groups) {
             Group group = new Group(rgroup.name + PACK_EXT);
             for (String cssFilePath : rgroup.resources.css) {
                  group.addResource(Resource.create(cssFilePath,ResourceType.CSS));
             }
             for (String jsFilePath : rgroup.resources.js) {
                  group.addResource(Resource.create(jsFilePath,ResourceType.JS));
             }
             model.addGroup(group);
        }
        return model;
    }
    /**
    * va parser la variable resources dans mon fichier freemarker
    * à l’aide de (l’indispensable) Gson http://code.google.com/p/google-gson/
    */
    public ParsedResourceContainer parseModel() {
         //
    }
    /**
     *Un bean pour stocker les données parsée par Gson
    */
    private class ParsedResourceContainer{
         //
    }
}
</pre>
<p><em>NB : Comme les variables freemarker on un format proche du Json j&#8217;ai utilisé Gson pour parser.</em></p>
<p>Puis il suffit de faire un CustomWroManager factory qui va appeller CustomWroModelFactory :</p>
<pre class="brush: java; title: ; notranslate">
/**
* Factory pour un wro manager (objet 'central' de wro4j)
* surchargeant la méthode newModelFactory afin de renvoyer
* la CustomWroModelFactory
*/
public class CustomWroManagerFactory extends DefaultStandaloneContextAwareManagerFactory {
    @Override
    protected WroModelFactory newModelFactory() {
        return new CustomWroModelFactory();
    }
}</pre>
<p>Il ne reste qu’a configurer le build maven en lui spécifiant la WroManagerFactory à utiliser :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
    &lt;groupId&gt;ro.isdc.wro4j&lt;/groupId&gt;
    &lt;artifactId&gt;wro4j-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;1.4.1&lt;/version&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;phase&gt;compile&lt;/phase&gt;
            &lt;goals&gt;
                &lt;goal&gt;run&lt;/goal&gt;
            &lt;/goals&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
    &lt;configuration&gt;
          &lt;wroManagerFactory&gt;webcore.buildhelper.CustomWroManagerFactory&lt;/wroManagerFactory&gt;
          &lt;minimize&gt;true&lt;/minimize&gt;
          &lt;destinationFolder&gt;${project.build.directory}/${project.build.finalName}/wro/&lt;/destinationFolder&gt;
          &lt;contextFolder&gt;${basedir}/src/main/webapp/&lt;/contextFolder&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;
</pre>
<p>&#8230;pour que les fichiers compressés/fusionnés soient créés lors du build, à partir des données de mon fichier freemarker.</p>
<h2>Conclusion</h2>
<p>Il existe des solutions similaires à wro4j, telles que <a href="http://jawr.java.net/">Jawr</a> (dont wro4j s&#8217;est surement inspiré), mais j&#8217;ai choisi de l&#8217;utiliser car :</p>
<ul>
<li>Il est très bien documenté.</li>
<li>L’activité du groupe google-code wro4j est importante.</li>
<li>J’avais un bug &#8211; non bloquant &#8211; sur un cas particulier de réécriture des urls des images css, je l’ai signalé au groupe google de wro4j et il a été corrigé dans la release suivante.</li>
<li>Les releases sont fréquentes, et ajoute de nouvelles fonctionalités.</li>
<li>Il gère un nombre varié d&#8217;algorithmes de compression et de traitement des ressources (je pense notamment à à des &#8220;langages&#8221; comme CoffeScript ou Sass).</li>
</ul>
<p>Enfin, je mentionnais en introduction qu&#8217;il existe une autre manière d&#8217;optimiser le chargement des images que les feuilles de sprite : il s&#8217;agit des <a href="http://en.wikipedia.org/wiki/Data_URI_scheme">data URIs</a>, un type d&#8217;uri de plus en plus utilisé qui plutôt que de donner une référence à une donnée via une url, donne directement cette donnée encodée en Base64. Et bien wro4j gère également la conversion d&#8217;images en base64 dans vos css.</p>
<p>Si vous avez affaire à des problématiques d’optimisation des ressources statiques, je vous recommande donc de jeter un oeil sur wro4j. J’ai été vraiment impressionné par son adaptabilité, son extensibilité et sa simplicité d’utilisation.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/5QQaVIhEXOM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/27/optimiser-ses-resources-web-statiques-avec-wro4j/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/27/optimiser-ses-resources-web-statiques-avec-wro4j/</feedburner:origLink></item>
		<item>
		<title>Ippevent Hibernate OGM : le film</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/mco6_5wdUd4/</link>
		<comments>http://blog.ippon.fr/2012/02/26/ippevent-hibernate-ogm-le-film/#comments</comments>
		<pubDate>Sun, 26 Feb 2012 07:34:28 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Vidéo]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Infinispan]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5196</guid>
		<description><![CDATA[<p>Voilà (avec un peu de retard) la capture de notre Ippevent du 9 février dernier sur Hibernate OGM par Emmanuel Bernard. Vidéo très instructive sur un sujet prometteur.</p> <p></p> ]]></description>
			<content:encoded><![CDATA[<p>Voilà (avec un peu de retard) la capture de notre Ippevent du 9 février dernier sur Hibernate OGM par Emmanuel Bernard. Vidéo très instructive sur un sujet prometteur.</p>
<p><iframe src="http://player.vimeo.com/video/37425227?title=0&amp;byline=0&amp;portrait=0" width="500" height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/mco6_5wdUd4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/26/ippevent-hibernate-ogm-le-film/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/26/ippevent-hibernate-ogm-le-film/</feedburner:origLink></item>
		<item>
		<title>Liferay et GWT : C’est possible !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/pdJnv-UkD88/</link>
		<comments>http://blog.ippon.fr/2012/02/24/liferay-et-gwt/#comments</comments>
		<pubDate>Fri, 24 Feb 2012 16:19:47 +0000</pubDate>
		<dc:creator>Alexandre FILLATRE</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[Portail]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[Liferay]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=2237</guid>
		<description><![CDATA[<p>Les projets GWT (Google WebToolkit) se multiplient depuis un petit moment dans le monde du Java. Cependant, si vous avez déjà essayé d&#8217;intégrer des Widget GWT dans votre portail, il y a de grandes chances pour que votre tête et votre mur s&#8217;en souviennent. La documentation est encore relativement rare dans ce domaine, et c&#8217;est <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/24/liferay-et-gwt/">Liferay et GWT : C&#8217;est possible !</a></span>]]></description>
			<content:encoded><![CDATA[<p>Les projets GWT (Google WebToolkit) se multiplient depuis un petit moment dans le monde du Java. Cependant, si vous avez déjà essayé d&#8217;intégrer des Widget GWT dans votre portail, il y a de grandes chances pour que votre tête et votre mur s&#8217;en souviennent. La documentation est encore relativement rare dans ce domaine, et c&#8217;est bien dommage !</p>
<p>Dans cet article, je vais vous expliquer pas à pas, la recette pour transformer un widget en portlet. Pas la peine d&#8217;aller chercher dans votre grenier s&#8217;il reste des champignons magiques. Tous les ingrédients peuvent se trouver sur le net, et pour pas un sou ! En plus, du GWT oui, mais avec RPC.</p>
<p><span id="more-2237"></span></p>
<h1>Introduction</h1>
<p>Tout d&#8217;abord, pourquoi Liferay et pas un autre portail ? Tout simplement car c&#8217;est le portail que je connais le mieux, et qu&#8217;il faut bien en choisir un pour faire du pas à pas. Et pourquoi GWT ? Parce que Liferay sans GWT, c&#8217;est trop facile, et donc c&#8217;est pas marrant.</p>
<p>Plus sérieusement, cet article vous permettra de coupler GWT (avec ses appels RPC) à un portail Liferay, sans faire de bidouilles avec les iFrames ou autres solutions bancales. De plus, la solution proposée est relativement simple et rapide à mettre en place. Pourquoi s&#8217;en priver ?</p>
<p>Attention cependant, il ne s&#8217;agit pas ici d&#8217;expliquer comment développer une portlet Liferay ou une application GWT, mais simplement de proposer un moyen d&#8217;intégrer les 2. De plus, l&#8217;intégration n&#8217;est pour le moment que graphique (pas d&#8217;utilisation de services portail).</p>
<h1>Explication de la solution</h1>
<p>La solution proposée ici n&#8217;est pas de développer directement une portlet en GWT, mais plutôt de &#8220;backporter&#8221; une application GWT dans une portlet. Les avantages sont les suivants :</p>
<ul>
<li>Utilisation native dans l&#8217;IDE des outils GWT fournis par Google</li>
<li>Développement d&#8217;un réel projet GWT, utilisable avec n&#8217;importe quel serveur</li>
<li>Facilité pour intégrer une application ancienne en portlet</li>
</ul>
<div>Cependant, on peut noter que le processus de transformation de l&#8217;application GWT en portlet (expliqué par la suite) est relativement long (quoi que plutôt facile) et répétitif. Dans le cadre de d&#8217;un réel développement pour un projet, il est fortement recommandé d&#8217;écrire un script ant, ou bien un module Maven pour automatiser le processus.</div>
<h1>Préparation de l&#8217;environnement de développement</h1>
<h2>Liferay SDK</h2>
<p>Pour l&#8217;installation, il vous faut un simple SDK Liferay (v4+), correctement configuré (fichier build.${username}.properties). Cet article ne couvre pas la configuration basique de Liferay. Créez une nouvelle portlet en suivant les étapes suivantes :</p>
<ul>
<li>En ligne de commande, allez dans le répertoire &#8220;portlets&#8221; du SDK</li>
<li>Tapez la ligne suivante  : <em>./create.sh test-GWT &#8220;Test GWT&#8221;</em> qui vous permettra de créer une simple portlet Liferay</li>
<li>Dans Eclipse, faites une clic droit &gt; &#8220;Rafraichir&#8221; sur le dossier &#8220;portlets&#8221; du SDK</li>
<li>Vérifiez que votre portlet est bien présente.</li>
</ul>
<h2>Outils GWT</h2>
<p>Premièrement, il faut installer les outils de développement google sur votre IDE (Eclipse 3.6 pour moi). Vous trouverez toutes les informations <a href="http://code.google.com/eclipse/docs/getting_started.html" target="_blank">ici</a> (nouvelle fenêtre).</p>
<p>Une fois les outils Google installés, créez un nouveau projet GWT : Clic droit &gt; New &gt; &#8220;Web Application Project&#8221;. Cette manipulation créera un projet de test, qui nous servira dans cet article. Ce projet affiche un mini formulaire vous demandant votre prénom. A la validation, une fenêtre GWT s&#8217;ouvrira avec différents messages, comme par exemple une salutation, et le user agent de votre navigateur internet.</p>
<h1>Installation de la portlet GWT</h1>
<p>Nous y voilà ! Vous avez donc à présent un projet GWT vierge (mis à part le code généré par Google lors de la création), et une portlet Liferay, vierge elle aussi.</p>
<p>Avant de rentrer dans les détails de l&#8217;installation, voyons quelques fichiers importants.</p>
<h2>Points d&#8217;intérêts du projet GWT</h2>
<p>Les projets GWT étant des projets Web, on y retrouve facilement les bases de Java EE. Par exemple, l&#8217;application packagée sera un WAR, avec ses dépendances et configurations spécifiques. Pour ce qui nous intéresse ici, on peut remarquer :</p>
<ul>
<li>Le dossier source &#8216;<em>src</em>&#8216; : il contient le code source de l&#8217;application, partagée (grâce aux packages) en différentes couches (client, server, shared). Plus particulièrement, on trouvera, dans le package &#8216;<em>client</em>&#8216; le point d&#8217;entrée de l&#8217;application, nommé ${nom_du_projet}.java</li>
<li>Un dossier &#8216;<em>war</em>&#8216; : il contiendra tous les fichiers générés par la compilation de l&#8217;application, ainsi que le <em>web.xml</em></li>
<li>Les dépendances :  ce sont les <em>jar</em> situés dans le dossier &#8216;<em>war/WEB-INF/lib</em>&#8216;</li>
<li>Le fichier <em>web.xml</em> : il est situé dans le dossier &#8216;<em>war/WEB-INF</em>&#8216; et contient la définition de la ou des servlet(s) liée(s) à l&#8217;application, et permettant la communication RPC entre le client (navigateur) et le serveur.</li>
</ul>
<h2>Compilation du projet GWT</h2>
<p>Afin de pouvoir déployer le projet GWT dans notre portlet Liferay, il faut d&#8217;abord le compiler. Les outils Google installés précédemment permettent de la faire. Pour cela, faites un clic droit sur le projet &gt; Google &gt; &#8216;GWT compile&#8217;. Une fois la compilation terminée, rafraichissez le projet. Un nouveau dossier correspondant au nom du projet est apparu dans le dossier &#8216;<em>war</em>&#8216;. Il contient le projet généré à partir du code Java.</p>
<h2>Configuration de la portlet Liferay</h2>
<p>Dans la suite de cette section, nous utiliserons les variables suivantes :</p>
<table border="0">
<tbody>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
<tr>
<td>${GWT_portlet_docroot}</td>
<td>Chemin : ${liferay_sdk}/portlets/${portlet_name}/docroot</td>
</tr>
<tr>
<td>${GWT_project_name}</td>
<td>Nom du projet GWT, avec des &#8220;_&#8221; à la place des espaces (ex: GWT_Project)</td>
</tr>
<tr>
<td>${GWT_project_war}</td>
<td>Dossier <em>war</em> du projet GWT</td>
</tr>
<tr>
<td>${GWT_project_html}</td>
<td>Dossier généré suite à la compilation du projet GWT (dans le dossier <em>${GWT_project_war}</em>)</td>
</tr>
</tbody>
</table>
<h3>Copie de l&#8217;application GWT dans la portlet</h3>
<ol>
<li>Créer le dossier <em>${GWT_portlet_docroot}/html</em></li>
<li>Copier  le contenu du dossier <em>${GWT_project_html}</em> dans <em>${GWT_portlet_docroot}/html</em> (c&#8217;est tout le fonctionnel de l&#8217;application GWT)</li>
<li>Ouvrir le fichier <em>${GWT_project_war}/${GWT_project_name}.html</em> et, copier le formulaire dans le fichier <em>view.jsp </em>de la portlet. Vous devriez avoir un résultat du genre :
<pre class="brush: xml; title: ; notranslate">
&lt;%@ taglib uri=&quot;http://java.sun.com/portlet_2_0&quot; prefix=&quot;portlet&quot; %&gt;
&lt;portlet:defineObjects /&gt;
&lt;table align=&quot;center&quot;&gt;
    &lt;tr&gt;
        &lt;td colspan=&quot;2&quot; style=&quot;font-weight: bold;&quot;&gt;Please enter your name:&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td id=&quot;nameFieldContainer&quot;&gt;&lt;/td&gt;
        &lt;td id=&quot;sendButtonContainer&quot;&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td colspan=&quot;2&quot; style=&quot;color: red;&quot; id=&quot;errorLabelContainer&quot;&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
</pre>
</li>
</ol>
<h3>Copie des dépendences GWT dans la portlet</h3>
<ol>
<li>Copiez le jar <em>${GWT_project_war}/WEB-INF/lib/gwt-servlet.jar</em> dans <em>${GWT_portlet_docroot}/WEB-INF/lib</em></li>
<li>Faites un jar des sources du projet GWT (clic droit sur le projet &gt; Exporter &gt; Jar), et placez le dans <em>${GWT_portlet_docroot}/WEB-INF/lib</em></li>
</ol>
<h3><em>Configuration de la portlet Liferay</em></h3>
<ol>
<li>Editez le fichier <em>${GWT_portlet_docroot}/WEB-INF/liferay-portlet.xml</em>, et ajoutez la ligne <em>&lt;header-portlet-javascript&gt;/html/${GWT_project_name}.nocache.js&lt;/header-portlet-javascript&gt;</em> dans la configuration de la portlet</li>
<li>Editez le fichier <em>${GWT_portlet_docroot}/WEB-INF/web.xml</em> et ajouter la configuration de la servlet :
<pre class="brush: xml; title: ; notranslate">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE web-app PUBLIC &quot;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&quot; &quot;http://java.sun.com/dtd/web-app_2_3.dtd&quot;&gt;
&lt;web-app&gt;
    &lt;!-- Servlets --&gt;
    &lt;servlet&gt;
        &lt;servlet-name&gt;greetServlet&lt;/servlet-name&gt;
        &lt;servlet-class&gt;fr.ippon.myfirstgwtportlet.server.GreetingServiceImpl&lt;/servlet-class&gt;
    &lt;/servlet&gt;
    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;greetServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/html/greet&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</pre>
<p>Bien entendu, adaptez le nom des packages à votre projet. L&#8217;URL patern <em>/greet</em> vient du la configuration par défaut du projet GWT. Si vous ouvrez le fichier <em>fr.ippon.myfirstgwtportlet.server.GreetingService</em>, vous retroueverez ce mapping dans l&#8217;annotation <em>@RemoteServiceRelativePath(&#8220;greet&#8221;)</em>.</li>
</ol>
<div>Voilà, votre projet est configuré. Vous devriez avoir une arborescence de la sorte :</div>
<div><a href="http://blog.ippon.fr/wp-content/uploads/2012/02/GWT-portlet.png"><img title="Sources GWT portlet" src="http://blog.ippon.fr/wp-content/uploads/2012/02/GWT-portlet.png" alt="Sources GWT portlet" /></a></div>
<p>Il ne vous reste plus qu&#8217;à déployer votre portlet, et la tester.</p>
<h1>Conclusion</h1>
<p>L&#8217;installation d&#8217;une portlet GWT peut être un peu fastidieuse au premier abord, mais elle devient plutôt facile une fois que l&#8217;on a compris le mécanisme. Pour résumer, il y a plusieurs étapes à respecter :</p>
<ul>
<li>Compilation du projet GWT</li>
<li>Déplacement des fichiers compilés dans la portlet</li>
<li>Configuration de la portlet pour accéder au javascript GWT, et à la servlet d&#8217;appels RPC</li>
<li>Mise à jour des dépendances</li>
</ul>
<p>Une fois ces étapes vérifiées, votre portlet GWT fonctionne. Pour les plus téméraires, vous pouvez par la suite étendre cette solution pour profiter d&#8217;un SSO, utiliser un LDAP etc&#8230; Aspirine ?</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/pdJnv-UkD88" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/24/liferay-et-gwt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/24/liferay-et-gwt/</feedburner:origLink></item>
		<item>
		<title>Mustache.js et ICanHaz.js au secours de jQuery</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/PPvD1SWFhwQ/</link>
		<comments>http://blog.ippon.fr/2012/02/20/mustache-js-et-icanhaz-js-au-secours-de-jquery/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 14:58:04 +0000</pubDate>
		<dc:creator>Ludovic CHANE WON IN</dc:creator>
				<category><![CDATA[Outils]]></category>
		<category><![CDATA[Tutoriel]]></category>
		<category><![CDATA[icanhaz]]></category>
		<category><![CDATA[icanhazjs]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[mustache]]></category>
		<category><![CDATA[mustachejs]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5024</guid>
		<description><![CDATA[<p align="LEFT">Qui n&#8217;a jamais entendu de la bouche d&#8217;un développeur backend (pour ne pas dire Java) &#8220;Javascript, moins j&#8217;en fais, mieux je me porte&#8221;. Je parle en connaissance de cause car j&#8217;étais assez imperméable au Javascript par le passé. Mais je ne faisais que &#8220;bidouiller&#8221; du Javascript car en vérité, je ne connaissais pas le <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/20/mustache-js-et-icanhaz-js-au-secours-de-jquery/">Mustache.js et ICanHaz.js au secours de jQuery</a></span>]]></description>
			<content:encoded><![CDATA[<p align="LEFT"><img class="alignleft" style="padding: 0px; margin-top: -1px; margin-right: 10px; border-width: 0px;" title="Mustache" src="http://blog.ippon.fr/wp-content/uploads/2012/02/verre-moustache.jpg" alt="Mustache" width="150" height="112" />Qui n&#8217;a jamais entendu de la bouche d&#8217;un développeur backend (pour ne pas dire Java) &#8220;Javascript, moins j&#8217;en fais, mieux je me porte&#8221;. Je parle en connaissance de cause car j&#8217;étais assez imperméable au Javascript par le passé. Mais je ne faisais que &#8220;bidouiller&#8221; du Javascript car en vérité, je ne connaissais pas le langage et après quelques lectures d&#8217;ouvrages de référence (<a href="http://shop.oreilly.com/product/9780596517748.do" target="_blank">Javascript: The Good Parts</a> de Douglas Crockford par exemple), je me suis surpris à apprécier Javascript de plus en plus. Et du Javascript il y en a partout, déguisé derrière du jQuery, et même côté serveur avec Node.js.<br />
Dans cet article, je vais vous parler d&#8217;une librairie Javascript très spécifique, qui ne fait qu&#8217;une seule chose mais qui le fait bien. Il s&#8217;agit de la librairie de templating <a href="http://mustache.github.com/" target="_blank">Mustache.js</a>.</p>
<p align="LEFT"><span id="more-5024"></span></p>
<h2 style="margin-top: 60px;">1. jQuery sans les moustaches</h2>
<p>Imaginons qu&#8217;on veuille afficher une liste de livres (titre, auteur) que l&#8217;on récupère sous forme d&#8217;objets Javascript. Voici le code Javascript/jQuery correspondant :</p>
<pre class="brush: jscript; title: ; notranslate">
var book = { title: &quot;Javascript: the Good Parts&quot;, author: &quot;Douglas Crockford&quot; };
$('#example').append('Title: &lt;b&gt;' + book.title + '&lt;/b&gt;&lt;br/&gt;Author: ' + book.author);
</pre>
<p>Et le résultat :</p>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Title: <strong>Javascript: the Good Parts</strong><br />
Author: Douglas Crockford</p>
<p style="margin-top: 25px;">Je ne sais pas vous mais cette ligne là, elle m&#8217;irrite un peu quand je la lis et encore plus quand je l&#8217;écris :</p>
<pre class="brush: jscript; title: ; notranslate">
$('#example').append('Title: &lt;b&gt;' + book.title + '&lt;/b&gt;&lt;br/&gt;Author: ' + book.author);
</pre>
<p style="margin-top: 25px;">Pleins de <code>'</code> et de <code>+</code>, c&#8217;est facile de s&#8217;y perdre et surtout on mélange affichage et données. En Java, il existe de nombreux systèmes de templates pour mettre en oeuvre cette séparation : <a href="http://velocity.apache.org/" target="_blank">Velocity</a>, <a href="http://freemarker.sourceforge.net/" target="_blank">Freemarker</a>, <a href="http://stringtemplate.org/" target="_blank">StringTemplate</a> et j&#8217;en passe. Et bien en Javascript, il existe également des systèmes de template dont Mustache, que je trouve simple et pourtant très puissant. Alors faisons appel à Mustache.js et voyons comment on peut rendre l&#8217;exemple précédent plus sexy.</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {title: &quot;Javascript: the Good Parts&quot;, author: &quot;Douglas Crockford&quot;};
var template = 'Title: &lt;b&gt;{{title}}&lt;/b&gt; &lt;br/&gt; Author: {{author}}';
var output = Mustache.render(template, data);
$('#example').append(output);
</pre>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Title: <strong>Javascript: the Good Parts</strong><br />
Author: Douglas Crockford</p>
<p style="margin-top: 25px;">Aaah fini les <code>'</code> et <code>+</code> parasites ! On a maintenant une belle séparation entre le template et les données. On utilise <code>Mustache.render</code> qui prend en paramètre le template et notre objet de données data. Dans le template, il y a deux tags <code>{{title}}</code> et <code>{{author}}</code> qui vont être remplacés par les valeurs correspondantes de l&#8217;objet data lors de l&#8217;appel à <code>Mustache.render</code>.</p>
<p>On peut faire donc une première observation, un template Mustache est composé de tags et un tag est délimité par des doubles accolades : les fameuses moustaches !</p>
<h2 style="margin-top: 50px;">2. Les tags Mustache</h2>
<p>Pour l&#8217;instant, nous n&#8217;avons vu qu&#8217;un type de tag <code>{{name}}</code> qui permet d&#8217;afficher la valeur de l&#8217;attribut name de votre objet de données. Dans le jargon Mustache, name est la clé du tag. Voici un petit listing des tags Mustache qui existent :</p>
<h4 style="margin-top: 40px;">{{#name}}, la moustache de section</h4>
<p>Ce tag va ouvrir ce que Mustache appelle une section. Cette section peut contenir du <code>text/html</code> ou des tags Mustache. Une section est fermée par un tag <code>{{/name}}</code>. Si l&#8217;attribut name existe dans votre objet de données et est non null, non vide, non undefined alors Mustache va interpréter cette section. Dans le cas contraire, la section n&#8217;est pas interprétée.</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {title: &quot;Javascript: the Good Parts&quot;, author: &quot;&quot;};
var template = '{{#title}} Title: &lt;b&gt;{{title}}&lt;/b&gt; {{/title}} {{#author}} ne sera pas affiché {{/author}}';
var output = Mustache.render(template, data);
$('#example').append(output);
</pre>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Title: <strong>Javascript: the Good Parts</strong></p>
<p style="margin-top: 25px;">Si name est un array, alors Mustache va itérer sur cet array et interpréter la section autant de fois que nécessaire.</p>
<pre class="brush: jscript; title: ; notranslate">
var data = { books: [ &quot;Javascript: the Good Parts&quot;, &quot;Clean Code&quot; ] };
var template = '{{#books}}&lt;li&gt;{{.}}&lt;/li&gt;{{/books}}';
var output = Mustache.render(template, data);
$('#example').append(output);
</pre>
<div style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">
<ul>
<li>Javascript: the Good Parts</li>
<li>Clean Code</li>
</ul>
</div>
<p>Notez l&#8217;utilisation de <code>{{.}}</code> afin d&#8217;afficher l&#8217;élément de l&#8217;array.</p>
<h4 style="margin-top: 40px;">{{^name}}, la moustache inverse</h4>
<p>C&#8217;est l&#8217;inverse du tag <code>{{#name}}</code>, c&#8217;est-à-dire que le body du tag ne sera interprété que si l&#8217;attribut name n&#8217;existe pas, est vide, null ou undefined dans votre objet de données. Exemple :</p>
<pre class="brush: jscript; title: ; notranslate">
var data = { books: [ ] };
var template = '{{#books}}&lt;li&gt;{{.}}&lt;/li&gt;{{/books}} {{^books}}Aucun livre{{/books}}';
var output = Mustache.render(template, data);
$('#example').append(output);
</pre>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Aucun livre</p>
<h4 style="margin-top: 40px;">{{! comment}}, la moustache invisible</h4>
<p>C&#8217;est le tag de commentaire. Tout ce qu&#8217;il y a entre les moustaches est ignorée.</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {title: &quot;Javascript: the Good Parts&quot;, author: &quot;Douglas Crockford&quot;};
var template = 'Le commentaire suivant ne sera pas affiché : {{! ne doit pas être affiché}}';
var output = Mustache.render(template, data);
$('#example').append(output);
</pre>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Le commentaire suivant ne sera pas affiché :</p>
<h4 style="margin-top: 40px;">{{&gt; tag}}, la moustache partielle</h4>
<p>Avec Mustache, il est possible de définir des templates partiels afin de décomposer des templates qui seraient trop verbeux ou des templates que vous récupérez de plusieurs sources.</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {title: &quot;Javascript: the Good Parts&quot;, author: &quot;Douglas Crockford&quot;};
var template = 'Title: &lt;b&gt;{{title}}&lt;/b&gt; &lt;br/&gt;{{&gt; tplAuthor}}';
var partials = { tplAuthor: 'Author: {{author}}' };
var output = Mustache.render(template, data, partials);
$('#example').append(output);
</pre>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Title: <strong>Javascript: the Good Parts</strong><br />
Author: Douglas Crockford</p>
<h2 style="margin-top: 50px;">3. Fonctions</h2>
<p>Dans votre objet de données, vous n&#8217;êtes pas cantonnés à avoir uniquement des valeurs ou des arrays. Vous pouvez également définir des fonctions qui vont déterminer le texte à afficher. Exemple :</p>
<pre class="brush: jscript; title: ; notranslate">
var i = 0;
var data = { currentdate: function() { return i++;} };
var template = '&lt;li&gt;{{currentdate}}&lt;/li&gt;';
$('#example').append(Mustache.render(template, data));
$('#example').append(Mustache.render(template, data));
$('#example').append(Mustache.render(template, data));
</pre>
<div style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
</ul>
</div>
<p style="margin-top: 25px;">Ok j&#8217;avoue, ça c&#8217;était l&#8217;exemple facile avec les fonctions. On peut faire un poil plus évolué. Dans les exemples précédents avec les livres, on affiche le titre en gras. Imaginons qu&#8217;on veuille rendre paramétrable l&#8217;affichage de &#8220;Title&#8221;, donc au choix en gras, en italique ou ce que vous voulez. Il suffit de fournir une fonction qui va faire ça.</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {
  title: &quot;Javascript: the Good Parts&quot;,
  titleDisplay: function() {
    return function(text, render) {
      return '&lt;b&gt;' + render(text) + '&lt;/b&gt;';
    }
  }
};
var template = 'Title: {{#titleDisplay}} {{title}} {{/titleDisplay}}';
var output = Mustache.render(template, data);
$('#example').append(output);
</pre>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Title: <strong>Javascript: the Good Parts</strong></p>
<p style="margin-top: 25px;">Mais maintenant si je veux afficher le titre en italique et l&#8217;entourer par des guillemets, on remplace le corps de la fonction par :</p>
<pre class="brush: jscript; title: ; notranslate">
return '&quot;&lt;i&gt;' + render(text) + '&lt;/i&gt;&quot;';
</pre>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Title: &#8220;<em>Javascript: the Good Parts</em>&#8220;</p>
<p style="margin-top: 25px;">Donc celui qui fournit l&#8217;objet <code>data</code> peut maintenant personnaliser l&#8217;affichage du titre.</p>
<h2 style="margin-top: 50px;">4. Template multi lignes</h2>
<p>&#8220;T&#8217;es bien gentil Ludo, mais tes exemples sont simplistes, tes templates ne tiennent que sur une seule ligne. Tiens prend ce template là. C&#8217;est beaucoup moins beau du coup et on peut vite oublier un <code>antislash</code>&#8230;&#8221;</p>
<pre class="brush: jscript; title: ; notranslate">
var template = 'Title: {{title}} &lt;br/&gt;\
Author: {{author}} &lt;br/&gt;\
Edition: {{edition}}';
</pre>
<p style="margin-top: 25px;">Effectivement, ce n&#8217;est pas très sexy. Alors il y a une petite astuce. Il suffit de mettre le template dans une balise &lt;script&gt; de type <code>text/html</code>, de récupérer son contenu et de le passer à Mustache ! En exemple ça donne :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script id=&quot;book&quot; type=&quot;text/html&quot;&gt;
Title: {{title}} &lt;br/&gt;
Author: {{author}} &lt;br/&gt;
Edition: {{edition}}
&lt;/script&gt;
</pre>
<p>&nbsp;</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {title: &quot;Javascript: the Good Parts&quot;, author: &quot;Douglas Crockford&quot;, edition: &quot;O'Reilly&quot;};
var template = $('#book').html();
var output = Mustache.render(template, data);
$('#example').append(output);
</pre>
<p style="background-color: #ffff99; padding: 3px; border-style: solid; border-width: thin; border-color: #ff6600;">Title: Javascript: the Good Parts<br />
Author: Douglas Crockford<br />
Edition: O&#8217;Reilly</p>
<p style="margin-top: 25px;">Mais on peut faire encore mieux !</p>
<h2 style="margin-top: 50px;">5. ICanHaz.js</h2>
<p><a href="http://icanhazjs.com/" target="_blank">ICanHaz.js</a> est une petite librairie Javascript qui wrappe Mustache.js et qui reprend l&#8217;idée de définir ses templates dans des balises script de type <code>text/html</code>. Au chargement de la page, ICanHaz.js va rechercher tous les templates de la page, créer un cache contenant ces templates et une fonction pour chaque template. A l&#8217;utilisation, c&#8217;est encore plus simple que Mustache.js. Si on reprend l&#8217;exemple précédent, le javascript devient :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script id=&quot;book&quot; type=&quot;text/html&quot;&gt;
Title: {{title}} &lt;br/&gt;
Author: {{author}} &lt;br/&gt;
Edition: {{edition}}
&lt;/script&gt;
</pre>
<p>&nbsp;</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {title: &quot;Javascript: the Good Parts&quot;, author: &quot;Douglas Crockford&quot;, edition: &quot;O'Reilly&quot;};
var output = ich.book(data);
$('#example').append(output);
</pre>
<p>ICanHaz.js fournit un objet <code>ich</code> et a créé une méthode <code>book</code> correspondant à l&#8217;id de la balise script. ICanHaz.js permet également de gérer les partials Mustache de manière élégante en indiquant un attribut à la balise script. Si on remplace la partie &#8220;edition&#8221; par un partial :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script id=&quot;book&quot; type=&quot;text/html&quot;&gt;
Title: {{title}} &lt;br/&gt;
Author: {{author}} &lt;br/&gt;
{{&gt; edition}}
&lt;/script&gt;

&lt;script id=&quot;edition&quot; type=&quot;text/javascript&quot;&gt;
Edition: {{edition}}
&lt;/script&gt;
</pre>
<p>et l&#8217;appel à <code>ich.book(data)</code> reste le même !</p>
<p>Comme je vous le disais précédemment, ICanHaz.js gère un cache de templates et fournit donc des méthodes pour rajouter des templates dans le cache, nettoyer le cache ou recharger le cache.</p>
<h2 style="margin-top: 50px;">Conclusion</h2>
<p>Si, sur votre projet, vous utilisez jQuery et n&#8217;utilisez pas de système de template côté client, alors foncez ! Essayez Mustache.js et ICanHaz.js ! Le tout ne fait que 5,4ko minifié.<br />
Ensuite, je voudrais donner quelques précisions sur Mustache.js. Mustache.js est en fait l&#8217;implémentation Javascript du système de template Mustache (sans le .js). En effet, il existe de nombreuses implémentations de Mustache, en Java, Ruby, Python, PHP, etc&#8230;<br />
De plus, on dit souvent que Mustache est un système de template &#8220;logic-less&#8221;, car il n&#8217;y a pas de if, else ou autre, il n&#8217;y a que des tags, que des moustaches :}}</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/PPvD1SWFhwQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/20/mustache-js-et-icanhaz-js-au-secours-de-jquery/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/20/mustache-js-et-icanhaz-js-au-secours-de-jquery/</feedburner:origLink></item>
		<item>
		<title>Speaker Ippon à la soirée Web Stateless vs Stateful du Chti Jug le 23 février 2012</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/kQ8gLJA3M78/</link>
		<comments>http://blog.ippon.fr/2012/02/13/speaker-ippon-a-la-soiree-web-stateless-vs-stateful-du-chti-jug-le-23-fevrier-2012/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 14:23:48 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JUG]]></category>
		<category><![CDATA[Play! Framework]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=5033</guid>
		<description><![CDATA[<p></p> <p>(EDIT) : Le JUG a récupéré une nouvelle salle donc les inscriptions sont ré-ouvertes. Rendez vous sur le site du Ch&#8217;ti Jug pour vous inscrire.</p> <p>Une nouvelle fois, votre humble serviteur ira présenter la conférence &#8220;Stateful is Beautiful&#8221; dans l&#8217;un des nombreux Jugs français. Cette fois, c&#8217;est à Lille, au Cht&#8217;i, Jug que j&#8217;aurai <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/13/speaker-ippon-a-la-soiree-web-stateless-vs-stateful-du-chti-jug-le-23-fevrier-2012/">Speaker Ippon à la soirée Web Stateless vs Stateful du Chti Jug le 23 février 2012</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://chtijug.org/wp-content/uploads/2012/01/logoJug-full-e1327596969647.png" alt="" width="120" height="115" /></p>
<p><strong>(EDIT) :</strong> Le JUG a récupéré une nouvelle salle donc les inscriptions sont ré-ouvertes. Rendez vous sur <a href="http://chtijug.org/reouverture-des-inscriptions-pour-la-session-du-23-fevrier/" target="_blank">le site du Ch&#8217;ti Jug</a> pour vous inscrire.</p>
<p>Une nouvelle fois, votre humble serviteur ira présenter la conférence &#8220;Stateful is Beautiful&#8221; dans l&#8217;un des nombreux Jugs français. Cette fois, c&#8217;est à Lille, au Cht&#8217;i, Jug que j&#8217;aurai le plaisir d&#8217;officier le 23 février prochain.</p>
<p>Comme la fois précédente (au Lyon Jug), je serai opposé à un défenseur des architectures Stateless en la personne de Thomas Recloux (<a href="https://twitter.com/#!/thomasrecloux" target="_blank">@thomasrecloux</a>), régional de l&#8217;étape qui viendra parler des bienfaits de Play! Framework. Tous les détails de cette soirée Architecture Web Stateless vs Stateful sur le <a href="http://chtijug.org/architecture-web-stateless-et-stateful-avec-ineat-conseil/" target="_blank">site du Chti Jug</a>.</p>
<p>Les places pour cette session sont parties en quelques minutes (c&#8217;est dire l&#8217;engouement autour du Stateful <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ), mais il est toujours possible (et chaudement recommandé) de s&#8217;inscrire pour permettre aux organisateurs d&#8217;obtenir une salle plus grande. N&#8217;hésitez donc pas à vous mettre en liste d&#8217;attente pour <a href="http://chtijug.org/des-places-pour-la-session-du-23-fevrier/" target="_blank">débloquer cette salle</a>.</p>
<p>Venez nombreux : le débat sur la question est toujours enrichissant et peux même être surprenant.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/kQ8gLJA3M78" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/13/speaker-ippon-a-la-soiree-web-stateless-vs-stateful-du-chti-jug-le-23-fevrier-2012/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/13/speaker-ippon-a-la-soiree-web-stateless-vs-stateful-du-chti-jug-le-23-fevrier-2012/</feedburner:origLink></item>
		<item>
		<title>Liferay et CAS : quand le SSL s’en mêle</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/vU_k6DkOzB0/</link>
		<comments>http://blog.ippon.fr/2012/02/06/liferay-et-cas-quand-le-ssl-sen-mele/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 09:12:02 +0000</pubDate>
		<dc:creator>Alexandre FILLATRE</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Portail]]></category>
		<category><![CDATA[CAS]]></category>
		<category><![CDATA[Liferay]]></category>
		<category><![CDATA[SSL]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3463</guid>
		<description><![CDATA[<p>Si vous travaillez sur la réalisation de sites web, vous avez surement déjà dû mettre en place une couche SSL, pour chiffrer certaines données sensibles, comme le mot de passe des internautes. Au delà du fait que la génération et l&#8217;utilisation des certificats non signés (pour le dev et les tests) reste relativement douloureuse et <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/06/liferay-et-cas-quand-le-ssl-sen-mele/">Liferay et CAS : quand le SSL s&#8217;en mêle</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://blog.excilys.com/wp-content/uploads/2010/05/Liferay_logo-large.png" alt="Liferay" width="238" height="68" />Si vous travaillez sur la réalisation de sites web, vous avez surement déjà dû mettre en place une couche SSL, pour chiffrer certaines données sensibles, comme le mot de passe des internautes. Au delà du fait que la génération et l&#8217;utilisation des certificats non signés (pour le dev et les tests) reste relativement douloureuse et peu intuitive, il est possible de rencontrer une multitude d&#8217;autres problèmes. L&#8217;idée de ce post vient de ma volonté de partager une situation où un problème lié au SSL est apparu. J&#8217;y explique le problème, sa cause, ainsi que les différentes étapes de sa résolution. J&#8217;espère qu&#8217;il vous sera utile, et qu&#8217;il vous permettra d&#8217;éviter certains pièges vicieux dont j&#8217;ai été la victime.</p>
<p><span id="more-3463"></span></p>
<h2>Introduction : Contexte technique du projet</h2>
<p>Le contexte technique du projet est relativement banal : un portail (Liferay) avec plusieurs portlet externes (webapps), un sytème de SSO &#8211; Single Sign On &#8211; (CAS), et un frontal faisant office de firewall et load-balancer (par exemple un apache tomcat).<br />
Pour des raisons fonctionnelles, nous avons du intégrer le SSO (CAS) dans une iFrame se trouvant sur le portail. Ainsi, l&#8217;internaute reste en permanence sur le portail, est n&#8217;est pas redirigé vers une page tierce du SSO. Bien entendu, il reste possible de brancher d&#8217;autres applications sur ce SSO, et ce composant reste donc tout à fait justifié.</p>
<h2>Le problème</h2>
<p>Bien que tout fonctionnait correctement, nous avons décidé de mettre en place une couche SSL sur le portail, pour toutes les pages d&#8217;authentification, et les pages contenant des données utilisateur (création de compte, mise à jour du profil, etc). Après quelques tests, nous avons remarqué que l&#8217;on perdait parfois la session utilisateur en passant de HTTP à HTTPS. Concrètement, après s&#8217;être connecté via une page en HTTPS, on pouvait naviguer tranquillement sur le site, sur toutes les adresses en HTTP. Par contre, dès que l&#8217;on passait en HTTPS, l&#8217;utilisateur était déconnecté. En repassant sur des pages en HTTP, on retrouvait notre compte, sans aucune redirection vers le CAS. Nous avions donc ici 2 informations interessantes :</p>
<ul>
<li>Le problème est aléatoire (reproduit sur 3 plateformes sur 5)</li>
<li>Le problème se situe au niveau du sessionId envoyé au serveur (tomcat), car le compte reste actif en HTTP, sans redirection vers CAS pour nouvelle confirmation de connexion</li>
</ul>
<p>De plus, ce problème se produisait seulement sur notre plateforme de staging (avec firewall et load-balancer), et non sur nos environnements d&#8217;intégration (pas de load-balancer). Le problème semblait donc lié au load-balancing. Après désactivation de l&#8217;une des 2 machines du cluster… le problème persitait ! Nous étions donc dans un cas où un problème aléatoire se produit seulement sur une plateforme load-balancée, même avec désactivation du balancing. Incompréhensible…</p>
<h2>Résolution du problème</h2>
<p>Après plusieurs manipulations infructueuses, nous sommes arrivés à la conclusion que le jsessionId envoyé en HTTP et HTTPS n&#8217;était pas le même. Cela semble logique, mais nous avions déjà essayé, sans succès, plusieures configurations différentes du portail, pour par exemple forcer l&#8217;utilisation de la même session en HTTP et HTTPS, ou bien répliquer les paramètres d&#8217;une session à l&#8217;autre. Lorsque que l&#8217;on regardait les cookies du navigateur, nous avions 2 jsessionId :</p>
<table>
<tbody>
<tr>
<th>Nom</th>
<th>Domaine</th>
<th>Path</th>
<th>Sécurisé</th>
</tr>
<tr>
<td>JSESSIONID</td>
<td>my.com</td>
<td>/</td>
<td>Non</td>
</tr>
<tr>
<td>JSESSIONID</td>
<td>sub.my.com</td>
<td>/</td>
<td>Oui</td>
</tr>
</tbody>
</table>
<p>Bizzare.<br />
Le site est accessibles par l&#8217;url sub.my.com, mais le portail réécrit les cookies pour les mettre sur my.com, afin que tous les sous-domaines utilisent la même session. Si le second cookie venait du portail, il devrait aussi être changé de domaine. Ce n&#8217;est évidement pas le cas. Au niveau du serveur, les autres webapps que nous avons sont :</p>
<ul>
<li>Des portlets personnalisées -&gt; Pas de raison de créer un nouveau jsessionId</li>
<li>Le CAS -&gt; Ses cookies devraient avoir l&#8217;attribut &#8220;path&#8221; à &#8220;/cas-server&#8221; (d&#8217;ailleurs plusieurs l&#8217;ont)</li>
</ul>
<p>En fait, le problème vient d&#8217;un paramètre du connecteur tomcat. En effet, il existe un attribut &#8220;emptySessionPath&#8221;, mis à &#8220;true&#8221; par Liferay. Cela permet de forcer le &#8220;path&#8221; des cookies à &#8220;/&#8221;. C&#8217;est très utile pour les portlet, car elles partagent le même jsessionId, mais… ce n&#8217;est pas ce que l&#8217;on veut pour le CAS. Comme le portail fonctionne majoritairement en HTTP, la session HTTPS est créée par le CAS, et non par le portail. A cause de la configuration du portail, le cookie du cas est configuré avec un &#8220;path&#8221; à &#8220;/&#8221; et non à &#8220;/cas-server&#8221;. Du coup, lorsque le portail passe en en HTTPS, il utilisae la session de la webapp CAS, et non celle du portail. L&#8217;utilisateur perd donc sa session. Quand on revient en HTTP, il la retrouve, car on utilise de nouveau le bon jsessionId. Nous avons donc mis le CAS sur un autre serveur tomcat, pour qu&#8217;il ait ses propres cookies, non modifiés. On dirait que ça fonctionne.</p>
<p>CQFD ? Par vraiment, malheureusement. Alors que nous pensions avoir résolu le problème, il est réapparu après quelques tests ! Pourtant, l&#8217;explication précédant se tient parfaitement. Il se trouve que nous avions oublié un paramètre important : le load-blancing. Nous l&#8217;avions mis de coté car le problème se produisait même avec une seule machine active. En fait, le calcul d&#8217;affinité sur le load-balancer se fait par le jsessionId. Ainsi, si vous fournissez toujours le même jsessionId, vous tomberez toujours sur la même machine ? Toujours ? Eh non, justement ! Suivant que la requête soit sécurisée ou non, un même identifiant ne renverra pas sur la machine. C&#8217;est évidement un problème de configuration du load-balancer. Après quelques tests, tout fonctionne de nouveau.</p>
<h2>Conclusion</h2>
<p>Bien que les explications du problème soient relativement simples, il n&#8217;a vraiment pas été facile à identifier, car il s&#8217;agissait en fait de deux problèmes imbriqués :</p>
<ul>
<li>Configuration du serveur qui &#8220;mélangeait&#8221; les cookies des différentes webapps</li>
<li>Mauvaise configuration du load-balancer qui pouvait changer l&#8217;utilisateur de machine, avec un même identifiant, suivant que la requête était sécurisée ou non</li>
</ul>
<p>La correction de l&#8217;un ne faisait pas disparaitre le problème (ce qui poussait à penser que cette correction était fausse), mais était obligatoire. Dans un cas de test normal, on essaie de modifier le moins possible la configuration orginale, pour ne pas inclure d&#8217;autres facteurs à risque et de faux comportements dans la résolution du problème. Pour résoudre celui-là, il ne fallait donc pas procéder comme cela, contre toute attente.</p>
<p>Voilà donc quelques conseils pour débugger ce type de cas :</p>
<ul>
<li>Vérifiez les cookies de session</li>
<li>Soyez sûrs de bien comprendre la configuration de votre serveur (dans notre cas, nous avions utilisé un bundle tout fait, donc nous n&#8217;avions pas ajouté nous-même l&#8217;attribut &#8220;emptySessionPath&#8221; qui posait problème)</li>
<li>Dans la cas d&#8217;une architecture avec load-balancer, testez toujours avec une seule machine, derrière le load-balancer. Cela permet de dissocier les problèmes inhérents à une config de serveur, et ceux liés à une config du load-balancer. Il peut arriver (comme ici) que le problème vienne de 2 endroits.</li>
</ul>
<p>Si vous avez des problèmes similaires, n&#8217;hésitez pas à les partager ici !</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/vU_k6DkOzB0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/06/liferay-et-cas-quand-le-ssl-sen-mele/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/06/liferay-et-cas-quand-le-ssl-sen-mele/</feedburner:origLink></item>
		<item>
		<title>Monitorer une JVM en local</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/MIKPf_Y16vw/</link>
		<comments>http://blog.ippon.fr/2012/02/05/monitorer-une-jvm-en-local/#comments</comments>
		<pubDate>Sun, 05 Feb 2012 19:40:52 +0000</pubDate>
		<dc:creator>Fabien ARRAULT</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[jconsole]]></category>
		<category><![CDATA[JMX]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4967</guid>
		<description><![CDATA[<p>Le JDK de Sun/Oracle propose plusieurs outils et APIs pour monitorer une jvm locale et ceci, depuis le JDK 6, sans avoir besoin de configurer cette jvm de manière particulière (enfin, ca c&#8217;est dans les cas simples nous verrons qu&#8217;il faut parfois ajouter une petite option)</p> <p></p> Les outils du JDK <p>Le JDK propose deux <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/05/monitorer-une-jvm-en-local/">Monitorer une JVM en local</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://blogbebe.org/photos/2011/06/Le-monitoring.jpg" alt="Monitoring" width="193" height="143" />Le JDK de Sun/Oracle propose plusieurs outils et APIs pour monitorer une jvm locale et ceci, depuis le JDK 6, sans avoir besoin de configurer cette jvm de manière particulière (enfin, ca c&#8217;est dans les cas simples <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  nous verrons qu&#8217;il faut parfois ajouter une petite option)</p>
<p><span id="more-4967"></span></p>
<h1>Les outils du JDK</h1>
<p>Le JDK propose deux utilitaires avec une interface graphique : JConsole et JVisualVM. Le premier permettant principalement d&#8217;accéder facilement aux MBeans JMX exposés par la JVM. Le deuxième étant beaucoup plus complet, en particulier si vous utilisez les plugins en téléchargement optionnel.</p>
<p>Il propose aussi des outils en ligne de commande :</p>
<ul>
<li>jps (liste des process java)</li>
<li>jstat (statistique sur le jvm en particulier sur l&#8217;état de la mémoire)</li>
<li>jstack (pour demander un thread dump), jmap (pour demander un heap dump)</li>
</ul>
<p>Tous ces outils sont présents dans le répertoire bin du JDK.</p>
<p>Ces outils sont soumis à quelques restrictions :</p>
<ul>
<li>certaines sont liées à des questions de sécurité. En particulier, ils ne sont souvent utilisables que par l&#8217;utilisateur qui exécute les jvms à monitorer</li>
<li>d&#8217;autres restrictions sont moins évidentes ; elles sont en partie décrites ici : <a href="http://visualvm.java.net/troubleshooting.html">http://visualvm.java.net/troubleshooting.html</a></li>
</ul>
<p>Sous windows, je rencontre actuellement des problèmes lorsque je me connecte à un serveur à distance (via Remote Desktop) : généralement, il faut toujours au moins que je me connecte en mode admin (mstsc.exe /admin (ou /console dans les anciennes versions) ) pour que les outils de monitoring puisse fonctionner. Mais cela ne suffit pas toujours &#8230;</p>
<h1>Accès programmatiques</h1>
<p>Ces outils sont très intéressants, mais il est parfois nécessaire d&#8217;accéder à des métriques particulières d&#8217;une jvm ou de l&#8217;application que la jvm héberge. Ou ils peuvent tout simplement ne pas fonctionner dans certains cas particuliers.</p>
<p>Dans la suite de ce post, je vais me focaliser sur les différentes façons d&#8217;accéder au serveur jmx des jvms en local sans avoir à configurer l&#8217;accès distant : qui peut se révéler complexe si l&#8217;on veut que cet accès reste sécurisé ( tout est dédrit ici : <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html">http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html</a> )</p>
<h2>L&#8217;API Attach</h2>
<p>L&#8217;utilisation de l&#8217;API Attach pour se connecter à un serveur jmx en local est décrit sur la même page web que l&#8217;accès distant :</p>
<p><a href="http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html#gdhkz">http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html#gdhkz</a></p>
<p>Cette api permet essentiellement :</p>
<ul>
<li>de découvrir les jvms disponibles</li>
<li>récupérer quelques  informations sur ces jvms (propriétés système et propriétés des agents chargés)</li>
<li>charger un agent à l&#8217;intérieur de la JVM cible</li>
</ul>
<p>Cette dernière fonctionnalité permet en particulier de charger l&#8217;agent JMX si il n&#8217;est pas déjà lancé. On peut lancer l&#8217;agent jmx au démarrage de la jvm via l&#8217;option -Dcom.sun.management.jmxremote. A partir du JDK 6, c&#8217;est grâce à l&#8217;API Attach, que cette option n&#8217;est souvent plus nécessaire : l&#8217;agent peut être chargé à la demande comme montré dans l&#8217;exemple ci-dessous.</p>
<p>(ce programme nécessite que le jar tools.jar présent dans le répertoire lib du JDK soit dans le classpath)</p>
<pre class="brush: java; title: ; notranslate">
package jmx;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

public class JmxAttachAPI {
	public static void main(String[] args) throws Exception {
		new JmxAttachAPI().dotIt();
	}

	static final String CONNECTOR_ADDRESS = &quot;com.sun.management.jmxremote.localConnectorAddress&quot;;

	private void dotIt() throws Exception {

		System.out.println(&quot;Available local vms : &quot;);
		List vmdList = VirtualMachine.list();
		for(VirtualMachineDescriptor vmd : vmdList) {
			System.out.printf(&quot;%s : %s%n&quot;, vmd.id() , vmd.displayName());
		}

		// Choose one vm :
		System.out.println();
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        String pid = &quot;&quot;;
        while(pid.length() == 0)  {
            System.out.println(&quot;vm id ? &quot;);
            pid = stdin.readLine();
        }

        System.out.println();
        System.out.printf(&quot;Connecting to jvm : %s%n&quot;,pid);
		VirtualMachine vm = VirtualMachine.attach(pid);
		String connectorAddress = null;
		try {
			// get the connector address
			connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);

			// no connector address, so we start the JMX agent
			if (connectorAddress == null) {
			   System.out.println(&quot;Agent not Started, loading it ...&quot;);
			   String agent = vm.getSystemProperties().getProperty(&quot;java.home&quot;) +
			       File.separator + &quot;lib&quot; + File.separator + &quot;management-agent.jar&quot;;
			   vm.loadAgent(agent);

			   // agent is started, get the connector address
			   connectorAddress =
			       vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
			} else {
				System.out.println(&quot;JMX Agent already started !&quot;);
			}
		} finally {
			vm.detach();
		}

		System.out.println();
		System.out.printf(&quot;Connecting to jmx server with connectorAddress : %s%n&quot;,connectorAddress);

		// establish connection to connector server
		JMXServiceURL url = new JMXServiceURL(connectorAddress);
		JMXConnector connector = JMXConnectorFactory.connect(url);

		MBeanServerConnection con = connector.getMBeanServerConnection();

        RuntimeMXBean runtime = ManagementFactory.newPlatformMXBeanProxy(
               con, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
        System.out.printf(&quot;Extracted classpath : %s%n&quot;,runtime.getClassPath());

	}
}
</pre>
<p>Et voici un exemple de son exécution :</p>
<pre>Available local vms :
8372 : org.apache.catalina.startup.Bootstrap start
2108 : jmx.JmxAttachAPI

vm id ?
8372

Connecting to jvm : 8372
Agent not Started, loading it ...
Connecting to jmx server with connectorAddress : service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc6AAtVbmljYXN0UmVmMgAADzE2OS4yNTQuMTQxLjIwNAAA1Qkf/eH4sQVkBOeL7SsAAAE1TnnPy4ABAHg=

Extracted classpath : C:\products\apache-tomcat-6.0.32\bin\bootstrap.jar</pre>
<p>Après avoir listé les jvms disponibles, ce programme s&#8217;attache à la jvm sélectionné et regarde si l&#8217;agent jmx est déjà chargé (en cherchant la propriété com.sun.management.jmxremote.localConnectorAddress)</p>
<p>Si il ne la trouve pas, il demande à la jvm de charger cet agent (l&#8217;agent est dans le jar management-agent.jar présent dans le répertoire jre/lib/ de la jvm cible)</p>
<p>Notez que la JConsole fait exactement la même chose : elle l&#8217;indique d&#8217;ailleurs dans la fenêtre de connexion en affichant &#8220;Note : The management agent will be enabled on this process&#8221; sous la liste des process disponibles lorsque le process sélectionné n&#8217;a pas encore l&#8217;agent JMX chargé</p>
<p>Une fois l&#8217;adresse jmx locale récupérée, l&#8217;API Attach a terminé son travail. L&#8217;api JMX prend ensuite le relai.</p>
<p>Ici on se contente d&#8217;extraire le classpath de la JVM cible. Mais l&#8217;ensemble des MBeans JMX de la JVM sont maintenant accessibles : que ce soit les MBeans de la JVM ou les MBeans que l&#8217;application aurait exposé dans le serveur JMX de la JVM</p>
<h2>L&#8217;API MonitoredHost</h2>
<p>Dans certains cas, l&#8217;API Attach ne fonctionne pas &#8230; (lorsque la JVM est exécutée par un service windows en particulier ; du moins dans l&#8217;environnement où je travaille actuellement)</p>
<p>JConsole utilise une 2ème API pour lister les jvms et extraire des infos : sun.jvmstat.monitor.MonitoredHost. Il utilise aussi une autre api bas niveau sun.management.ConnectorAddressLink : pour récupérer l&#8217;adresse JMX local</p>
<p>La limitation principale de cette api est qu&#8217;elle n&#8217;est pas capable d&#8217;activer l&#8217;agent JMX s&#8217;il ne l&#8217;est pas déjà. Il faut donc l&#8217;avoir activer explicitement via l&#8217;option -Dcom.sun.management.jmxremote (même avec un jdk 6 ou plus)</p>
<p>Sous réserve que l&#8217;agent jmx soit activé, on peut donc accéder au serveur JMX de cette façon :</p>
<p>(ce programme, très fortement inspiré du code source de la JConsole, nécessite aussi que le jar tools.jar soit dans le classpath)</p>
<pre class="brush: java; title: ; notranslate">
package jmx;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;
import sun.management.ConnectorAddressLink;

public class JmxMonitoredHost {

    public static void main(String[] args) throws Exception {
        new JmxMonitoredHost().doIt();
    }

    private void doIt() throws Exception {
        MonitoredHost localMonitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null));
        Set activeVms = localMonitoredHost.activeVms();

        Map pidToAddress = new HashMap();

        System.out.println(&quot;Available local vms : &quot;);
        for(Integer vmId : activeVms) {
            String pid = vmId.toString();
            try {
              MonitoredVm localMonitoredVm = localMonitoredHost.getMonitoredVm(new VmIdentifier(pid));

              String commandLine = MonitoredVmUtil.commandLine(localMonitoredVm);
              boolean attachable = MonitoredVmUtil.isAttachable(localMonitoredVm);
              String connectorAddress = ConnectorAddressLink.importFrom(vmId.intValue());

              System.out.printf(&quot;%5s %30s %4s%n&quot;,pid,commandLine,attachable);
              pidToAddress.put(pid,connectorAddress);

              localMonitoredVm.detach();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

		// Choose one vm :
        System.out.println();
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        String pid = &quot;&quot;;
        while(pid.length() == 0)  {
            System.out.println(&quot;vm id ? &quot;);
            pid = stdin.readLine();
        }

        // get the connector address
        String connectorAddress = pidToAddress.get(pid);
		System.out.println();
		System.out.printf(&quot;Connecting to jmx server with connectorAddress : %s%n&quot;,connectorAddress);

        // establish connection to connector server
        JMXServiceURL url = new JMXServiceURL(connectorAddress);
        JMXConnector connector = JMXConnectorFactory.connect(url);

        MBeanServerConnection con = connector.getMBeanServerConnection();

        RuntimeMXBean runtime = ManagementFactory.newPlatformMXBeanProxy(
        		con, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
        System.out.printf(&quot;Extracted classpath : %s%n&quot;,runtime.getClassPath());

    }

}
</pre>
<h2>L&#8217;API LocalVirtualMachine de la JConsole</h2>
<p>La JConsole a implémenté sa propre api de découverte au dessus des apis décrites ci-dessus : sun.tools.jconsole.LocalVirtualMachine ( On pourra trouvé son code source ici par exemple : <a href="http://javasourcecode.org/html/open-source/jdk/jdk-6u23/sun/tools/jconsole/LocalVirtualMachine.java.html">http://javasourcecode.org/html/open-source/jdk/jdk-6u23/sun/tools/jconsole/LocalVirtualMachine.java.html</a>)</p>
<p>Plutôt que d&#8217;utiliser ces deux Apis directement, il est donc plus simple d&#8217;utiliser LocalVirtualMachine</p>
<p>Cela nous donne ceci :</p>
<p>( ce programme nécessite tools.jar ET jconsole.jar dans la classpath pour fonctionner ) :</p>
<pre class="brush: java; title: ; notranslate">
package jmx;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.Map;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import sun.tools.jconsole.LocalVirtualMachine;

public class JmxJConsole {

	public static void main(String[] args) throws Exception {
		new JmxJConsole().doIt();
	}

	private void doIt() throws Exception {

		Map allVirtualMachines = LocalVirtualMachine.getAllVirtualMachines();

		System.out.println(&quot;Available local vms : &quot;);
		for(Integer vmId : allVirtualMachines.keySet()) {
			LocalVirtualMachine vm = allVirtualMachines.get(vmId);
			System.out.printf(&quot;%10s %50s %s%n&quot;,vmId,vm.displayName(),vm.isAttachable());
		}

		// Choose one vm :
        System.out.println();
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        String pid = &quot;&quot;;
        while(pid.length() == 0)  {
            System.out.println(&quot;vm id ? &quot;);
            pid = stdin.readLine();
        }

        // get the connector address
        LocalVirtualMachine vm = allVirtualMachines.get(new Integer(pid));
        // load jmx agent if necessary/possible :
        vm.startManagementAgent();
        String connectorAddress = vm.connectorAddress();

        System.out.println();
		System.out.printf(&quot;Connecting to jmx server with connectorAddress : %s%n&quot;,connectorAddress);

        // establish connection to connector server
        JMXServiceURL url = new JMXServiceURL(connectorAddress);
        JMXConnector connector = JMXConnectorFactory.connect(url);

        MBeanServerConnection con = connector.getMBeanServerConnection();

        RuntimeMXBean runtime = ManagementFactory.newPlatformMXBeanProxy(
        		con, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
        System.out.printf(&quot;Extracted classpath : %s%n&quot;,runtime.getClassPath());

	}
}
</pre>
<h1>Conclusion</h1>
<p>Avec ce dernier code, vous devriez être paré pour vous connecter en local aussi bien que JConsole et extraire vos propres métriques ou lancer des opérations de diagnostique (au hasard : lancer un heap dump) via les Apis JMX de la jvm</p>
<p>Toutefois même la JConsole n&#8217;arrive pas tout le temps à se connecter ou à voir une jvm local.</p>
<p>En cas de soucis, voici au moins trois pré-requis qui m&#8217;ont été nécessaire récemment :</p>
<ul>
<li>exécuter JConsole (ou votre code custom) avec le même utilisateur que la JVM cible</li>
<li>si vous vous connecté en remote desktop sur un serveur Windows : utiliser le mode admin : mstsc.exe /admin</li>
<li>activer explicitement l&#8217;agent jmx sur votre jvm cible (via -Dcom.sun.management.jmxremote)</li>
</ul>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/MIKPf_Y16vw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/05/monitorer-une-jvm-en-local/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/05/monitorer-une-jvm-en-local/</feedburner:origLink></item>
		<item>
		<title>Ippevent Hibernate OGM par Emmanuel Bernard le 9 février</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/7DKCdw4w94w/</link>
		<comments>http://blog.ippon.fr/2012/01/30/ippevent-hibernate-ogm-par-emmanuel-bernard-le-9-fevrier/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 09:00:39 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[DataGrid]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Infinispan]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4904</guid>
		<description><![CDATA[<p>PaaS, Cloud. Mais le vrai challenge c&#8217;est comment et où stocker vos données. Dans du NoSQL ? Peut-on utiliser une API familière ?</p> <p>L&#8217;objectif d&#8217;Hibernate OGM est d&#8217;explorer comment réutiliser Java Persistence et son API familière pour persister les entités dans une base NoSQL.</p> <p>Il offre une implémentation JPA (manipulation d&#8217;objet et requêtes JP-QL) tout <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/01/30/ippevent-hibernate-ogm-par-emmanuel-bernard-le-9-fevrier/">Ippevent Hibernate OGM par Emmanuel Bernard le 9 février</a></span>]]></description>
			<content:encoded><![CDATA[<p><img style="float: left;" src="http://www.devoxx.com/download/attachments/5014404/thumbnail.gif?version=1&amp;modificationDate=1311272361000" alt="Emmanuel Bernard" width="100" height="111" />PaaS, Cloud. Mais le vrai challenge c&#8217;est comment et où stocker vos données. Dans du NoSQL ? Peut-on utiliser une API familière ?</p>
<p>L&#8217;objectif d&#8217;Hibernate OGM est d&#8217;explorer comment réutiliser Java Persistence et son API familière pour persister les entités dans une base NoSQL.</p>
<p>Il offre une implémentation JPA (manipulation d&#8217;objet et requêtes JP-QL) tout en stockant et requêtant les données d&#8217;une grille clé/valeur (et d&#8217;autres approches NoSQL dans un second temps). Cela inclus notamment de supporter des applications JPA existantes.</p>
<p>Dans cette présentation, nous allons:</p>
<ul>
<li>faire un survol du monde (NoSQL) et voir en quoi une API comme JPA apporte un intérêt</li>
<li>voir comment Hibernate OGM stocke les entités et les associations dans la base clé/valeur et explorer les compromis fait</li>
<li>voir comment les requêtes JP-QL sont implémentés au dessus d&#8217;une technologie qui ne supporte pas la notion de requête (clé/valeur) et quel niveau peut être couvert</li>
</ul>
<p><span style="color: #ff0000;"><strong>Attention: contient des démos qui tournent !</strong></span></p>
<p>Pour vous inscrire, il vous suffit de cliquer sur le bouton ci-dessous (si vous désirez plus d&#8217;information vous pouvez aussi vous inscrire depuis notre <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/">page Ippevent</a> :</p>
<div style="width: 100%; text-align: left;"><iframe frameborder="0" height="192" marginheight="5" marginwidth="5" scrolling="auto" src="http://www.eventbrite.com/tickets-external?eid=2862552973&amp;ref=etckt" width="100%"></iframe></p>
<div style="font-family: Helvetica, Arial; font-size: 10px; padding: 5px 0 5px; margin: 2px; width: 100%; text-align: left;"><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/r/etckt" target="_blank">Billetterie en ligne</a><span style="color: #ddd;"> pour </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/event/2862552973?ref=etckt" target="_blank">Ippevent Hibernate OGM: JPA pour NoSQL (par Emmanuel Bernard)</a><span style="color: #ddd;"> produit par </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com?ref=etckt" target="_blank">Eventbrite</a></div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/7DKCdw4w94w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/30/ippevent-hibernate-ogm-par-emmanuel-bernard-le-9-fevrier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/30/ippevent-hibernate-ogm-par-emmanuel-bernard-le-9-fevrier/</feedburner:origLink></item>
		<item>
		<title>Ippevent Arquillian : Le film !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/hVCEljtZbZs/</link>
		<comments>http://blog.ippon.fr/2012/01/30/ippevent-arquillian-le-film/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 08:00:08 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Vidéo]]></category>
		<category><![CDATA[Arquillian]]></category>
		<category><![CDATA[CDI]]></category>
		<category><![CDATA[EJB 3.1]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JUnit]]></category>
		<category><![CDATA[Tests]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4899</guid>
		<description><![CDATA[<p>Notre Ippevent du 19 janvier dernier sur Arquillian est enfin dans la boîte. Retrouvez Alexis Hassler nous présentant ce bel outil qui permet de faire du test d&#8217;intégration d&#8217;applications Java EE et bien plus encore.</p> <p></p> ]]></description>
			<content:encoded><![CDATA[<p>Notre Ippevent du 19 janvier dernier sur Arquillian est enfin dans la boîte. Retrouvez Alexis Hassler nous présentant ce bel outil qui permet de faire du test d&#8217;intégration d&#8217;applications Java EE et bien plus encore.</p>
<p><iframe src="http://player.vimeo.com/video/35683432?title=0&amp;byline=0&amp;portrait=0" width="800" height="450" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/hVCEljtZbZs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/30/ippevent-arquillian-le-film/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/30/ippevent-arquillian-le-film/</feedburner:origLink></item>
		<item>
		<title>Ippevent Bonita le remake</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/5PXxoag7EFk/</link>
		<comments>http://blog.ippon.fr/2012/01/26/ippevent-bonita-le-remake/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 10:53:26 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[ESB et SOA]]></category>
		<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Vidéo]]></category>
		<category><![CDATA[Bonita]]></category>
		<category><![CDATA[BPM]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4879</guid>
		<description><![CDATA[<p>Notre Ippevent &#8220;Au coeur du BPM avec Bonita&#8221; du 19 mai 2012 avait connu un gros succès. Malheureusement un soucis technique nous avait empêché de diffuser la vidéo de cette conférence. Comme le sujet est important et nous sort un peu des considération purement technique de notre quotidien pour nous parler d&#8217;outils permettant de travailler <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/01/26/ippevent-bonita-le-remake/">Ippevent Bonita le remake</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.bonitasoft.com/images/bonitasoft-logo.png" alt="" width="168" height="62" />Notre Ippevent &#8220;Au coeur du BPM avec Bonita&#8221; du 19 mai 2012 avait connu un gros succès. Malheureusement un soucis technique nous avait empêché de diffuser la vidéo de cette conférence. Comme le sujet est important et nous sort un peu des considération purement technique de notre quotidien pour nous parler d&#8217;outils permettant de travailler avec les gens du métier, nous avons refait cette présentation pour que chacun puisse en bénéficier.</p>
<p>Ça tombe également bien avec le partenariat que vient de signer Ippon avec BonitaSoft en ce début d&#8217;année.</p>
<p><iframe frameborder="0" height="450" src="http://player.vimeo.com/video/35679944?title=0&amp;byline=0&amp;portrait=0" width="800"></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/5PXxoag7EFk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/26/ippevent-bonita-le-remake/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/26/ippevent-bonita-le-remake/</feedburner:origLink></item>
		<item>
		<title>La sécu c’est bien, la négliger ça craint – Un white-paper par David Martin</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/SebvDpywNPk/</link>
		<comments>http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 07:30:00 +0000</pubDate>
		<dc:creator>David MARTIN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Livre Blanc]]></category>
		<category><![CDATA[habilitations]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[livre blanc]]></category>
		<category><![CDATA[sécurité]]></category>
		<category><![CDATA[white-paper]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4842</guid>
		<description><![CDATA[<p>S&#8217;il est bien un sujet qui revient régulièrement dans l&#8217;actualité, c&#8217;est la sécurité. Et bien souvent, ce n&#8217;est pas pour faire bonne presse à l&#8217;acteur concerné (La faille du PSN a coûté à Sony plusieurs dizaines de millions de dollars et une importante perte d&#8217;image plus difficilement quantifiable). Le sujet est vaste et complexe. Vaste <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/">La sécu c&#8217;est bien, la négliger ça craint &#8211; Un white-paper par David Martin</a></span>]]></description>
			<content:encoded><![CDATA[<p>S&#8217;il est bien un sujet qui revient régulièrement dans l&#8217;actualité, c&#8217;est la sécurité. Et bien souvent, ce n&#8217;est pas pour faire bonne presse à l&#8217;acteur concerné (La faille du PSN a coûté à Sony plusieurs dizaines de millions de dollars et une importante perte d&#8217;image plus difficilement quantifiable). Le sujet est vaste et complexe. Vaste car il couvre un spectre très large de technologies pouvant souffrir de failles et qu&#8217;il convient de bien maîtriser et suivre pour contrer le risque. Complexe car les techniques mises en œuvre pour contourner les protections peuvent être extrêmement sophistiquées.<br />
En tant que développeurs d&#8217;application, il nous faut connaître les risques majeurs encourus par une application et les différentes parades qu&#8217;il convient de savoir mettre en place pour s&#8217;en prémunir. L&#8217;écosystème Java est riche et offre un panel de solutions et d&#8217;outils presque prêts à l&#8217;emploi qui permettent d&#8217;apporter une réponse fiable aux menaces les plus courantes. Ajoutez à cela des bonnes pratiques, une connaissance élargie autour de la stack d&#8217;exécution et vous détenez une base solide pour garantir à vos clients un premier niveau de sécurité tout à fait crédible.<br />
<a href="http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/securite_applications_java_blog/" rel="attachment wp-att-4843"><img class="alignright size-medium wp-image-4843" style="margin: 10px; border: 1px solid black;" title="securite_applications_java_blog" src="http://blog.ippon.fr/wp-content/uploads/2012/01/securite_applications_java_blog-300x199.jpg" alt="La securite dans les applications Java EE" width="300" height="199" /></a><br />
Mais la sécurité, ce n’est pas seulement se protéger contre des attaques. C’est aussi savoir prendre en compte les habilitations dans une application, comprendre les enjeux de gestion des utilisateurs et de leurs droits en entreprise, savoir s’inscrire dans un environnement qui mutualise ces données. Le contrôle des accès aux ressources, l’audit des actions réalisées dans une application, etc. sont des besoins souvent exprimés par les demandeurs, peut être trop rarement au lancement des projets, pour lesquels encore une fois une connaissance des outils techniques dédiés apporte une réponse éprouvée et robuste.</p>
<p>Le livre blanc sur la sécurité des applications Java introduit le sujet sous ces différents aspects. Il présente les vulnérabilités ainsi que les solutions possibles pour y répondre. Vous y trouverez aussi les informations relatives à la gestion des identités et des droits ainsi que l&#8217;intégration de ces dimensions dans une application Java. Enfin, il aborde les différentes contraintes et enjeux fréquemment rencontrés en entreprise.</p>
<p>Si vous souhaitez approfondir le sujet de la sécurité ou tout simplement le (re)découvrir, vous pouvez <a href="http://www.ippon.fr/livres-blancs">télécharger le livre blanc dans la rubrique dédiée sur le site d’Ippon Technologies</a>.</p>
<p>Et bien évidement j&#8217;attends avec impatience vos remarques et réactions sur ce blog.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/SebvDpywNPk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/</feedburner:origLink></item>
		<item>
		<title>Meilleurs voeux 2012 de la part d’Ippon Technologies</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/QJYiRwIliYk/</link>
		<comments>http://blog.ippon.fr/2012/01/03/meilleurs-voeux-2012-de-la-part-dippon-technologies/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 13:30:11 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Ippon]]></category>
		<category><![CDATA[Ippon Technologies]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4818</guid>
		<description><![CDATA[<p></p> ]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.ippon.fr/2012/01/03/meilleurs-voeux-2012-de-la-part-dippon-technologies/image/" rel="attachment wp-att-4817"><img class="aligncenter size-full wp-image-4817" title="Bonne année 2012" src="http://blog.ippon.fr/wp-content/uploads/2012/01/image.jpeg" alt="" width="500" height="500" /></a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/QJYiRwIliYk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/03/meilleurs-voeux-2012-de-la-part-dippon-technologies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/03/meilleurs-voeux-2012-de-la-part-dippon-technologies/</feedburner:origLink></item>
		<item>
		<title>Ippevent Arquillian le 19 janvier</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/N5jREmxc-Fw/</link>
		<comments>http://blog.ippon.fr/2012/01/03/ippevent-arquillian-le-19-janvier/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 13:02:32 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Arquillian]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[Tests]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4808</guid>
		<description><![CDATA[<p>Pour débuter cette nouvelle année 2012 (que je vous souhaite bonne et heureuse), nous démarrons avec un outil novateur : Arquillian.</p> <p>Une critique fréquente faite à l&#8217;encontre Java EE est la difficulté à tester ses composants comme les EJB ou les Beans CDI. L&#8217;outil de test JBoss Arquillian apporte une réponse puissante à ce problème <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/01/03/ippevent-arquillian-le-19-janvier/">Ippevent Arquillian le 19 janvier</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.google.fr/url?source=imglanding&amp;ct=img&amp;q=http://design.jboss.org/arquillian/logo/ui/images/success/arquillian_ui_success_256px.png&amp;sa=X&amp;ei=QIoBT_uiB4WAhQfojt3RAQ&amp;ved=0CAwQ8wc&amp;usg=AFQjCNEXcWwy3JNRVdEpxStArkPKqHKvdw" alt="" width="100" height="100" />Pour débuter cette nouvelle année 2012 (que je vous souhaite bonne et heureuse), nous démarrons avec un outil novateur : Arquillian.</p>
<p>Une critique fréquente faite à l&#8217;encontre Java EE est la difficulté à tester ses composants comme les EJB ou les Beans CDI. L&#8217;outil de test JBoss Arquillian apporte une réponse puissante à ce problème et à bien d&#8217;autres concernant les tests d&#8217;intégration.</p>
<p>Alexis Hassler, spécialiste Java EE 6 et membre éminent du Lyon Jug nous présentera lors de cet Ippevent cette solution de test nouvelle génération qui vous aidera que vous utilisez Java EE ou Spring.</p>
<p>Pour vous inscrire, il vous suffit de cliquer sur le bouton ci-dessous ou de vous rendre sur notre <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/">page Ippevent</a>.</p>
<div style="width: 100%; text-align: left;"><iframe frameborder="0" height="192" marginheight="5" marginwidth="5" scrolling="auto" src="http://www.eventbrite.com/tickets-external?eid=2620461872&amp;ref=etckt" width="100%"></iframe></p>
<div style="font-family: Helvetica, Arial; font-size: 10px; padding: 5px 0 5px; margin: 2px; width: 100%; text-align: left;"><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/r/etckt" target="_blank">La gestion d&#8217;événements</a><span style="color: #ddd;"> pour </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/event/2620461872?ref=etckt" target="_blank">Ippevent Arquillian</a><span style="color: #ddd;"> produit par </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com?ref=etckt" target="_blank">Eventbrite</a></div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/N5jREmxc-Fw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/03/ippevent-arquillian-le-19-janvier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/03/ippevent-arquillian-le-19-janvier/</feedburner:origLink></item>
		<item>
		<title>Ippevent Springfuse : le film !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/_XbtdE7XRVw/</link>
		<comments>http://blog.ippon.fr/2012/01/02/ippevent-springfuse-le-film/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 14:26:28 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Vidéo]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[SpringFuse]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4798</guid>
		<description><![CDATA[<p>Notre Ippevent du mois dernier sur Springfuse est enfin disponible en vidéo. Venez (re)-découvrir la présentation de Florent Ramière et de Springfuse l&#8217;outil de génération de code de Jaxio.</p> <p></p> ]]></description>
			<content:encoded><![CDATA[<p>Notre Ippevent du mois dernier sur Springfuse est enfin disponible en vidéo. Venez (re)-découvrir la présentation de Florent Ramière et de Springfuse l&#8217;outil de génération de code de Jaxio.</p>
<p><iframe frameborder="0" height="350" src="http://player.vimeo.com/video/34454849?title=0&amp;byline=0&amp;portrait=0" width="600"></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/_XbtdE7XRVw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/02/ippevent-springfuse-le-film/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/02/ippevent-springfuse-le-film/</feedburner:origLink></item>
		<item>
		<title>Pourquoi tous les consultants Ippon iront à DevoXX France</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/aMR3By3cwM8/</link>
		<comments>http://blog.ippon.fr/2011/12/16/pourquoi-tous-les-consultants-ippon-iront-a-devoxx-france/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 08:00:14 +0000</pubDate>
		<dc:creator>Geoffray GRUEL</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippon RH]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Ippon Technologies]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4787</guid>
		<description><![CDATA[<p></p> <p>Il y a quelques semaines nous vous annoncions notre soutien en tant que sponsor de DevoXX France les 18, 19 et 20 avril 2012 à Paris.</p> <p>Alors être sponsor c&#8217;est sympa :</p> On soutient une équipe de bénévoles qui monte un événement ÉNORME, On se montre avec nos habits du dimanche, y compris avec <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/12/16/pourquoi-tous-les-consultants-ippon-iront-a-devoxx-france/">Pourquoi tous les consultants Ippon iront à DevoXX France</a></span>]]></description>
			<content:encoded><![CDATA[<p><a title="Devoxx France" href="http://www.devoxx.com/display/FR12/Accueil" target="_blank"><img title="DevoXX France 2012" src="http://blog.ippon.fr/wp-content/uploads/2011/12/FR12.png" alt="DevoXX France 2012" width="222" height="92" /></a></p>
<p>Il y a quelques semaines nous vous annoncions notre soutien en tant que sponsor de <a title="Devoxx France" href="http://www.devoxx.com/display/FR12/Accueil" target="_blank">DevoXX France</a> les 18, 19 et 20 avril 2012 à Paris.</p>
<p>Alors être sponsor c&#8217;est sympa :</p>
<ul>
<li>On soutient une équipe de bénévoles qui monte un événement ÉNORME,</li>
<li>On se montre avec nos habits du dimanche, y compris avec un slot de conférence offert (alors qu&#8217;on n&#8217;a pas le niveau tout le monde le sait),</li>
<li>On rencontre de nouveaux copains et tous les vieux copains qui eux aussi ont un stand,</li>
<li>On fait des jeux sympas, on distribue des goodies,&#8230;</li>
</ul>
<p>Maintenant quand tu es consultant Ippon, que tu passes ta vie en mission, savoir que ta boîte soutient DevoXX c&#8217;est sympa mais ça ne résoud pas ton problème : toi tu veux y être à DevoXX France. Tu as déjà envoyé un petit mail à ton manager, tu en as parlé rapido dans le couloir à ton DG et tu veux faire partie des &#8220;happy fews&#8221; qui vont avoir leurs tickets.</p>
<p>Et bien c&#8217;est fait, Ippon Technologies a décidé d&#8217;envoyer TOUS ses consultants à DevoXX France (y compris les bordelais et les nantais) et nous venons d&#8217;acheter un gros paquet de tickets en conséquence.</p>
<p>Nous considérons en effet que DevoXX France va concentrer sur 3 jours :</p>
<ul>
<li>Tout le savoir et l&#8217;innovation sur les thèmes de notre quotidien : Web, Mobile, Cloud, Agile, langages de JVM et même notre bon vieux Java EE,</li>
<li>La crème de la communauté : les JUGers, les SUGers, les Duchess,</li>
<li>La crème des speakers,</li>
<li>Le tout dans un espace d&#8217;échange convivial.</li>
</ul>
<p>Bref nous n&#8217;avons pas tergiversé et nous avons pris nos tickets pour 100 consultants.</p>
<p>Et on a même un peu de stock pour les consultants qui voudraient nous rejoindre en début d&#8217;année et qui &#8220;of course&#8221; viendront à DevoXX France avec tous les Ippons.</p>
<p>Joyeux Noël,</p>
<p>Joyeux DevoXX,</p>
<p>Geoffray</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/aMR3By3cwM8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/12/16/pourquoi-tous-les-consultants-ippon-iront-a-devoxx-france/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/12/16/pourquoi-tous-les-consultants-ippon-iront-a-devoxx-france/</feedburner:origLink></item>
		<item>
		<title>Attaque brute force, Java et parallélisme</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/5KRTVEkyFSA/</link>
		<comments>http://blog.ippon.fr/2011/12/12/attaque-brute-force-java-et-parallelisme/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 14:01:22 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4755</guid>
		<description><![CDATA[<p>Ippon a lancé il y a un peu plus d&#8217;une semaine un jeu qui a eu un beau succès:</p> <p>http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/</p> <p>Un excellent retour sur ce jeu a été fait par Sébastien Prunier, et nous allons d&#8217;ailleurs nous baser sur sa solution pour la suite de ce billet. En effet, la dernière partie du jeu consistait <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/12/12/attaque-brute-force-java-et-parallelisme/">Attaque brute force, Java et parallélisme</a></span>]]></description>
			<content:encoded><![CDATA[<p>Ippon a lancé il y a un peu plus d&#8217;une semaine un jeu qui a eu un beau succès:</p>
<p><a href="http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/">http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/</a></p>
<p>Un excellent retour sur ce jeu a été fait par <a href="http://sebprunier.wordpress.com/2011/12/05/dimanche-pluvieux-ippon-recrute-au-coin-du-feu/" target="_blank">Sébastien Prunier</a>, et nous allons d&#8217;ailleurs nous baser sur sa solution pour la suite de ce billet. En effet, la dernière partie du jeu consistait à faire un algorithme de &#8220;brute force&#8221; afin de déchiffrer un mot de passe. Certaines personnes ont cru, à tort, qu&#8217;il s&#8217;agissait juste de faire une boucle &#8220;while&#8221; et de tester tous les cas possibles: cela rendait le déchiffrable impossible, à moins d&#8217;avoir beaucoup de temps disponible&#8230; Bien entendu il y avait une astuce, que pas mal de monde (dont Sébastien) a trouvé: étant donné qu&#8217;il s&#8217;agissait de trouver les lettres d&#8217;un pseudo-Sudoku, il n&#8217;y avait que 9 lettres possibles, qui ne répétaient pas, soit 9! possibilités (9! = 9*8*7*6*5*4*3*2*1 = 362 880 possibilités).</p>
<p>Le code de Sébastien permet ainsi de trouver la bonne combinaison en 80 secondes (sur mon MacBook):</p>
<p><a href="https://github.com/sebprunier/IpponRecrute/blob/master/src/main/java/fr/ippon/rh/support/ForceBrute.java" target="_blank">https://github.com/sebprunier/IpponRecrute/blob/master/src/main/java/fr/ippon/rh/support/ForceBrute.java</a></p>
<p>Cependant, on peut faire plus performant: pour être exact, &#8220;probablement plus performant&#8221;, car tout dépend de vos données (plus le résultat se trouve &#8220;loin&#8221; dans notre jeu de test, plus la parallélisation va nous faire gagner du temps).</p>
<p>Nous allons pour cela voir plusieurs méthodes différentes: Node.js, Scala, Java &#8220;pur&#8221; et Spring.<br />
<span id="more-4755"></span></p>
<h2>Méthode n°1: utilisation de Node.js</h2>
<p>Plusieurs personnes ont remonté qu&#8217;en utilisant Node.js, on pourrait certainement faire mieux. Voilà un bon exemple du &#8220;hype oriented computing&#8221;, que l&#8217;on m&#8217;a déjà sorti plusieurs fois lors du challenge USI 2011: node.js n&#8217;est volontairement pas multi-threadé, pour éviter de faire du context switching et éviter d&#8217;empiler des threads (typiquement une thread par utilisateur, comme c&#8217;est le cas dans beaucoup de nos &#8220;vieux&#8221; serveurs d&#8217;applications Java qui ne font pas de NIO). Cela permet d&#8217;avoir des applications très réactives, et qui supportent beaucoup d&#8217;utilisateurs, à partir du moment où ces applications &#8220;attendent&#8221; la majeure partie du temps. C&#8217;est un cas classique d&#8217;utilisation des serveurs d&#8217;applications: ils passent une grande partie de leur temps à attendre les données provenant d&#8217;une base de données. Node.js est donc particulièrement adapté à des sites Web utilisant une base de données complexe, mais est par contre peu adapté à des sites Web faisant beaucoup de calcul en local: un excellent exemple est donné en début du post maintenant célèbre &#8220;<a href="http://teddziuba.com/2011/10/node-js-is-cancer.html" target="_blank">Node.js is Cancer</a>&#8220;.</p>
<p>Ajoutons que sur nos machines modernes, l&#8217;histoire va plutôt dans le sens inverse de Node.js: nous avons de plus en plus de coeurs, chacun étant généralement moins puissant que la génération précédente.</p>
<h2>Méthode n°2: utilisation de Scala</h2>
<p>Scala 2.9 permet d&#8217;avoir des collections utilisant automatiquement les différents coeurs de votre système: c&#8217;est en quelque sorte l&#8217;inverse de l&#8217;approche de Node.js! Vous pouvez donc itérer sur une collection, et les traitements sur cette collection utilisent alors automatiquement plusieurs threads, répartissant ainsi les traitements sur l&#8217;ensemble des coeurs du système.</p>
<pre class="brush: java; title: ; notranslate">
(1 to 1000000).toArray.par.map(_*2)
</pre>
<p>Le <strong>.par</strong> dans le code précédent dit à Scala d&#8217;utiliser les collections &#8220;parallèles&#8221;. Dans la pratique, ce code a cependant beaucoup de problèmes:</p>
<ul>
<li>Il va utiliser le framework Fork/Join de Java 7: donc si vous êtes sour Mac OS X, comme moi, cela ne va simplement fonctionner que sur une seule thread.</li>
<li>&lt;troll&gt; Il est écrit en Scala, et donc personne ne le comprend &lt;/troll&gt;</li>
</ul>
<div>Pour une critique de cette fonctionnalité, nous vous conseillons de lire <a href="http://beust.com/weblog/2011/08/15/scalas-parallel-collections/" target="_blank">ce post de Cédric Beust</a>.</div>
<h2>Méthode n°3: Java pur</h2>
<div>L&#8217;avantage de coder en Java &#8220;pur&#8221; est d&#8217;avoir enfin le niveau de contrôle voulu, avec un niveau de complexité très réduit (pas la peine de passer la semaine à apprendre un nouveau langage ou framework). Après, tout dépend de ce que l&#8217;on entend par complexité: personnellement, je préfère avoir 10 lignes de code de plus, que je comprends sans problème, plutôt que de devoir apprendre un nouveau langage, qui d&#8217;ailleurs me cache beaucoup de son fonctionnement.</div>
<div>Voici donc mon code en Java:</div>
<div>
<pre class="brush: java; title: ; notranslate">
package fr.ippon.rh.service;

import org.jasypt.util.text.BasicTextEncryptor;

import java.util.*;

/**
 * Resolution de l'etape 3 par force brute.
 *
 * @author Sébastien Prunier
 * @author Julien Dubois
 */
public class MultiForceBrute {

    // Texte a decrypter
    private static final String etape4Texte = &quot;5oi/MCVWOrk2V8bI2LY4XM4gKf/hqRnz6/d0HftJYadMv7xkIjUsTfvXyyf0kJ/D1Or0QMicOUf7YIAkAMWkbNJpLA5cgOHZvGZVC1LBGdpe0n3zY5VfyYjUIFu/0VNyLVMOAu4BaC3ncdPkh5Q0r+IQeTV+IqOOBlsozTfxeLYBJhxIUdSaXIVubo7RSPOn1Y0aLrTEZhlPkJFJhQohhOr5d0/zqre7HnFdc/9vSC3qda6VKwxd+yAhl762kOGReE4YbeMX/1wg175ruUaT4tgVYaOLXIRg0fqZYIwu37KUrOvtUD+inZSYwMpUrNSeV9Wshwoi6kBXkriEoc2Qg58b6WVfNTzGMFsRp/D4TGMx04hGg2WTT4lRPebqGl5cPm6qSeb7WET3xbJ4LUCvOgX0cDr22inxlGUgkbF7m8ApZw2kOverBgnhW+dE3amE+bP1Ac1ky4sSY0Sjeec2n4QI6hX9mwl7GBc9Ep8uF7t+XdZFmuml4/bFgxtDOpi8zQ6NYXe2/UT5S6i/hPPHHRa6OGL2ZAswBtAkcsYiw564hshKvzVOMtP05Zu19C1zY+84kmpsGbxxknSI61owCNOvF1tJitww4EmkLsIhgveV+RcmTQOiwONJET7Q9qK4RFpFuz+hu1Kel0QsMPZMlvhSsSTj+lmLHzG9nC5s4RcvLR1JeL27MvcfO0CxZx9XSYazu+LqVK2qlv+NXftT9JFx19hVIvAI/T4oM9xf3wYrLozs1GDRrPju2yVXZb91vn4TdWWIoXI8yGQ5AaHYVLNu5LVez/Q4sH/DRjjMHLGTsYpXNm/xRrwf10Aw78dO58dvUy+ClP6//0wq+9+tw4knCtZwPK6Ov1gqvCzUlp3voDO+J/7/9+OoA4OkdJv8Nsu02lWZ6/mDsrr49U8D8mJgmqze4jVLbXg61HCuzSCOhnHPtMmyfykDSFHXvSGCiuyGoWN5ObIAo/k9XxYlZNrGpwYq3aTwaKJwG1vTtLzHop0bfQ50+cz18LqynMB2t+Y5AQ9IGAvJX6nWrO/C8GBD/bE/lZT+i1XYhYJ0JB0zoadQK+AkyNNiwUe9Dv31e614zgVTGlJ/JvSQGBCAcK+wYNDK1fVY2EEWyQhlQ3BYdwcqF4myOI7wtZsPscwO1Kc8TwlPGypQ/6JG4Q5AUeXmzrXi67boN0tB4YUyG5cQk7Ehe3gaHI7rF5IGYT1id7agEcxphjRWMTo9fT9zIb2tsA9SBw+tici5y2E7xHbnEcMjF4xuGWjEy7sr8+PktLQldvcyAo0jkwlN8G6PyL7R1HcWITr8W9T3Qr4Yq3vazV16pDf7tofDEdoI9/9jt8wchTd1gCh/fnZk88TblEJqGnbrsPL+V2S+/YaLv7A7nZ1Bjy9WiQYiGnO1tgqMMbwt470eb1mIKyOcarrGcAATiEq8DxE1H8xeEpy23BtdTHJwT5COhCY+WbEWcYvCh6tBVs2PPvGSCJvClW2sR0n16kdtQiYS7uOiyOANoVy5ZygJ4jITiik3Lcfm3rE1DLaOM44DjRy1W5YTq7dXYKBsXcdoc+JmZ+7naVcBQ2q2XlZ/t2EvN9k1rVW4x7o7V7YsE2bbPqyvAxt0w1NsgVUaAsff361KxJgD7JXQXdpEyD+6KE1N+SmUOOUG22OxOZbsHy/+WPTKboQ5AMFG8pgR61TfAA6YqPakrGMKYGkpe0T+1t82Zo1t3Q+z2WxSLdRX5bslJjfuZSqqCpao40BbIEEFYAlmkTgDuKIaP4dA9o+b0M+lPjIM/mwWjxDdOraR3w0ncnyrUigGGisYsT5KHh89VHcyv94gJdMeT+5LC/7plTAd5HhMfp1Gq8f/6L1NWuhgyD/ne8VhNOuThkf53e5QzEuhUJqc8P/A68U/TG83SFgVRiPG2h06bEGC6yztEYlT/LPBQJkcB0I2Yg4BbcJRXTc6mZT54Fato3zRPYlqXdniQsxTR8w6WgVbRF93bn99lrJc9lLnqn9F8cFTG5QKp9u45yExo2Hy/0jmcpHyhaLlJP/ECuEeQK7M5H2Ro3rG2wwcAiuK0JV0meM6Isij2z4ldl2agyR2TKNgVcCynrScqFpzkEgwmPY6XuU/+qN89fgsRJ+8uuL0V1ah4zl70ymEzMYX48bI8icCIP4BFVp+mBymy2AUo7ln8zfxW4DKlZgVeyBsluDUqjn111m4oq/JkbzwlW3/D+KU9Yb52KwcHmbnpO8TcKXprhk2iJ04ak3IWY1u+pNU8WZRz3+jQWoPpIQtA8DQQdIYXrKwgXVerMsp2g4Tj0Irf5RnpcbjzXNM2A2mBo6ak/dp1I0tFK3Ue5HfSeBZ6iLBGsKii8VJPCw2AxM/JI74/Cl2BaggiMvpqAhMDyG7EhnaMZfgj+8Kd9P1hTp5nsZWGe3vnwDLLpnDqH4vER7J1uKpm3ig2XGuq3XFo7Fp6naG+B7qlSRF&quot;;

    private static long startTime;
    private static boolean stopDecryption;

    /**
     * Programme principal
     */
    public static void main(String args[]) {
        startTime = Calendar.getInstance().getTimeInMillis();

        MultiForceBrute multiForceBrute = new MultiForceBrute();
        multiForceBrute.decrypt();
    }

    private void decrypt() {
        Set passwords = new HashSet();
        permute(&quot;&quot;, &quot;ABCDEGHIJ&quot;, passwords);
        System.out.println(&quot;Password size: &quot; + passwords.size());

        int cores = Runtime.getRuntime().availableProcessors();
        System.out.println(&quot;Number of cores: &quot; + cores);
        String[] passwordArray = new String[passwords.size()];
        passwordArray = passwords.toArray(passwordArray);
        Collection partitions = new ArrayList();
        int partitionSize = passwordArray.length / cores;
        for (int c = 0; c &lt; cores; c++) {
            String[] partition = Arrays.copyOfRange(passwordArray, c * partitionSize, (c + 1) * partitionSize);
            partitions.add(partition);
        }
        for (String[] partition : partitions) {
            DecryptionThread decryptionThread = new DecryptionThread(partition);
            decryptionThread.start();
        }
    }

    /**
     * Calcul des permutations.
     *
     * @param sStart    chaine de depart.
     * @param sEnd      chaine d'arrivee.
     * @param passwords ensemble des mots de passe.
     */
    private void permute(String sStart, String sEnd, Set passwords) {
        if (sEnd.length()             passwords.add(sStart + sEnd);
        } else {
            for (int i = 0; i &lt; sEnd.length(); i++) {
                String newString = sEnd.substring(0, i) + sEnd.substring(i + 1);
                permute(sStart + sEnd.charAt(i), newString, passwords);
            }
        }
    }

    private class DecryptionThread extends Thread {

        private String[] passwords;

        DecryptionThread(String[] passwords) {
            this.passwords = passwords;
        }

        public void run() {
            for (String password : passwords) {
                if (stopDecryption) {
                    return;
                }
                try {
                    BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
                    textEncryptor.setPassword(password);
                    String decryptedText = textEncryptor.decrypt(etape4Texte);
                    if (decryptedText.contains(&quot;ippon&quot;)) {
                        System.out.println(&quot;Result: &quot; +password);
                        long totalTime = Calendar.getInstance().getTimeInMillis() - startTime;
                        System.out.println(&quot;Solved in: &quot; + totalTime + &quot; ms.&quot;);
                        stopDecryption = true;
                    }
                } catch (Exception e) {
                    // Bad password !
                }
            }
        }
    }
}
</pre>
</div>
<div>Cette méthode permet de trouver la solution en <strong>seulement 15 secondes</strong> (toujours sur mon MacBook, qui utilise alors ses 8 coeurs et commence à chauffer).</div>
<h2>Méthode n°4: Spring</h2>
<p>Les trois solutions que nous avons vu, malheureusement, ne sont pas très industrielles: sur un projet en production, personne n&#8217;a envie de lancer ainsi des threads qui utilisent tous les coeurs disponibles, sans aucun contrôle.</p>
<p>Pour cela Spring propose une abstraction très intéressante, le TaskExecutor. Nous utilisons ici Spring 3.0 (<a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html" target="_blank">voici la documentation officielle</a>), sachant qu&#8217;il est prévu que Spring 3.1 supporte le framework Fork/Join, comme Scala, mais qu&#8217;à l&#8217;heure actuelle (Spring 3.1.0.M1), la documentation n&#8217;est pas à jour.</p>
<p>Dans sa version la plus simple, ce TaskExecutor permet de définir un pool de threads:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;taskExecutor&quot; class=&quot;org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor&quot;&gt;
  &lt;property name=&quot;corePoolSize&quot; value=&quot;5&quot; /&gt;
  &lt;property name=&quot;maxPoolSize&quot; value=&quot;10&quot; /&gt;
  &lt;property name=&quot;queueCapacity&quot; value=&quot;25&quot; /&gt;
&lt;/bean&gt;</pre>
<p>Dans la pratique, ce système permet de centraliser dans un seul endroit la configuration de son pool de Thread, et de pouvoir ainsi l&#8217;optimiser:</p>
<ul>
<li>On peut bien entendu utiliser le nombre de coeurs disponibles: c&#8217;est une variable qui est tout à fait intéressante, car dans un environnement virtualisé le nombre de coeurs disponibles peut être amené à évoluer</li>
<li>On peut utiliser la configuration Spring pour modifier ces valeurs en fonction des environnements: c&#8217;est la notion de profils, qui va elle aussi apparaître avec Spring 3.1, mais qui elle est <a href="http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/" target="_blank">très bien documentée</a></li>
<li>On peut choisir de n&#8217;utiliser qu&#8217;un seul thread: c&#8217;est ce qui arrive en fait très souvent pour les applications Web, car on veut garder la majeure partie des coeurs disponibles pour les utilisateurs. Ainsi, l&#8217;ensemble des traitements de fond sont soumis à une seule et même thread, ce qui permet d&#8217;avoir une application toujours réactive, quels que soient les traitements lancés. L&#8217;intérêt ici est également d&#8217;utiliser la même thread pour des traitements différents.</li>
<li>On peut utiliser le pool de thread du serveur d&#8217;applications, et c&#8217;est ce que nous allons détailler plus bas.</li>
</ul>
<div>En effet, les &#8220;gros&#8221; serveurs d&#8217;applications du marché (Websphere et Weblogic) proposent leur propre système de pool de thread, autour d&#8217;une API commune appelée CommonJ. Cette API devait être standardisée, <a href="http://www.jcp.org/en/jsr/detail?id=237">et a fini par être abandonnée</a>, mais elle est toujours disponible sur ces deux serveurs.</div>
<div>Le TaskExecutor permet donc d&#8217;utiliser ces APIs sans avoir à les connaître, et bien entendu uniquement en production (on pourrait avoir un profil &#8220;dev&#8221; qui utilise un pool de thread normal, et un profil &#8220;prod&#8221; qui utilise celui de Websphere):</div>
<pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;taskExecutor&quot; class=&quot;org.springframework.scheduling.commonj.WorkManagerTaskExecutor&quot;&gt;
    &lt;property name=&quot;workManagerName&quot; value=&quot;wm/default&quot;/&gt;
    &lt;property name=&quot;resourceRef&quot; value=&quot;false&quot;/&gt;
&lt;/bean&gt;
</pre>
<p>Cette configuration permet ainsi au administrateurs de votre serveurs d&#8217;applications de modifier le nombre de threads disponibles en fonction des besoins et des capacités disponibles, ce qui est essentiel en cas de charge importante sur le serveur.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/5KRTVEkyFSA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/12/12/attaque-brute-force-java-et-parallelisme/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/12/12/attaque-brute-force-java-et-parallelisme/</feedburner:origLink></item>
		<item>
		<title>Jeu “Ippon Recrute”, deuxième édition</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/BglcXUPK-yo/</link>
		<comments>http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 09:14:39 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Recrutement]]></category>
		<category><![CDATA[Concours]]></category>
		<category><![CDATA[Ippon Technologies]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4735</guid>
		<description><![CDATA[<p>Dans le cadre de sa politique de recrutement, Ippon Technologies avait lancé en début d&#8217;année un jeu qui a eu beaucoup de succès:</p> <p>https://github.com/ippontech/IpponRecrute</p> <p>Cependant, certaines personnes ont trouvé ce jeu trop facile, et nous avions alors promis une nouvelle version plus difficile&#8230; Voici donc la deuxième édition de ce jeu!</p> Surveillez notre dépôt GitHub https://github.com/ippontech/IpponRecrute <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/">Jeu &#8220;Ippon Recrute&#8221;, deuxième édition</a></span>]]></description>
			<content:encoded><![CDATA[<p>Dans le cadre de sa politique de recrutement, Ippon Technologies avait lancé en début d&#8217;année un jeu qui a eu beaucoup de succès:</p>
<p><a href="https://github.com/ippontech/IpponRecrute" target="_blank">https://github.com/ippontech/IpponRecrute</a></p>
<p>Cependant, certaines personnes ont trouvé ce jeu trop facile, et nous avions alors promis une nouvelle version plus difficile&#8230; Voici donc la deuxième édition de ce jeu!</p>
<ul>
<li>Surveillez notre dépôt GitHub <a href="https://github.com/ippontech/IpponRecrute" target="_blank">https://github.com/ippontech/IpponRecrute</a></li>
<li>Vendredi 2 Décembre, à 20h30, nous pousserons une nouvelle version de notre code</li>
<li>A vous de trouver la solution!</li>
</ul>
<div>Nous sélectionnerons en priorité les personnes qui ont résolu l&#8217;énigme le plus rapidement possible (donc à priori Vendredi soir 20h35&#8230; A voir si cette version est vraiment plus difficile!), ainsi que celles qui l&#8217;ont résolue de manière élégante (avec par exemple un petit script Groovy, et une explication).</div>
<div>Et bien entendu, n&#8217;oubliez pas d&#8217;aller lire nos offres d&#8217;emploi sur <a href="http://www.ippon.fr/offres-d-emploi" target="_blank">http://www.ippon.fr/offres-d-emploi</a></div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/BglcXUPK-yo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/</feedburner:origLink></item>
		<item>
		<title>Devoxx : les évolutions de JMS 2.0</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/wC8XL9fNmiY/</link>
		<comments>http://blog.ippon.fr/2011/11/25/devoxx-les-evolutions-de-jms-2-0/#comments</comments>
		<pubDate>Fri, 25 Nov 2011 08:20:20 +0000</pubDate>
		<dc:creator>Fabien ARRAULT</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JMS]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4714</guid>
		<description><![CDATA[<p>A Devoxx, j&#8217;ai assisté à la présentation de Nigel Deakin, spec lead de JMS 2.0, sur l&#8217;état actuel des travaux de l&#8217;expert group JMS. Les propositions de l&#8217;expert group sont toujours en discussion, il nous a indiqué que sa présentation était déjà un peu différente de celle qu&#8217;il avait faite à JavaOne et que ce <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/25/devoxx-les-evolutions-de-jms-2-0/">Devoxx : les évolutions de JMS 2.0</a></span>]]></description>
			<content:encoded><![CDATA[<p>A Devoxx, j&#8217;ai assisté à la présentation de Nigel Deakin, spec lead de JMS 2.0, sur l&#8217;état actuel des travaux de l&#8217;expert group JMS.<br />
Les propositions de l&#8217;expert group sont toujours en discussion, il nous a indiqué que sa présentation était déjà un peu différente de celle qu&#8217;il avait faite à JavaOne et que ce qu&#8217;il nous présentait n&#8217;était que provisoire.</p>
<p>Sa présentation complète est disponible depuis mardi soir ici : <a href="http://java.net/projects/jms-spec/downloads/download/JMS2.0Devoxx2011.pdf">JMS2.0Devoxx2011.pdf</a></p>
<p>Nigel a commencé par nous rappeler que JMS est une spécification stable et ayant eut beaucoup de succès (JMS 1.02b à 10 ans).<br />
Mais depuis l&#8217;éco-système Java EE a évolué, et il était temps de faire une mise à jour.</p>
<h1>Buts de cette version</h1>
<ul>
<li>Simplification de l&#8217;API</li>
<li>Intégration avec CDI</li>
<li>Clarifier les ambiguités de l&#8217;API et les relations avec les autres spécifications Java EE</li>
<li>PAAS / multi-tenancy</li>
<li>Standardisation de l&#8217;interface entre les fournisseurs JMS et les serveurs d&#8217;application</li>
<li>Standardisation de fonctionnalités proposées par les différentes implémentations JMS disponibles</li>
</ul>
<p>Je reprends ici une partie de ce qu&#8217;il nous présenté.</p>
<h1><span id="more-4714"></span><br />
Simplications de l&#8217;API existante</h1>
<p>Voici quelques exemples qui nous ont été présentés :</p>
<h2>Création des sessions  JMS</h2>
<p>Toutes les combinaisons de la signature actuelle de createSession n&#8217;ont pas forcément de sens. De plus dans un environnement Java EE les valeurs des paramètres de cette méthode sont simplement ignorés (la sémantique transactionnelle de l&#8217;EJB étant celle qui prévaut alors) :</p>
<ul>
<li>signature actuelle :</li>
</ul>
<pre class="brush: java; title: ; notranslate">
connection.createSession(transacted, deliveryMode)
</pre>
<ul>
<li>nouvelle signature pour Java SE :</li>
</ul>
<pre class="brush: java; title: ; notranslate">
connection.createSession(sessionMode)
</pre>
<ul>
<li>nouvelle signature pour Java EE :</li>
</ul>
<pre class="brush: java; title: ; notranslate">
connection.createSession()
</pre>
<h2>Implémentation de AutoCloseable</h2>
<p>Les javax.jms.Connection implémenteront java.lang.AutoCloseable ce qui permettra de les utiliser dans la construction try-with-resources du jdk 7</p>
<h2>Méthode raccourcie pour envoyer un message</h2>
<p>Lorsqu&#8217;il n&#8217;est pas nécessaire de manipuler une instance de javax.jms.Message : en particulier pour positionner un entête ou une propriété ; il sera possible d&#8217;utiliser une nouvelle signature de la méthode send sur javax.jms.MessageProducer :</p>
<pre class="brush: java; title: ; notranslate">
producer.send(String body)
</pre>
<p>au lieu de devoir créer un message JMS avant de l&#8217;envoyer via :</p>
<pre class="brush: java; title: ; notranslate">
producer.send(javax.jms.Message message)
</pre>
<h1>Création d&#8217;une nouvelle API JMS</h1>
<p>Un des problèmes de l&#8217;API JMS est qu&#8217;elle demande beaucoup de code qui n&#8217;est pas toujours utile.<br />
Ainsi rien que pour envoyer un message, elle nécessite l&#8217;obtention de nombreux objets : en particulier une ConnectionFactory,<br />
une Connection, une Session, un MessageProducer&#8230;</p>
<p>Depuis quelques semaines, l&#8217;Expert Group réfléchit donc à la création d&#8217;une nouvelle classe : MessagingContext regroupant les responsabilités de : Connection + Session + MessageProducer</p>
<p>Voici l&#8217;exemple d&#8217;utilisation que Nigel nous a donné :</p>
<pre class="brush: java; title: ; notranslate">
@Resource(mappedName=&quot;JMS/contextFactory&quot;)
ContextFactory contextFactory;
@Resource(mappedName=&quot;JMS/orderQueue&quot;)
Queue orderQueue;
public void sendMessage(String payload) {
  try (MessagingContext mCtx = contextFactory.createContext();){
    TextMessage textMessage = mCtx.createTextMessage(payload);
    mCtx.send(orderQueue,textMessage);
  }
}
</pre>
<p>Cette nouvelle API lancerait des exceptions runtime plutôt que l&#8217;exception checkée JMSException actuellement utilisée</p>
<h1>Intégration avec CDI</h1>
<p>L&#8217;Expert Group est toujours en pleine discussion sur la façon d&#8217;intégrer JMS à CDI (JSR 299 &#8211; Contexts and Dependency Injection for Java EE).<br />
J&#8217;ai repris ci-dessous les exemples d&#8217;injection qui nous ont été présentés. Mais Nigel nous a indiqué qu&#8217;ils devaient se rajouter de l&#8217;Expert Group de CDI pour valider la faisabilité de cette approche. A suivre donc.</p>
<p>Proposition pour l&#8217;injection de la nouvelle API MessageContext :</p>
<pre class="brush: java; title: ; notranslate">
@Resource(mappedName=&quot;JMS/orderQueue&quot;)
Queue orderQueue;

@Inject
@MessagingContext(lookup=&quot;JMS/contextFactory&quot;)
MessagingContext mCtx;
@Inject
TextMessage textMessage;
public void sendMessage(String payload) {
  textMessage.setText(payload);
  mCtx.send(orderQueue,textMessage);
}
</pre>
<p>Proposition pour l&#8217;injection des objets de l&#8217;ancienne API :</p>
<pre class="brush: java; title: ; notranslate">
@Inject
@JMSConnection(lookup=&quot;JMS/connFactory&quot;)
@JMSDestination(lookup=&quot;JMS/inboundQueue&quot;)
MessageProducer producer;

@Inject
TextMessage textMessage;

public void sendMessage (String payload){
  try {
    textMessage.setText(payload);
    producer.send(textMessage);
  } catch {JMSException e}
    // do something
  }
}
</pre>
<h1>De nouvelles fonctionnalités</h1>
<p>Nigel nous a présenté aussi de nouvelles fonctionnalités qui pourraient être standardisées dans cette version de la spec :</p>
<ul>
<li>&#8220;Livraison retardée&#8221; (Delivery delay) :</li>
</ul>
<p>Permettant de spécifier la date à laquelle un message sera consommable.<br />
(Weblogic Integration implèmente de cette manière les timers afin de permettre de déclencher des opérations à une date ultérieure.<br />
J&#8217;ai déjà parlé de ce type de message dans <a href="http://blog.ippon.fr/2010/06/29/gestion-des-ressources-jms-de-weblogic-en-jmx-avec-groovy-3eme-partie-acces-au-contenu-des-messages/">mon billet sur le gestion des ressources JMS</a>)</p>
<ul>
<li>Accusé de réception asynchrone (Asynchronous acknowledgement) :</li>
</ul>
<p>La méthode send redonnerait alors la main immédiatement au thread l&#8217;appelant sans attendre que le fournisseur JMS (JMS provider)<br />
valide la prise en charge du message. Une fois pris en charge, le fournisseur JMS appelerait un objet callback pour notifier l&#8217;application.</p>
<ul>
<li>la propriété JMSXDeliveryCount devient obligatoire</li>
</ul>
<p>En cas d&#8217;erreur de traitement, un message peut être remis dans une queue (lors du rollback de la transaction du consommateur).<br />
A chaque fois qu&#8217;un message est relivré par le fournisseur, celui-ci incrémente la propriété JMSXDeliveryCount.<br />
En se basant sur la valeur de cette propriété, les applications pourront prendre des décisions particulières et en particulier se prémunir<br />
contre des retry infinis. (Toutefois, la plupart des fournisseurs JMS permettent déjà de définir un nombre maximal de retry)</p>
<ul>
<li>Hiérarchies de Topic</li>
</ul>
<p>Pour reprendre l&#8217;exemple de la présentation, il est possible de définir des Topic suivant une règle de nommage hiérarchique :</p>
<ul style="list-style-type: circle;">
<li>STOCK.NASDAQ.TECH.ORCL</li>
<li>STOCK.NASDAQ.TECH.GOOG</li>
<li>STOCK.NASDAQ.TECH.ADBE</li>
<li>STOCK.NYSE.TECH.HPQ</li>
</ul>
<p>Les consommateurs pourront alors souscrire à plusieurs Topic liés en utilisant des wildcards. Par exemple :</p>
<ul style="list-style-type: circle;">
<li>STOCK.*.TECH.*</li>
<li>STOCK.NASDAQ.TECH.*</li>
</ul>
<ul style="list-style-type: disc;">
<li>Consommateurs multiples sur une souscription à un Topic</li>
</ul>
<p>Actuellement hormis dans le cadre des multiples instances d&#8217;un MDB (Message Driven Bean) sur un serveur unique, chaque consommateur d&#8217;un Topic reçoit une copie de chaque message qui y est publié (un consommateur = une souscription) ce qui limite la scalabilité de chaque souscription.<br />
Avec cette fonctionnalité, il serait possible d&#8217;associer une unique souscription à plusieurs consommateurs (plusieurs threads) potentiellement sur plusieurs JVMs : un seul des consommateurs d&#8217;une souscription recevrait alors chaque message.</p>
<ul>
<li>Réception de messages par lot (Batch delivery)</li>
</ul>
<p>Pour la réception, cela passerait par une nouvelle interface (en plus de MessageListener ) :</p>
<pre class="brush: java; title: ; notranslate">
void onMessages(Message[] messages)
</pre>
<p>Cela permettrait d&#8217;améliorer les performances de réception (une seule transaction par lot de messages).</p>
<h1>La suite</h1>
<p>Reportez-vous à la présentation référencé plus haut, pour l&#8217;ensemble des aspects que Nigel nous a présenté.</p>
<p>La finalisation de la spécification est prévue pour le 3ème trimestre 2012. Il reste encore pas mal de possibilités d&#8217;évolution. Par exemple, il semble qu&#8217;ils réfléchissent à l&#8217;introduction d&#8217;annotation permettant de cacher complètement les API JMS cf : <a href="http://java.net/projects/messageapi/pages/Annotations">http://java.net/projects/messageAPI/pages/Annotations</a></p>
<p>Si vous êtes intéressé, vous pouvez aller sur <a href="http://jms-spec.java.net">http://JMS-spec.java.net</a> et vous abonner à la mailing list <a href="mailto:users@jms-spec.java.net">users@JMS-spec.java.net</a> pour recevoir les discussions de l&#8217;expert group. Elles contiennent en particulier des liens vers des pages du wiki qui expliquent les propositions en cours de discussion.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/wC8XL9fNmiY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/25/devoxx-les-evolutions-de-jms-2-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/25/devoxx-les-evolutions-de-jms-2-0/</feedburner:origLink></item>
		<item>
		<title>Présentation Hibernate/NoSQL au NantesJUG et au NormandyJUG</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/M2rEM6GWEJ0/</link>
		<comments>http://blog.ippon.fr/2011/11/24/presentation-hibernatenosql-au-nantesjug-et-au-normandyjug/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 07:44:04 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JUG]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4696</guid>
		<description><![CDATA[<p>Julien Dubois, directeur du pôle conseil d&#8217;Ippon Technologies, va animer une conférence autour d&#8217;Hibernate et des bases de données NoSQL (en particulier Cassandra) :</p> Le 13/12/2011 à Rouen au NormandyJUG : Inscriptions Le 14/12/2011 au NantesJUG : Inscriptions Ces conférences termineront le cycle entamé sur ce thème en milieu d&#8217;année, qui ont permis de faire <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/24/presentation-hibernatenosql-au-nantesjug-et-au-normandyjug/">Présentation Hibernate/NoSQL au NantesJUG et au NormandyJUG</a></span>]]></description>
			<content:encoded><![CDATA[<p>Julien Dubois, directeur du pôle conseil d&#8217;Ippon Technologies, va animer une conférence autour d&#8217;Hibernate et des bases de données NoSQL (en particulier Cassandra) :</p>
<ul>
<li>Le 13/12/2011 à Rouen au NormandyJUG : <a href="http://jugevents.org/jugevents/event/42859" target="_blank">Inscriptions</a></li>
<li>Le 14/12/2011 au NantesJUG : <a href="http://jugevents.org/jugevents/event/42844" target="_blank">Inscriptions</a></li>
</ul>
<div>Ces conférences termineront le cycle entamé sur ce thème en milieu d&#8217;année, qui ont permis de faire un retour d&#8217;expérience à la communauté sur l&#8217;utilisation d&#8217;Hibernate et de Cassandra dans des environnements à forte montée en charge. Pour rappel, cette conférence a déjà eu lieu à Paris, au ToursJUG, au BreizhJUG, au JugSummerCamp et au BordeauxJUG.</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/M2rEM6GWEJ0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/24/presentation-hibernatenosql-au-nantesjug-et-au-normandyjug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/24/presentation-hibernatenosql-au-nantesjug-et-au-normandyjug/</feedburner:origLink></item>
		<item>
		<title>Devoxx « Bleeding Edge » HTML 5</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/s-fTAJuReKU/</link>
		<comments>http://blog.ippon.fr/2011/11/22/devoxx-%c2%ab-bleeding-edge-%c2%bb-html-5/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 08:30:46 +0000</pubDate>
		<dc:creator>Laurent SORIN</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[HTML5]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4651</guid>
		<description><![CDATA[<p>S’il y a bien une technologie qui a fait salle comble à toutes les conférences de ce Devoxx 2011 c’est HTML 5. Quel engouement !! Et on peut dire que les intervenants ont réussi à en mettre plein la vue de l’auditoire. J’ai eu la chance d’assister (assis ) à l’une de celles qui a <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/22/devoxx-%c2%ab-bleeding-edge-%c2%bb-html-5/">Devoxx « Bleeding Edge » HTML 5</a></span>]]></description>
			<content:encoded><![CDATA[<p>S’il y a bien une technologie qui a fait salle comble à toutes les conférences de ce Devoxx 2011 c’est HTML 5.<br />
Quel engouement !! Et on peut dire que les intervenants ont réussi à en mettre plein la vue de l’auditoire.<br />
J’ai eu la chance d’assister (assis <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ) à l’une de celles qui a été parmi les plus réussies. Je vais tenter de vous la faire partager avec une petite revue des nouveautés (et plus…) les plus marquantes présentées durant cette conférence par Paul Kinlan.</p>
<p><span id="more-4651"></span></p>
<p><strong>On commence par du classique… mais pratique</strong></p>
<div id="attachment_4654" class="wp-caption alignright" style="width: 220px"><a href="http://dev.w3.org/html5/spec/Overview.html"><img class="size-medium wp-image-4654" title="HTML5_Logo_512" src="http://blog.ippon.fr/wp-content/uploads/2011/11/HTML5_Logo_512-300x300.png" alt="Logo HTML 5" width="210" height="210" /></a><p class="wp-caption-text">Logo HTML 5</p></div>
<p><em>Collapse</em></p>
<p>Qui n’a jamais utilisé javascript pour faire du collapse de div et bien en HTML 5 on se pose plus la question, il suffit d’utiliser la balise &lt;détail&gt; puis &lt;summary&gt; et le navigateur se charge du reste.</p>
<p><em>Une balise &lt;output&gt; au sein d’une balise &lt;form&gt;</em></p>
<p>Cette balise permet, à partir d’une donnée saisie dans une on plusieurs balise(s) input de calculer (en javascript) un résultat directement présent dans une balise &lt;ouput&gt;. Pas très impressionnant, mais encore une fois pratique.</p>
<p><em>Le WebkitSpeech</em></p>
<p>Il s’agit d’un &lt;input&gt; texte qui est simplement rempli via la reconnaissance vocale du contenu dicté au micro par l’utilisateur. Ceci permettra de rajouter un niveau d’accessibilité à des sites web de manière très simple.</p>
<p><strong>Un peu plus complexe</strong></p>
<p><em>Synchronized based animation</em></p>
<p>Le navigateur synchronise les animations Javascript selon la fréquence de l’écran du device d’exécution. Ceci permet ainsi de gagner en fluidité d’animation de navigation ou dans les jeux.</p>
<p><em>Visibilité des onglets.</em></p>
<p>Il est possible de savoir si la page courante est affichée ou masquée (via les onglets). On peu ainsi faire en sorte qu’une musique soit jouée seulement lorsque la page correspond à l’onglet affiché.  Ceci permettra d’éviter de se demander de quel onglet provient la musique quand on navigue… (Que ceux qui n’ont jamais connu ça se lèvent !)</p>
<p><em>Pré-rendering page.</em></p>
<p>Plutôt sympa, cette fonctionnalité permet de pré-charger une page derrière un lien. Lorsque l’on clique dessus, l’affichage est alors instantané !</p>
<p><em>Etat de la connexion</em></p>
<p>Une fonctionnalité sympa permet de savoir quel est l’état de notre connexion internet (connecté/pas connecté)… merci la mobilité ! On imagine derrière l’avantage d’une telle fonctionnalité comme pouvoir sauvegarder en local les données de l’utilisateur (via les nouvelles fonctionnalités de webstorage), jouer plus finement avec le cache ou tout simplement avertir l’utilisateur.</p>
<p><em>Web Intent</em></p>
<p>A l’heure où les API fleurissent sur le net (comme twitter, facebook) il n’est pas évident de les manipuler. Google a donc décidé de créer une sorte d’API simplifiée (qui maintenant sera unifiée avec Mozilla) qui permet d’utiliser celle de votre réseau social favori ou autre.<br />
Les utilisateurs d’Android y retrouveront là une forte similitude avec leur OS avec la proposition de différentes applications a l’ouverture d’un fichier (et les objets « intent » pour ceux qui en ont déjà développé).</p>
<p>Pour résumer, cela fonctionne comme suit :</p>
<p>- Un site qui propose des services d’édition d’image rajoutera la balise suivante  afin de proposer à l’utilisateur d’enregistrer ce site comme proposant un service d’édition et l’enregistrer parmis ses « favoris » :</p>
<p><code>&lt;intent<br />
action="http://webintents.org/edit"<br />
type="image/*"<br />
/&gt;</code></p>
<p>- Lorsque l’utilisateur ira sur un site qui fait appel à un « intent » pour déléguer l’édition d’une image, l’utilisateur aura le choix de faire appel à un de ses services d’édition d’image déjà enregistrés à l’étape précédente.</p>
<p>- Une fois l’édition de l’image terminée dans ce nouveau contexte, l’ « intent » est posté et l’application qui avait fait la demande de ce service reprend la main à la réception de l’  « intent ».</p>
<p><strong>Rich Multimedia</strong></p>
<p><em>Paste file</em></p>
<p>Ceci permet le drag’n’drop de fichiers depuis le bureau vers l’application et déclenche ainsi un événement qu’on implémente ensuite (ex : l’upload d&#8217;un fichier directement). Cette fonctionnalité est déjà bien connue des utilisateurs des GMail sur Chrome pour joindre des fichiers.</p>
<p><em>Camera/Microphone</em></p>
<p>Une API permet de capturer le son et la vidéo de la webcam et de les manipuler (rectifier la couleur des images, manipuler le signal sonore).</p>
<p><em>FullScreen API</em></p>
<p>On connaît bien le fullscreen des navigateurs classiques. Dans le cas de HTML 5 il s’agit d’un véritable plein écran. Via javascript/CSS on peut savoir que l’on est en plein écran et modifier complètement l’aspect  ou le comportement de la page.</p>
<p><em>WebRTC</em></p>
<p>C’est un projet proposant une API Javascript visant à faciliter l’interaction entre utilisateurs souhaitant discuter vocalement et/ou avec la vidéo.<br />
Il est actuellement supporté par Google, Mozilla et Opéra.</p>
<p><em>Audio</em></p>
<p>Enfin, la dernière partie fut consacrée à la nouvelle balise audio. Il faut savoir que de base l’accès aux données d’un signal audio est très limité. Mozilla a donc de son coté étendu l’API avec « Audio Data API » et Google a de son coté très récemment adopté « <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html"> Web Audio API</a> » du W3C. L’objectif est de réussir à faire du traitement audio poussé (chorus, delay, mixage, spatialisation et autres modulations de fréquences).</p>
<p>Aux dires du speaker, il semblerait que l’API de Firefox soit plus lente car toutes les opérations de traitement audio  sont effectuées en JavaScript alors que coté Chrome elles sont implémentées de manière sous-jacentes ( optimisé  C / C + + ). En tous les cas au vu des démos plutôt épatantes (déformation d’un signal en temps réel, affichage de spectres (style K2000), etc… ), les développeurs de jeux en auront pour leur compte.</p>
<p><strong>Conclusion</strong></p>
<p>Présentation agréable de quelques nouveautés HTML 5 même s’il a manqué quelques éléments importants (CSS 3,  Canvas, XHR 2…) alors que l’on a eu droit à des extras comme l&#8217;API Web audio ou bien les Web Intents (qui me semblent eux promis à un bel avenir).<br />
En tous cas, on sent le navigateur poussé encore à un niveau plus élevé en tant que plateforme multimédia avec pour toile de fond la volonté de la fin du Flash, l’OS semble désormais relayé au second plan.</p>
<p>La guerre entre navigateurs (sans fin ?) fait rage :</p>
<ul>
<li>Tous les codecs (audio/video)  n&#8217;étant pas supportés par tous les navigateurs, il faut en tenir compte.</li>
<li>Chaque navigateur cherche à adopter au plus vite de nouvelles spécifications poussées (tel que le Web Audio API) tout en cherchant à se distinguer par des performances accrues (tel que l&#8217;implémentation sous jacente du traitement audio) ou l&#8217;API facilitant l&#8217;accès à ces ressources.</li>
</ul>
<p><em>Articles liés à la Conférence</em> :</p>
<p><a title="HTML5 Rocks" href="http://www.html5rocks.com/">http://www.html5rocks.com/</a></p>
<p><a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html</a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/s-fTAJuReKU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/22/devoxx-%c2%ab-bleeding-edge-%c2%bb-html-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/22/devoxx-%c2%ab-bleeding-edge-%c2%bb-html-5/</feedburner:origLink></item>
		<item>
		<title>Paris JUG : Petites librairies Java</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/5MXUF8OMpK4/</link>
		<comments>http://blog.ippon.fr/2011/11/21/paris-jug-petites-librairies-java/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 07:00:28 +0000</pubDate>
		<dc:creator>Pierre TEMPLIER</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[Commons Configuration]]></category>
		<category><![CDATA[GPars]]></category>
		<category><![CDATA[Guava]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Lombok]]></category>
		<category><![CDATA[ParisJUG]]></category>
		<category><![CDATA[PrettyTime]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4622</guid>
		<description><![CDATA[<p class="wp-caption-text">G. Laforge expliquant Pretty Time</p> <p>La session du Paris JUG du 8 novembre 2011 était consacrés aux petites librairies Java.</p> I. Pretty Time <p>Guillaume Laforge, leader du projet Groovy nous a présenté la librairie PrettyTime développée par Lincoln Baxter III qui travaille chez OcpSoft et RedHat. Celle-ci permet de présenter des dates sous forme <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/21/paris-jug-petites-librairies-java/">Paris JUG : Petites librairies Java</a></span>]]></description>
			<content:encoded><![CDATA[<div id="attachment_4703" class="wp-caption alignleft" style="width: 234px"><img class="size-medium wp-image-4703" title="Guillaume Laforge" src="http://blog.ippon.fr/wp-content/uploads/2011/11/IMG_0098-224x300.jpg" alt="" width="224" height="300" /><p class="wp-caption-text">G. Laforge expliquant Pretty Time</p></div>
<p>La session du Paris JUG du 8 novembre 2011 était consacrés aux petites librairies Java.</p>
<h2>I. Pretty Time</h2>
<p>Guillaume Laforge, leader du projet Groovy nous a présenté la librairie <a href="http://ocpsoft.com/prettytime/">PrettyTime</a> développée par Lincoln Baxter III qui travaille chez OcpSoft et RedHat. Celle-ci permet de présenter des dates sous forme de dates relatives du type : à l&#8217;instant, dans 10 minutes, il y a 3 heures. Guillaume l&#8217;utilise sur <a href="https://glaforge.appspot.com/">son blog</a> pour afficher la date des posts ce qui permet d&#8217;indiquer la date de la façon suivante : <em>Posted on 09 November, 2011 (2 days ago). </em>La librairie est constituée d&#8217;un jar n&#8217;a pas de dépendance. Elle supporte 18 langues dont le français et l&#8217;anglais et est très simple à utiliser.</p>
<p><span id="more-4622"></span></p>
<pre class="brush: java; title: ; notranslate">
// on initialise avec une date de reference
PrettyTime t = new PrettyTime(new Date(1000 * 60 * 12), new Locale(&amp;quot;fr&amp;quot;));
// on formate une date par rapport a cette date de reference
assertEquals(&amp;quot;il y a 12 minutes&amp;quot;, t.format(new Date(0)));
</pre>
<p>on peut utiliser facilement PrettyTime avec Grails ou JSF.</p>
<h2>II. GPars</h2>
<p>GPars (prononcez Jeepers) est une librairie permettant de s&#8217;adapter au multi-processeurs et au multi-coeurs en faisant de la programmation concurrente.</p>
<p>il est difficile de bien utiliser ce  que le JDK propose : threads / synchronize / wait-notify-notifyAll, qui peuvent conduire à</p>
<ul>
<li>des dead-locks, des live-locks (in interblocage qui consomme du CPU), des race conditions ou l&#8217;épuisement de ressources</li>
<li>des problèmes de gestion d&#8217;accès à la mémoire partagée</li>
</ul>
<p>Pour éviter ces problèmes, GPars propose d&#8217;utiliser l&#8217;immuabilité et le passage de messages au travers des paradigmes suivants</p>
<ul>
<li><a title="Actor" href="http://gpars.codehaus.org/Actor">Acteurs</a></li>
<li><a title="ForkJoin" href="http://gpars.codehaus.org/ForkJoin">Fork/Join</a></li>
<li><a title="Parallelizer" href="http://gpars.codehaus.org/Parallelizer">Collections parallèles</a></li>
<li><a title="Asynchronizer" href="http://gpars.codehaus.org/Asynchronizer">Executors</a></li>
<li><a title="Dataflow" href="http://gpars.codehaus.org/Dataflow">Dataflow</a></li>
<li><a title="Agent" href="http://gpars.codehaus.org/Agent">Agent</a> &#8211; an thread-safe reference to mutable state</li>
<li><a title="STM" href="http://gpars.codehaus.org/STM">STM</a> (Software Transactional Memory)</li>
<li><a title="CSP" href="http://gpars.codehaus.org/CSP">CSP</a></li>
</ul>
<h3>un exemple avec les fonctions parallèles pour les collections</h3>
<pre class="brush: groovy; title: ; notranslate">
@Grab('org.codehaus.gpars:gpars:0.12')
import static groovyx.gpars.GParsPool.withPool

defnums=1..100000
withPool(5){
def squares=nums.collectParallel{it**2}
.grepParallel{it%7==it%5}
.grepParallel{it%3==0}
println squares[0..3]+&amp;quot;...&amp;quot;+squares[-3..-1]

assertsquares[0..3]==[36,144,1089,1296]
}
</pre>
<p>on utilise un pool de taille nombre de coeurs + 1 afin de maximiser l&#8217;utilisation du CPU car souvent on a un thread qui sert à la coordination des autres et qui consomme peu de ressources. GPars a comme dépendance les librairies jsr166y et extra166y. Il dispose d&#8217;une API Java et d&#8217;une API Groovy.</p>
<p>Selon le problème que l&#8217;on a à résoudre on utilisera des outils différents. Cela est bien présenté par le graphe suivant.</p>
<p style="text-align: center;"><img class="aligncenter" src="http://blog.ippon.fr/wp-content/uploads/2011/11/GPars_when_to_use_what.png" alt="GPars when to use what" width="741" height="310" /></p>
<p>les slides de la présentation de Guillaume <a href="http://www.slideshare.net/glaforge/gpars-et-prettytime-paris-jug-2011-guillaume-laforge">ici</a></p>
<h2>III. Project Lombok (ou comment cacher la plomberie)</h2>
<p>Florent Ramière de la société Jaxio nous a présenté <a href="http://projectlombok.org/">Lombok</a>, &#8220;un outil qui sert à enlever la plomberie&#8221;. Il s&#8217;agit d&#8217;un plugin eclipse qui va générer du code technique grâce à des annotations, le source ne sera donc pas pollué par ce code technique qui existera néanmoins dans le bytecode après compilation. En utilisant Lombok on pourra donc clarifier son code et se concentrer sur d&#8217;autres parties de son code. On peut bien sûr utiliser les assistants eclipse pour générer un code similaireà celui généré par Lombok.</p>
<p>on dispose notamment des annotations suivantes</p>
<p>@Getter</p>
<p>@Setter</p>
<p>@EqualsAndHashCode</p>
<p>@RequiredArgsConstructor un constructeur avec tous les champs finaux</p>
<p>@Data est un raccourci pour @ToString, @EqualsAndHashCode, @Getter sur tous les champs et @Setter sur tous les champs non-finaux, et @RequiredArgsConstructor! à utiliser pour ses beans.</p>
<p>@Delegate permet de déléguer toutes les méthodes publiques de l&#8217;attribut annoté, excepté les méthodes présentes dans java.lang.Object.</p>
<p>@Log et ses variantes @CommonsLog, @Log4j et @Slf4j permet d&#8217;instancier une variable statique privée log</p>
<p>@Synchronized permet de générer un bloc synchronize sur une variable privée $lock ou $LOCK (dans le cas d&#8217;une méthode statique)</p>
<p>val est un type Lombok permettant d&#8217;avoir des variables &#8216;final&#8217; et de bénéficier de l&#8217;inférence de type.On peut ainsi écrire</p>
<pre class="brush: java; title: ; notranslate">
val map = new HashMap();
</pre>
<p>la page <a href="http://projectlombok.org/features/index.html">suivante</a> explique très bien le code généré par Lombok. on peut d&#8217;ailleurs si besoin générer ce code en utilisant delombok (pour GWT notamment ou si l&#8217;on veut utiliser le code générer sans dépendre de lombok). <a href="https://github.com/peichhorn/lombok-pg">lombok-pg</a> est un ensemble d&#8217;extensions pour lombok.</p>
<p>Lombok peut également être utilisé via ant, maven ou javac.</p>
<p>Au détour de ses démonstrations, florent nous a également conseillé l&#8217;outil <a href="https://code.google.com/p/awaitility/">awaitility</a> qui permet de faire des tests sur du code asynchrone</p>
<h2>IV. Apache Commons Configuration</h2>
<p><a href="https://twitter.com/#!/smanux">Emmanuel Bourg</a> est membre de la fondation Apache et est commiter sur le projet <a href="https://commons.apache.org/configuration/index.html">Apache Commons Configuratio</a> qu&#8217;il est venu nous présenter. Il s&#8217;agit d&#8217;une abstraction de la configuration d&#8217;une application qui présente une interface simple de type clé/valeur pour les données. Elle permet de gérer différents formats de données et des transformations dans les types voulus.</p>
<p>On peut gérer un format Properties amélioré</p>
<pre class="brush: java; title: ; notranslate">
list1=val1,val2,val3
list2=val1
list2=val2
list2=val3
include=chunk.properties
</pre>
<p>On peut également utiliser des fichiers XML, Property List XML, Ini ou encore une base données.</p>
<p>Plusieurs formats sont prévus : OGDL, YAML, JSON, Registry Windows, Binary Property List. Les contributions sont les bienvenues si vous voulez aider à ajouter le support des nouveaux formats. On peut combiner plusieurs configurations grâce à CompositeConfiguration. On peut également utiliser un descripteur de configuration. Commons Configuration s&#8217;intègre très bien avec la librairie d&#8217;abstraction de systeme de fichiers Apache Commons VFS.</p>
<p>Sauvegarde automatique</p>
<pre class="brush: java; title: ; notranslate">
PropertiesConfiguration config = new PropertiesConfiguration(&amp;quot;usergui.properties&amp;quot;);
config.setAutoSave(true);
</pre>
<p>Rechargement automatique (on peut également déclencher le rechargement)</p>
<pre class="brush: java; title: ; notranslate">
PropertiesConfiguration config = new PropertiesConfiguration(&amp;quot;usergui.properties&amp;quot;);
config.setReloadingStrategy(new FileChangedReloadingStrategy());
</pre>
<h2>V. Guava (N&#8217;aime pas les null)</h2>
<p><a href="http://www.thierryler.com/">Thierry Leriche-Dessirier</a> (Indépendant) et <a href="https://twitter.com/#!/eneveu">Etienne Neveu</a> (SFEIR) nous ont fait faire un tour du propriétaire de <a href="https://code.google.com/p/guava-libraries/">Guava</a>, la librairie utilitaire de Google autrefois nommée google-collections.</p>
<h3>Factory methods</h3>
<p>Inférence de type : grâce à des factory statiques on peut écrire</p>
<pre class="brush: java; title: ; notranslate">
List primeNumbers = newArrayList();
Set colors = newTreeSet();
Map ages = newHashMap();
</pre>
<p>ce qui n&#8217;est plus si intéressant que ca en Java 7 avec la notation diamant.<br />
L&#8217;initialisation de collection est également facilitée</p>
<pre class="brush: java; title: ; notranslate">
List dogs = newArrayList(Dog1, Dog2, Dog3)
</pre>
<h3>Programmation fonctionnelle</h3>
<p>On peut filtrer une collection grâce à un prédicat</p>
<pre class="brush: java; title: ; notranslate">
Iterable maleDogs = Iterables.filter(dogs,
  new Predicate() {
    public boolean apply(Dog dog) {
      return dog.getSex() == MALE;
    }
});
</pre>
<p>un predicat peut utiliser les prédicats and, in, or, not déjà définis dans la classe Predicates</p>
<pre class="brush: java; title: ; notranslate">
boolean isMilouInBoth = and(in(dogs), in(superDogs))
            .apply(new Dog(&amp;quot;Milou&amp;quot;));
</pre>
<p>on peut transformer les elements d&#8217;une liste en utilisant une <em>Function</em></p>
<pre class="brush: java; title: ; notranslate">
List chiens =
Lists.transform(dogs, new Function() {
  public Chien apply(Dog dog) {
    return new Chien(dog.getName());
  }
});
</pre>
<p>Attention ce sont des vues qui sont retournées. cela peremt d&#8217;avoir du <em>lazy-loading</em> mais la conversion sera faite autant de fois que nécessaire.<br />
Iterables.find utilise le même prédicat que pour Iterables filter mais renvoit le premier objet correspondant au predicat ou un objet par défaut si rien ne correspondait au prédicat.</p>
<pre class="brush: java; title: ; notranslate">
Dog firstMale = Iterables.find(dogs, malePredicate, DEFAULT);
</pre>
<h3>collections immuables</h3>
<p>on a des syntaxes plus concises que la syntaxe standard tout en proposant de la copie défensive.</p>
<pre class="brush: java; title: ; notranslate">
ImmutableSet.of(1, 2, 3, 5, 7);
ImmutableSet.copyOf(favoriteColors)
</pre>
<h3>base.Objects</h3>
<p>cette classe propose d&#8217;aider à la simplification de l&#8217;écriture des méthodes equals(), hashcode() ou toString()</p>
<pre class="brush: java; title: ; notranslate">
//equals
Objects.equal(name, that.name)
&amp;amp;&amp;amp; Objects.equal(weight, that.weight)
&amp;amp;&amp;amp; sex == that.sex;
// hashcode
Objects.hashCode(name, weight, sex);
//toString
Objects.toStringHelper(this)
   .add(&amp;quot;name&amp;quot;, name)
   .add(&amp;quot;weight&amp;quot;, weight)
   .add(&amp;quot;sex&amp;quot;, sex)
   .toString();
</pre>
<p>on peut créer facilement un comparateur</p>
<pre class="brush: java; title: ; notranslate">
public int compareTo(Dog other) {
  return ComparisonChain.start()
    .compare(name, other.name)
    .compare(weight, other.weight)
    .compare(sex, other.sex)
    .result();
}
</pre>
<h3>base.Preconditions</h3>
<p>on peut vérifier des paramètres</p>
<pre class="brush: java; title: ; notranslate">
this.currency = checkNotNull(currency, &amp;quot;currency cannot be null&amp;quot;);
checkArgument(amount.signum() &amp;gt;= 0, &amp;quot;must be positive: %s&amp;quot;, amount);
</pre>
<h3>base.CharMatcher</h3>
<p>il s&#8217;agit d&#8217;un outil permettant d&#8217;exprimer une expression régulière en language naturel. Il permet de remplacer avantageusement StringUtils des Apache Commons.</p>
<h3>Collections</h3>
<p>on dispose de collections n&#8217;existant pas dans le JDK</p>
<p>MultiMap : il s&#8217;agit d&#8217;une map pouvant avoir plusieurs valeurs pour une même clé</p>
<pre class="brush: java; title: ; notranslate">
Multimap favoriteColors = HashMultimap.create();
</pre>
<p>BiMap : il s&#8217;agit d&#8217;une map pouvant n&#8217;ayant pas 2 fois la même valeur</p>
<pre class="brush: java; title: ; notranslate">
BiMap favoriteColors = HashBiMap.create();
</pre>
<p>Multiset: il s&#8217;agit d&#8217;un set pouvant contenir plusieurs fois la même valeur (on peut même connaître le nombre de doublons)</p>
<pre class="brush: java; title: ; notranslate">
Multiset primeNumbers = HashMultiset.create();
</pre>
<p>Joiner et Splitter permettent de manipuler les conversions entre chaine de caractères et liste de String.<br />
En utilisant Joiner, on aura une NullPointerException si un des éléments de la liste vaut null mais l&#8217;on pourra utiliser skipNulls() ou userForNull(MY_DEFAULT) pour spécifier le comportement lorsque l&#8217;on rencontre un null.</p>
<pre class="brush: java; title: ; notranslate">
List&amp;lt;String&amp;gt; dogs = newArrayList(&amp;quot;Milou&amp;quot;, &amp;quot;Idefix&amp;quot;, &amp;quot;Rintintin&amp;quot;);
String names = Joiner.on(&amp;quot;, &amp;quot;).join(dogs);
</pre>
<p>En utilisant Splitter on peut nettoyer le résultat en utilisant trimResults() et omitEmptyStrings()</p>
<pre class="brush: java; title: ; notranslate">
Iterable&amp;lt;String&amp;gt; superDogs = Splitter.on(&amp;quot;,&amp;quot;)
   .trimResults()
   .omitEmptyStrings()
   .split(&amp;quot;Lassie, , Volt, Milou&amp;quot;);
</pre>
<h3>Cache</h3>
<h4>Memoization</h4>
<p>la memoization permet de garder en cache une unique valeur. l&#8217;exemple donné était la mise en cache du numéro de version du dernier jdk. On défini via l&#8217;utilisation d&#8217;un Supplier comment aller chercher la valeur qui nous intéresse. Celle valeur ne sera récupérée que lors du premier appel (lazy loading). Les appels suivant utiliserons le cache.</p>
<pre class="brush: java; title: ; notranslate">
private Supplier&amp;lt;JdkVersion&amp;gt; versionCache =
  Suppliers.memoize(
    new Supplier&amp;lt;JdkVersion&amp;gt;() {
      public JdkVersion get() {
        return jdkWebService.checkLatestVersion();
      }
    }
);
</pre>
<p>On peut également préciser une durée de validité du cache avec memoizeWithExpiration()</p>
<h4>Key-Value</h4>
<p>On peut construire un Cache à plusieurs entrées grâce aux classes CacheBuilder et CacheLoader</p>
<pre class="brush: java; title: ; notranslate">
private Cache&amp;lt;Long, Film&amp;gt; filmCache = CacheBuilder.newBuilder()
  .maximumSize(2000)
  .expireAfterWrite(30, TimeUnit.MINUTES)
  .build(new CacheLoader&amp;lt;Long, Film&amp;gt;() {
    public Film load(Long filmId) {
      return imdbWebService.loadFilmInfos(filmId);
    }
});
</pre>
<h2>Concurrent</h2>
<p>Guava propose d&#8217;étendre Future avec la classe ListenableFuture. On peut ainsi associer un listener à un Future.</p>
<pre class="brush: java; title: ; notranslate">
ListenableFuture&amp;lt;Result&amp;gt; future = ...
future.addListener(new Runnable() {
  public void run() {
    logger.debug(&amp;quot;Future is done&amp;quot;);
  }
}, executor);
</pre>
<p>On peut également faire de la programmation asynchrone grâce à FutureCallback. cela permet d&#8217;isoler le traitement des exceptions.</p>
<pre class="brush: java; title: ; notranslate">
Futures.addCallback(future, new FutureCallback&amp;lt;Result&amp;gt;() {
  public void onSuccess(Result result) {
    storeInCache(result);
  }
  public void onFailure(Throwable t) {
    reportError(t);
  }
});
</pre>
<p>pour utiliser des ListenableFuture on utilise un ListeningExecutorService de la façon suivante.</p>
<pre class="brush: java; title: ; notranslate">
ListeningExecutorService executor = MoreExecutors.listeningDecorator(executor);

public ListenableFuture&amp;lt;Note&amp;gt; getNote(final Film film) {
  return executor.submit(new Callable&amp;lt;Note&amp;gt;() {
    public Note call() {
      return imdbWebService.getNote(film);
    }
  });
}
</pre>
<p>En utilisant les méthodes proposées par Futures on peut facilement proposer des méthodes non bloquantes qui renvoient un Future au lieu d&#8217;une liste de notes. Cela permet au programme appelant de ne pas bloquer pendant la récupération des notes et d&#8217;effectuer d&#8217;autres traitements pendant celle-ci.</p>
<pre class="brush: java; title: ; notranslate">
ListenableFuture
&amp;lt;List&amp;lt;Note&amp;gt;&amp;gt; getNotes(Film film) {
  ListenableFuture&amp;lt;Note&amp;gt; noteImdb = imdbService.getNote(film);
  ListenableFuture&amp;lt;Note&amp;gt; noteAllo = allocineService.getNote(film);
  return Futures.allAsList(noteImdb, noteAllo);
}
</pre>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/5MXUF8OMpK4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/21/paris-jug-petites-librairies-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/21/paris-jug-petites-librairies-java/</feedburner:origLink></item>
		<item>
		<title>Devoxx: Les deux nouveaux candidats à la succession au langage Java</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/d-SkseNm_IU/</link>
		<comments>http://blog.ippon.fr/2011/11/18/devoxx-les-deux-nouveaux-candidats-a-la-succession-au-langage-java/#comments</comments>
		<pubDate>Fri, 18 Nov 2011 20:38:30 +0000</pubDate>
		<dc:creator>Fabien ARRAULT</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Langage]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4624</guid>
		<description><![CDATA[Deux nouveaux langages qui commencent fort <p>Lors de ce Devoxx 2011, une catégorie de sessions était consacrée aux différents langages de la JVM. Etaient présents Scala, Phantom, Groovy, JRuby, Clojure et les deux petits nouveaux révélés cette année par leur sponsor : Kotlin (JetBrains) et Ceylon (JBoss/Redhat)</p> <p>Personnellement, ce sont ces deux nouveaux langages qui <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/18/devoxx-les-deux-nouveaux-candidats-a-la-succession-au-langage-java/">Devoxx: Les deux nouveaux candidats à la succession au langage Java</a></span>]]></description>
			<content:encoded><![CDATA[<h1>Deux nouveaux langages qui commencent fort</h1>
<p>Lors de ce Devoxx 2011, une catégorie de sessions était consacrée aux différents langages de la JVM.<br />
Etaient présents Scala, Phantom, Groovy, JRuby, Clojure et les deux petits nouveaux révélés cette année par leur sponsor : Kotlin (JetBrains) et Ceylon (JBoss/Redhat)</p>
<p>Personnellement, ce sont ces deux nouveaux langages qui m&#8217;intéressaient le plus : j&#8217;adore la concision de Groovy mais le fait qu&#8217;il ne soit pas statiquement typée m&#8217;empêche de l&#8217;utiliser pour un projet avec un minimum d&#8217;envergure. Peut-être que l&#8217;un de ces deux langages pourra amener le meilleur de ces deux mondes&#8230;</p>
<p>Ces deux langages sont tout nouveaux et toujours en cours d&#8217;implémentation. Il n&#8217;est pas encore question de les utiliser sur de vrais projets mais nous avons pu voir durant les sessions de Devoxx que chacun avait déjà un compilateur fonctionnel et un IDE pouvant faire la démonstration de complétion, refactoring, debugging, &#8230; De quoi commencer à jouer avec a priori.</p>
<p><span id="more-4624"></span></p>
<h1>Caractéristiques</h1>
<p>Ces deux langages ont une bonne partie de leurs objectifs en commun :</p>
<ul>
<li>langage s&#8217;exécutant sur la JVM</li>
<li>statiquement typé</li>
<li>compilateur permettant de détecter plus d&#8217;erreurs</li>
<li>avoir une syntaxe plus simple et plus expressive que Java sans être aussi compliqué que Scala</li>
<li>complètement interopérable avec Java</li>
</ul>
<p>Il en ressort un grand nombre de caractéristiques communes, comme par exemple :</p>
<ul>
<li>inférence de type étendue</li>
<li>null safety (cf ci-dessous)</li>
<li>smart cast ou plus généralement des optimisations de syntaxe locale (cf ci-dessous)</li>
<li>constructeur primaire dans la syntaxe</li>
</ul>
<p>Par contre, durant la présentation de Ceylon la notion de closure n&#8217;a pas du tout été évoquée, il n&#8217;est pas clair pour moi si elle sera supporté ou non. Kotlin de son côté les supportera très bien, avec en particulier la possibilité de mettre en oeuvre des &#8220;higher-order function&#8221;.</p>
<p>Je ne peux pas faire de comparaisons précises sur la base de ces deux présentations, mais au dire de Stéphane Epardaud qui nous a présenté Ceylon avec Emmanuel Bernard : Ceylon et Kotlin ont beaucoup en commun en termes de fonctionnalités. Pour lui, Ceylon se distingue par un système de typage plus abouti ( avec en particulier les union type, intersection type, &#8230; ).</p>
<h1>Syntaxe</h1>
<p>Au niveau de la syntaxe, les deux langages restent assez accessibles aux programmeurs Java, mais s&#8217;éloignent tout de même de la syntaxe Java.<br />
Pour citer deux exemples :</p>
<ul>
<li>dans Kotlin : le type des paramètres est écrit après son nom, et le type de retour après la définition d&#8217;une fonction. Par exemple :</li>
</ul>
<pre class="brush: scala; title: ; notranslate">
fun main(args : List&lt;String&gt;) : Unit
</pre>
<ul>
<li>dans Ceylon : de nouveaux keywords sont introduits qui remplacent une partie de ceux utilisés en Java ( abstract =&gt; formal, @Overide =&gt; actual, public/protected remplacé par &#8220;shared&#8221;, &#8230;), du code peut être associé à des properties (pour implémenter le getter ou le setter associé), &#8230;</li>
</ul>
<h1>Documentation</h1>
<p>Jetbrains a très rapidement mis en place un wiki pour son langage avec pas mal de documentation et des discussions sur les choix effectués et leurs objectifs : <a href="http://confluence.jetbrains.net/display/Kotlin/Welcome">http://confluence.jetbrains.net/display/Kotlin/Welcome</a></p>
<p>Pour Ceylon, c&#8217;était plutôt le brouillard en terme de doc, la plupart des références se trouvaient dans des blogs, des présentations, &#8230; rendant difficile la création d&#8217;un communauté.</p>
<p>Jusqu&#8217;à ce matin en fait, où ils nous ont révélé une &#8220;One more thing&#8221; à la fin de la présention : le tout nouveau site de ceylon : <a href="http://www.ceylon-lang.org/">http://www.ceylon-lang.org/</a> et le github des développements en cours <a href="https://github.com/ceylon">https://github.com/ceylon</a></p>
<h1>Un petit focus sur deux des caractéristiques communes</h1>
<h2>Null safety</h2>
<p>Dans les deux langages : les références ne peuvent pas être null par défaut.<br />
Un type Integer (par exemple) correspondrait à un objet entier non null.<br />
Un type Integer? correspondrait à un objet entier pouvant être null</p>
<p>Pour accéder à un champ ou une méthode sur une référence pouvant être null, il faut absolument utiliser ?. au lieu de simplement . sans quoi le compilateur génère une erreur. Si l&#8217;objet est null : l&#8217;opérateur ?. aura pour effet d&#8217;ignorer la suite de l&#8217;expression et de renvoyer simplement null<br />
Exemple en Kotlin :</p>
<pre class="brush: groovy; title: ; notranslate">
Int? x = getAnIntegerOrNull()
print (x?.times(2)) // ici, x peut être null : il est nécessaire d'utiliser ?.
                    // pour appeler la méthode times qui correspond à l'opérateur *
if(x!=null) {
  print(x * 2)    // ici, le compilateur sait que x n'est pas null,
                  // on peut utiliser x * 2 qui est équivalent à x.times(2)
)
</pre>
<p>Exemple en Ceylon :</p>
<pre class="brush: groovy; title: ; notranslate">
Cube? cube = getCubeOrNull()
print cubs?.area()
if(exists cube) {      // permet de tester que la référence n'est pas null
  print cube.area()
} else {
  print &quot;Cube is null&quot;
}
</pre>
<h2>Smart Cast</h2>
<p>En Kotlin :</p>
<pre class="brush: groovy; title: ; notranslate">
Object object = ...
if(object is String) {
  object.substring(1)  // pas besoin de caster l'objet en String,
                       // le compilateur le déduit de la clause if
}
</pre>
<p>En Ceylon :</p>
<pre class="brush: groovy; title: ; notranslate">
Apple|Snail food = ...  // union type : food référence un objet soit de type Apple soit de type Snail.
if(is Apple food) {    // on s'assure que food est de type Apple
  food.eat()    // la méthode eat() n'existe que sur Apple, et pas sur Snail
                // dans le bloc du if, il n'est pas nécessaire de caster food en Apple pour l'appeler
}
</pre>
<p>On peut aussi considérer les deux exemples du paragraphe &#8220;null safety&#8221; comme des smarts cast : où le compilateur change le type de la référence d&#8217;un type nullable à un type non nullable.</p>
<h1>Conclusion</h1>
<p>Plus simple que Scala, ces langages pourraient répondre aux attentes de ceux qui veulent un langage sur la JVM qui soit plus expressif que Java.</p>
<p>Mais attention, Groovy les attend au tournant : la vérification statique du typage est en cours d&#8217;implémentation pour la prochaine version du langage : <a href="http://docs.codehaus.org/display/GroovyJSR/GEP+8+-+Static+type+checking">http://docs.codehaus.org/display/GroovyJSR/GEP+8+-+Static+type+checking</a></p>
<p>Il permettrait d&#8217;indiquer au compilateur d&#8217;effectuer un contrôle de type strict sur certaines classes : tout compte fait c&#8217;est peut-être juste ça que j&#8217;attendais moi ! <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/d-SkseNm_IU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/18/devoxx-les-deux-nouveaux-candidats-a-la-succession-au-langage-java/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/18/devoxx-les-deux-nouveaux-candidats-a-la-succession-au-langage-java/</feedburner:origLink></item>
		<item>
		<title>Devoxx: Play! Framework 2.0</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/iVXgSjJllVY/</link>
		<comments>http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 18:08:36 +0000</pubDate>
		<dc:creator>Antoine BUSCH</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Play! Framework]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4589</guid>
		<description><![CDATA[<p>Deuxième retour de la conférence Devoxx qui bat en ce moment même son plein à Anvers en Belgique. J&#8217;ai assisté hier matin à la session sur Play! Framework 2.0 animée par Guillaume Bort et Sadek Drobi.</p> <p></p> Introduction <p>Pour ceux qui ne connaissent pas Play! (et qui visiblemement ne lisent pas ni le blog d&#8217;Ippon, <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/">Devoxx: Play! Framework 2.0</a></span>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/play_logo-2/" rel="attachment wp-att-4607"><img class="alignleft size-full wp-image-4607" title="play_logo" src="http://blog.ippon.fr/wp-content/uploads/2011/11/play_logo.png" alt="" width="136" height="50" /></a>Deuxième retour de la conférence Devoxx qui bat en ce moment même son plein à Anvers en Belgique. J&#8217;ai assisté hier matin à la session sur <a title="Play! Framework" href="http://www.playframework.org/" target="_blank">Play! Framework</a> 2.0 animée par Guillaume Bort et Sadek Drobi.</p>
<p><span id="more-4589"></span></p>
<h1>Introduction</h1>
<p>Pour ceux qui ne connaissent pas Play! (et qui visiblemement ne lisent pas ni <a title="Sous le capot de Play! Framework" href="http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/">le blog d&#8217;Ippon</a>, ni <a title="Le Touilleur Express" href="http://www.touilleur-express.fr/tag/playframework/">le Touilleur Express</a>), il s&#8217;agit d&#8217;un framework orienté web, full-stack (contient toutes les briques nécessaires pour développer, déjà intégrées et configurées), et qui met l&#8217;accent sur la facilité et la rapidité de développement. Il a aussi la particularité de ne rien faire comme les autres&#8230; Pour résumer grossièrement, il s&#8217;agit d&#8217;un équivalent de Ruby on Rails pour le monde Java.</p>
<p>Guillaume Bort, créateur du framework, et Sadek Drobi, un des développeurs principaux, nous ont donc parlé de la prochaine évolution majeure du framework. Ils commencent par faire deux annonces:</p>
<ul>
<li>La sortie de la première bétâ de la future version 2.0.</li>
<li>Typesafe (la société créée par Martin Odersky et Jonas Bonér, les créateurs de Scala et d&#8217;Akka respectivement), vont intégrer officiellement Play! 2.0 dans leur stack. Une intégration naturelle puisque Play 2.0! s&#8217;appuie fortement sur Scala, Akka et sbt&#8230; Guillaume Bort en profite également pour intégrer l&#8217;Advisory Board de Typesafe, où il sera plutôt en bonne compagnie puisqu&#8217;il y rejoint James Gosling et Doug Lea.</li>
</ul>
<h1>Historique</h1>
<p>Sadek Drobi, commence par nous rappeler que le framework Play! est né chez Zenexity pour répondre aux besoins de projets réels, avant d&#8217;être rendu open source. Il nous fait un rapide rappel de l&#8217;évolution du web ces dernières années: d&#8217;abord un web statique, composé de simples pages HTML, puis un web dynamique, où on découvre que l&#8217;on peut manipuler une page dynamiquement, parfois avec certains excès, ce qui donne lieu à une phase de structuration qui est celle dans laquelle nous nous trouvons actuellement.</p>
<p>Selon Sadek Drobi, la prochaine étape qui nous attends est celle du temps réel, où les informations dans la page seront mises à jour en permanence (pensez Twitter&#8230;). Cette évolution du web entraine de nouvelles contraintes : besoin d&#8217;une gestion efficace des flux de données, une gestion plus facile de la concurrence, une meilleure élasticité au déploiement&#8230; Le but de Play! 2.0 est de répondre à ces nouveaux besoins tout en gardant la philosophie qui le caractérise: prise en main facile et intuitive, full-stack, rapidité de développement&#8230;</p>
<h1>Nouveautés</h1>
<p>Guillaume nous fait ensuite une démo rapide de la console Play! Il s&#8217;agit en fait de la console <a title="SBT" href="https://github.com/harrah/xsbt/wiki">SBT</a>. On peut y lancer des commandes comme compile ou run. SBT est wrappée dans le script &#8220;play&#8221; ce qui permet d&#8217;utiliser les même commandes que pour Play! 1.x (ex: play new, play run, play test&#8230;). On peut également lancer l&#8217;interpréteur scala depuis la console, et ainsi avoir accès directement aux classes de notre projet, y compris les templates compilées. On peut donc appeler une template à la main et voir tout de suite le HTML généré. Utile pour débogger&#8230;</p>
<p>Guillaume nous montre ensuite qu&#8217;on peut mélanger Java et Scala dans le même projet, avec le même système de recompilation à la volée, de rechargement à chaud, et d&#8217;affichage des erreurs directement dans le navigateur. Il nous présente aussi le nouveau système de templating. Exit Groovy, place à Scala.  L&#8217;avantage est que les templates sont compilées comme des fonctions Scala, et bénéficient de tous les avantages du typage fort. Si vous renommez un champ d&#8217;un bean, vous saurez dès la compilation que vous avez oublié de mettre à jour un template. Plutôt pratique&#8230;</p>
<p>Fin de la démo. Sadek reprend la parole pour nous parler des besoins grandissant d&#8217;asynchronicité pour les applications web. Lorsqu&#8217;on appelle un système externe pour récupérer des données (appel REST, WS, ou autre&#8230;), il n&#8217;est plus question de bloquer un thread de traitement des requêtes pendant qu&#8217;on attend la réponse. Lorsqu&#8217;on veut traiter un gros flux de données, il n&#8217;est pas question de tout charger en mémoire pour le traiter ensuite. Il faut mieux maîtriser la consommation des ressources (threads, CPU, mémoire). Il faut sortir des API bloquantes (genre InputStream), et mettre en place une méthode plus efficace que simplement passer un callback à une méthode asynchrone. Sadek nous dit qu&#8217;il faut faire du &#8220;reactive programming&#8221;: réagir à des évènements (une requête arrive, la réponse d&#8217;un processus long est arrivée&#8230;).</p>
<p>Il introduit ensuite la réponse de Play! à ce problème: le concept d&#8217;<strong>Iteratee</strong> et d&#8217;<strong>Enumerator</strong>. Concept apparement inspiré par le langage Haskell. De ce que j&#8217;en ai compris, il s&#8217;agit d&#8217;une sorte d&#8217;un producteur (l&#8217;Enumerator) qui notifie un consomateur (l&#8217;Iteratee) que de nouvelles données sont disponibles. L&#8217;Iteratee peut ensuite répondre de plusieurs façons:</p>
<ul>
<li><strong>Continue</strong>: envoie moi encore des données, et traite les de cette façon là.</li>
<li><strong>Stop</strong>: arrête de m&#8217;envoyer des données (et libère potentiellement les resources)</li>
<li><strong>Error</strong>: tu m&#8217;envoies des données invalides.</li>
</ul>
<p>Play! utilise Akka et le modèle d&#8217;acteur pour implémenter ces concepts. Ce point à vraiment l&#8217;air d&#8217;être une des nouveautés importantes, et je suis curieux de voir un exemple concret de mise en pratique de ce pattern&#8230;</p>
<p>Sadek nous parle ensuite de la couche de persistance. Il nous dit qu&#8217;il est illusoire pour eux d&#8217;essayer de faire une couche d&#8217;abstraction générique de la persistance, les technologies sous-jacentes étant trop différentes (bases relationnelles, bases NoSQL, etc&#8230;). Ils préfèrent implémenter des API spécifiques grâce à des modules spécifiques. Pour la version Scala, l&#8217;implémentation par défaut est Anorm (une simple couche au dessus de JDBC). Pour la version Java, EBeans est utilisé comme implémentation légère de JPA.</p>
<p>Sadek et Guillaume nous parlent ensuite de l&#8217;avantage d&#8217;utiliser SBT comme outil de build. SBT étant extensible, il est possible d&#8217;écrire des modules qui viendront étendre le cycle de vie de l&#8217;application. Par exemple, on peut déclarer des &#8220;compiled assets&#8221;, c&#8217;est à dire des resources qui seront compilées automatiquement par Play! en cas de changement, et dont les erreurs seront affichées dans le navigateur, de la même manière que pour les fichiers sources Java ou Scala. On peut par exemple gérer ainsi la compilation des CSS avec Less, ou bien des fichiers Javascript avec CoffeeScript.</p>
<h1>Conclusion</h1>
<p>En conclusion, la réécriture de Play! leur a apporté un certain nombre d&#8217;effets de bords bénéfiques, tels que de meilleures performances, mais aussi d&#8217;apporter du &#8220;type-safety&#8221; partout, y compris dans la couche présentation (les templates), et dans le fichier route (une route définie qui pointe vers une méthode de contrôleur inexistante sera détectée à la compilation).</p>
<p>Un bémol toutefois: il est à noter que Play 2.0 sera incompatible avec Play 1.x, tant au niveau des API que du moteur de templating, et qu&#8217;il n&#8217;existe pas de stratégie de migration bien définie. Les changements d&#8217;API devront être gérés à la main. Pour ce qui est des templates, il faudra soit les réécrire toutes (pas forcément très réaliste), soit espérer que quelqu&#8217;un fasse un module pour pouvoir utiliser le moteur de templating basé sur Groovy avec Play! 2.0. Les projets existants sous Play 1.x risquent de ne pas être migrés vers la version 2.0, mais combien de temps la branche 1.x sera-t-elle maintenue ? De même, Play! 2.0 propose une API Java et une API Scala. On peut se demander combien de temps ces deux APIs seront maintenues en parallèle, et si l&#8217;API Java ne sera pas dans le futur reléguée au deuxième plan.</p>
<p>Play! est souvent perçu comme le trublion des frameworks web, et génère souvent des réactions assez polarisées (on adore ou on déteste). Mais on ne peut que constater en étant à Devoxx qu&#8217;il jouit d&#8217;une popularité croissante en voyant le nombre talks lui sont consacrés cette année. Et l&#8217;annonce de son intégration à la stack Typesafe, qui offrira un support commercial, en est une preuve supplémentaire.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/iVXgSjJllVY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/</feedburner:origLink></item>
		<item>
		<title>Les nouveautés de Spring 3.1 présentées à Devoxx</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/XKDwQj9XNrs/</link>
		<comments>http://blog.ippon.fr/2011/11/17/les-nouveautes-de-spring-3-1-presentees-a-devoxx/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 10:02:24 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4590</guid>
		<description><![CDATA[<p>A Devoxx, il y a une session que je ne pouvais pas manquer: les nouveautés de Spring 3.1, par Costin Leau.</p> <p>En voici un résumé, avec ma propre interprétation de ses slides et mes commentaires.</p> <p>Spring est aujourd&#8217;hui un framework mature, ce qui signifie que son mode de fonctionnement et ses APIs ne changent pas <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/17/les-nouveautes-de-spring-3-1-presentees-a-devoxx/">Les nouveautés de Spring 3.1 présentées à Devoxx</a></span>]]></description>
			<content:encoded><![CDATA[<p>A Devoxx, il y a une session que je ne pouvais pas manquer: les nouveautés de Spring 3.1, par Costin Leau.</p>
<p>En voici un résumé, avec ma propre interprétation de ses slides et mes commentaires.</p>
<p>Spring est aujourd&#8217;hui un framework mature, ce qui signifie que son mode de fonctionnement et ses APIs ne changent pas à chaque nouvelle version. Cependant, le framework continue à évoluer en fonction des nouvelles technologies et tendances qui arrivent: essentiellement le Cloud Computing et les nouvelles versions de Java et Jave EE dans notre cas.</p>
<p>Au cours des deux dernières années, nous avons ainsi vu une explosion du nombre de plateformes sur lesquels on peut déployer son application:</p>
<ul>
<li>Java EE (JBoss 7, Glassfish 3, Websphere 8 )</li>
<li>Tomcat 7 avec les Servlets 3.0</li>
<li>Les platformes de Cloud: GAE (Jetty), Beanstalk (Tomcat), CloudFoundry (Tomcat), CloudBees (Tomcat)</li>
</ul>
<p>Ces plateformes ont un certain dénominateur commun (l&#8217;API Servlet, en particulier), mais elles ont toutes des spécificités qui font qu&#8217;elles sont plus ou moins intéressantes en fonction du besoin et du moment (car ces spécificités changent avec le temps).</p>
<p>D&#8217;où l&#8217;importance d&#8217;être portable au niveau du déployement.<br />
<span id="more-4590"></span><br />
Commençons par un rappel historique: cette portabilité du déployement a toujours été le point fort de Spring: à l&#8217;origine, nous sommes nombreux à être passés à Spring car nous voulions pouvoir déployer la même application en développement (Tomcat) qu&#8217;en production (Websphere/Weblogic).</p>
<p>D&#8217;autre part, on a classiquement 4 environnements dans lesquels on déploie son application:</p>
<ul>
<li>Le développement</li>
<li>Les tests d&#8217;intégration</li>
<li>La pré-production (&#8220;staging&#8221; en Anglais)</li>
<li>La production</li>
</ul>
<p>Comment permettre à son application de se déployer de manière portable?</p>
<ul>
<li>JNDI est la technologie d&#8217;origine, proposée par J2EE. Bien entendu, son défaut est de ne fonctionner qu&#8217;avec un container. Dans mon expérience, elle est généralement compliquée à configurer pour les équipes de production.</li>
<li>Les propriétés systèmes. C&#8217;est une solution appréciée des équipes de production, par contre en Java il nous faut un moyen d&#8217;y accéder de manière simple (ce que propose Spring).</li>
<li>Des &#8220;application contexts&#8221; Spring différents. Une solution &#8220;pure&#8221; Spring qui est très répandue.</li>
<li>Les &#8220;PlaceHolder&#8221; de Spring (avec le tag), qui est une amélioration de la méthode précédente.</li>
</ul>
<p>Spring 3.1 vient ajouter une nouveauté: les profils de beans. On peut grouper les beans par type d&#8217;environnement cible, par exemple &#8220;dev&#8221;, &#8220;test&#8221;, &#8220;prod&#8221;.</p>
<ul>
<li>Typiquement on peut avoir deux beans avec l&#8217;id &#8220;dataSource&#8221;, qui sont instanciés en fonction du profil: une dataSource de &#8220;dev&#8221; et une dataSource de &#8220;test&#8221;.</li>
<li>Cette configuration n&#8217;est pas nécessairement en XML, rappelons que Spring peut maintenant être configuré en Java (avec des annotations), ce qui permet plus de liberté dans ce cas.</li>
</ul>
<p>Ces profils peuvent être activés via une configuration XML, ou via une API Java: il faut donc activer le bon profil au démarrage, par exemple en lisant une variable d&#8217;environnement.</p>
<p>Lors de la conférence, Costin a fait un sondage: la moitié des gens utilisent la configuration XML, la moitié via Java. Précisons, pour les gens qui croient encore que Spring ne se configure que par XML, que cette configuration &#8220;pure Java&#8221; est inclue dans Spring depuis 4 ans.</p>
<p>Cette configuration Java est généralement plus concise à utiliser pour de la configuration d&#8217;infrastructure: la définition de votre data source, de votre gestionnaire de transaction, etc&#8230; Elle est également plus puissante, car on peut plus aisément faire des branchements conditionnels ou du code spécifique qu&#8217;avec du XML.</p>
<p>Cette première partie de la conférence, très intéressante, a cependant un défaut: on n&#8217;y a pas rééllement parlé des nouveautés de Spring 3.1. La deuxième partie de la conférence par contre, était plus orientée sur les nouveautés de cette version 3.1.</p>
<h4>L&#8217;abstraction du cache</h4>
<p>Evidemment, avec l&#8217;achat de Gemfire par VMWare/SpringSource, le support du cache dans Spring est une priorité de Spring 3.1. La bonne nouvelle c&#8217;est que cette abstraction fonctionne avec plusieurs &#8220;fournisseurs&#8221; de cache, et pas que Gemfire: Ehcache (Terracotta), ConcurentMap (implémentation basique mais utile pour les tests), Redis (base NoSQL également sponsorisée par VMWare). D&#8217;autre part, des implémentations Infinispan (JBoss) et Websphere eXtreme Scale (IBM) sont en train d&#8217;être contribuées. Cette fonctionnalité est particulièrement importante pour moi:</p>
<ul>
<li>La JSR Cache commence à redémarrer après des années de stagnation: c&#8217;est donc intéressant d&#8217;avoir quelque chose de déjà utilisable.</li>
<li>Dans un contexte &#8220;Cloud&#8221;, qui implique des applications multi-tenantes, avoir un cache distrbué est absolument essentiel.</li>
</ul>
<h4>Support des Servlets 3.0</h4>
<p>Spring 3.1 va supporter l&#8217;API Servlet 3.0, avec Tomcat 7 ou GlassFish 3, tout en préservant la compatibilité Servlet 2.4.<br />
On peut donc maintenant configurer son application Web sans fichier web.xml</p>
<p>Au niveau de Spring MVC, cela apporte la gestion des requêtes HTTP asynchrones. Cette fonctionnalité est particulièrement importante pour pouvoir monter en charge lorsqu&#8217;on a beaucoup de clients, et que l&#8217;on veut faire une application Web moderne, avec beaucoup d&#8217;appels Ajax (dont certains peuvent être asynchrones).</p>
<p>Au niveau de Spring MVC REST, un refactoring complet a été réalisé. Costin nous promet de meilleures performances, une API plus propre pour les utilisateurs avancés, tout en restant backward compatible.</p>
<p>A ce sujet, deux nouveautés sur l&#8217;annotation @RequestMapping sont intéressantes:</p>
<ul>
<li>&#8220;consumes&#8221;, pour indiquer le type de media consumé (le &#8220;content-type header&#8221;)</li>
<li>&#8220;produces&#8221;, pour indiquer ce que l&#8217;on produit</li>
</ul>
<p>On peut par exemple avoir la configuration suivante:<br />
<code>@RequestMapping(value="/foo", consumes="application/pdf")</code></p>
<h4>Mises à jour de librairies</h4>
<p>Au niveau de JPA, on peut désormais avoir le package scanning sans fichier persistence.xml, ce qui simplifie les applications avec une seule persistence unit.</p>
<p>Spring 3.1 va supporter nativement Hibernate 4.0, avec en particulier des packages spécifiques en fonction des versions (org.springframework.orm.hibernate3 et org.springframework.orm.hibernate4).</p>
<p>De même, Spring 3.1 supporte Quartz 2.x (nombreux changements dans l&#8217;API Quartz 2.0/2.1), avec compatibilité Quartz 1.5. D&#8217;où l&#8217;importance d&#8217;un système d&#8217;abstraction de la configuration, afin de pouvoir monter de version facilement.</p>
<h4>Spring 3.1 supporte Java 7</h4>
<ul>
<li>Utilisation au mieux de Java 7 si il est disponible, sinon Spring utilisera Java 5 ou 6 (oui Spring 3.1 est toujours compatible Java 5)</li>
<li>Support de JDBC 4.1, en particulier pour JdbcTemplate</li>
<li>Support de la nouvelle API Fork/Join arrivée avec Java 7</li>
</ul>
<p>Cette dernière nouveelle concerne la programmation concurrente dans le contexte actuel: nous avons en effet de plus en plus de cores sur nos machines, mais ils sont généralement moins puissants. Donc si on n&#8217;utilise pas tous ces cores de manière optimale, les performances sont moins bonnes que sur certaines &#8220;vieilles&#8221; machines.<br />
Spring permet donc d&#8217;avoir des pools d&#8217;objets spécialisés, qui &#8220;comprennent&#8221; l&#8217;API fork/join et s&#8217;optimisent automatiquement en fonction du nombre de cores disponibles sur le serveur.<br />
Dans un environnement &#8220;cloud&#8221; cette fonctionnalité prend tout son sens: on peut rajouter ou enlever des cores en fonction des besoins, il est donc nécessaire d&#8217;avoir une application capable de s&#8217;optimiser automatiquement en fonction de ces changements.</p>
<h4>L&#8217;avenir et Spring 3.2</h4>
<p>Peu d&#8217;informations sur Spring 3.2, si ce n&#8217;est que le focus sera sur les technologies suivantes:</p>
<ul>
<li>Java EE 7</li>
<li>JCache (JSR 107)</li>
<li>JMS 2.0</li>
<li>Bean Validation 1.1</li>
<li>JPA 2.1</li>
<li>JSF 2.2</li>
</ul>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/XKDwQj9XNrs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/17/les-nouveautes-de-spring-3-1-presentees-a-devoxx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/17/les-nouveautes-de-spring-3-1-presentees-a-devoxx/</feedburner:origLink></item>
		<item>
		<title>Tempête sur les RIAs</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/UBtMFWahdpw/</link>
		<comments>http://blog.ippon.fr/2011/11/17/tempete-sur-les-rias/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 07:13:00 +0000</pubDate>
		<dc:creator>Geoffray GRUEL</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[silverlight]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4583</guid>
		<description><![CDATA[<p>Ceci n&#8217;est pas un billet de fond mais un appel à commentaires :</p> Adobe se désengage plus ou moins en douceur de Flex, MS va bientôt arrêter le support Silverlight, Google ne proposera jamais de support sur GWT. <p>De l&#8217;autre coté des serveurs les utilisateurs raffolent de ces applications enfin ergonomiques et qui fonctionnent sur <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/17/tempete-sur-les-rias/">Tempête sur les RIAs</a></span>]]></description>
			<content:encoded><![CDATA[<p>Ceci n&#8217;est pas un billet de fond mais un appel à commentaires :</p>
<ul>
<li>Adobe <a title="Adobe Flex" href="http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html" target="_blank">se désengage plus ou moins en douceur de Flex</a>,</li>
<li>MS va bientôt <a title="ZDNet Silverlight" href="http://www.zdnet.com/blog/microsoft/will-there-be-a-silverlight-6-and-does-it-matter/11180" target="_blank">arrêter le support Silverlight</a>,</li>
<li>Google ne proposera jamais de support sur GWT.</li>
</ul>
<p>De l&#8217;autre coté des serveurs les utilisateurs raffolent de ces applications enfin ergonomiques et qui fonctionnent sur les vieux coucous des services administratifs du CAC 40 équipé du bon vieil IE.</p>
<p>Que devons-nous faire en phase de choix :</p>
<ul>
<li>Revenir à du JS le temps que la tempête passe ?</li>
<li>Miser sur la communauté pour assurer l&#8217;avenir de Flex et de GWT ?</li>
<li>Miser sur les alternatifs : Vaadin,&#8230;?</li>
<li>Traverser la tempête vitesse grand V et mettre du HTML5 partout ?</li>
</ul>
<p>A vos commentaires.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/UBtMFWahdpw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/17/tempete-sur-les-rias/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/17/tempete-sur-les-rias/</feedburner:origLink></item>
		<item>
		<title>Ippon Technologies sponsor de Devoxx France!!</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/XmAFtRohch0/</link>
		<comments>http://blog.ippon.fr/2011/11/16/ippon-technologies-sponsor-de-devoxx-france/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 09:29:31 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Ippon Technologies]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4579</guid>
		<description><![CDATA[<p>LA grande nouvelle du jour est donc la tenue de Devoxx France dans 5 mois, du 18 au 20 Avril 2012 !</p> <p>Impliqué dès le début dans le projet, c’est avec enthousiasme qu’Ippon Technologies s’est engagé à devenir l’un des premiers sponsors de l’événement.</p> <p>Le projet est en cours, mais vous pouvez déjà compter sur <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/16/ippon-technologies-sponsor-de-devoxx-france/">Ippon Technologies sponsor de Devoxx France!!</a></span>]]></description>
			<content:encoded><![CDATA[<p>LA grande nouvelle du jour est donc la tenue de <a href="http://www.devoxx.fr" target="_blank">Devoxx France</a> dans 5 mois, du 18 au 20 Avril 2012 !</p>
<p>Impliqué dès le début dans le projet, c’est avec enthousiasme qu’Ippon Technologies s’est engagé à devenir l’un des premiers sponsors de l’événement.</p>
<p>Le projet est en cours, mais vous pouvez déjà compter sur une présence importante d’Ippon Technologies à l’événement: en tant que partenaire et sponsor de longue date des événements de la communauté Java en France, Ippon réaffirme une fois de plus son engagement dans notre plate-forme préférée!</p>
<p>Cette annonce, ainsi que la participation d’Ippon Technologies à l’événement, a été faite ce matin lors de la keynote d’ouverture de <a href="http://www.devoxx.com/display/DV11/Home" target="_blank">Devoxx 2011</a>.</p>
<p>Pour ceux qui auraient participé à l’<a href="http://www.esa.int/SPECIALS/Mars500/" target="_blank">ESA Mars 500</a>, et donc qui n’auraient pas attendu avec impatience <a href="http://www.devoxx.com/display/DV11/Home" target="_blank">Devoxx 2011</a>: il s’agit tout simplement de la plus grande conférence Java en Europe, avec 3200 personnes et les speakers les plus prestigieux.</p>
<p>Ippon Technologies a d’ailleurs envoyé une délégation de 6 de ses consultants sur place, qui vont vous tenir au courant des dernières nouveautés via ce blog, notre compte <a href="https://twitter.com/#!/ippontech" target="_blank">Twitter</a> et notre compte <a href="https://www.facebook.com/ippon.technologies" target="_blank">Facebook</a>: pour tous ceux qui n’ont pas eu la chance d’aller à Anvers cette année, cela donnera un avant-goût de <a href="http://www.devoxx.fr" target="_blank">Devoxx France</a>! Dépêchez-vous de vous inscrire, il ne reste plus que 5 mois!</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/XmAFtRohch0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/16/ippon-technologies-sponsor-de-devoxx-france/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/16/ippon-technologies-sponsor-de-devoxx-france/</feedburner:origLink></item>
		<item>
		<title>Ippevent Springfuse le 1er Décembre</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/xFBGP8sfdrk/</link>
		<comments>http://blog.ippon.fr/2011/11/14/ippevent-springfuse-le-1er-decembre/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 10:08:01 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[PrimeFaces]]></category>
		<category><![CDATA[SpringFuse]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4559</guid>
		<description><![CDATA[<p>Les Ippevents se suivent et ne se ressemblent pas. Après l&#8217;atelier Git du mois dernier, nous vous invitons le jeudi 1er décembre à découvrir Celerio et sa version online &#8220;SpringFuse&#8221; développés de Jaxio. Ces boosteurs de productivité vous permettent de générer très rapidement une Webapp Spring 3.0, JSF2 / Primefaces sous Maven à partir de votre <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/14/ippevent-springfuse-le-1er-decembre/">Ippevent Springfuse le 1er Décembre</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.springfuse.com/images/logo/springfuse.png" alt="Logo Springfuse" width="197" height="50" />Les Ippevents se suivent et ne se ressemblent pas. Après l&#8217;atelier Git du mois dernier, nous vous invitons le jeudi 1er décembre à découvrir Celerio et sa version online &#8220;<a href="http://www.springfuse.com/" target="_blank">SpringFuse</a>&#8221; développés de <a href="http://www.jaxio.com/" target="_blank">Jaxio</a>. Ces boosteurs de productivité vous permettent de générer très rapidement une Webapp Spring 3.0, JSF2 / Primefaces sous Maven à partir de votre base de données.</p>
<p><a href="http://twitter.com/framiere" target="_blank">Florent Ramière</a> l&#8217;un des fondateurs de Jaxio viendra nous présenter les outils en question et nous parler de leurs évolutions futures.</p>
<p>Rappelons que nos Ippevents sont gratuits et ouvert à tous.</p>
<p>Pour vous inscrire cliquez sur le bouton ci-dessous ou rendez-vous sur notre page <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/" target="_blank">Ippevent</a>.</p>
<div style="width: 100%; text-align: left;"><iframe frameborder="0" height="192" marginheight="5" marginwidth="5" scrolling="auto" src="http://www.eventbrite.com/tickets-external?eid=2150419964&amp;ref=etckt" width="100%"></iframe></p>
<div style="font-family: Helvetica, Arial; font-size: 10px; padding: 5px 0 5px; margin: 2px; width: 100%; text-align: left;"><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/r/etckt" target="_blank">Enregistrement en ligne à un événement</a><span style="color: #ddd;"> pour </span><a style="color: #ddd; text-decoration: none;" href="http://ippeventspringfuse.eventbrite.com?ref=etckt" target="_blank">Ippevent SpringFuse</a><span style="color: #ddd;"> produit par </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com?ref=etckt" target="_blank">Eventbrite</a></div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/xFBGP8sfdrk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/14/ippevent-springfuse-le-1er-decembre/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/14/ippevent-springfuse-le-1er-decembre/</feedburner:origLink></item>
		<item>
		<title>Java : Accès directs à la mémoire (off-Heap)</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/SP_RXo4AoDQ/</link>
		<comments>http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 08:00:23 +0000</pubDate>
		<dc:creator>Christophe PARAGEAUD</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[ByteBuffer]]></category>
		<category><![CDATA[Garbage]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[off-Heap]]></category>
		<category><![CDATA[Stack]]></category>
		<category><![CDATA[sun.misc.Unsafe]]></category>
		<category><![CDATA[Threads]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4397</guid>
		<description><![CDATA[<p>La zone mémoire la plus connue d&#8217;une JVM est la heap mais ce n&#8217;est pas la seule zone de stockage disponible.</p> <p>Nous verrons comment est structurée la mémoire d&#8217;une JVM et comment allouer de l&#8217;espace en dehors de la Heap ?</p> <p>Et ce, dans le but de pouvoir conserver les données en mémoire même pour <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/">Java : Accès directs à la mémoire (off-Heap)</a></span>]]></description>
			<content:encoded><![CDATA[<p>La zone mémoire la plus connue d&#8217;une JVM est la heap mais ce n&#8217;est pas la seule zone de stockage disponible.</p>
<p><img class="alignleft" style="margin-left: 15px; margin-right: 15px;" src="http://blog-dev.net/wp-content/uploads/2011/04/java.png" alt="" width="154" height="154" />Nous verrons comment est structurée la mémoire d&#8217;une JVM et comment allouer de l&#8217;espace en dehors de la Heap ?</p>
<p>Et ce, dans le but de pouvoir conserver les données en mémoire même pour les applications les plus consommatrices.</p>
<p>Points abordés :</p>
<ul>
<li>Quelles sont les méthodes pour instancier de la mémoire hors heap</li>
<li>Les cas d&#8217;applications (Cache, Memory Mapped File)</li>
<li>Performances</li>
<li>Problèmes rencontrés</li>
</ul>
<p><span id="more-4397"></span></p>
<h2>Introduction et théorie</h2>
<p>Voici les différentes zones que l&#8217;on peut retrouver dans un process Java :</p>
<div id="attachment_4399" class="wp-caption alignnone" style="width: 627px"><a href="http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/structjvm/" rel="attachment wp-att-4399"><img class="size-full wp-image-4399" title="Process Java" src="http://blog.ippon.fr/wp-content/uploads/2011/10/StructJVM.png" alt="" width="617" height="106" /></a><p class="wp-caption-text">Process Java</p></div>
<p style="padding-left: 60px;">On y trouve des zones techniques : JVM, OS.</p>
<p style="padding-left: 60px;">Des zones de stockage de données : Mémoire Heap et native.</p>
<p style="padding-left: 60px;">La zone d&#8217;échange entre la JVM et l&#8217;OS : Librairies.</p>
<p>La gestion de la memoire Java est parfois assez déroutante pour les débutants : les paramètres de gestion les plus connus sont ms et mx qui régissent la taille de la Heap alors que nous venons de voir que ce n&#8217;est pas la seule zone mémoire d&#8217;une JVM.</p>
<p>Java nio a introduit le principe de mémoire off-heap (java 1.4). Java 7 l&#8217;a étendu (JSR-203/NIO2).</p>
<p>Les objets concernés sont les ByteBuffers (java.nio.ByteBuffer) avec allocation directe (maximum de  2 Go par buffer).<br />
Concrètement il s&#8217;agit d&#8217;un tableau de Bytes qui sera stocké dans la mémoire native.<br />
La nature même du stockage (sous forme binaire) impose une sérialisation/désérialisation des objets.</p>
<p>Tout d&#8217;abord le tableau suivant montre pourquoi il faut privilégier la mémoire aux autres types d&#8217;accès.</p>
<p style="text-align: left;"><span style="color: #333399;">Comparaison des coûts de lecture en fonction du type de mémoire</span></p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Technologie</strong></th>
<th><strong>Vitesse lecture</strong></th>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Mémoire (RAM)</td>
<td style="text-align: center;"> 10-60 ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Accès réseau</td>
<td style="text-align: center;">10000-30000 ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Disques SSD</td>
<td style="text-align: center;">70000-120000 ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Disques durs</td>
<td style="text-align: center;">3000000-10000000 ns</td>
</tr>
</tbody>
</table>
<p>La conclusion semble évidente : pour des raisons de performances, il faut privilégier la mémoire locale à tout autre type de stockage.</p>
<h3>Gabarge Collector et problématiques</h3>
<p>Longtemps la taille maximale allouée à une JVM a été limitée par différents facteurs :</p>
<ul>
<li>Architecture 32 bits du processeur.</li>
<li>Système d&#8217;exploitation hébergeant la JVM (taille maximale d&#8217;un processus, maximum de RAM supportée)</li>
</ul>
<p>Mais aussi, et c&#8217;était souvent le premier seuil atteint, par le comportement du Garbage Collector.</p>
<p>Il s&#8217;agissait de trouver le meilleur ratio entre taille de la Heap et péjoration des performances dues aux traitements du Garbage Collector.<br />
De même, bien que plus rare que dans les langages sans gestion automatique de la mémoire, un programme Java n&#8217;est pas à l&#8217;abri des fuites mémoires.</p>
<p>C&#8217;est pourquoi, malgré la multiplication des architectures et OS 64 bits, cette barière n&#8217;a que peut évoluée depuis les débuts de Java.<br />
On peut la fixer à 3-4 Go.</p>
<p>Conscients de cette limite, les éditeurs tentent de réagir.</p>
<p>Oracle à introduit le collecteur G1 (Garbage first) en version 6 de Java SE.<br />
Ce collecteur a pour but de réduire les temps de passage du GC.</p>
<p>Azul System, s&#8217;est aussi positionné, avec la Zing Virtual Machine (<a href="http://www.azulsystems.com/zing/pgc">Pauseless Garbage Collection</a>).</p>
<p>En attendant, il est tentant d&#8217;utiliser le stockage hors heap dans des applications Java.</p>
<h2>Mémoire off-heap</h2>
<p>Une belle définition sous forme de lapalissade pourrait être : « tout ce qui n&#8217;est pas dans la heap est off heap ».</p>
<p>Tout d&#8217;abord voyons comment est structurée la mémoire dans la JVM</p>
<p><a href="http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/zonesmemoirejvm/" rel="attachment wp-att-4404"><img class="size-full wp-image-4404 aligncenter" title="ZonesMemoireJVM" src="http://blog.ippon.fr/wp-content/uploads/2011/10/ZonesMemoireJVM.png" alt="" width="700" height="262" /></a></p>
<h3>A &#8211; Zones méthodes (Method Area)</h3>
<p>Cette zone est essentiellement alimentée par le classloader.<br />
Quand la JVM charge une classe ou une interface, elle place les informations nécessaires dans cette zone.<br />
Cette zone est éligible au Garbage Collector. Quand une classe passe hors scope elle sera collectée lors du prochain passage du GC.<br />
Cette zone est partagée (accessible à tous les process de la JVM).</p>
<h4>1 &#8211; Pool constantes :</h4>
<h3><span class="Apple-style-span" style="font-size: 13px; font-weight: normal;">Contient toutes les constantes définies par l&#8217;application :</span></h3>
<p style="padding-left: 30px;">Littérales : int, long, float, double ou bien String.<br />
Références vers les types, les champs et les méthodes.</p>
<h4>2 &#8211; Code méthode :</h4>
<p>Implémentation (bytecode) de toutes les méthodes utilisées par la JVM.</p>
<h4>3 &#8211; Zone d&#8217;informations :</h4>
<p>Contient différents éléments d&#8217;information sur les classes.<br />
Champs de classe :</p>
<ul>
<li>Nom du champ.</li>
<li>Type du champ.</li>
<li>Modificateurs du champ.</li>
</ul>
<p>Méthodes :</p>
<ul>
<li>Nom de la méthode.</li>
<li>Type retourné.</li>
<li>Nombre et type des paramètres.</li>
<li>Modificateurs de la méthode.</li>
</ul>
<p>En plus pour les méthodes non abstraites ou natives :</p>
<ul>
<li>Taille de l&#8217;opérande et des variables locales (utilisée pour frame stack).</li>
<li>Table d&#8217;exception.</li>
</ul>
<h4>4 &#8211; Variables de classes</h4>
<p>Les variables de classes sont partagées par toutes les instances de la classe. De plus elles ne sont pas liées à l&#8217;instanciation d&#8217;une classe mais créées au chargement de la classe.</p>
<h3>B &#8211; Heap</h3>
<p>Lorsque la JVM doit instancier un objet java, elle le fait dans cette zone.<br />
On y retrouve les classes, les objets, les primitives Java.<br />
Cette zone est nettoyée par le GC.</p>
<p>Cette zone est partagée (accessible à tous les process de la JVM).</p>
<p>NB : il y a une seule Heap et Method Area par JVM.</p>
<h3>C &#8211; Threads</h3>
<p>Cette zone n&#8217;est pas partagée.</p>
<h4>Pointeur d&#8217;instruction :</h4>
<p>Indique la ligne de code actuellement exécutée.</p>
<h4>Java stack :</h4>
<p>Stocke les primitives et les références.</p>
<p>Stocke l&#8217;état des méthodes invoquées (non natives) par le thread, l&#8217;état comprend les variables locales à la méthode (ThreadLocal), les paramètres d&#8217;appel ainsi que la valeur retournée par la méthode.</p>
<p>Chaque état est stocké dans des frames (un par méthode) dont la durée de vie est liée au cycle d&#8217;appel de la méthode.</p>
<p><del>Cette zone est nettoyée par le GC.</del></p>
<p>Cette zone est parcourue par le GC afin d&#8217;identifier les objets non référencés dans la Heap.</p>
<h4>Frames :</h4>
<p>Trois sections compose les frames.</p>
<p><strong>Piles opérande</strong></p>
<ul>
<li>Pile FIFO 32/64 bits utilisée pour le stockage provisoire des variables ainsi que des calculs intermédiaires.</li>
</ul>
<p><strong>Données</strong></p>
<ul>
<li>Références RCP (Runtime Constant Pool).</li>
<li>Références vers le pool de constantes utilisées par le thread.</li>
<li>Résultats des retours de méthodes.</li>
</ul>
<p><strong>Variables locales</strong></p>
<ul>
<li>Tableau contenant les variables locales de la méthode. Soit les variables dont la durée de vie est celle de la méthode ainsi que les paramètres d&#8217;appel.</li>
</ul>
<div id="attachment_4405" class="wp-caption aligncenter" style="width: 314px"><a href="http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/thread/" rel="attachment wp-att-4405"><img class="size-full wp-image-4405 " title="Thread" src="http://blog.ippon.fr/wp-content/uploads/2011/10/Thread.png" alt="" width="304" height="353" /></a><p class="wp-caption-text">Stack Frames</p></div>
<h4>Méthodes natives</h4>
<p>A l&#8217;image des Frames l&#8217;état des méthodes natives est stocké dans cette zone.<br />
Mais contrairement à ces dernières, l&#8217;organisation est dépendante de l&#8217;OS et de l&#8217;implémentation de la méthode native.</p>
<h2>Création d&#8217;objets en dehors de la heap Java</h2>
<p>L&#8217;utilisation dans un programme Java de mémoire hors heap devra répondre aux problématiques suivantes :</p>
<ul>
<li>Accéder à la mémoire hors heap.</li>
<li>Gestion de la mémoire.</li>
<li>Référencement et accès à la mémoire off-heap.</li>
</ul>
<h3>A &#8211; Java Native Access (JNA)</h3>
<p>JNA permet l&#8217;accès aux librairies natives (dll, so) à partir de code Java uniquement (sans utiliser JNI ou du C).<br />
Une interface java décrit les méthodes et les structures de la librairie native.<br />
Il n&#8217;y a pas de génération de code tout se fait au Runtime.</p>
<p>JNA est fourni avec certaines librairies natives courantes ainsi que des classes utilitaires d&#8217;accès à la mémoire native.</p>
<p>Plus d&#8217;informations :</p>
<p style="padding-left: 30px;">Documentation : <a href="http://www.root-me.org/fr/Documentation/Hacking/Java-native-code-injection.html">http://www.root-me.org/fr/Documentation/Hacking/Java-native-code-injection.html</a><br />
Site web :<a href=" https://github.com/twall/jna"> https://github.com/twall/jna</a></p>
<p>Cette librairie fournie plusieurs méthodes pour créer des objets en dehors de la heap.</p>
<pre class="brush: java; title: ; notranslate">
int value = 12345;
int offset = 0;
int size = 128;

// on crée un objet mémory
Memory m = new Memory(1024);

// on alloue l'espace mémoire
ByteBuffer buff = m.getByteBuffer(0, size);

offset = offset + size;

// On insère l'objet
buff.putInt(value);

// RAZ de la position courante du buffer
buff.flip();

// On récupère et affiche l'objet
System.out.println(buff.getInt());

// On déclare un deuxième buffer
ByteBuffer buff2 = m.getByteBuffer(offset, size);

// On insère l'objet
buff2.putInt(value + 1);

// RAZ de la position courante du buffer
buff2.flip();

// On récupère et affiche l'objet
System.out.println(buff2.getInt());

// on libère la mémoire
m.clear();

// méthode 2
// on crée un objet mémory
// et on insère directement les objets
Memory m2 = new Memory(1024);

// On insère l'objet
m2.setInt(offset, value);

// On récupère et affiche l'objet
System.out.println(m2.getInt(offset));

// on libère la mémoire
m2.clear();
</pre>
<h3>B &#8211; Utilisation de la classe ByteBuffer</h3>
<p>L&#8217;utilisation de la mémoire native avec cette API est simple, voire transparente.<br />
Deux méthodes de création d&#8217;un ByteBuffer sont disponibles :</p>
<ol>
<li>ByteBuffer.allocateDirect()</li>
<li>ByteBuffer.allocate()</li>
</ol>
<p>Seule la première méthode instancie un objet en dehors de la heap.</p>
<p>Exemple de code :</p>
<pre class="brush: java; title: ; notranslate">
byte[] bytes = ...;
// allocate native memory to store our object
ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
buf.put(bytes);
</pre>
<p>Remarque : Le contenu stocké doit être de type tableau de byte, ce qui explique que le contenu stocké hors heap doit être sérialisable.</p>
<p><strong>Nota Bene</strong> : Ceux qui on déjà codé en C/C++ ne devront pas s&#8217;attendre a retrouver l&#8217;équivalent de malloc.<br />
En effet les possibilités offertes sont très limitées et le plus surprenant étant qu&#8217;il n&#8217;y a pas de méthode pour désallouer un objet stocké hors heap.</p>
<p>Comment ça marche alors ?<br />
En réalité une méthode de libération de la mémoire est crée automatiquement (sun.misc.Cleaner) et sera appelée par le GC lors de son prochain passage.</p>
<h4>Conclusion :</h4>
<p>Tout comme pour la heap, l&#8217;espace est libéré par le GC lorsque l&#8217;objet n&#8217;est plus référencé par le code.<br />
Tout comme la heap il n&#8217;y a pas de relation directe entre le moment ou l&#8217;objet est libérable et le moment ou il est effectivement libéré.<br />
Donc il n&#8217;y a pas de magie, les objets hors heap sont bien sensibles au GC.</p>
<p>Toutefois :</p>
<ul>
<li>Pas de phase de marquage des objets.</li>
<li>Pas de phase de compaction (réorganisation de l&#8217;espace mémoire) pendant le passage du GC.</li>
<li>Le nettoyage de la mémoire hors heap est donc plus rapide que son homologue de la heap.</li>
</ul>
<p>Il est possible d&#8217;appeler la méthode de nettoyage à tout moment (encore une fois en fouillant dans les profondeurs de l&#8217;API) :</p>
<pre class="brush: java; light: true; title: ; notranslate">
Method getCleanerMethod = buffer.getClass().getMethod(&quot;cleaner&quot;, new Class[0]);
getCleanerMethod.setAccessible(true);
sun.misc.Cleaner cleaner = (sun.misc.Cleaner)getCleanerMethod.invoke(buffer,
   new Object[0]);
cleaner.clean();
</pre>
<h3>C &#8211; Autres possibilité d&#8217;allocation directe</h3>
<h4>sun.misc.Unsafe</h4>
<p>Son utilisation est un peu plus complexe, il s&#8217;agit de la classe qui est derrière ByteBuffer.allocateDirect().<br />
Comme son nom l&#8217;indique cette classe est unsafe et doit donc être utilisée en toute connaissance de cause. En effet l’accès à une zone mémoire non allouée provoque immanquablement le crash de la JVM.<br />
Pour plus de sécurité les constructeurs sont privés et la méthode de classe getUnsafe() ne peut être appelée que par un Bootloader (et donc par la JVM elle même).</p>
<p>Heureusement il est possible de contourner cette sécurité.</p>
<p>Méthode de récupération d&#8217;une instance :</p>
<pre class="brush: java; light: true; title: ; notranslate">
private static Unsafe getUnsafeInstance() throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
   Field theUnsafeInstance = Unsafe.class.getDeclaredField(&quot;theUnsafe&quot;);
   theUnsafeInstance.setAccessible(true);
   return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
</pre>
<p>Autres cas d&#8217;utilisation de la classe :<br />
Cette classe permet de connaître l&#8217;adresse d&#8217;un objet stocké en mémoire.<br />
Plus précisément la position d&#8217;un champ dans la zone mémoire allouée aux instances de la classe.</p>
<pre class="brush: java; title: ; notranslate">
// Récupère une instance Unsafe
Unsafe unsafe = getUnsafeInstance();

// Réserve de la mémoire directe
Long allocateMemory = unsafe.allocateMemory(10);

// Récupération de l'espace d'allocation du champs code Commune
Field field = Commune.class.getDeclaredField(&quot;codeCommune&quot;);
Long offsetCodeCommune = unsafe.objectFieldOffset(field);

// On affecte une valeur à l'emplacement du champ
unsafe.putObject(allocateMemory, offsetCodeCommune, &quot;325555&quot;);
</pre>
<p>NB : qui a dit qu&#8217;il fallait obligatoirement un setter public ?</p>
<h4>MemoryMappedFile</h4>
<p>Le contenu du fichier est mappé dans l&#8217;espace mémoire du process depuis le fichier source. Une fois le fichier chargé (ou une portion du fichier) tous les accès se font en mémoire.<br />
Il en résulte des performances extrêmes par rapport aux méthodes traditionnelles qui utilisent les accès disques.</p>
<p>Cette méthode est la plus indiquée en cas de copie partielle ou totale d&#8217;un fichier.</p>
<pre class="brush: java; title: ; notranslate">

File file = new File(path);

// Creation d'un memory-mapped file en lecture seule
FileChannel roChannel = new RandomAccessFile(file, &quot;r&quot;).getChannel();

MappedByteBuffer mbb = roChannel.map(FileChannel.MapMode.READ_ONLY, 0,
   (int) roChannel.size());

// tableau de bits utilisé pour la lectre
ByteArrayBuffer bits = new ByteArrayBuffer();

while(mbb.hasRemaining()) {
   // on lit le prochain octet
   byte b = mbb.get();
   if (b == 10 || b == 13) {
      if (!firstLine) {
         // On ignore la première ligne (entête)
         firstLine = true;
      } else {
         // on affiche le contenu du fichier
         System.out.println(bits.toString());
      }

     // on passe à une nouvelle ligne
     // on réinitialise le tableau
     bits = new ByteArrayBuffer();
     } else
       // on ajoute l'octet au tableau
       bits.write(b);
}

// on ferme le canal
roChannel.close();

// on vide le buffer
mbb.clear();
...
</pre>
<p>Particularités :</p>
<ul>
<li>L&#8217;OS charge/décharge le contenu du fichier selon les besoins.</li>
</ul>
<ul>
<li>Utile pour les fichiers extrêmement volumineux.</li>
</ul>
<ul>
<li>Ou à l&#8217;inverse lorsque seul un fragment d&#8217;un fichier est utilisé.</li>
</ul>
<h2>Exemple</h2>
<p>Mise en cache d&#8217;un extrait de la liste des communes mondiales de plus de 1000 habitants (+/- 114000) à partir d&#8217;un csv. Le code présenté a été teste avec la JVM OpenJDK 1.7 sur MAC (elle apporte un MBean de monitoring de la mémoire allouée par AllocateDirect()).</p>
<p>Quatre versions :</p>
<ol>
<li>Une classique avec une Map</li>
<li>Une directbuffer en utilisant serialisation java</li>
<li>Une directbuffer en utilisant externalizable java</li>
<li>Une unsafe</li>
</ol>
<p>1)</p>
<pre class="brush: java; title: ; notranslate">
public class MemoryCache {

private Mapdata = new HashMap();

public void put(Object key, Commune object) throws IOException {
data.put(key, object);
}

public Object get(Object key) throws ClassNotFoundException, IOException {
return data.get(key);
}
…

}
</pre>
<p>2) &amp; 3)</p>
<pre class="brush: java; title: ; notranslate">
public class NativeMemoryCache {
private Map data = new HashMap();

public void put(Object key, Serializable object) throws IOException {
 byte[] bytes = serialize(object);
 // allocate native memory to store our object
 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
 buf.put(bytes);
 buf.flip();
 data.put(key, buf);
}

public Object get(Object key) throws ClassNotFoundException, IOException {
 ByteBuffer buf = data.get(key).duplicate();
 byte[] bytes = new byte[buf.remaining()];
 buf.get(bytes);
 return deserialize(bytes);
}
…

}
</pre>
<p>4)</p>
<pre class="brush: java; title: ; notranslate">
public class NativeMemoryCacheUnSafe {

/**
* Création de la map pour stocker la clé
* ainsi que l'adresse de l'objet en mémoire native
*/
private Map data = new HashMap(120000);

/**
* Objet Unsafe pour accéder
* à la mémoire native
*/
private static Unsafe unsafe = null;

/**
* Offset de stockage dans la mémoire native
*/
private static Long offset = new Long(0);

static {
 try {
   unsafe = getUnsafeInstance();
 } catch (SecurityException e) {
   System.out.println(&quot;Exception de sécurité :&quot; + e);
 } catch (NoSuchFieldException e) {
   System.out.println(&quot;Impossible d'accéder au champ de la classe Unsafe :&quot; + e);
 } catch (IllegalAccessException e) {
   System.out.println(&quot;Impossible d'accéder à la classe Unsafe :&quot; + e);
 }
}

public void put(Long key, long codeCommune, String nomCommune, double latitude,
double longitude, String codePays, String codeRegion, String codeAdministratif,
int population, String timeZone) throws IOException,
SecurityException, NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
//Taille max d'un objet (bytes)
Long allocateMemory = unsafe.allocateMemory(400);

unsafe.putObject(allocateMemory, offset, new Commune(codeCommune, nomCommune, latitude,
 longitude, codePays, codeRegion, codeAdministratif, population, timeZone));

data.put(key, allocateMemory);
}

/**
* @param key identifiant unique de l'objet
* @return
* @throws ClassNotFoundException
* @throws IOException
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public Commune get(Object key) throws ClassNotFoundException, IOException,
SecurityException, NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {

 Long adresse = data.get(key);
 return (Commune)unsafe.getObject(adresse, offset);
}

…

}
</pre>
<h2>Résultats</h2>
<p><strong>used</strong> : La quantité de mémoire réellement utilisée par l&#8217;application.<br />
<strong>committed</strong> : La quantité de mémoire qui a été réservée auprès du système d&#8217;exploitation.</p>
<p><strong>Paramètres JVM</strong> : -X:+AggressiveHeap</p>
<p>Test 1.</p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Type de test</strong></th>
<th><strong>Classic</strong></th>
</tr>
<tr align="center" valign="middle">
<td>Temps de traitement (ms)</td>
<td>477</td>
</tr>
<tr align="center" valign="middle">
<td>Collection Count</td>
<td> 0</td>
</tr>
<tr align="center" valign="middle">
<td> Collection Time</td>
<td> 0</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation heap</td>
<td>used=229749Ko<br />
committed=2636992Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation non Heap</td>
<td>used=3729Ko<br />
committed = 23744Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Buffer pool<br />
(si pas de libération de la mémoire)</td>
<td>_</td>
</tr>
</tbody>
</table>
<p>Test 2.</p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Type de test</strong></th>
<th><strong>Direct </strong><br />
<strong>(Serializable)</strong></th>
</tr>
<tr align="center" valign="middle">
<td>Temps de traitement (ms)</td>
<td>1697</td>
</tr>
<tr align="center" valign="middle">
<td>Collection Count</td>
<td> 1</td>
</tr>
<tr align="center" valign="middle">
<td> Collection Time</td>
<td>1329</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation heap</td>
<td>used=794123Ko<br />
committed=2652352Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation non Heap</td>
<td>used=4615Ko<br />
committed=23744Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Buffer pool<br />
(si pas de libération de la mémoire)</td>
<td>Type : Direct<br />
Count:113576<br />
MemoryUsed:31849106<br />
Total capacity:31849106</td>
</tr>
</tbody>
</table>
<p>Test 3.</p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Type de test</strong></th>
<th><strong>Direct </strong><br />
<strong>(Externalizable)</strong></th>
</tr>
<tr align="center" valign="middle">
<td>Temps de traitement (ms)</td>
<td>1473</td>
</tr>
<tr align="center" valign="middle">
<td>Collection Count</td>
<td>1</td>
</tr>
<tr align="center" valign="middle">
<td> Collection Time</td>
<td>413</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation heap</td>
<td>used=288094Ko<br />
committed=2655296Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation non Heap</td>
<td>used=4587Ko<br />
committed = 23744Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Buffer pool<br />
(si pas de libération de la mémoire)</td>
<td>Type : Direct<br />
Count:113576<br />
MemoryUsed:16175618<br />
Total capacity:16175618</td>
</tr>
</tbody>
</table>
<p>Test 4.</p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Type de test</strong></th>
<th><strong>Direct</strong><br />
<strong>(Unsafe)</strong></th>
</tr>
<tr align="center" valign="middle">
<td>Temps de traitement (ms)</td>
<td>490</td>
</tr>
<tr align="center" valign="middle">
<td>Collection Count</td>
<td>0</td>
</tr>
<tr align="center" valign="middle">
<td> Collection Time</td>
<td>0</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation heap</td>
<td>used=232327Ko<br />
committed=2652480Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation non Heap</td>
<td>used=3780Ko<br />
committed=23744Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Buffer pool<br />
(si pas de libération de la mémoire)</td>
<td>-</td>
</tr>
</tbody>
</table>
<h2>Frameworks utilisant l&#8217;accés direct à la mémoire</h2>
<p style="padding-left: 30px;"><a href="http://www.terracotta.org/products/bigmemory">Terracota BigMemory</a> (ehcache) : stockage de données dans la mémoire native<br />
<a href="http://www.oracle.com/fr/products/middleware/coherence/index.html"> Coherence</a> : Coherence propose le stockage off heap dans son cache<br />
<a href="https://github.com/raffaeleguidi/DirectMemory"> DirectMemory</a> : Equivalent open source de Big Memory<br />
<a href="http://code.google.com/p/vanilla-java/wiki/HugeCollections"> Huge collections</a> : Framework permettant de manipuler de grande collection en utilisant la mémoire native</p>
<h3>Références</h3>
<p>Java virtual machine specifications : <a href="http://java.sun.com/docs/books/jvms/">http://java.sun.com/docs/books/jvms/</a><br />
The Structure of the Java Virtual Machine : <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/Overview.doc.html">http://java.sun.com/docs/books/vmspec/2nd-edition/html/Overview.doc.html</a></p>
<h3>Options de la JVM relatives à la mémoire directe.</h3>
<p><strong>-d64</strong><br />
Permet de passer la JVM en mode 64bits, utile pour adresser plus de mémoire.</p>
<p><strong>-XX:MaxDirectMemorySize=</strong> ou <strong>-Dsun.nio.MaxDirectMemorySize=</strong><br />
Permet de définir la mémoire maximale réservées pour la mémoire off heap.</p>
<p><strong>-XX:+PageAlignDirectMemory</strong> ou <strong>-Dsun.nio.PageAlignDirectMemory=true</strong><br />
Permet de s&#8217;assurer qu&#8217;un espace de mémoire native est alignée sur une page mémoire. Avant le JDK7, une page entière (ou plus) était allouée quelle que soit la taille de l&#8217;objet (4096 octets sur une majorité d&#8217;OS).</p>
<h2>Conclusion</h2>
<p>L&#8217;exemple retenu n&#8217;est pas le plus favorable aux cas d&#8217;utilisation de la mémoire off-heap, c&#8217;est pourquoi il met en exergue les inconvénients de cette solution.</p>
<p>L&#8217;utilisation de la mémoire native est une solution à envisager si votre programme est très consommateur en mémoire et pas forcement pour les programmes affectés par les passages du GC.</p>
<p>Ce n&#8217;est donc pas forcement le miracle attendu dans le sens ou ne vous dispensera pas des tracas du GC.</p>
<p>De plus le programme consomme temporairement autant de heap qu&#8217;un programme traditionnel (creation d&#8217;objets avant de stocker off-heap).</p>
<p>Enfin la sérialisation est coûteuse en terme de performances (mais seuls les programmes les plus exigeants la verront comme un véritable obstacle).<br />
C&#8217;est pourquoi, sauf à utiliser la classe Unsafe, l&#8217;utilisation de la mémoire native est moins performante que son homologue Heap.</p>
<p>Conditions idéales d&#8217;utilisation de la mémoire native :</p>
<ul>
<li>Idéal quand la volumétrie de données est très importante (&gt; 2 Go).</li>
<li>Quand les données sont stables dans le temps (sinon les données sont collectées par le GC).</li>
<li>Et enfin quand les données sont sérialisables.</li>
</ul>
<p>L&#8217;utilisation des classes comme Unsafe est très dangereuse et réclamera une longue mise au point afin d&#8217;éviter un crash de la JVM avec pour seuls indices un code retour 139 (Segmentation violation) ou 134 (Dump core).<br />
Pour les programmes affectés par le passage du Garbage Collector, c&#8217;est une solution parmi d&#8217;autres :</p>
<p style="padding-left: 30px;">1. Tuning de la JVM et du GC<br />
2. Création d&#8217;un pool d&#8217;objets réutilisables (crées à l&#8217;avance et jamais libérés).</p>
<p>Le code source est disponible ici : <a href="http://blog.ippon.fr/wp-content/uploads/2011/11/IPPON_BLOG_OffHeap.zip">Source</a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/SP_RXo4AoDQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/</feedburner:origLink></item>
		<item>
		<title>Nouvelle version du site d’Ippon Technologies</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/LbbPP4xMcIg/</link>
		<comments>http://blog.ippon.fr/2011/10/25/nouvelle-version-du-site-ippon-technologies/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 12:26:24 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippon Technologies]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4372</guid>
		<description><![CDATA[<p>La nouvelle version de notre site http://www.ippon.fr est en ligne !</p> <p>Au menu, nous vous proposons de nouvelles rubriques détaillant nos offres, nos compétences, nos références et partenaires&#8230; Ainsi qu&#8217;une mise à jour des parties recrutement et société, avec de nouvelles pages pour nos agences de Bordeaux et Nantes.</p> <p>Nous avons voulu mettre l&#8217;accent sur <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/25/nouvelle-version-du-site-ippon-technologies/">Nouvelle version du site d&#8217;Ippon Technologies</a></span>]]></description>
			<content:encoded><![CDATA[<p>La nouvelle version de notre site <a href="http://www.ippon.fr" target="_blank">http://www.ippon.fr</a> est en ligne !</p>
<p>Au menu, nous vous proposons de nouvelles rubriques détaillant nos <a href="http://www.ippon.fr/offre" target="_blank">offres</a>, nos <a href="http://www.ippon.fr/expertise-technique" target="_blank">compétences</a>, nos <a href="http://www.ippon.fr/references" target="_blank">références</a> et <a href="http://www.ippon.fr/partenaires" target="_blank">partenaires</a>&#8230; Ainsi qu&#8217;une mise à jour des parties <a href="http://www.ippon.fr/recrutement" target="_blank">recrutement</a> et <a href="http://www.ippon.fr/societe" target="_blank">société</a>, avec de nouvelles pages pour nos agences de <a href="http://www.ippon.fr/bordeaux" target="_blank">Bordeaux</a> et <a href="http://www.ippon.fr/nantes" target="_blank">Nantes</a>.</p>
<p>Nous avons voulu mettre l&#8217;accent sur l&#8217;<a href="http://www.ippon.fr/societe" target="_blank">esprit d&#8217;Ippon</a>, <a href="http://www.ippon.fr/contributions" target="_blank">notre participation aux communautés Java et agile</a>, et nous avons intégré le site avec ce blog et nos comptes <a href="https://twitter.com/#!/ippontech" target="_blank">Twitter</a> et <a href="http://www.linkedin.com/company/ippon-technologies" target="_blank">LinkedIn</a>, afin de permettre une meilleure interactivité avec nos visiteurs.</p>
<p>Au niveau technique, car nous savons que c&#8217;est ce qui intéresse avant tout les lecteurs de ce blog:</p>
<ul>
<li>En tant qu&#8217;experts Liferay, il était évident pour nous que  le site devait être entièrement développé et mis en page sur un Liferay 6. Nous avons réalisé quelques portlets spécifiques, ainsi que notre propre template, mais l&#8217;essentiel du site est réalisé avec les fonctionnalités standard de Liferay. Nous avons particulièrement apprécié :
<ul>
<li>Les nouvelles fonctionnalités de CMS proposées par Liferay 6</li>
<li>La manière dont Liferay nous permet de gérer le SEO (Search Engine Optimization), à la fois simple et puissante</li>
</ul>
</li>
<li>Nous sommes hébergés sur le cloud Ippon, qui est une plateforme <a href="http://opennebula.org/" target="_blank">Open Nebula</a> (et sur laquelle nous hébergeons également nos clients qui le désirent)</li>
<li>Nous avons géré tous nos développements sur la plateforme de développement interne d&#8217;Ippon: <a href="http://subversion.apache.org/" target="_blank">SVN</a> et <a href="http://trac.edgewall.org/" target="_blank">Trac</a> en particulier. C&#8217;est la même plateforme que nous utilisons pour les forfaits réalisés dans nos locaux.</li>
</ul>
<p>Si vous êtes encore sous IE6 il faudra attendre la semaine prochaine pour un accès dégradé.</p>
<p>Bonne navigation,</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/LbbPP4xMcIg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/25/nouvelle-version-du-site-ippon-technologies/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/25/nouvelle-version-du-site-ippon-technologies/</feedburner:origLink></item>
		<item>
		<title>Sous le capot de Play! Framework</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/TnY7x1L7u1U/</link>
		<comments>http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 08:48:01 +0000</pubDate>
		<dc:creator>Ludovic CHANE WON IN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Play! Framework]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4288</guid>
		<description><![CDATA[<p align="LEFT">Play! Framework est un petit « nouveau » dans l&#8217;écosystème fourni des framework web Java et il a fait beaucoup parler de lui ces derniers temps. Pourquoi tant de bruit (bon ou mauvais d&#8217;ailleurs) me direz-vous ? Je n&#8217;entrerais pas dans ce débat et cet article n&#8217;est pas là pour faire l&#8217;éloge ou non de Play!. D&#8217;un <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/">Sous le capot de Play! Framework</a></span>]]></description>
			<content:encoded><![CDATA[<p align="LEFT"><strong></strong><img class="alignnone size-full wp-image-4296" style="float: left; padding: 0px; margin-top: -1px; margin-right: 10px; border-width: 0px;" title="play_logo" src="http://blog.ippon.fr/wp-content/uploads/2011/10/play_logo-e1318867072992.jpg" alt="" width="200" height="140" />Play! Framework est un petit « nouveau » dans l&#8217;écosystème fourni des framework web Java et il a fait beaucoup parler de lui ces derniers temps. Pourquoi tant de bruit (bon ou mauvais d&#8217;ailleurs) me direz-vous ? Je n&#8217;entrerais pas dans ce débat et cet article n&#8217;est pas là pour faire l&#8217;éloge ou non de Play!. D&#8217;un point de vue personnel, je dirais juste que Play! m&#8217;a redonné envie de faire du développement web en java. Après c&#8217;est une question de goût.</p>
<p align="LEFT">Deux des fonctionnalités de Play! que j&#8217;apprécie particulièrement sont : <strong>le rechargement à chaud du code Java</strong> et <strong>le bytecode enhancement</strong>. Je vous propose de voir comment, sous le capot, Play! met en œuvre ces 2 fonctionnalités.</p>
<p align="LEFT"><span id="more-4288"></span></p>
<h2 align="LEFT">Introduction</h2>
<p align="LEFT">Je vais passer très vite sur la présentation de Play!. Nombreux sont ceux qui l&#8217;ont déjà fait et mieux que je ne pourrais le faire. Si c&#8217;est la première fois que vous entendez le mot Play! (dans un article en français traitant de Java), je vous invite à vous rendre sur les liens suivants :</p>
<ul>
<li>
<p align="LEFT"><a href="http://www.playframework.org/" target="_blank">site officiel</a></p>
</li>
<li>
<p align="LEFT"><a href="http://www.touilleur-express.fr/2010/02/12/version-play-de-lapplication-zencontact-de-zenika/" target="_blank">article sur le touilleur-express.fr</a></p>
</li>
<li>
<p align="LEFT"><a href="http://www.zeroturnaround.com/blog/my-top-5-play-framework-features/" target="_blank">Les 5 meilleures features de Play! Framework</a> de Toomas Römer</p>
</li>
</ul>
<h2 align="LEFT">Le rechargement à chaud</h2>
<p align="LEFT">Avec Play!, en mode développement, on démarre notre serveur, on fait joujou avec l&#8217;application, on s&#8217;aperçoit qu&#8217;il y a un bug, on ouvre son IDE favori, on corrige le bug, on recompile, on redéploie et …. et NON NON NON ! On ne recompile pas et on ne redéploie pas ! On revient juste sur son navigateur, on rafraichit la page et hop magie, le bug a disparu (enfin peut-être) ! C&#8217;est juste simplement magique mais en informatique (comme dans la vraie vie en fait), la magie ça n&#8217;existe pas. Alors comment Play! s&#8217;y prend-t-il ? Sous le capot, Play! utilise le <a href="http://www.eclipse.org/jdt/core/" target="_blank">JDT Compiler d&#8217;Eclipse</a>, celui là même utilisé par l&#8217;IDE du même nom.</p>
<p align="LEFT">Déjà, au lancement de l&#8217;application, Play! va :</p>
<ul>
<li>
<p align="LEFT">scanner le répertoire de l&#8217;application à la recherche des fichiers sources .java</p>
</li>
<li>
<p align="LEFT">compiler ces fichiers à l&#8217;aide du JDT Compiler d&#8217;Eclipse</p>
</li>
<li>
<p align="LEFT">charger les classes en mémoire</p>
</li>
</ul>
<p align="LEFT">Ensuite, à chaque requête (et en mode développement), Play! essaye de détecter tout changement du code source.</p>
<p align="LEFT">En ce qui concerne des modifications apportées à des classes existantes, Play! conserve dans une HashMap l&#8217;ensemble des classes qu&#8217;il a compilées ainsi qu&#8217;un timestamp de la dernière compilation pour chacune des classes. Il suffit alors de comparer ce timestamp à la date de dernière modification du fichier correspondant pour savoir si Play! doit recompiler la classe et la recharger. Un petit coup de <span style="color: #333333;"><em>java.lang.Instrumentation.redefineClasses(classesDefinitions)</em></span> est alors nécessaire pour redéfinir les classes modifiées. Cette redéfinition de classe possède quelques limites :</p>
<ul>
<li>
<p align="LEFT">les instances existantes des classes redéfinies ne sont pas affectées</p>
</li>
<li>
<p align="LEFT">la redéfinition ne doit pas ajouter, supprimer ou renommer des attributs ou des méthodes, changer la signature des méthodes ou modifier l&#8217;héritage. Si c&#8217;est le cas, alors Play! va stopper et recharger l&#8217;application dans son intégralité.</p>
</li>
</ul>
<p align="LEFT">Maintenant, que fait Play! si l&#8217;on a ajouté ou supprimé des classes ? A la compilation des fichiers sources, Play! calcule un hash de la concaténation de toutes les classes compilées. Ainsi, il suffit de recalculer ce hash, de le comparer au précédent afin de savoir si un différentiel de classes existe. Si c&#8217;est le cas, alors encore une fois, Play! redémarre l&#8217;application dans son intégralité.</p>
<h2 align="LEFT">Le bytecode enhancement</h2>
<p align="LEFT">Quoi ? Play! fait du bytecode enhancement ? Mais où ? Pourquoi ?… au fait c&#8217;est quoi le bytecode enhancement ? Tentons de répondre à ces questions.</p>
<p align="LEFT">Pour commencer, où est-ce que Play! fait du bytecode enhancement ? Dans les classes de modèles par exemple. Dans Play!, on peut utiliser Hibernate (à travers JPA) pour persister nos objets Java dans une base de données. Il suffit d&#8217;annoter notre classe avec <span style="color: #333333;"><em>@javax.persistence.Entity</em></span>. Ensuite Play! fournit la classe Model qu&#8217;on peut étendre pour avoir un support out of the box de JPA :</p>
<pre class="brush: java; title: ; notranslate">
@Entity
public class Person extends Model {
    public String name;
    public Integer age;
}
</pre>
<p align="LEFT">L&#8217;arbre d&#8217;héritage de Person est : <span style="color: #333333;"><em>Person</em></span> &gt; <span style="color: #333333;"><em>Model</em></span> &gt; <span style="color: #333333;"><em>GenericModel</em></span> &gt; <span style="color: #333333;"><em>JPABase</em></span>. Grâce à cet héritage on a accès à des méthodes utilitaires du type find(), findAll(), findById(), count() :</p>
<pre class="brush: java; title: ; notranslate">Person.findAll() //va retourner toutes les entités de type Person</pre>
<p align="LEFT">Mais si on regarde bien l&#8217;implémentation de ces méthodes qui se trouvent dans la classe <span style="color: #333333;"><em>GenericModel</em></span>, voici ce qu&#8217;on observe pour la méthode findAll() :</p>
<pre class="brush: java; title: ; notranslate">
public static &amp;amp;lt;T extends JPABase&amp;amp;gt; List&amp;amp;lt;T&amp;amp;gt; findAll() {
    throw new UnsupportedOperationException(&amp;amp;quot;Please annotate your JPA model with @javax.persistence.Entity annotation.&amp;amp;quot;);
}
</pre>
<p align="LEFT">Pourtant lorsqu&#8217;on utilise la méthode statique findAll(), j&#8217;ai bien le résultat attendu et non pas une exception qui m&#8217;est remontée. C&#8217;est là qu&#8217;intervient l&#8217;enhancement de bytecode. Dans Play!, ce sont les rôles des classes de type <em><span style="color: #333333;">play.classloading.enhancers.Enhancer</span></em> que d&#8217;enhancer le bytecode.</p>
<p align="LEFT">Du coup répondons à la 2ème question, qu&#8217;est ce que l&#8217;enhancement de bytecode ? C&#8217;est tout simplement le fait de manipuler le bytecode, d&#8217;avoir la possibilité de définir une nouvelle classe au runtime et de modifier une classe lorsque la JVM la charge en mémoire. Plusieurs frameworks existent pour nous faciliter cette tache : <a href="http://cglib.sourceforge.net/" target="_blank">cglib</a>, <a href="http://asm.ow2.org/" target="_blank">ASM</a> ou encore <a href="http://www.javassist.org/" target="_blank">Javaassist</a>. Et c&#8217;est ce dernier qu&#8217;utilise Play!.<br />
Revenons à notre exemple et prenons la classe <span style="color: #333333;"><em>play.db.jpa.JPAEnhancer</em></span> qui va créer les méthodes des entités JPA de notre modèle.</p>
<pre class="brush: java; title: ; notranslate">
public class JPAEnhancer extends Enhancer {
    public void enhanceThisClass(ApplicationClass applicationClass) throws Exception {
        CtClass ctClass = makeClass(applicationClass)
        if (!ctClass.subtypeOf(classPool.get(&amp;amp;quot;play.db.jpa.JPABase&amp;amp;quot;))) {
            return;
        }

        // Enhance only JPA entities
        if (!hasAnnotation(ctClass, &amp;amp;quot;javax.persistence.Entity&amp;amp;quot;)) {
            return;
        }

        [...]

        // findAll
        CtMethod findAll = CtMethod.make(&amp;amp;quot;public static java.util.List findAll() { return getJPAConfig(&amp;amp;quot;+entityName+&amp;amp;quot;.class).jpql.findAll(&amp;amp;quot;&amp;amp;quot; + entityName + &amp;amp;quot;&amp;amp;quot;); }&amp;amp;quot;, ctClass);
        ctClass.addMethod(findAll);

        [...]
    }
}
</pre>
<ul>
<li>
<p align="LEFT">Ligne 1 à 2 :les classes qui étendent <span style="color: #333333;"><em>Enhancer</em></span> doivent implémenter la méthode <span style="color: #333333;"><em>enhanceThisClass().</em></span><span style="color: #333333;"><em><br />
ApplicationClass</em></span> est une classe de Play! et représente tout simplement une classe. Ses attributs notables sont par exemple javaFile (une référence au fichier source java), javaByteCode (le bytecode compilé), enhancedBytecode (le bytecode manipulé).</p>
</li>
</ul>
<ul>
<li>
<p align="LEFT">Ligne 3 : on instancie une <span style="color: #333333;"><em>javaassist.CtClass</em></span>. <span style="color: #333333;"><em>CtClass</em></span> est une classe du framework Javaassist et représente une classe.</p>
</li>
<li>
<p align="LEFT">Ligne 4 à 6 : on vérifie que cette classe hérite de <span style="color: #333333;"><em>Play.db.jpa.JPABase</em></span>. Sinon on ne fait rien</p>
</li>
<li>
<p align="LEFT">Ligne 9 à 11 : on vérifie que cette classe est annotée avec <span style="color: #333333;"><em>@javax.persistence.Entity</em></span>. Sinon on ne fait rien</p>
</li>
<li>
<p align="LEFT">Linge 16 à 17 : on crée la méthode<span style="color: #333333;"><em> findAll()</em></span> grâce à <span style="color: #333333;"><em>javaassist.CtMethod.make()</em></span>. Notez que cette méthode prend en paramètre une <span style="color: #333333;"><em>String</em></span> représentant du code Java (pas besoin de connaître le bytecode)</p>
</li>
</ul>
<p align="LEFT">La classe <span style="color: #333333;"><em>JPAEnhancer</em></span> va donc boucler sur toutes les entités et rajouter toutes ces méthodes au runtime. D&#8217;autres Enhancer existent dans Play! tels que <span style="color: #333333;"><em>PropertiesEnhancer</em></span> et <span style="color: #333333;"><em>ControllersEnhancer</em></span>. N&#8217;hésitez pas à y jeter un coup d&#8217;oeil, le code se trouve sur Github : <a href="https://github.com/playframework/play" target="_blank">https://github.com/Playframework/Play</a></p>
<h2 align="LEFT">Conclusion</h2>
<p align="LEFT">Nous avons ouvert le capot de Play! pour voir ce qu&#8217;il s&#8217;y cachait. L&#8217;utilisation du <a href="http://www.eclipse.org/jdt/core/" target="_blank">JDT Compiler d&#8217;Eclipse</a> permet de gérer la compilation à la volée et le rechargement à chaud de l&#8217;application. Néanmoins cette fonctionnalité a ses limites : dès qu&#8217;on ajoute/supprime des classes ou qu&#8217;on modifie « trop » (changement de signature, ajout de champ, d&#8217;annotation, …) une classe, toute l&#8217;application est rechargée ce qui peut être pénalisant si l&#8217;application prend du temps à démarrer.<br />
L&#8217;enhancement de bytecode, qui permet d&#8217;enrichir nos classes au runtime, fait appel à <a href="http://www.javassist.org/" target="_blank">Javassist</a> et donne encore plus à Play! ce côté « magique ». Par contre jouer avec le bytecode, c&#8217;est sympa mais après à débugger c&#8217;est tout de suite plus compliqué. Pour cela, vous pouvez utiliser <a href="http://java.decompiler.free.fr/?q=jdgui" target="_blank">JD-GUI</a> pour désassembler les .class précompilés par Play!.<br />
Plein d&#8217;autres choses se cachent sous le capot de Play!, n&#8217;hésitez pas à l&#8217;ouvrir et à laisser un commentaire si vous découvrez quelque chose d&#8217;intéressant.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/TnY7x1L7u1U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/</feedburner:origLink></item>
		<item>
		<title>L’héritage de Dennis Ritchie (1941-2011)</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/HjrUZWcaDS8/</link>
		<comments>http://blog.ippon.fr/2011/10/14/lheritage-de-dennis-ritchie/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 12:25:49 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Culture]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[UNIX]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4262</guid>
		<description><![CDATA[<p class="wp-caption-text">Dennis Ritchie (debout) et Ken Thompson devant un PDP-11 en 1972 Chez Bell.</p> <p>La semaine dernière, à l&#8217;occasion de la disparition de Steve Jobs, Geoffray évoquait l&#8217;héritage technologique que celui-ci avait apporté à la communauté des développeurs en général et Java EE en particulier. N&#8217;en déplaise aux intégristes (comme le Molah Stallman), aux grincheux <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/14/lheritage-de-dennis-ritchie/">L&#8217;héritage de Dennis Ritchie (1941-2011)</a></span>]]></description>
			<content:encoded><![CDATA[<div class="wp-caption aligncenter" style="width: 538px"><img class=" " src="http://blog-admin.wired.com/wiredenterprise/wp-content/uploads/2011/10/thompson-and-ritchie.jpg" alt="" width="528" height="422" /><p class="wp-caption-text">Dennis Ritchie (debout) et Ken Thompson devant un PDP-11 en 1972 Chez Bell.</p></div>
<p>La semaine dernière, à l&#8217;occasion de la disparition de Steve Jobs, <a title="Nous sommes tous, experts JavaEE, des enfants de Steve Jobs" href="http://blog.ippon.fr/2011/10/06/nous-sommes-tous-experts-javaee-des-enfants-de-steve-jobs/" target="_blank">Geoffray évoquait l&#8217;héritage technologique</a> que celui-ci avait apporté à la communauté des développeurs en général et Java EE en particulier. N&#8217;en déplaise aux intégristes (comme le <a href="http://www.zdnet.com/blog/hardware/richard-m-stallman-on-steve-jobs-im-not-glad-hes-dead-but-im-glad-hes-gone/15275" target="_blank">Molah Stallman</a>), aux grincheux ou aux incultes, cet apport est bien réel et la micro informatique de 2011 doit beaucoup à l&#8217;Apple II, au Macintosh ou à Next Step. Evidemment quasiment toutes ces &#8220;inventions&#8221; attribuées à Jobs ne sont que du recyclage d&#8217;idées mises au rebut par d&#8217;autres (<a href="http://en.wikipedia.org/wiki/PARC_(company)" target="_blank">Xerox pourrait aujourd&#8217;hui être à la place d&#8217;Apple ou Microsoft</a>), mais n&#8217;est-ce pas ce que tous les innovateurs font : aller plus haut en montant sur les épaules des géants qui les ont précédés ? Les épaules sur lesquelles Jobs est monté sont nombreuses, mais celles de Dennis Ritchie sont probablement les plus larges. <span style="direction: ltr;">Car si la micro-informatique doit beaucoup à Jobs, l&#8217;informatique en général doit encore plus à Dennis Ritchie qui nous a quitté le week-end dernier à l&#8217;age de 70 ans.</span><br />
 <span id="more-4262"></span></p>
<h2><span style="direction: ltr;">L&#8217;histoire</span></h2>
<h2></h2>
<p>A la fin des années 60, Ritchie travaillait aux <a href="http://en.wikipedia.org/wiki/Bell_Labs" target="_blank">Bell Laboratories</a> avec Ken Thompson au développement d&#8217;un nouvel OS : Unix. La première version du système fut écrite en assembleur, mais rapidement, ils réalisèrent qu&#8217;ils auraient besoin d&#8217;un langage de plus haut niveau pour développer la seconde version, notamment pour gérer les structures de données indispensables au différentes fonctions de l&#8217;OS. La première tentative en Fortran fut rapidement abandonnée et  Ritchie proposa de créer un  nouveau langage basé sur le language B créé par Thompson quelques années plus tôt.</p>
<p>Plusieurs légendes courrent au sujet du langage B : Thompson l&#8217;aurait nommé de la sorte d&#8217;après le nom de sa femme &#8220;Bonnie&#8221; ou moins romantique d&#8217;après le nom du language BCPL dont il était inspiré. J&#8217;avais pour ma part entendu raconté que le B était pour Bell. Toujours est-il que l&#8217;itération suivante s&#8217;appelerait logiquement le <strong>language C</strong>.</p>
<p>La langage B était interprété et comme Ritchie et Thompson avaient autant besoin de rapidité que de flexibilité, il décidèrent que le C serait compilé pour produire un code proche de la machine.</p>
<p>La première version du C n&#8217;était pas très différente de celle d&#8217;aujourd&#8217;hui quoiqu&#8217;un peu moins étoffée. Les types étaient déjà là ainsi que les fameuse structures de données (<code>struct{};</code>pour les intimes).</p>
<p>En résumé, C fut inventé pour pouvoir écrire un programme et ce programme était le noyau Unix, rien que ça&#8230;</p>
<p>En 1973, Ritchie publia un article scientifique sur le langage C et 5 ans plus tard, lui et son collègue Brian Kernighan (qui avait rédigé les premiers tutoriels sur C et qui força un peu la main de Ritchie) publièrent le classique &#8220;<a href="http://www.google.fr/url?sa=t&#038;source=web&#038;cd=5&#038;sqi=2&#038;ved=0CEkQFjAE&#038;url=http%3A%2F%2Fwww.inf.unideb.hu%2Fgrafika%2Feng%2Frtornai%2FKernighan_Ritchie_Language_C.pdf&#038;rct=j&#038;q=ritchie%20and%20kernighan&#038;ei=i_2XTpK5GoSi4gTQqaD4Aw&#038;usg=AFQjCNEe0iSo6C0EofmmKStH9SlQA3Jaqg" target="_blank">C programming language</a>&#8220;.</p>
<p>Bell ayant laissé ouvert et accessible le code source d&#8217;Unix, il se répandit avec le C dans les université comme une trainée de poudre pour atteindre le succès qu&#8217;on lui connait.</p>
<h2>L&#8217;héritage</h2>
<p>Est-il besoin d&#8217;expliquer l&#8217;importance de ces deux inventions sur ce blog ? Je ne pense pas (ou alors vous vous êtes vraiment perdu). Je résumerai juste par deux schéma trouvé sur le Web :</p>
<div id="attachment_4268" class="wp-caption aligncenter" style="width: 774px"><img class="size-full wp-image-4268 " title="Language_history_JRL" src="http://blog.ippon.fr/wp-content/uploads/2011/10/Language_history_JRL.png" alt="" width="764" height="717" /><p class="wp-caption-text">History of programming language (sur http://civilprogrammers.blogspot.com)/</p></div>
<p style="text-align: left;">dans ce premier schéma qui présente un aperçu des principaux langages par décénie et héritage, on voit bien que tous les langages utilisés aujourd&#8217;hui ont C comme ancêtre commun et gardons à l&#8217;esprit également que leur compilateur et/ou environnement d&#8217;éxécution ont été ou sont encore écrit en C.</p>
<div id="attachment_4267" class="wp-caption aligncenter" style="width: 1088px"><a href="http://blog.ippon.fr/wp-content/uploads/2011/10/Unix_history-simple.png"><img class="size-full wp-image-4267 " title="Unix_history-simple" src="http://blog.ippon.fr/wp-content/uploads/2011/10/Unix_history-simple.png" alt="" width="1078" height="695" /></a><p class="wp-caption-text">Historique simplifié d&#39;Unix (Wikipedia)</p></div>
<p style="text-align: left;">Ce deuxième schéma illustre une version simplifiée de la galaxie Unix. En parcourant ce diagramme on se rend compte qu&#8217;en dehors de Windows (qui reste donc l&#8217;OS grand public le plus propriétaire mais est malgré tout développé en C), tous les autres sont basés sur Unix. Les deux premières cases du haut c&#8217;est Ritchie, la troisième colonne c&#8217;est Steve Jobs (au passage on peut voir, que <a href="http://fr.wikipedia.org/wiki/Darwin_(informatique)" target="_blank">Darwin</a>, la version de BSD qui constitue la base de Mac OS X a son code ouvert (en fait open source mais avec une licence non reconnue par l&#8217;OSI)). Ainsi, si Jobs fait partie de l&#8217;héritage de beaucoup d&#8217;entre nous Ritchie fait partie de notre Héritage à tous.</p>
<p style="text-align: left;">C&#8217;est parfois bon de se sortir le nez le l&#8217;IDE pour se rappeler que nous avons une histoire. <span style="direction: ltr;">Car, Etre compétent ou expert techniquement ne suffit pas pour faire un bon développeur. La culture informatique doit également s&#8217;appuyer sur le passé. Comprendre la raison d&#8217;être des outils que nous utilisons et connaître leurs ancêtres est capital. Ca évite de dire des imbécilités ou de ré-inventer la roue.</span></p>
<p style="text-align: right;"><em><span style="direction: ltr;">&#8220;Celui qui ne connait pas l&#8217;histoire est condamné à la revivre&#8221;<br />
 K. Marx</span></em></p>
<pre class="brush: cpp; title: ; notranslate">
#include &amp;amp;lt;stdio.h&amp;amp;gt;

main(int argc, *char argv[]){
	if(argc!=1)
		exit(1);
	else {
		char *dennis=&amp;amp;quot;Dennis&amp;amp;quot;;
		char *world=&amp;amp;quot;World&amp;amp;quot;;
		if(strcmp(dennis,argv[0])==0) {
			printf(&amp;amp;quot;Hello %s says %s n&amp;amp;quot;,world,dennis);
			printf(&amp;amp;quot;Good bye %s says the %s n&amp;amp;quot;,dennis,world);
			exit(0);
		}
	}
</pre>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/HjrUZWcaDS8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/14/lheritage-de-dennis-ritchie/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/14/lheritage-de-dennis-ritchie/</feedburner:origLink></item>
		<item>
		<title>JPA : une magie qui se mérite (retour aux sources de JPA)</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/uSd_cZ38viw/</link>
		<comments>http://blog.ippon.fr/2011/10/11/jpa-une-magie-qui-se-merite-retour-aux-sources-de-jpa/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 13:25:05 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[CDI]]></category>
		<category><![CDATA[EJB 3.1]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JPA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3820</guid>
		<description><![CDATA[<p> Cet article fait partie d&#8217;une série sur les technologies incluses dans Java EE 6. Vous pouvez également lire l&#8217;article d&#8217;introduction de cette série : Java EE 6 ici et maintenant et celui sur JSF : JSF je t&#8217;aime, moi non plus</p> <p>L&#8217;une des technologies les plus populaires dans le monde Java EE est sans aucun <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/11/jpa-une-magie-qui-se-merite-retour-aux-sources-de-jpa/">JPA : une magie qui se mérite (retour aux sources de JPA)</a></span>]]></description>
			<content:encoded><![CDATA[<p><em> <img class="alignleft size-full wp-image-4700" title="DB_Magic" src="http://blog.ippon.fr/wp-content/uploads/2011/10/DB_Magic.png" alt="" width="191" height="163" />Cet article fait partie d&#8217;une série sur les technologies incluses dans Java EE 6. Vous pouvez également lire l&#8217;article d&#8217;introduction de cette série :<a title="Java EE 6 ici et maintenant !" href="http://blog.ippon.fr/2011/03/21/java-ee-6-ici-et-maintenant/" target="_blank"> Java EE 6 ici et maintenant</a> et celui sur JSF : <a title="JSF je t’aime, moi non plus" href="http://blog.ippon.fr/2011/04/27/jsf-je-taime-moi-non-plus/" target="_blank">JSF je t&#8217;aime, moi non plus</a></em></p>
<p><em></em>L&#8217;une des technologies les plus populaires dans le monde Java EE est sans aucun doute JPA. Il suffit de voir le nombre de livres et d&#8217;articles sur le sujet. Toutefois, si JPA est très répandu, il s&#8217;agit aussi de l&#8217;une des spécifications Java EE les moins bien maîtrisées par les développeurs et donc une source récurrente d&#8217;échecs des projets. Fort de ce constat je ne vais pas m&#8217;apesentir sur les nouveauté de JPA 2.0 dans ce post (en dehors de l&#8217;API criteria, celles-ci sont pluôt à la marge) pour me permettre de faire un retour aux sources sur JPA qui pourra profiter à certains. Ceux qui pensent maîtriser ces concepts pourraient être quand même intéressés par la fin de la&#8217;article qui traite de l&#8217;extended persistence context et de ses mérites.</p>
<p><span id="more-3820"></span></p>
<h2>Une &#8220;magie&#8221; complexe</h2>
<p>La popularité de JPA et les échecs que cette techno engendre sont probablement liées au mélange de magie, de concepts compliqués qu&#8217;elle camoufle et de dissimulation de ces concepts au sein de frameworks destinés à faciliter son utilisation. La magie et les raccourcis offert par Spring (entre autres) permettent  de se lancer dans l&#8217;utilisation de l&#8217;outil sans avoir besoin de trop comprendre les couches sous-jacentes. Lorsque l&#8217;on arrive dans des cas concrets qui posent des problèmes, une grande partie des développeurs désinvestissent l&#8217;outil en critiquant ses limitations sans chercher à creuser plus avant. Parce que JPA nous fait sortir du confort du code pour aller nous battre avec des notions parfois mal digérés de gestion de transaction et base de données, il reste une énigme pour beaucoup. Certains développeurs pensent que le concept d&#8217;ORM en général et JPA en particulier permet de négliger SQL et les mécanismes bas niveau d&#8217;échange avec la BDD en les ramenant au rang de technologies inférieures. En pensant cela ils commettent une erreur : JPA rend l&#8217;utilisation de ces technologies plus facile et puissante mais ne nous permet pas des les occulter totalement. Il est un facilitateur pas une technologie de substitution.</p>
<h2>Les 4 piliers de JPA</h2>
<div id="attachment_4205" class="wp-caption alignright" style="width: 424px"><img class="size-full wp-image-4205  " title="Schema_JPA" src="http://blog.ippon.fr/wp-content/uploads/2011/10/Schema_JPA.png" alt="" width="414" height="618" /><p class="wp-caption-text">Schema Global du fonctionnement de JPA</p></div>
<p>JPA s&#8217;inscrit autour de ces 4 notions fondamentales :</p>
<ul>
<li>Les entités</li>
<li>Les Persistence Units (au runtime on les manipulera via la classe PersistenceManagerFactory)</li>
<li>L&#8217;Entity Manager (ou persistence manager)</li>
<li>Les transactions</li>
</ul>
<p>Le schéma ci-contre illustre le fonctionnement de JPA et comment ces 4 éléments fonctionnent ensemble. Pour synthétiser :</p>
<ul>
<li>La<strong> Persistence Unit</strong> organise les meta données qui définissent le mapping entre les entités et la base</li>
<li>La <strong>Persistence Manager Factory</strong> récupère ces metas données de la Persistence Unit et les interprètent pour créer des Persistence Manager</li>
<li>Le <strong>Persistence Mangager</strong> gère les échanges entre le code et la base de donnée, c&#8217;est à dire le cycle de vie des <strong>entités</strong></li>
<li>Enfin, le travail du Persistence Manager est englobé dans une <strong>Transaction. </strong>Cette dernière peut éventuellement gérer les opérations de plusieurs Persistence Managers comme un traitement unitaire.</li>
</ul>
<p>Sans faire un cours exhaustif, il parait intéressant de faire un point sur les concepts clés liés à chacune de ces notions clés</p>
<h2>Les transactions</h2>
<p>Les transactions ne faisant pas stricto sensu partie de JPA, mais étant une composante indispensable au fonctionnement et donc à la compréhension de cette technologie, il est intéressant de commencer notre tour d&#8217;horizon par un rappel sur les concepts liés au transactionnel. Les transactions sont en effet aussi importantes que les mécanismes de persistence décrits plus loin. Sans elles les données échangées avec la base risqueraient d&#8217;être corrompues ou incohérente. C&#8217;est pourquoi il est important de vérifier que le périmètre des transactions soit bien défini lors de l&#8217;interaction de votre code avec la base de données.</p>
<p>L&#8217;objet de ce post n&#8217;est pas de faire un cours magistral sur le transactionnel, mais il me semble intéressant de rappeler quelques concepts de base puisqu&#8217;on parle de base de données et de persistence.</p>
<h3>Retour sur les différentes APIs transactionnelles</h3>
<p>Une transaction est un regroupement d&#8217;instructions SQL effectuant un traitement fonctionnel atomique (par exemple l&#8217;ajout d&#8217;un article dans un panier d&#8217;achat accompagné d&#8217;une décrémentation des stock pour la référence concernée). Ce regroupement est orchestré à l&#8217;aide d&#8217;instructions SQL dédiées comme : BEGIN, COMMIT ou ROLLBACK. Bien sûr, si on ne souhaite pas agir à si bas niveau on aura plutôt recours en Java à des API chargées d&#8217;automatiser la gestion des transactions pour nous. A cette fin, nous disposons de trois possibilités :</p>
<ul>
<li>Les transactions gérées par JDBC</li>
<li>Les transactions de type Resource-local</li>
<li>Les transactions gérées par  JTA</li>
</ul>
<div>JDBC est hors sujet pour cet article, gardons juste à l&#8217;esprit que les appels JDBC sont toujours exécutés par défaut dans une transaction. Vous pouvez décider de gérer vous-même le début et la fin de celle-ci avec setAutocommit(false) dans une java.sql.Connection puis lorsque vous le souhaitez, lancer un commit() ou un rollback() à partir de cette même connexion. La gestion de la transaction reste simpliste et ne permettra pas de l&#8217;utiliser correctement au niveau de l&#8217;ORM,  mais elle est présente.</div>
<div>Les transactions de type Resource-Local sont elles gérées à un niveau supérieur, celui du Persistence Manager. Ce type de transaction rencontré dans Spring est axé sur la base et permet de gérer le cycle de vie de la transaction au niveau de l&#8217;ORM et d&#8217;automatiser facilement certains comportement (Rollback systématique en cas d&#8217;exception par exemple).</div>
<div>Enfin, les transactions JTA sont gérées par le container Java EE et permettent de travailler avec plusieurs datasources facilement. JTA est une spec Java EE, aussi on sera amené à l&#8217;utiliser dès qu&#8217;on voudra effectuer des tâches transactionnelles avec les EJB.</div>
<div>Pour conclure, gardez à l&#8217;esprit que la base de données ouvre et ferme une transaction à chaque opération si aucune démarcation de transaction n&#8217;est spécifiée dans votre code. C&#8217;est ce qui s&#8217;appelle la transaction implicite. Donc quand vous négligez de gérer les transactions, la base s&#8217;en charge à votre place à chaque instruction SQL y compris les lectures. Le mécanisme de la transaction étant assez coûteux, il est donc important d&#8217;opérer cette démarcation de manière explicite ne serait-ce que pour améliorer les performances de vos lectures.</div>
<p><span style="font-size: 20px; font-weight: bold;">Les entité et le Mapping</span></p>
<p>JPA permet donc d&#8217;associer des objets dans notre code à des données dans une ou plusieurs bases. Les metas données du mapping (sous forme d&#8217;annotations) apportent la souplesse indispensable qui évite d&#8217;avoir un modèle de données mémoire totalement calqué que le modèle de donnée relationnel dans la base. On pourra ainsi gérer les colonnes associées à un champ (avec @column), créer une entité sur plusieurs tables (avec @SecondaryTable) ou gérer des champs ne devant pas être stockés (avec @Transient). Bien sûr la magie n&#8217;est pas absolue et il peut arriver un moment où votre structure de base de données est trop complexe pour assurer un mapping satisfaisant et où le choix de JPA peut commencer à être remis en cause. Une notion qu&#8217;il est capitale de comprendre est la persistance transitive : les associations entre entités avec les fameux @OneToOne, @OneToMany ou @ManyToMany. Le débutant en JPA rencontrera très vite ses premiers problèmes avec ces concepts. Soit parce que les associations déclencheront des chargements en cascade et créeront des grappes d&#8217;objets monstrueuses en mémoire, soit parce qu&#8217;il aura eu recours au mécanisme de Lazy loading qui peut devenir un cauchemar si on ne maîtrise pas le cycle de vie des entités et les concepts liés au transactionnel. On se reportera à la documentation des <a href="http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping">annotations JPA </a>d&#8217;Hibernate pour avoir une liste exhaustive des possibilités de mapping disponibles dans JPA 2.</p>
<h2>La Persistence Unit</h2>
<p>C&#8217;est le point de départ du moteur JPA. Elle permet de lister les entités à manager et la façon dont elles sont mappées vers la base. Elle indique également le type de transaction utilisée lors des échanges avec la base. Elle est constituée à partir de trois parties :</p>
<ol>
<li>Les meta données sur les entités (sous forme d&#8217;annotations, elles peuvent être surchargées par du XML)</li>
<li>Le descripteur de la Persistence Unit : le fichier de configuration Peristence.xml qui permet de configurer la connexion à la base et la nature des transactions et des paramètres spécifiques à l&#8217;implémentation de JPA utilisée.</li>
<li>La Persistence Manager Factory : Objet au runtime représentant la configuration complète de la persistence unit. Cette factory permet de créer un ou plusieurs persistence manager fournissant les services nécessaires à la gestions des entités</li>
</ol>
<p>Mais n&#8217;oublions pas la plomberie JDBC sous JPA et la fameuse datasource, point de départ à la connexion vers la base&#8230;</p>
<h3>JDBC et pool de connexion</h3>
<p>JDBC reste donc la brique de base pour interagir avec la base de données et comme a priori votre application effectuera plusieurs requêtes simultanément vers la base vous avez besoin de fournir à JPA un pool de connexions JDBC. Dans un container Java EE tout cela se fait en général en définissant une data source, soit via un fichier (comme dans Glassfish ou JBoss) soit via une interface d&#8217;admin (comme dans Websphere). Cette data source est ensuite appelée via JNDI dans le fichier persistence.xml. La datasource consitue donc un pool de connexions JDBC. son rôle est de pouvoir vous fournir une connexion déjà &#8220;prête à l&#8217;emploi&#8221; (ouverte) quand vous voulez requêter la base et de faire le ménage quand un échange s&#8217;est mal passé (timeout, connexion mal fermée, etc&#8230;). Ce pool est fourni avec votre serveur d&#8217;application. exemple de data source JBoss :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;datasources&gt;
	&lt;local-tx-datasource&gt;
		&lt;jndi-name&gt;DefaultDS&lt;/jndi-name&gt;
		&lt;connection-url&gt;jdbc:hsqldb:/Data/hypersonic/localDB&lt;/connection-url&gt;
		&lt;driver-class&gt;org.hsqldb.jdbcDriver&lt;/driver-class&gt;
		&lt;user-name&gt;sa&lt;/user-name&gt;
		&lt;password/&gt;
		&lt;min-pool-size&gt;5&lt;/min-pool-size&gt;
		&lt;max-pool-size&gt;20&lt;/max-pool-size&gt;
		&lt;idle-timeout-minutes&gt;0&lt;/idle-timeout-minutes&gt;
	&lt;/local-tx-datasource&gt;
&lt;/datasources&gt;
</pre>
<p>La plupart des containers légers permettent de faire la même chose, quasiment tous fournissent un gestionnaire de Pool JDBC. Pour les utilisateurs de Spring, il y a dans le framework de quoi déclarer un bean Datasource auquel on pourra adjoindre le pool JDBC de son choix. Je vous laisse le soin de lire cette <a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html">doc croustillante</a> qui fourmille de trolls vintage sur Java EE, (heu&#8230; pardon J2EE). Toute pique mise à part, Spring sera très utile pour gérer cet aspect ainsi que les problématiques transactionnelles dans un environnement Java SE, l&#8217;alternative étant de créer ce pool dans votre code. Quoiqu&#8217;il en soit, on se gardera bien de définir sa connexion JDBC dans le fichier persistence.xml car celle-ci ne permet pas (en standard) de choisir la nature du pool utilisé. Ainsi si votre implémentation JPA est hibernate, déclarer votre connexion JDBC dans persistence.xml vous amènera à utiliser le pool de connexion Hibernate par défaut qui n&#8217;est pas recommandé en production. Des propriétés propres à Hibernate permettent dans persistence.xml d&#8217;activer d&#8217;autres gestionnaires de pool fournis par le framework comme C3PO ou Proxool. Ces gestionnaires sont également peu recommandés, on essaiera d&#8217;utiliser en priorité le gestionnaire de pool du serveur d&#8217;application.</p>
<h3>Le fichier persistence.xml</h3>
<p>Là non plus je ne rentrerai pas dans les détails de la configuration du fichier de persistence. Je donnerai juste deux versions de la même unité de persistence. L&#8217;une avec une gestion du transactionnel et de la datasource au niveau container :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;persistence version=&quot;2.0&quot;
xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;&gt;
        &lt;persistence-unit name=&quot;myPu&quot;&gt;
		&lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
		&lt;jta-data-source&gt;java:/DefaultDS&lt;/jta-data-source&gt;
		&lt;properties&gt;
                        &lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.HSQLDialect&quot; /&gt;
		&lt;/properties&gt;
	&lt;/persistence-unit&gt;
&lt;/persistence&gt;
</pre>
<p>La persistence unit définie dans ce fichier exploite la Datasource définie plus haut. Elle utilise Hibernate comme implementation JPA d&#8217;où la propriété hibernate.dialect propre à cette implémentation. La deuxième PU, définie une connexion et un pool JDBC géré en local dans l&#8217;application (en l&#8217;occurence par Hibernate)</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;persistence version=&quot;2.0&quot;
	xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
	xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;&gt;
	&lt;persistence-unit name=&quot;myPu&quot; transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;
	&lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
		&lt;properties&gt;
                        &lt;property name=&quot;javax.persistence.jdbc.driver&quot; value=&quot;org.hsqldb.jdbcDriver&quot; /&gt;
                        &lt;property name=&quot;javax.persistence.jdbc.user&quot; value=&quot;se&quot; /&gt;
			&lt;property name=&quot;javax.persistence.jdbc.password&quot; value=&quot;&quot; /&gt;
                        &lt;property name=&quot;javax.persistence.jdbc.url&quot; value=&quot;jdbc:hsqldb:/Data/hypersonic/localDB&quot; /&gt;
			&lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.HSQLDialect&quot; /&gt;
		&lt;/properties&gt;
	&lt;/persistence-unit&gt;
&lt;/persistence&gt;
</pre>
<p>Spring propose une configuration en partie propriétaire dans son fichier de configuration pour la Datasource, puis dans persistence.xml, ce qui n&#8217;est pas toujours très clair. Comme on parle ici de Java EE , on se reportera à <a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html" target="_blank">la documentation du Framework printanier qui fait pousser le XML</a>,  pour plus d&#8217;informations sur ce dernier.</p>
<h3>La gestion des persistence managers</h3>
<p>La aussi il y a plusieurs possibilités pour gérer le cycle de vie des persistence manager JPA :</p>
<ol>
<li>Géré par l&#8217;application dans le code en créant des instances via le Persistence Manager Factory</li>
<li>Géré par un framework du type Spring, Seam  (si on on est sur un serveur léger). Cette solution est techniquement équivalente à la première mais vous décharge d&#8217;avoir à gérer les instanciations</li>
<li>Dans le cas d&#8217;un serveur Java EE, ceux-ci sont gérés par le container ce qui permet par exemple de partager les mêmes persistence units entre plusieurs war au sein d&#8217;un même EAR</li>
</ol>
<div>En fonction de qui gère les persistences manager (le Serveur ou l&#8217;application) on pourra utiliser différents  modes transactionnels comme on l&#8217;a vu ci-dessus.</div>
<div>Techniquement cette gestion revient à savoir qui bootstrap JPA en transformant la persistent unit en persistence manager factory.</div>
<h3>Le persistence manager Factory</h3>
<p>Le chargement de la persistence unit (par le serveur ou l&#8217;application) donne lieu à la création d&#8217;un objet immuable : le persistence manager factory (ou entity manager factory) qu&#8217;on va récupérer automatiquement dans un context Java EE  via :</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
@PersistenceUnit
private EntityManagerFactory pu;
</pre>
<p>si vous devez le faire à la main (sans un container ou framework qui le fait pour vous) cela donnera</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory(&quot;my_pu&quot;);
</pre>
<p>Le code précédent bootstrap JPA et déclenche la lecture du Persistence Context &#8220;my_pu&#8221;. Ce code est comme on s&#8217;en doute extrêmement coûteux, aussi on fera en sorte de ne lancer qu&#8217;au démarrage de l&#8217;application. On travaillera rarement avec l&#8217;EntityManagerFactory et on préferera demander au container directement un EntityManager.</p>
<h2>Au coeur du Persistence manager</h2>
<p>Le persistence manager (ou entity manager, la littérature utilise l&#8217;un ou l&#8217;autre) est l&#8217;API responsable de gérer le cycle de vie des entités JPA. Au delà des échanges explicites avec la base de données,  il est en charge de vérifier l&#8217;état des entités qu&#8217;il manage pour propager les modifications automatiquement vers la base et gérer le cache  de niveau 1 permettant d&#8217;optimiser les accès SQL. Pour l&#8217;obtenir à partir du container on utilisera</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
@PersistenceContext
private EntityManager em;
</pre>
<p>si on veut le faire à la main (après avoir récupéré l&#8217;entityManagerFactory avec le code &#8216;&#8221;à la main&#8221; précédent):</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
EntityManager em=entityManagerFactory.createEntityManager();
</pre>
<p>Dans ce cas gardez à l&#8217;esprit que vous devrez gérer le cycle de vie de l&#8217;entityManager vous-même.</p>
<p>Une fois cela fait, nous parvenons enfin au coeur de JPA avec le Persistence Manager dont les responsabilités sont les suivantes :</p>
<ul style="list-style-type: circle;">
<li><strong>Gérer les instances des entités</strong> : l&#8217;API du Persistence manager permettent de gérer les entités. Cette API dispose des méthodes pour créer, chercher, requêter, mettre à jour et détruire les instances des entités. Ce faisant, il gère les quatre états possibles pour chaque objet entité : transient, persisté, détaché et détruit. (c.f. le schéma sur le cycle de vie ci-dessous)</li>
<li><strong>Maintenir le context de persistance (Pesistence Context en VO)</strong> : Le contexte de persistance correspond à un cache mémoire des objets entité qui ont été chargés via le persistence manager. C&#8217;est le point d&#8217;entrée pour l&#8217;optimisation des performances dans la technologie JPA. vous le connaissez probablement aussi sous le nom de <strong>cache de premier niveau. </strong>Notez aussi que le terme Persistence Context est aussi parfois utilisé à la place de Persistence Manager (ou Entity Manager <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ) bien que ce ne soit pas exactement la même chose.</li>
<li><strong>Réaliser des contrôles automatiques des objets managés</strong> (dirty checks dans le texte) : l&#8217;état des objets présents dans le contexte de persistance est automatiquement surveillé pendant toute la durée de vie de ce dernier. Quand un événement de &#8220;flush&#8221; intervient sur le persistence manager, les modifications detectées par ce mécanisme sont poussées vers la base de données  sous forme de de commandes SQL Lorsque une instance d&#8217;entité entre dans l&#8217;état &#8220;détaché&#8221; (detached) ses modifications ne sont plus surveillées.</li>
</ul>
<div><img class="alignright" title="cycle_de_vie" src="http://blog.ippon.fr/wp-content/uploads/2011/10/cycle_de_vie.png" alt="" width="313" height="249" />Le persistence manager travaille à plus haut niverau que le SQL. Grace aux annotations de mapping, il comprend que les données transitant depuis la base ont une structure objet (l&#8217;entité) et que cette structure à un cycle de vie (voir ci-contre).</div>
<div>Les instances d&#8217;entité débutent leur vie comme étant non managées (stade transient), puis elles deviennent managées ce qui leur permet d&#8217;être synchronisées avec la base de données. Si elles sont détruites cette synchronisation devient une suppression. Lorsqu&#8217;elles sont supprimées de la base ou que le persistence context est fermé elles passent à l&#8217;état détaché et ne sont plus gérées par le persistence manager.</div>
<div>L&#8217;atout majeur du persistence manager est probablement le persistence context qui donne tout son intérêt à JPA. En effet, il peut optimiser ses échanges avec la base de données en les évitant lorsqu&#8217;il detecte qu&#8217;une instance demandée est déjà dans le persistence context (souvenez-vous, c&#8217;est le cache de niveau 1). Plus intéressant encore: le persistence manager vous garantit l&#8217;unicité de chaque instance d&#8217;entité présente dans le persistence context grâce à son identifiant et son type. Conséquence : l&#8217;entity manager peut surveiller l&#8217;état des instances des entités et peut propager leurs modifications vers la base éventuellement même en cascade pour les entités ou collections associées. En outre, tant que le persistence manager reste ouvert, il est possible d&#8217;effectuer des chargements tardifs (le fameux Lazy Loading) de collections associées sans avoir à requêter le base.</div>
<div>Ces fonctionnalités font tout l&#8217;intérêt du persistence manager et le rendent bien plus riche que la simple couche d&#8217;accès aux données à laquelle on l&#8217;assimile trop souvent.</div>
<div>Cela dit pour pouvoir tirer partie de ces fonctionnalités il est important de savoir (et pouvoir) gérer le scope du persistence context.</div>
<h3>Scoper le persistence context : une approche trop souvent négligée</h3>
<p>Le persistence Manager (et par association le contexte de persistence) est souvent victime d&#8217;une méconnaissance des développeurs qui le pensent lié à la connexion avec la base ou à la durée de vie d&#8217;une transaction.  Cette erreur provient principalement des architectures stateless dont le framework Spring a fait la promotion depuis ses débuts. A cause de cette vision simpliste et restrictive, beaucoup de développeurs considèrent comme une mauvaise pratique (voire ignorent complètement) le fait de laisser ouvert le persistence manager pour une durée supérieure à une transaction ou une requête HTTP et correspondant à un cas d&#8217;utilisation de leur application. En fait le persistence manager est bien plus polyvalent que l&#8217;approche hyper partielle et pauvre prêchée par Spring. Oui, il peut être stateful (le mot est lâché), et donc laissé ouvert le temps de réaliser un cas d&#8217;utilisation complet (plusieurs écrans et actions de l&#8217;utilisateur). Contrairement à ce qu&#8217;on pourrait craindre, le persistence manager ne laissera pas la connexion vers la base ouverte tout le temps de sa durée de vie mais saura se reconnecter de manière transparente si le besoin s&#8217;en fait sentir.</p>
<p>Le mauvais réglage du scoping du Persistence Manager est la cause principale des critiques adressées à JPA. Avoir recours à des outils ou patterns qui ne permettent que de l&#8217;associer à la requête HTTP ou à la transaction en cours amène les développeurs à bricoler des solutions de contournement qui sont autant de mauvaises pratiques : comme le hideux pattern <a href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/support/OpenSessionInViewInterceptor.html" target="_blank">Open Session in view</a>, une redéfinition du mapping JPA pour mettre en Fetch.Eager des associations qui auraient du rester lazy ou du requetage HSQL en pagaille pour  récupérer la grappe d&#8217;objets nécessaire pour traiter la requête et ses suites (comme des échanges Ajax par exemple). Comme je l&#8217;ai écrit dans de précédents articles, si Spring a été un apport précieux pour la mise en place de bonnes pratiques en terme d&#8217;architecture, on atteint là ses limites qui sont liées à des choix idéologiques de ses concepteurs qui n&#8217;ont autorisé pendant très longtemps qu&#8217;une approche purement stateless des architectures.</p>
<p>Ce qu&#8217;on doit faire pour que le persistence manager ait une durée de vie supérieure à la requête HTTP, c&#8217;est le gérer en mode stateful. C&#8217;est cette approche qui permettra de gérer un scope conversation comme le fait Seam 2 depuis 2006 et comme le propose CDI en standard dans Java EE 6. Cette approche nécessite de faire attention où le persistence manager est stocké, car il ne doit pas être dans un scope partagé (scope application par exemple) puisqu&#8217;il n&#8217;est pas thread safe. Voyons comment Java EE 6 gère ce mécanisme.</p>
<h2>Le peristence context étendu</h2>
<p>Depuis Java EE 5,  nous avons la possibilité de créer un persistence context étendu. Comme dit, plus haut, c&#8217;est un persistence context qui reste actif au dela de la transaction (mode par défaut du persistence context).</p>
<p>Avoir recours à un Persitence context étendu :</p>
<ul>
<li>Permet de gérer proprement le lazy loading des entités ou collections associées</li>
<li>Evite d&#8217;avoir à merger des entités détachées pour les synchroniser avec la base</li>
<li>Vous assure de n&#8217;avoir qu&#8217;une seule référence à un objet pour un id d&#8217;entité donné</li>
<li>Fonctionne avec les mécanisme d&#8217;Optimistic Locking pour supporter les unités de traitement à durée de vie longue (l&#8217;annotation JPA @Version est très utile pour ce dernier point)</li>
</ul>
<p>Le persistence context étendu doit donc résider dans un scope stateful, et non partagé. La session ou la conversation pourraient faire l&#8217;affaire, mais la gestion de son cylce de vie resterait un peu fastidieuse. C&#8217;est pourquoi, la meilleure place pour le gérer est de le placer au sein d&#8217;un EJB Session Sateful (Stateful Session Bean ou SFSB).</p>
<p>On ne va pas trop entrer dans les détails des EJB ici (je garde cela pour mon prochain post), il faut juste savoir qu&#8217;un SFSB est géré par un container spécifique qui n&#8217;a rien à voir au conteneur servlet. Notre Bean a donc un cycle de vie indépendant des scopes servlet mais pourra être manipulé depuis ces fameux scopes soit en étant injecté via @EJB, soit, encore mieux en étant injecté ou directement utilisé via CDI. Le persistence context étendu ainsi utilisé ne sera fermé que lorsque le SFSB sera recyclé.  Nous reviendrons sur tout ça dans un post ultérieur. Pour le moment voici un petit exemple que j&#8217;ai emprunté à <a href="http://www.adam-bien.com/roller/abien/entry/building_perfect_anti_facades_almost" target="_blank">Adam Bien </a>.</p>
<pre class="brush: java; highlight: [1,2,3,4,7,31]; title: ; notranslate">
@Stateful
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Named
@ConversationScoped
public class OrderGateway{

  @PersistenceContext(type=PersistenceContextType.EXTENDED)
  EntityManager em;

  private Load current;

  public Load find(long id){
    current = em.find(Load.class, id);
    return current;
  }

  public Load getCurrent() {
    return current;
  }

  public void create(Load load){
    em.persist(load);
    current = load;
  }

  public void remove(long id){
    Load ref = em.getReference(Load.class, id);
    em.remove(ref);
  }

  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  public void save(){
    //nothing to do
  }
}
</pre>
<p>La ligne 1 fait de notre classe un SFSB (EJB Stateful), la deuxième ligne désactive le support transactionnel sur l&#8217;EJB en question, la ligne 3 fait que la version CDI de cet EJB pourra être utilisé dans une page JSF via l&#8217;expression language. Et la quatrième stock le composant CDI dans le scope conversation.</p>
<p>On voit que dans le SFSB on inject un entity manger étendu en ligne 7. Diverses méthodes permettent de chercher, créer et supprimer des entités et en ligne 31 on annote une methode save() avec l&#8217;attribut REQUIRES_NEW qui va créer une transaction et la fermer dans la foulée commitant ainsi toutes les modifications effectuées (rappelez-vous l&#8217;entity manager empile les  modification jusqu&#8217;à ce qu&#8217;une transaction lui permette de pousser ces modifications). Ce scénario simplifié permet d&#8217;imaginer les possibilités offertes par l&#8217;extended persistence context.</p>
<h2>Conclusion</h2>
<p>L&#8217;empilement de technologies masquées par JPA  constitue à la fois l&#8217;origine de son succès et la principale raison des critiques que la spécification essuie. Les cas d&#8217;utilisations restreints mis en avant par Spring en ne permettant que de concevoir des architecture stateless pour les services, sont également à l&#8217;origine de pas mal de galères sur JPA. Pour utiliser cette technologie au mieux je ne vous donnerai que 3 conseils :</p>
<ul>
<li>Apprenez Java EE 6, ça ouvre des horizons.</li>
<li>Si vous ne pouvez pas travailler avec Java EE, utilisez Seam 2 qui marche très bien sur des conteneurs léger type Tomcat et qui reprend ces concepts.</li>
<li>Lisez la doc de JPA (vous pouvez commencer par <a href="http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/" target="_blank">ici</a>) et non pas la version Springifiée de celle-ci.</li>
</ul>
<h3><em>Bibliographie </em></h3>
<p><em>Cet Article s&#8217;appuie sur les livres suvants</em></p>
<ul>
<li><em><a href="http://www.manning.com/dallen/" target="_blank">Seam In Action</a> écrit par Dan Allen</em></li>
<li><em><a href="http://www.manning.com/bauer2/" target="_blank">Java Persistence with Hibernate</a> par Christian Bauer et Gavin King</em></li>
<li><em><a href="http://press.adam-bien.com/" target="_blank">Real World Java EE Patterns, Rethinking the best practices</a>  et  <a href="http://press.adam-bien.com/" target="_blank">Real World Java EE Night Hacks</a> par Adam Bien</em></li>
</ul>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/uSd_cZ38viw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/11/jpa-une-magie-qui-se-merite-retour-aux-sources-de-jpa/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/11/jpa-une-magie-qui-se-merite-retour-aux-sources-de-jpa/</feedburner:origLink></item>
	</channel>
</rss>

