<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.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>Excilys Labs</title>
	
	<link>http://labs.excilys.com</link>
	<description />
	<lastBuildDate>Tue, 23 Apr 2013 12:53:18 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ExcilysLabs" /><feedburner:info uri="excilyslabs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>AngularJS et Spring Data MongoDB</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/g5JocVCw9_M/</link>
		<comments>http://labs.excilys.com/2013/04/23/angularjs-et-spring-data-mongodb/#comments</comments>
		<pubDate>Tue, 23 Apr 2013 12:53:18 +0000</pubDate>
		<dc:creator>Rémy Francillette</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3991</guid>
		<description><![CDATA[Si vous vous êtes intéressés par AngularJS et MongoDB, allez faire un tour sur ce repository : https://github.com/rfrancillette/shopping-list. Vous y trouverez une petite démonstration de l’intégration de ces deux technologies pour créer une application de liste de courses. Coté serveur, &#8230; <a href="http://labs.excilys.com/2013/04/23/angularjs-et-spring-data-mongodb/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p dir="ltr" style="text-align: center"><img class="aligncenter" alt="" src="https://raw.github.com/rfrancillette/shopping-list/master/screenshots/screenshot.png" width="643" height="233" /></p>
<p dir="ltr">Si vous vous êtes intéressés par AngularJS et MongoDB, allez faire un tour sur ce repository : <a href="https://github.com/rfrancillette/shopping-list">https://github.com/rfrancillette/shopping-list</a>. Vous y trouverez une petite démonstration de l’intégration de ces deux technologies pour créer une application de liste de courses.</p>
<p dir="ltr">Coté serveur,  grâce Spring Data, Spring MVC et Jackson, l’application expose des données stockées dans MongoDB sous forme de web services REST. Coté client, il y a peu d&#8217; HTML5, de Bootstrap et AngularJs avec sa gestion des ressources REST.</p>
<p dir="ltr">Bonne lecture</p>
<p dir="ltr">Et pour plus d’infos :</p>
<ul>
<li><span style="line-height: 16px"><a href="http://angularjs.org/">http://angularjs.org/</a><br />
</span></li>
<li><a href="http://www.springsource.org/spring-data/mongodb">http://www.springsource.org/spring-data/mongodb</a></li>
</ul>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2013/04/23/angularjs-et-spring-data-mongodb/" data-text="AngularJS et Spring Data MongoDB"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2013/04/23/angularjs-et-spring-data-mongodb/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2013%2F04%2F23%2Fangularjs-et-spring-data-mongodb%2F&amp;title=AngularJS%20et%20Spring%20Data%20MongoDB" id="wpa2a_2"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/g5JocVCw9_M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2013/04/23/angularjs-et-spring-data-mongodb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2013/04/23/angularjs-et-spring-data-mongodb/</feedburner:origLink></item>
		<item>
		<title>Eclipse ResourceBundle Editor Plugin</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/rHu2loVKnv8/</link>
		<comments>http://labs.excilys.com/2012/12/26/eclipse-resourcebundle-editor-plugin/#comments</comments>
		<pubDate>Wed, 26 Dec 2012 09:13:06 +0000</pubDate>
		<dc:creator>Baptiste Pagnier</dc:creator>
				<category><![CDATA[Non classé]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3904</guid>
		<description><![CDATA[Il est souvent fastidieux de gérer plusieurs fichiers ResourceBundle pour internationaliser un projet : - Les clés ne sont pas triées, - Il est difficile de savoir quel message est présent pour quelle langue, quelles sont les clés manquantes ou &#8230; <a href="http://labs.excilys.com/2012/12/26/eclipse-resourcebundle-editor-plugin/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il est souvent fastidieux de gérer plusieurs fichiers ResourceBundle pour internationaliser un projet :<br />
- Les clés ne sont pas triées,<br />
- Il est difficile de savoir quel message est présent pour quelle langue, quelles sont les clés manquantes ou en double,<br />
- On doit jongler entre les fichiers à chaque insertion / modification / suppression de clé,<br />
- &#8230;<span id="more-3904"></span></p>
<h3>Que fait l&#8217;outil ?</h3>
<p>Eclipse ResourceBundle Editor est un petit plugin très simple qui facilite beaucoup cette tâche !<br />
Il permet de tout faire dans un même écran, et possède de nombreuses fonctionnalités très pratiques :<br />
- Les clés sont triées (ordre alphabétique ou par hiérarchie de groupe)<br />
- La recherche est simple (possibilité de filtrer les clés affichées)<br />
- Les clés manquantes ou en double sont marquées d&#8217;un petit icone,<br />
- Il est possible de renommer et de supprimer des groupes de clés,<br />
- Les caractères non ASCII sont convertis vers de l&#8217;unicode<br />
- Les fichiers sont réorganisés proprement<br />
- &#8230;</p>
<p><a href="http://labs.excilys.com/2012/12/26/eclipse-resourcebundle-editor-plugin/screenshot005/" rel="attachment wp-att-3950"><img class="alignnone size-medium wp-image-3950" alt="ScreenShot005" src="http://labs.excilys.com/wp-content/uploads/2012/12/ScreenShot005-300x194.jpg" width="300" height="194" /></a></p>
<p>De plus l&#8217;outil est assez personnalisable, via le menu des préférences Eclipse.</p>
<p>Ce plugin n&#8217;avait pas eu de mise à jour depuis plus de 5 ans, mais une nouvelle version est sortie ce mois-ci !<br />
Elle corrige de nombreux bugs, améliore les performances et ajoute des fonctionnalités bien pratiques comme par exemple le filtre sur les propriétés affichées.</p>
<h3>Installation</h3>
<p>Pour l&#8217;installer c&#8217;est très simple, il suffit de télécharger le plugin en <a href="http://sourceforge.net/projects/eclipse-rbe/files/latest/download">cliquant ici</a>, puis de déplacer le contenu du .zip dans le dossier /plugins/ de votre installation Eclipse (C:/Program Files/eclipse/plugins/ par exemple).<br />
Un redémarrage d&#8217;Eclipse, et c&#8217;est terminé !</p>
<p>Il fonctionne sur les version 2.x, 3.x et 4.x d&#8217;Eclipse.</p>
<p>Petite remarque : dans les préférences, certains messages ne sont pas traduits, et la clé est affichée à la place du message, &#8230; amusant pour un outil d&#8217;édition de ResourceBundle ! <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Site officiel : <a href="http://eclipse-rbe.sourceforge.net/index.htm">http://eclipse-rbe.sourceforge.net/index.htm</a></p>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/12/26/eclipse-resourcebundle-editor-plugin/" data-text="Eclipse ResourceBundle Editor Plugin"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/12/26/eclipse-resourcebundle-editor-plugin/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F12%2F26%2Feclipse-resourcebundle-editor-plugin%2F&amp;title=Eclipse%20ResourceBundle%20Editor%20Plugin" id="wpa2a_4"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/rHu2loVKnv8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/12/26/eclipse-resourcebundle-editor-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/12/26/eclipse-resourcebundle-editor-plugin/</feedburner:origLink></item>
		<item>
		<title>Smock, ou comment tester un webService</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/1R40jMi6TTE/</link>
		<comments>http://labs.excilys.com/2012/12/12/smock-ou-comment-tester-un-webservice/#comments</comments>
		<pubDate>Wed, 12 Dec 2012 13:31:42 +0000</pubDate>
		<dc:creator>Audrey Romanet</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[librairie]]></category>
		<category><![CDATA[Smock]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3892</guid>
		<description><![CDATA[Dans le cadre de ma mission actuelle, je devais réécrire quelques webservices qui utilisaient de vieilles librairies pas forcement adaptées au mapping XML (Castor, en l&#8217;occurence&#8230;). Sauf que, bien sûr, je n&#8217;avais pas le droit de tout casser (quelle surprise &#8230; <a href="http://labs.excilys.com/2012/12/12/smock-ou-comment-tester-un-webservice/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Dans le cadre de ma mission actuelle, je devais réécrire quelques webservices qui utilisaient de vieilles librairies pas forcement adaptées au mapping XML (Castor, en l&#8217;occurence&#8230;).<br />
Sauf que, bien sûr, je n&#8217;avais pas le droit de tout casser (quelle surprise !), et j&#8217;ai donc dû m&#8217;assurer que le contrat du webservice n&#8217;était pas rompu, et en particulier que le mapping XML du webservice mappait  toujours les classes de la même façon. Je vais donc vous parler d&#8217;une librairie bien utile pour cela : <a href="https://code.google.com/p/smock/" title="Smock" target="_blank">Smock</a>.<br />
<span id="more-3892"></span></p>
<p>Smock teste les &#8220;entrées/sorties&#8221; d&#8217;un webservice : on lui donne un XML en entrée, il l&#8217;envoie au webservice, et il nous rend le XML de sortie. On peut donc s&#8217;assurer que l&#8217;interface du webservice n&#8217;est pas modifiée.</p>
<p>On se retrouve au final à écrire quelque chose d&#8217;assez simple :</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">net.javacrumbs.smock.http.cxf.server.servlet.AbstractSmockServerTest</span><span style="color: #339933;">;</span><br />
<br />
@RunWith<span style="color: #009900;">&#40;</span>SpringJUnit4ClassRunner.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><br />
@ContextConfiguration<span style="color: #009900;">&#40;</span>locations <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&quot;classpath:test-appContext.xml&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> WebServiceTest <span style="color: #000000; font-weight: bold;">extends</span> AbstractSmockServerTest <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; @Value<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;wsPath&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #003399;">String</span> wsPath<span style="color: #339933;">;</span><br />
<br />
&nbsp; @Test<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> getPersonByUid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; sendRequestTo<span style="color: #009900;">&#40;</span>wsPath, withMessage<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;GetPersonByUid/GetPersonByUidRequest.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; .<span style="color: #006633;">andExpect</span><span style="color: #009900;">&#40;</span>message<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;GetPersonByUid/GetPersonByUidResponse.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Le webservice est déclaré dans la config Spring comme d&#8217;habitude, ce qui permet de soit faire un test d&#8217;intégration vraiment complet, soit mocker les services et tester uniquement la partie &#8220;mapping&#8221; du webservice.</p>
<p>On a également la possibilité d&#8217;écrire des requêtes et/ou réponses XML modulables, en utilisant le GroovyTemplateProcessor.</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sendRequestTo<span style="color: #009900;">&#40;</span>WS_PATH,<br />
&nbsp; withMessage<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;GetPersonByUid/GetPersonByUidRequest.xml&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; .<span style="color: #006633;">withParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;uid&quot;</span>, uid<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; .<span style="color: #006633;">andExpect</span><span style="color: #009900;">&#40;</span>message<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;GetPersonByUid/GetPersonByUidResponse.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Cette librairie m&#8217;a permis entre autres de me rendre compte que j&#8217;étais en train de modifier les namespaces de mes objets, par exemple&#8230;</p>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/12/12/smock-ou-comment-tester-un-webservice/" data-text="Smock, ou comment tester un webService"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/12/12/smock-ou-comment-tester-un-webservice/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F12%2F12%2Fsmock-ou-comment-tester-un-webservice%2F&amp;title=Smock%2C%20ou%20comment%20tester%20un%20webService" id="wpa2a_6"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/1R40jMi6TTE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/12/12/smock-ou-comment-tester-un-webservice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/12/12/smock-ou-comment-tester-un-webservice/</feedburner:origLink></item>
		<item>
		<title>Gatling in the sky with diamonds</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/1viVwOFtd4I/</link>
		<comments>http://labs.excilys.com/2012/12/03/gatling-in-the-sky-with-diamonds/#comments</comments>
		<pubDate>Mon, 03 Dec 2012 09:01:24 +0000</pubDate>
		<dc:creator>Bastien L.</dc:creator>
				<category><![CDATA[Outils]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[Gatling]]></category>
		<category><![CDATA[Gridinit]]></category>
		<category><![CDATA[Load testing]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[SaaS]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3871</guid>
		<description><![CDATA[Gatling est un projet open-source lancé en 2011 et sponsorisé par eBusiness Information. Il s’agit d’un outil de stress d’application nouvelle génération, visant à être beaucoup plus performant que les standards du marché. Ceci est rendu possible en tirant parti &#8230; <a href="http://labs.excilys.com/2012/12/03/gatling-in-the-sky-with-diamonds/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Gatling est un projet open-source lancé en 2011 et sponsorisé par eBusiness Information. Il s’agit d’un outil de stress d’application nouvelle génération, visant à être beaucoup plus performant que les standards du marché. Ceci est rendu possible en tirant parti des processeurs multicores et d’I/O non bloquantes, grâce à Akka et AsyncHttpClient/Netty notamment.</p>
<p>Alors quoi de neuf ? Et bien Gridinit a annoncé le 29 novembre dernier le support de Gatling pour ses utilisateurs payants et ses bêta-utilisateurs.</p>
<p>Gridinit est un SaaS (Software as a Service) qui propose une collection d&#8217;outils pour réaliser des tests de performances. Cela va du test de charge basique sur une URL à l&#8217;exécution d&#8217;un plan plus complexe grâce à des simulations JMeter. Les outils sont déployés dans le cloud, principalement sur des instances Amazon Web Services, ce qui permet de réaliser des tests de performances sans avoir à investir dans des machines coûteuses ou de disposer de nœuds à l’extérieur du SI, voire tout autour du globe. On va donc pouvoir dès à présent lancer des tests de charge Gatling dans les nuages.</p>
<div id="attachment_3873" class="wp-caption aligncenter" style="width: 621px"><a href="http://labs.excilys.com/wp-content/uploads/2012/12/screenshot-a454790b0605b3ca17b611bc564696b01.jpg"><img class="wp-image-3873  " src="http://labs.excilys.com/wp-content/uploads/2012/12/screenshot-a454790b0605b3ca17b611bc564696b01.jpg" alt="Gridinit dashboard" width="611" height="375" /></a><p class="wp-caption-text">Gridinit : tableau de bord</p></div>
<p>Plutôt une bonne nouvelle quand on sait que Altentee, la société derrière ce SaaS, est relativement active sur JMeter qui représente actuellement son coeur de marché. Pour autant Gridinit semble être à l&#8217;affût des avancées dans le monde des tests de performances. En effet quand on facture à ses clients des nœuds/heures, c&#8217;est à dire des ressources, on aimerait pouvoir leur offrir le meilleur rapport ressource/performance.</p>
<div id="attachment_3875" class="wp-caption aligncenter" style="width: 508px"><a href="http://labs.excilys.com/wp-content/uploads/2012/12/screen-shot-2012-11-29-at-3-16-58-pm.png"><img class="size-full wp-image-3875   " src="http://labs.excilys.com/wp-content/uploads/2012/12/screen-shot-2012-11-29-at-3-16-58-pm.png" alt="Gridinit tools supported" width="498" height="250" /></a><p class="wp-caption-text">Gridinit : injecteurs supportés</p></div>
<p style="text-align: left">Or l&#8217;arrivée d&#8217;outils utilisant des moteurs asynchrones basés sur le modèle des acteurs, comme Gatling, a permis d&#8217;obtenir des gains de performance non négligeables par rapport aux solutions précédentes basées sur le principe d&#8217;un utilisateur = un thread. Dans cette optique proposer une solution permettant d&#8217;utiliser au mieux les ressources mises à disposition fait sens. Gridinit a ainsi publié sur son blog une vidéo démontrant la puissance de Gatling en réalisant un test de charge avec 50k utilisateurs et 5k requêtes/sec en 5 minutes avec seulement 8 nœuds sur les 160 qui sont utilisables.</p>
<p style="text-align: left">D’ailleurs Gridinit annonce la possibilité de lancer en moyenne 20 000 utilisateurs sur un noeud avec Gatling, quand JMeter permet seulement 1000 utilisateurs en moyenne. On peut donc espérer diviser par 20 ses coûts dans un tel contexte.</p>
<div id="attachment_3883" class="wp-caption aligncenter" style="width: 586px"><a href="http://labs.excilys.com/wp-content/uploads/2012/12/gridinit-gatling_vs_jmeter.jpg"><img class=" wp-image-3883   " src="http://labs.excilys.com/wp-content/uploads/2012/12/gridinit-gatling_vs_jmeter-1024x488.jpg" alt="Gridinit : Gatling vs Jmeter" width="576" height="275" /></a><p class="wp-caption-text">Gridinit : Gatling vs Jmeter</p></div>
<p style="text-align: left">Sources :</p>
<ul>
<li><a href="http://gridinit.com/">http://gridinit.com</a></li>
<li><a href="https://gridinit.wordpress.com/2012/11/29/announcing-support-for-gatling-on-the-grid/">http://gridinit.wordpress.com/2012/11/29/announcing-support-for-gatling-on-the-grid/</a></li>
<li><a href="http://gatling-tool.org/">http://gatling-tool.org/</a></li>
</ul>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/12/03/gatling-in-the-sky-with-diamonds/" data-text="Gatling in the sky with diamonds"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/12/03/gatling-in-the-sky-with-diamonds/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F12%2F03%2Fgatling-in-the-sky-with-diamonds%2F&amp;title=Gatling%20in%20the%20sky%20with%20diamonds" id="wpa2a_8"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/1viVwOFtd4I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/12/03/gatling-in-the-sky-with-diamonds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/12/03/gatling-in-the-sky-with-diamonds/</feedburner:origLink></item>
		<item>
		<title>Un simple POJO !</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/Ml1fA0UzLjg/</link>
		<comments>http://labs.excilys.com/2012/11/02/un-simple-javabean/#comments</comments>
		<pubDate>Fri, 02 Nov 2012 11:05:45 +0000</pubDate>
		<dc:creator>Yassine Ben-Khaled</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3834</guid>
		<description><![CDATA[Chez le client, j&#8217;interviens depuis peu sur un autre projet. Pour ne pas rentrer dans les détails, je me retrouve à créer des vues de paramétrage pour certaines tables qui étaient jusqu&#8217;ici alimentées à la main par requêtes SQL Je &#8230; <a href="http://labs.excilys.com/2012/11/02/un-simple-javabean/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Chez le client, j&#8217;interviens depuis peu sur un autre projet.<br />
Pour ne pas rentrer dans les détails, je me retrouve à créer des vues de paramétrage pour certaines tables qui étaient jusqu&#8217;ici alimentées à la main par requêtes SQL <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Je me lance sur un petit test (juste de l&#8217;affichage !) sur une seule entité (et j&#8217;ai choisi la bonne <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ).<br />
<span id="more-3834"></span><br />
Voici l&#8217;entité :</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TypePrime <span style="color: #000000; font-weight: bold;">implements</span> XXX <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Integer</span> id<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> code<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> libelle<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Boolean</span> calculee<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/*...*/</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Boolean</span> isCalculee<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">calculee</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setCalculee<span style="color: #009900;">&#40;</span><span style="color: #003399;">Boolean</span> calculee<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">calculee</span> <span style="color: #339933;">=</span> calculee<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Je me rends sur la page de test, et là surprise ! Exception !<br />
(On utilise du JSF.)</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">javax.faces.el.PropertyNotFoundException: /faces/parametrage/tableau-prime.xhtml @27,101<br />
value=&quot;#{parametre.calculee}&quot;: Bean: xxx.TypePrime, property: calculee</div></div>
<p>Aux premiers abords, je suis surpris par l&#8217;exception retournée, je re-regarde l&#8217;entité, tout à l&#8217;air correct.<br />
Bien évidemment, je relance mon serveur et refais le même test mais rien n&#8217;y fait l&#8217;exception est toujours là !</p>
<p>Je commence à me dire qu&#8217;il y a quelque chose quand même (biensur !).<br />
Je transforme le type de &#8220;calculee&#8221; en primitif, je me retrouve ainsi :</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TypePrime <span style="color: #000000; font-weight: bold;">implements</span> XXX <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/*...*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">boolean</span> calculee<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/*...*/</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> isCalculee<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">calculee</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setCalculee<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">boolean</span> calculee<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">calculee</span> <span style="color: #339933;">=</span> calculee<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Je vais à nouveau sur ma nouvelle page de test, et là surprise ! Ça marche !</p>
<p>Etant tout de même désireux de mieux comprendre, je cherche la raison et je retourne voir la spéc. des <a href="http://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/" target="_blank">JavaBeans</a>.</p>
<p>Chapitre 8.3.2, on lit :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">In addition, for boolean properties, we allow a getter method to match the pattern:<br />
<br />
public boolean is‹PropertyName›();<br />
<br />
This “is‹PropertyName›” method may be provided instead of a “get‹PropertyName›” method, or it may be provided in addition to a “get‹PropertyName›” method.<br />
<br />
In either case, if the “is‹PropertyName›” method is present for a boolean property then we will use the “is‹PropertyName›” method to read the property value.</div></div>
<p>En résumé, le getter &#8220;isXXX()&#8221; est pris en compte que pour le type primitif boolean et non son wrapper.</p>
<p>Enfin pour finir, si on aurait pas voulu changer le type de son attribut, il aurait fallu créer la méthode</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Boolean</span> getCalculee<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">calculee</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Ça fonctionne également <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  !</p>
<blockquote><p>Je suis allé vérifié dans le bouquin de la SCJP et c&#8217;est bien écrit également, chapitre 1, paragraphe &#8220;JavaBeans Standards&#8221; =&gt; J&#8217;arrête l&#8217;article !</p></blockquote>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/11/02/un-simple-javabean/" data-text="Un simple POJO !"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/11/02/un-simple-javabean/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F11%2F02%2Fun-simple-javabean%2F&amp;title=Un%20simple%20POJO%20%21" id="wpa2a_10"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/Ml1fA0UzLjg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/11/02/un-simple-javabean/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/11/02/un-simple-javabean/</feedburner:origLink></item>
		<item>
		<title>Angular.js et Spring Security</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/MWrSn0jsYMM/</link>
		<comments>http://labs.excilys.com/2012/10/22/angular-js-et-spring-security/#comments</comments>
		<pubDate>Mon, 22 Oct 2012 19:55:52 +0000</pubDate>
		<dc:creator>Hugo Cordier</dc:creator>
				<category><![CDATA[Non classé]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3806</guid>
		<description><![CDATA[Il y a déjà quelques temps, Olivier Croisier nous initiait à Angular.js via une application Spring MVC. Question dans les commentaires : comment sécuriser ce type d&#8217;application ? Spring Security En général, j&#8217;essaie de ne pas réinventer la roue, surtout &#8230; <a href="http://labs.excilys.com/2012/10/22/angular-js-et-spring-security/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il y a déjà quelques temps, Olivier Croisier <a href="http://thecodersbreakfast.net/index.php?post/2012/07/30/D%C3%A9velopper-une-application-REST-avec-Spring-MVC-Angular.js" target="_blank">nous initiait à</a> <a href="http://thecodersbreakfast.net/index.php?post/2012/07/30/D%C3%A9velopper-une-application-REST-avec-Spring-MVC-Angular.js" target="_blank">Angular.js</a> via une application Spring MVC. <a href="http://thecodersbreakfast.net/index.php?post/2012/07/30/D%C3%A9velopper-une-application-REST-avec-Spring-MVC-Angular.js#c1060" target="_blank">Question dans les commentaires</a> : comment sécuriser ce type d&#8217;application ?</p>
<p><span id="more-3806"></span></p>
<h2>Spring Security</h2>
<p>En général, j&#8217;essaie de ne pas réinventer la roue, surtout quand il s&#8217;agit de sécurité. Ici, puisque l&#8217;application se base sur Spring, Spring-Security me semble la solution la plus indiquée.</p>
<p>J&#8217;ai commencé par configurer mon serveur grâce à la méthode <a href="http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-form-and-basic" target="_blank">RTHM</a> (Read The Holy Manual). Spring stocke un id de session chez le client et l&#8217;état sur le serveur (il faut bien faire quelques concessions, todo.ng n&#8217;est plus complètement stateless).</p>
<p>Notre application s&#8217;attend à recevoir les informations de connexion via un formulaire. Après vérification de la validité du login/mdp, il renvoie au client une redirection vers la page correspondante (failed ou success). C&#8217;est ce mécanisme de redirect qu&#8217;il va falloir remplacer, et cela se fait très facilement.</p>
<p>J&#8217;ai <a href="https://github.com/HugoCrd/todo.ng" target="_blank">forké</a> (du verbe forker : je fork, tu forks, il fork,..) l&#8217;application d&#8217;Olivier pour lui ajouter ce nouveau comportement. Je vous passe les détails de configuration de Spring-security, le manuel est bien plus bavard et précis que moi. Intéressons-nous plutôt à ce morceau de <a href="https://github.com/HugoCrd/todo.ng/blob/master/src/main/resources/spring/context-security.xml" target="_blank">context-security.xml</a> :</p>
<pre>&lt;http auto-config='true' entry-point-ref="authenticationEntryPoint"&gt;
&lt;form-login authentication-success-handler-ref="ajaxAuthenticationSuccessHandler"
            authentication-failure-handler-ref="ajaxAuthenticationFailureHandler"/&gt;
&lt;logout success-handler-ref="ajaxLogoutSuccessHandler" /&gt;
&lt;/http&gt;

&lt;beans:bean id="authenticationEntryPoint" 
     class="net.thecodersbreakfast.todo.security.Http401DeniedEntryPoint"/&gt;
&lt;beans:bean id="ajaxAuthenticationSuccessHandler" 
     class="net.thecodersbreakfast.todo.security.AjaxAuthenticationSuccessHandler"/&gt;
&lt;beans:bean id="ajaxAuthenticationFailureHandler" 
     class="net.thecodersbreakfast.todo.security.AjaxAuthenticationFailureHandler"/&gt;
&lt;beans:bean id="ajaxLogoutSuccessHandler" 
     class="net.thecodersbreakfast.todo.security.AjaxLogoutSuccessHandler"/&gt;</pre>
<p>L&#8217;entryPoint définit l&#8217;objet qui est appelé si l&#8217;on veut accéder à une ressource interdite. Et comme leurs noms l&#8217;indiquent, chaque handler traite une situation du processus : le <a href="https://github.com/HugoCrd/todo.ng/blob/master/src/main/java/net/thecodersbreakfast/todo/security/AjaxAuthenticationSuccessHandler.java" target="_blank">login réussit</a>, le <a href="https://github.com/HugoCrd/todo.ng/blob/master/src/main/java/net/thecodersbreakfast/todo/security/AjaxAuthenticationFailureHandler.java" target="_blank">mauvais login</a> et le <a href="https://github.com/HugoCrd/todo.ng/blob/master/src/main/java/net/thecodersbreakfast/todo/security/AjaxLogoutSuccessHandler.java" target="_blank">logout</a>.</p>
<p>Le paramètre auto-config gère le reste : les URLs à appeller pour se connecter sont celles par défaut :</p>
<p>S&#8217;authentifier : POST(&#8216;j_spring_security_check&#8217;, username/password, content-type=x-www-form-urlencoded)</p>
<p>Se déconnecter : GET(j_spring_security_logout)</p>
<p>J&#8217;ai donc définit mes propres handlers, qui renvoient un statut 200 en cas de connexion réussie, 403 si le login/mdp est invalide et 401 si on essaye d&#8217;accéder à une ressource interdite.</p>
<p>Il ne reste plus qu&#8217;à sécuriser les URLs, et plus finement, les controllers : @PreAuthorize devrait vous y aider.</p>
<h2>Angular.js</h2>
<p>Je vous laisse découvrir <a href="https://github.com/HugoCrd/todo.ng/blob/master/src/main/webapp/js/app/loginCtrl.js" target="_blank">ici</a> le <em>controller</em> Angular.js qui gère ces appels. Rien de bien sorcier.</p>
<h2>Test</h2>
<p><strong></strong>Pour tester le bon fonctionnement de l&#8217;application, on ne va autoriser la création d&#8217;entrées Todo qu&#8217;aux personnes connectées. J&#8217;ai donc ajouté une annotation @PreAuthorize au dessus du handler correspondant, <a href="https://github.com/HugoCrd/todo.ng/blob/master/src/main/java/net/thecodersbreakfast/todo/web/controller/TodoController.java" target="_blank">dans TodoController</a> (il faut penser à activer les annotations security et ajouter les modules AOP de Spring).</p>
<p>L&#8217;identifiant est &#8216;rod&#8217;, mot de passe &#8216;koala&#8217; (comme dans la doc de Spring)</p>
<p>Dorénavent, seul les personnes connectées peuvent créer des Todo.</p>
<p>&nbsp;</p>
<p>Source : Un monsieur en parlait avant moi, et en anglais <a href="http://gal-levinsky.blogspot.fr/2011/08/spring-security-3-ajax-login.html" target="_blank">ici</a> (<a href="http://gal-levinsky.blogspot.fr/2011/08/spring-security-3-ajax-login.html" target="_blank">http://gal-levinsky.blogspot.fr/2011/08/spring-security-3-ajax-login.html</a>)</p>
<p>[1] Oui, le mot de passe est envoyé en clair au serveur, mais cela suffit pour le type de service que je développe.</p>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/10/22/angular-js-et-spring-security/" data-text="Angular.js et Spring Security"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/10/22/angular-js-et-spring-security/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F10%2F22%2Fangular-js-et-spring-security%2F&amp;title=Angular.js%20et%20Spring%20Security" id="wpa2a_12"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/MWrSn0jsYMM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/10/22/angular-js-et-spring-security/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/10/22/angular-js-et-spring-security/</feedburner:origLink></item>
		<item>
		<title>Liferay 6.0 – Corriger la recherche de contenu Web par type</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/GYGSirxmUxY/</link>
		<comments>http://labs.excilys.com/2012/09/30/liferay-6-0-la-recherche-de-contenu-web-par-type/#comments</comments>
		<pubDate>Sun, 30 Sep 2012 06:58:46 +0000</pubDate>
		<dc:creator>Florian Lemarchand</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[Trucs & astuces]]></category>
		<category><![CDATA[liferay]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=2368</guid>
		<description><![CDATA[Liferay est un portail d&#8217;entreprise open-source conçu en Java. Il comporte un grand nombre de fonctionnalités de publication, de gestion de contenu, de documents ainsi que divers composants collaboratifs. Liferay propose également de créer ses propres composants et de redéfinir &#8230; <a href="http://labs.excilys.com/2012/09/30/liferay-6-0-la-recherche-de-contenu-web-par-type/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify">Liferay est un portail d&#8217;entreprise open-source conçu en Java. Il comporte un grand nombre de fonctionnalités de publication, de gestion de contenu, de documents ainsi que divers composants collaboratifs. Liferay propose également de créer ses propres composants et de redéfinir le comportement et la structure du portail et de ses composants.</p>
<p style="text-align: justify">En tant que gestionnaire de contenu Web, Liferay offre la possibilité de créer et de rechercher du contenu au sein du portail tout en filtrant les différents contenus en fonction de leur type, que ce soit une page wiki, de blog, une actualité &#8230;</p>
<p style="text-align: justify">La procédure à suivre pour cela est très simple : il suffit de préciser le type d&#8217;un contenu créé comme présenté ci-dessous en utilisant la portlet &#8220;Web Content Display&#8221; :</p>
<p style="text-align: justify"><a href="http://labs.excilys.com/wp-content/uploads/2012/02/CatCWS.png"><img class="alignnone size-full wp-image-2377" src="http://labs.excilys.com/wp-content/uploads/2012/02/CatCWS.png" alt="" width="652" height="263" /></a></p>
<p style="text-align: justify">La portlet de recherche doit ensuite être configurée de la manière suivante afin de pouvoir rechercher du contenu à partir du type de contenu souhaité :</p>
<p style="text-align: justify"><a href="http://labs.excilys.com/wp-content/uploads/2012/02/TypeCWS.png"><img class="alignnone size-full wp-image-2378" src="http://labs.excilys.com/wp-content/uploads/2012/02/TypeCWS.png" alt="" width="821" height="309" /></a></p>
<p style="text-align: justify">Cependant, je me suis aperçu lors d&#8217;une mission qu&#8217;une erreur s&#8217;était glissée dans la portlet de recherche. En effet, non seulement la recherche retourne les documents de la catégorie attendue mais aussi tous les autres documents du portail. Cette fonctionnalité n&#8217;a donc aucunement le comportement attendu.</p>
<p> <span id="more-2368"></span></p>
<p style="text-align: justify">Cela étant, cette erreur ne concerne que les versions antérieures à la 6.1.0, version où cette erreur a été corrigée.</p>
<h3 style="text-align: justify">Pourquoi ?</h3>
<p style="text-align: justify">Regardons comment une recherche de contenu est effectuée. Lors d&#8217;une recherche, les mots-clés saisis, &#8220;Keywords&#8221; et la catégorie des documents recherchés, ici appelée type, sont récupérés sur la page Search.jsp de la portlet &#8220;Journal Content Search&#8221;. Ces paramètres sont ensuite transmis dans un Contexte de Recherche (SearchContext) et utilisés par un Indexer qui va se charger de retourner les résultats.</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Indexer indexer = IndexerRegistryUtil.<span style="color: #006633;">getIndexer</span><span style="color: #009900;">&#40;</span>JournalArticle.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
SearchContext searchContext = SearchContextFactory.<span style="color: #006633;">getInstance</span><span style="color: #009900;">&#40;</span>request<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
searchContext.<span style="color: #006633;">setAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;type&quot;</span>, type<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
searchContext.<span style="color: #006633;">setGroupIds</span><span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
searchContext.<span style="color: #006633;">setKeywords</span><span style="color: #009900;">&#40;</span>keywords<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
Hits results = indexer.<span style="color: #006633;">search</span><span style="color: #009900;">&#40;</span>searchContext<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p style="text-align: justify">Or, cette recherche ne produit pas le résultat attendu. En effet, bien que le type soit précisé en tant qu&#8217;attribut, celui-ci n&#8217;est pas récupéré et utilisé par l&#8217;Indexer (ici, <a title="Source de JournalIndexer" href="http://grepcode.com/file/repo1.maven.org/maven2/com.liferay.portal/portal-impl/6.0.6/com/liferay/portlet/journal/util/JournalIndexer.java/" target="_blank">JournalIndexer</a>).</p>
<p style="text-align: justify">La logique voudrait que l&#8217;on surcharge la fonction Search de la classe JournalIndexer, mais cette manipulation impliquant l&#8217;utilisation d&#8217;un plugin EXT, nous allons utiliser une méthode alternative.</p>
<p style="text-align: justify">Pourquoi ne pas utiliser de plugin EXT ?</p>
<p style="text-align: justify">A la vue des implications qu&#8217;engendre l&#8217;utilisation d&#8217;un plugin EXT, nous allons plutôt utiliser un plugin HOOK. Pour plus d&#8217;informations, je vous invite à lire l&#8217;<a href="http://www.liferay.com/community/wiki/-/wiki/Main/Ext+Plugin" target="_blank">article wiki</a> à ce sujet.</p>
<p style="text-align: justify">Il suffit de créer un plugin HOOK, de modifier la page search.jsp de la portlet Journal Content Search et d&#8217;ajouter une condition booléenne (qui doit donc répondre par &#8220;true&#8221;) au SearchContext :</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Indexer indexer = IndexerRegistryUtil.<span style="color: #006633;">getIndexer</span><span style="color: #009900;">&#40;</span>JournalArticle.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
SearchContext searchContext = SearchContextFactory.<span style="color: #006633;">getInstance</span><span style="color: #009900;">&#40;</span>request<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
searchContext.<span style="color: #006633;">setAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;type&quot;</span>, type<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; &nbsp;font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>type.<span style="color: #006633;">isEmpty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
BooleanClause clause = BooleanClauseFactoryUtil.<span style="color: #006633;">create</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;type&quot;</span>, type, <span style="color: #0000ff;">&quot;MUST&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
BooleanClause<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> clauses =<span style="color: #009900;">&#123;</span>clause<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
searchContext.<span style="color: #006633;">setBooleanClauses</span><span style="color: #009900;">&#40;</span>clauses<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
searchContext.<span style="color: #006633;">setGroupIds</span><span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
searchContext.<span style="color: #006633;">setKeywords</span><span style="color: #009900;">&#40;</span>keywords<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
Hits results = indexer.<span style="color: #006633;">search</span><span style="color: #009900;">&#40;</span>searchContext<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p style="text-align: justify">Ainsi, nous allons récupérer les informations des documents de la catégorie souhaitée uniquement, en incluant, si besoin est, une condition supplémentaire à la recherche.</p>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/09/30/liferay-6-0-la-recherche-de-contenu-web-par-type/" data-text="Liferay 6.0 &#8211; Corriger la recherche de contenu Web par type"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/09/30/liferay-6-0-la-recherche-de-contenu-web-par-type/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F09%2F30%2Fliferay-6-0-la-recherche-de-contenu-web-par-type%2F&amp;title=Liferay%206.0%20%E2%80%93%20Corriger%20la%20recherche%20de%20contenu%20Web%20par%20type" id="wpa2a_14"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/GYGSirxmUxY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/09/30/liferay-6-0-la-recherche-de-contenu-web-par-type/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/09/30/liferay-6-0-la-recherche-de-contenu-web-par-type/</feedburner:origLink></item>
		<item>
		<title>Foundation 3 et Twitter Bootstrap 2</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/BlqGvdjT89k/</link>
		<comments>http://labs.excilys.com/2012/09/26/foundation-3-et-twitter-bootstrap-2/#comments</comments>
		<pubDate>Wed, 26 Sep 2012 14:19:29 +0000</pubDate>
		<dc:creator>Victor Leroy</dc:creator>
				<category><![CDATA[Non classé]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3622</guid>
		<description><![CDATA[Introduction Si vous êtes ici, c&#8217;est que le web, vous connaissez. Vous faites du développement web toute la journée, mais le jour où vous voulez créer votre propre site, un gros problème se pose. Le site fonctionne parfaitement bien, mais &#8230; <a href="http://labs.excilys.com/2012/09/26/foundation-3-et-twitter-bootstrap-2/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div style="text-align:justify;text-indent:2em">
<h2>Introduction</h2>
<p>Si vous êtes ici, c&#8217;est que le web, vous connaissez. Vous faites du développement web toute la journée, mais le jour où vous voulez créer votre propre site, un gros problème se pose. Le site fonctionne parfaitement bien, mais il est moche. En plus, vous avez passé des journées à en arriver là. La frustration vous guette. Et pourtant, il va falloir vous y faire, vous n&#8217;êtes pas graphiste et vos goûts personnels sont plutôt discutables.</p>
<p>Pas de panique ! Comme toujours (ou presque), des outils sont là pour vous aider. Mais parmi eux, lequel choisir ? Je vais vous parler ici de deux d&#8217;entre eux, <a href="http://foundation.zurb.com/">Foundation</a> et le désormais fameux <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a>.</p>
<p><span id="more-3622"></span></p>
<h2>CSS preprocessor</h2>
<p>Ces deux outils reposent en partie sur des framework CSS : <a href="http://lesscss.org">LESS</a> pour Twitter Boostrap et <a href="http://sass-lang.com">SASS</a> pour Foundation. Je ne vais pas trop m&#8217;étendre sur cette partie, les deux outils sont assez similaires. Si vous ne souhaitez pas modifier les styles fournis, ne cherchez pas trop longtemps lequel vous correspond le mieux. Cependant, SASS semble être un peu plus complet et surtout compatible avec <a href="http://compass-style.org">Compass</a>. Si vous souhaitez plus d&#8217;informations, vous pouvez aller lire <a href="http://css-tricks.com/sass-vs-less/">cet article comparant LESS et SASS</a>.</p>
<h2>Grille et Responsive design</h2>
<h3>La grille</h3>
<p>Foundation et Twitter Bootstrap disposent tous deux d&#8217;un système de grille pour faciliter le placement des éléments sur la page. Ces grilles sont découpées en 12 colonnes par défaut mais dans chacun des frameworks, cela est configurable. Cette grille s&#8217;ajuste à la taille de l&#8217;écran (du navigateur), ce qui est indispensable si l&#8217;on souhaite faire du « responsive-design ».</p>
<p>Au niveau du code, voilà à quoi ça ressemble :</p>
<h4>Foundation</h4>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;four columns&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Sidebar...<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;eight columns&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Main content...<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></td></tr></tbody></table></div>
<h4>Twitter Bootstrap</h4>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row-fluid&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span4&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Sidebar ...<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Main content...<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Les syntaxes sont plutôt proches mais celle de Foundation me paraît plus lisible bien que moins concise.  De plus, Foundation est beaucoup plus souple sur le « Source Ordering ». C&#8217;est à dire qu&#8217;il est possible d&#8217;ordonner son code de manière différente par rapport à l&#8217;affichage voulu (ou l&#8217;inverse).
</p>
<p>Par exemple :</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;two columns push-ten&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cellule 2<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;ten columns pull-two&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cellule 1<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></td></tr></tbody></table></div>
<p>S&#8217;affichera :</p>
<p style="text-indent:0">
<a href="http://labs.excilys.com/wp-content/uploads/2012/09/Grid_1346943116315.png"><img src="http://labs.excilys.com/wp-content/uploads/2012/09/Grid_1346943116315.png" alt="" width="765" height="28" class="size-full wp-image-3646" /></a>
</p>
<h3>Responsive Web Design</h3>
<p>Qu&#8217;est-ce que c&#8217;est ?</p>
<blockquote cite="http://fr.wikipedia.org/wiki/Responsive_Web_Design">
<p>La notion de Responsive Web Design regroupe différents principes et technologies mais il indique globalement qu&#8217;un site est conçu pour s&#8217;adapter aux différentes tailles d&#8217;écran et aux différents terminaux permettant d&#8217;afficher le site (navigateur, tablette, mobile, télé connectée, &#8230;). Ainsi, les mobinautes pourront avoir une expérience adaptée à leur terminal sans dégradation et sans devoir utiliser les fonctionnalité de zoom (ou un autre type de redimensionnement). Ils pourront consulter la même information, mais organisée différemment selon le type de terminal utilisé.</p>
<p style="text-align:right">
Wikipedia
</p>
</blockquote>
<p>Pour nous aider, Foundation propose la gestion d&#8217;une deuxième grille en plus de celle à 12 colonnes. Cette grille est orientée mobile, comprendre petits écrans, et est composée de 4 colonnes (par défaut). Elle permet de conserver une disposition correcte sur des écrans à largeur réduite.</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row display&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;three mobile-one columns&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; 3 colonnes de largeur sur écran large (sur les 12 colonnes)<br />
&nbsp; &nbsp; &nbsp; &nbsp; 1 colonne de largeur sur écran réduit (sur les 4 colonnes)<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;nine mobile-three columns&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; 9 colonnes de largeur sur écran large (sur les 12 colonnes)<br />
&nbsp; &nbsp; &nbsp; &nbsp; 3 colonnes de largeur sur écran réduit (sur les 4 colonnes)<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Par défaut, les éléments se seraient retrouvés les uns en dessous des autres, ce qui peut être un comportement déjà satisfaisant.</p>
<p>Avec Twitter Bootstrap, le responsive design est aussi au rendez-vous. Lorsque la largeur de la fenêtre du navigateur/terminal change, la largeur des colonnes change et les éléments s&#8217;empilent si l&#8217; écran n&#8217;est plus assez large.</p>
<p>Les deux frameworks donnent aussi la possibilité d&#8217;afficher ou cacher certains éléments selon la largeur du terminal utilisé, en partie à base de media queries. Foundation propose aussi la détection des écrans tactiles et des modes paysages et portraits.</p>
<p>Pour ma part, je donnerais donc un point à Foundation pour la gestion de la deuxième grille.</p>
<h2>Typographie</h2>
<p>Au niveau de la typographie (h1, h2, p, ul &#8230;), les deux frameworks fonctionnent à peu près de la même manière. Les tailles des caractères et des hauteurs de lignes sont prédéfinies mais peuvent être  entièrement personnalisées, soit en utilisant le configurateur en ligne, soit en modifiant après coup le CSS via des variables globales LESS ou SASS. Match nul sur ce point.</p>
<h2>Éléments graphiques et Javascript</h2>
<p>Vous trouverez un bon nombre d&#8217;éléments HTML déjà stylisés en utilisant ces frameworks. Plus besoin de passer des heures sur les styles de vos boutons, formulaires, tableaux&#8230; et la liste est longue. Mais ça ne s&#8217;arrête pas là. Tous les éléments courants en web sont présents. Tool-tips, breadcrumbs, onglets, fenêtres modales, menus déroulants, accordéons, carrousels&#8230;</p>
<p>Là, Twitter Bootstrap semble gagner la manche par le nombre de composants disponibles. Cependant vous trouverez peut-être dans l&#8217;un ou l&#8217;autre, LA fonctionnalité que vous recherchiez.</p>
<h2>Conclusion</h2>
<p>Les deux frameworks présentés ne sont pas si différents l&#8217;un de l&#8217;autre. Alors, lequel choisir ? Déjà, cela dépendra de vos obligations, professionnelles ou personnelles. Foundation n&#8217;étant pas compatible IE7, ça peut refroidir  plus d&#8217;un DSI. Cependant, cela explique quelques unes des différences au niveau du responsive design. Ensuite, la communauté autour de Twitter Bootstrap semble plus grande (je n&#8217;ai pas dit plus active). Environ 35000 « stars » et 8000 « forks » sur github pour Twitter et presque 6000 « stars » et 800 « forks » pour Foundation (je ne suis pas sûr que la métrique soit la meilleure). Ce qui peut être un avantage en environnement professionnel.</p>
<p>Au niveau des licences, Twitter Bootstrap est sous licence Apache 2 et Foundation sous licence MIT. Ce qui ne devrait pas changer grand chose pour vous.</p>
<p>J&#8217;entends déjà les « Ouais mais moi j&#8217;veux pas avoir le même site que les autres ». Bon déjà, comme vu dans l&#8217;introduction, quand on a pas bon goût, on évite de se plaindre. Ensuite, il existe des sites pour vous aider à choisir la palette de couleurs qu&#8217;il vous faut, et ainsi personnaliser le plus possible votre site. <a href="http://webdesignledger.com/tools/10-super-useful-tools-for-choosing-the-right-color-palette">Vous en trouverez une liste ici</a>.</p>
<p>Vous voilà maintenant au courant. Fini les : « je sais que c&#8217;est moche mais j&#8217;ai fait ça vite fait ! ».</p>
</div>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/09/26/foundation-3-et-twitter-bootstrap-2/" data-text="Foundation 3 et Twitter Bootstrap 2"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/09/26/foundation-3-et-twitter-bootstrap-2/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F09%2F26%2Ffoundation-3-et-twitter-bootstrap-2%2F&amp;title=Foundation%203%20et%20Twitter%20Bootstrap%202" id="wpa2a_16"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/BlqGvdjT89k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/09/26/foundation-3-et-twitter-bootstrap-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/09/26/foundation-3-et-twitter-bootstrap-2/</feedburner:origLink></item>
		<item>
		<title>Guide pratique sur l’encodage à l’usage des développeurs JavaEE</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/y-wvOXP-O-U/</link>
		<comments>http://labs.excilys.com/2012/09/20/guide-pratique-sur-lencodage-a-lusage-des-developpeurs-javaee/#comments</comments>
		<pubDate>Thu, 20 Sep 2012 14:55:04 +0000</pubDate>
		<dc:creator>mgrenonville</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Trucs & astuces]]></category>
		<category><![CDATA[Bonnes pratiques]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3696</guid>
		<description><![CDATA[Au cours de mes différentes missions, j&#8217;ai pu être confronté plusieurs fois à des problèmes d&#8217;encodage. À chaque fois (ou presque), le problème était situé entre la chaise et le clavier. Et une fois, il s&#8217;agissait d&#8217;IE7. Cette fois exceptée, &#8230; <a href="http://labs.excilys.com/2012/09/20/guide-pratique-sur-lencodage-a-lusage-des-developpeurs-javaee/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Au cours de mes différentes missions, j&#8217;ai pu être confronté plusieurs fois à des problèmes d&#8217;encodage. À chaque fois (ou presque), le problème était situé entre la chaise et le clavier. Et une fois, il s&#8217;agissait d&#8217;IE7. Cette fois exceptée, des règles simples permettent de les éviter. Et en comprenant les erreurs fréquentes, on trouve plus facilement la solution. Ces erreurs trouvent leurs origines dans la manière dont sont encodés les caractères. </p>
<p><span id="more-3696"></span></p>
<h2>Deux approches</h2>
<h3>Coder le caractère</h3>
<p><a href="http://500px.com/photo/13098915"><img src="http://labs.excilys.com/wp-content/uploads/2012/09/4-300x200.jpg" alt="" width="300" height="200" class="alignleft size-medium wp-image-3752" /></a> L&#8217;origine des encodages vient des <a href="http://fr.wikipedia.org/wiki/T%C3%A9l%C3%A9scripteur">Téléscripteurs</a> (1866 !), dont le but était de transmettre des informations via des signaux électriques. Il a donc fallu un code. Un des premiers standardisés est le Code Baudot, suivi de très près par le code ASCII. Pas de chance pour les non-anglophones, il ne permet pas de coder les caractères accentués. L&#8217;ASCII est composé de 128 caractères, dont 33 de contrôles. Ces caractères de contrôles sont très fortement liés à la technologie de l&#8217;époque : mon petit préféré ? le caractère <a href="http://en.wikipedia.org/wiki/Bell_character">BEL</a>. Si vous avez déjà tapé à la machine à écrire, il doit vous être familier, c&#8217;est annonciateur de fin de ligne <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Mais pourquoi seulement 128 caractères, sachant que c&#8217;est 2^7 ? Il aurait été plus intelligent de faire un octet complet ! Sauf qu&#8217;à l&#8217;origine, le dernier bit de l&#8217;octet est utilisé en bit de parité, pour détecter les erreurs de transmissions. Mais les non-anglophones finissent par avoir raison de celui-ci et développe rapidement des encodings qui incluent les caractères de la localisation (la devise, les accents, etc.). Sauf qu&#8217;avec 8 bits, les possibilités de représentation sont limitées. Ainsi, il existe un <a href="http://en.wikipedia.org/wiki/ISO_8859">ISO-8859</a> par alphabet (Grec, Cyrillique, Latin, &#8230;). Bien sur, ils ne sont pas compatibles entre eux, puisque tous les caractères dont le code est supérieur à 128 sont des caractères locaux. Les échanges de mails sont rapidement devenus une plaie. </p>
<p>Sans compter qu&#8217;on ne peut pas représenter sur 256 valeurs l&#8217;intégralité des <a href="http://fr.wikipedia.org/wiki/Logogramme">logogrammes</a> présents dans les langues orientales notamment. C&#8217;est pourquoi des gens ont commencé à travailler sur Unicode.</p>
<h3>Coder la représentation d’un caractère&#8230;</h3>
<p>
Unicode est une couche d’abstraction entre le caractère et son encodage. Pour bien comprendre, il faut savoir qu’un caractère Unicode porte un nom. La lettre “a” s’appelle “LATIN SMALL LETTER A”. La lettre “À” s’appelle “LATIN CAPITAL LETTER A WITH ACUTE”, etc. Ce nom est normé, et ne dépend absolument pas de la forme de la lettre, de la police, ou de sa représentation. On peut penser en caractère d’imprimerie. Par exemple, si vous avez déjà utilisé LaTeX (ou un éditeur de PAO type inDesign), vous avez sûrement noté les ligatures sur ff et fi : il existe un caractère Unicode (et bien un seul caractère, essayez de le sélectionner : <a href="http://www.fileformat.info/info/unicode/char/fb00/index.htm">ﬁ</a> et <a href="http://www.fileformat.info/info/unicode/char/fb01/browsertest.htm">ﬀ</a>) pour chacune d’entre-elle.</p>
<p>
Chaque caractère Unicode est ensuite numéroté : “LATIN SMALL LETTER A” est U+0061. Ce numéro est un “code-point”. Le U+ définit qu’il s’agit d’Unicode, les chiffres qui suivent sont en hexadécimal. Il existe sous les différents OS un utilitaire pour trouver les valeurs unicode de chaque caractère, et une multitude de sites internet.<br />
Une chaîne Unicode n’est rien d’autre qu’une suite de codes-points Unicode. UTF-8, UTF-16, UCS-2, … sont des encodages. Ils servent à coder les codes-points.
</p>
<p>
Intéressons-nous au célèbre UTF-8. C’est un format dont le but initial était de faciliter la migration à Unicode de documents ASCII vers UTF-8. L’astuce se situe dans l’attribution des mêmes octets entre l’UTF-8 et l’ASCII : Un “A” encodé en ASCII s’écrit 0&#215;61, et en UTF-8, 0&#215;61 (mais en Unicode, le “A” s’écrira U+0061 ou “LATIN SMALL LETTER A”, pas autrement !)<br />
Jusqu’ici, tout est simple, sauf que Unicode définit dans la dernière version 110 182 codes-points. Nous sommes donc très loin des 256 valeurs possibles dans un octet. Voyons comment UTF-8 s’en sort.</p>
<h3>&#8230; et encoder un code-point</h3>
<p>
Dans le tableau ci-dessous, on peut voir la manière dont sont stockées les chaînes Unicode en UTF-8. (NB : le tableau complet est disponible sur wikipedia)</p>
<table style="overflow:scroll;font-size:12px">
<tbody>
<tr>
<th>Bits</th>
<th>Last code point</th>
<th>Byte 1</th>
<th>Byte 2</th>
<th>Byte 3</th>
</tr>
<tr>
<th>&nbsp;&nbsp;7</th>
<td>U+007F</td>
<td>0xxxxxxx</td>
</tr>
<tr>
<th>11</th>
<td>U+07FF</td>
<td>110xxxxx</td>
<td>10xxxxxx</td>
</tr>
<tr>
<th>16</th>
<td>U+FFFF</td>
<td>1110xxxx</td>
<td>10xxxxxx</td>
<td>10xxxxxx</td>
</tr>
</tbody>
</table>
<blockquote><p>
<a href="http://en.wikipedia.org/wiki/UTF-8#Description">source et version complète</a>
</p></blockquote>
<p>Pour encoder le caractère &#8220;ũ&#8221; U+0169 en UTF-8, </p>
<ul>
<li>D&#8217;après le tableau, le code-point (0&#215;169) est compris entre 0x007F et 0x07FF, il faudra donc 2 octets pour l&#8217;encoder.</li>
<li>0&#215;169 est égal en binaire à 101101001b. </li>
<li>Les bits du code-point servent à remplacer les x du tableau : 110xxxxx 10xxxxxx devient : 110<strong>0101</strong> 10<strong>101001</strong></li>
</ul>
<p>Une erreur courante est de confondre Unicode et UTF-8. UTF-8 est un encodage permettant de représenter Unicode, pas Unicode.</p>
<h2>Et dans la pratique ?</h2>
<h3>Vers de l’Unicode</h3>
<p>Prenons la chaîne suivante &#8220;à&#8221;. Il est impossible de l’encoder en ASCII, puisque &#8220;à&#8221; ne fait pas partie de cet encodage. En revanche, en ISO8859-1, c’est tout à fait possible :</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> bytes <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;à&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getBytes</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;iso8859-1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">byte</span> aByte <span style="color: #339933;">:</span> bytes<span style="color: #009900;">&#41;</span>  <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">format</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;%X&quot;</span>,aByte<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>
On obtient : <b>0xE0, soit 11100000, ou 224 en décimal</b>. Qu’en est-il de l’UTF-8 ? On obtient <strong>0xC3 0xA0</strong>. Ainsi, UTF-8 utilise bien 2 octets pour coder un caractère, là où ISO8859-1 n’en utilisait qu’un.
</p>
<p>Simulons une erreur courante : un caractère encodé en ISO-8859-1 est lu en tant que chaîne UTF-8.</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> bytes <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#41;</span> 0xE0<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #003399;">String</span> test <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#40;</span>bytes, <span style="color: #0000ff;">&quot;utf-8&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>test<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Un caractère qui doit vous être familier s’affiche : � (soit : &#8216;REPLACEMENT CHARACTER&#8217; ou U+FFFD). Ce caractère sert à représenter un caractère non représentable dans l’encodage choisi (UTF-8 ou UTF-16). On a donc connaissance des erreurs de décodage. On peut donc “sans risque” décoder un flux ISO-8859 en UTF-8 : UTF-8 saura repérer certains caractères en erreur. En revanche, le remplacement se fera avec le même caractère pour toutes les erreurs : il y a perte d’information (mais elle est connue !)</p>
<h2>Depuis l’Unicode</h2>
<p>
Toujours avec notre chaîne “à”, il est possible de l’encoder via Unicode en UTF-8. On obtient alors les 2 octets 0xC3 et 0xA0. Simulons une autre erreur courante : le caractère encodé en UTF-8 et lu en tant que chaîne ISO-8859-1 :</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> bytes <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#41;</span> 0xC3, <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#41;</span> 0xA0<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #003399;">String</span> test <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#40;</span>bytes, <span style="color: #0000ff;">&quot;iso8859-1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>test<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Cette fois, on obtient : &#8220;Ã &#8221; (soit, en Unicode : &#8220;LATIN CAPITAL LETTER A WITH TILDE (U+00C3)&#8221; &#8220;NO-BREAK SPACE (U+00A0)&#8221;). UTF-8 utilisant 2 octets, il est normal que ISO-8859-1 voit 2 caractères. Cependant ici, aucun moyen de détecter une erreur, et pourtant, celle-ci doit aussi vous être familière ! Et le problème ici est qu&#8217;il n&#8217;y a aucun moyen de détecter l&#8217;erreur ! Pas de perte d’information, juste une mauvaise interprétation, sans remplacement.
</p>
<p>S&#8217;il vous est déjà arrivé de manipuler des fichiers ouverts par des outils mal configurés (ISO-8859-1 vs UTF-8), vous avez surement remarqué qu&#8217;un fichier ISO-8859-1 ouvert en UTF-8 et écrasé n&#8217;est plus récupérable (du fait du caractère de remplacement U+FFFD). En revanche, ouvrir un fichier UTF-8 en ISO-8859-1, l&#8217;éditer avec des caractères ASCII et l&#8217;enregistrer ne l&#8217;affecte pas. Voici l&#8217;explication !</p>
<h2>Et dans la vie de tous les jours ?</h2>
<h3>Un flux d’octet n’a aucun sens sans Charset</h3>
<p>Décoder un flux d’octet est une opération courante, à chaque requête, l’implémentation de HttpServletRequest présente dans le conteneur web décode les informations associées à la requête : ici dans tomcat</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
* Parse request parameters.<br />
*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> parseRequestParameters<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; requestParametersParsed <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; Parameters parameters <span style="color: #339933;">=</span> coyoteRequest.<span style="color: #006633;">getParameters</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">String</span> enc <span style="color: #339933;">=</span> coyoteRequest.<span style="color: #006633;">getCharacterEncoding</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> useBodyEncodingForURI <span style="color: #339933;">=</span> connector.<span style="color: #006633;">getUseBodyEncodingForURI</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>enc <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameters.<span style="color: #006633;">setEncoding</span><span style="color: #009900;">&#40;</span>enc<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>useBodyEncodingForURI<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameters.<span style="color: #006633;">setQueryStringEncoding</span><span style="color: #009900;">&#40;</span>enc<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameters.<span style="color: #006633;">setEncoding</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#40;</span>org.<span style="color: #006633;">apache</span>.<span style="color: #006633;">coyote</span>.<span style="color: #006633;">Constants</span>.<span style="color: #006633;">DEFAULT_CHARACTER_ENCODING</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>useBodyEncodingForURI<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameters.<span style="color: #006633;">setQueryStringEncoding</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#40;</span>org.<span style="color: #006633;">apache</span>.<span style="color: #006633;">coyote</span>.<span style="color: #006633;">Constants</span>.<span style="color: #006633;">DEFAULT_CHARACTER_ENCODING</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; parameters.<span style="color: #006633;">handleQueryParameters</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>usingInputStream <span style="color: #339933;">||</span> usingReader<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>getMethod<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">equalsIgnoreCase</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;POST&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">String</span> contentType <span style="color: #339933;">=</span> getContentType<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>contentType <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; contentType <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">int</span> semicolon <span style="color: #339933;">=</span> contentType.<span style="color: #006633;">indexOf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">';'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>semicolon <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; contentType <span style="color: #339933;">=</span> contentType.<span style="color: #006633;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span>, semicolon<span style="color: #009900;">&#41;</span>.<span style="color: #006633;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; contentType <span style="color: #339933;">=</span> contentType.<span style="color: #006633;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;application/x-www-form-urlencoded&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>contentType<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">int</span> len <span style="color: #339933;">=</span> getContentLength<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>len <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> formData <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>len <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> CACHED_POST_LEN<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>postData <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; postData <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span>CACHED_POST_LEN<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; formData <span style="color: #339933;">=</span> postData<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; formData <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span>len<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">int</span> actualLen <span style="color: #339933;">=</span> readPostBody<span style="color: #009900;">&#40;</span>formData, len<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>actualLen <span style="color: #339933;">==</span> len<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameters.<span style="color: #006633;">processParameters</span><span style="color: #009900;">&#40;</span>formData, <span style="color: #cc66cc;">0</span>, len<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Throwable</span> t<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Ignore</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Voyons comment le régler correctement dans une solution Spring MVC déployé dans un tomcat.</p>
<h3>Client</h3>
<p>Le client (ici le navigateur WEB) reçoit une réponse HTTP depuis un serveur (peu importe la requête d’origine). Il existe plusieurs moyens de jouer sur l’encoding.<br />
La  <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">RFC 2616 (HTTP/1.1)</a> est claire de ce point de vue : le Header HTTP Content-Type est dédié à cet effet.<br />
En Spring MVC, il est facile de mettre ce header dans toutes les pages générées, directement dans le ViewResolver :</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;freemarkerViewResolver&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;contentType&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;text/html; charset=UTF-8&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
<p>Il est bien entendu possible de surcharger cette valeur directement dans la View. En JSP, il suffit de mettre dans la page :</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;%@page <span style="color: #000066;">contentType</span>=<span style="color: #ff0000;">&quot;text/html; charset=UTF-8&quot;</span> %<span style="color: #000000; font-weight: bold;">&gt;</span></span></div></td></tr></tbody></table></div>
<p>On peut aussi mettre ce Header directement dans Apache/nginx. Il faudra aussi penser à régler les outils pour générer de l’UTF-8 (dans Freemarker, la propriété url_escaping_charset et output_encoding). Malheureusement, il se peut que nous n’ayons pas accès à cette possibilité. Que faire alors ?<br />
Dans la page HTML, il est possible de définir un meta dans l’élément head :</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">http-equiv</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Content-Type&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/html; charset=utf-8&quot;</span>&gt;</span></div></td></tr></tbody></table></div>
<p>
Quelle bizarrerie ! Commencer à lire un flux sans définir son encoding et attendre quelques octets avant de le connaître&#8230; Heureusement que la plupart des encodings utilisent les mêmes octets que dans l’ASCII.
</p>
<p>
Ne pas suivre ces recommandations vous expose à toutes sortes de choses incluant <a href="http://www.fileformat.info/info/unicode/char/1f525/index.htm">des incendies</a>, <a href="http://www.fileformat.info/info/unicode/char/1f34c/index.htm">des pluies de bananes</a>, <a href="http://www.fileformat.info/info/unicode/char/1f4a9/index.htm"> des tas de m****</a>  &#8211; oui, il y a un caractère pour tout &#8211; et <a href="http://www.fileformat.info/info/unicode/char/1f51e/index.htm">de la p****graphie (SFW)</a> ! Plus sérieusement, les navigateurs essayeront de deviner à partir d’analyses statistiques le couple langue/encodage le plus probable. Chose qui fonctionne bien, jusqu’au jour où l’utilisateur écrit un texte qui sort du profil statistique, ce qui est fréquent, en particulier s&#8217;il poste du code.
</p>
<p>
Une fois l’encodage détecté (avec succès ou pas), le navigateur enverra éventuellement des données au serveur (via des requêtes GET, POST ou PUT). L’encoding utilisé par le navigateur pour envoyer le flux au serveur est celui de la page. D’où l’importance de maitriser celui-ci !
</p>
<h3>Serveur</h3>
<p>
Ainsi, nous savons que le navigateur nous poste le flux en, au hasard, UTF-8. Parfait. La RFC 2616 définit dans le paragraphe <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1">3.7.1</a> que par défaut, si aucun encoding n’est spécifié, il faut lire les données en ISO-8859-1.
</p>
<p>
De fait, dans la spécification de JSP, le point SRV.3.9 définit que l’encoding utilisé par défaut pour le décodage des paramètres (GET et POST) est ISO 8859-1 (<a href="http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q9">Plus d’informations ici sur le pourquoi du comment</a>)
</p>
<p>
Cependant, lorsque les pages sont affichées en UTF-8, le navigateur enverra les données en UTF-8. Pour forcer le conteneur de servlet à lire les paramètres en UTF-8, une solution à base de Filter est disponible dans Spring : CharacterEncodingFilter
</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CharacterEncodingFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.springframework.web.filter.CharacterEncodingFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>encoding<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>UTF-8<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>forceEncoding<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CharacterEncodingFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>webapp<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
<p>
Ainsi, à chaque requête, le filtre s’applique et force (ou pas) l’encodage pour la lecture des paramètres. Lorsque le paramètre forceEncoding est vrai, le filtre va aussi forcer l’encoding sur la réponse.<br />
Attention, si vous avez bien lu le code de CoyoteRequest, à la première ligne de parseRequestParameters(), il y a un : requestParametersParsed = true. Je vous le donne en mille, l’interprétation des paramètres n’est faite qu’une seule fois. Le filtre qui force le Charset doit donc être appliqué avant la première lecture de paramètre !
</p>
<p>
Enfin, une dernière chose peut-être faite afin d’autoriser les URI en UTF-8 (comme wikipedia) : ajouter URIEncoding=&#8221;UTF-8&#8243; sur l’élément &lt;Connector&gt; dans le server.xml de tomcat.
</p>
<p>Une fois toutes ces manipulations effectuées, vous pouvez presque dire adieu aux problèmes d&#8217;encoding. Pourquoi presque ? Parce qu&#8217;il faut être sur que tous les flux que vous générez sont bien dans l&#8217;encoding que vous avez choisi. Attention tout particulièrement aux MessagesBundle dans Spring. La spécification des fichiers de properties indique qu&#8217;ils doivent être en ISO-8859-1. Et Eclipse suit cette norme. La solution pour stocker des caractères au delà des 256 possibles dans ISO-8859-1 ? Les mettre en UTF-8 et prier le dieu Unicode pour que personne n&#8217;écrase le fichier avec une version ISO-8859-1, ou alors utiliser native2ascii (en standard dans le JDK) pour transformer ses chaînes avant de les enregistrer dans le fichier (un plugin Eclipse existe pour le faire automatiquement <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ). Vous voilà prévenus !</p>
<h2>Pour aller plus loin</h2>
<p>Je ne saurai que trop vous conseiller la lecture des articles suivants :</p>
<ul>
<li><a href="https://unspecified.wordpress.com/2012/04/19/the-importance-of-language-level-abstract-unicode-strings/">The importance of language-level abstract Unicode strings </a></li>
<li><a href="http://www.joelonsoftware.com/articles/Unicode.html">The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)</a></li>
<li><a href="http://wiki.apache.org/tomcat/FAQ/CharacterEncoding">Tomcat FAQ : Character Encoding Issues</a></li>
</ul>
<p>Merci à Nicolas Maupu pour la photo <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Contrat Creative Commons" style="border-width:0" src="http://labs.excilys.com/wp-content/uploads/2012/08/80x15.png" /></a> Article écrit sous <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons 3.0 BY-SA</a>.</p>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/09/20/guide-pratique-sur-lencodage-a-lusage-des-developpeurs-javaee/" data-text="Guide pratique sur l&#8217;encodage à l&#8217;usage des développeurs JavaEE"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/09/20/guide-pratique-sur-lencodage-a-lusage-des-developpeurs-javaee/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F09%2F20%2Fguide-pratique-sur-lencodage-a-lusage-des-developpeurs-javaee%2F&amp;title=Guide%20pratique%20sur%20l%E2%80%99encodage%20%C3%A0%20l%E2%80%99usage%20des%20d%C3%A9veloppeurs%20JavaEE" id="wpa2a_18"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/y-wvOXP-O-U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/09/20/guide-pratique-sur-lencodage-a-lusage-des-developpeurs-javaee/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/09/20/guide-pratique-sur-lencodage-a-lusage-des-developpeurs-javaee/</feedburner:origLink></item>
		<item>
		<title>Meilleure gestion de logs sur Android</title>
		<link>http://feedproxy.google.com/~r/ExcilysLabs/~3/m9KS47Dni78/</link>
		<comments>http://labs.excilys.com/2012/09/12/meilleure-gestion-de-logs-sur-android/#comments</comments>
		<pubDate>Wed, 12 Sep 2012 17:06:11 +0000</pubDate>
		<dc:creator>Damien V.</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Non classé]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[log4j]]></category>
		<category><![CDATA[Logback]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[Slf4j]]></category>
		<category><![CDATA[Soja]]></category>
		<category><![CDATA[Stomp]]></category>

		<guid isPermaLink="false">http://labs.excilys.com/?p=3668</guid>
		<description><![CDATA[Mise en situation Android dispose d&#8217;une gestion de logs assez intéressante. On y retrouve la notion de niveau de logs, et la possibilité de poser un tag sur chaque ligne. Pour les visualiser, on passe par le plugin ADT et &#8230; <a href="http://labs.excilys.com/2012/09/12/meilleure-gestion-de-logs-sur-android/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<h1>Mise en situation</h1>
<p>Android dispose d&#8217;une gestion de logs assez intéressante. On y retrouve la notion de niveau de logs, et la possibilité de poser un tag sur chaque ligne. Pour les visualiser, on passe par le <a href="http://developer.android.com/tools/sdk/eclipse-adt.html">plugin ADT</a> et sa vue LogCat.</p>
<p>Tout cela c&#8217;est bien beau&#8230; Mais ce système impose d&#8217;avoir accès au smartphone (ou à la tablette) pour consulter les logs. Or, dans ma mission actuelle, le projet est envoyé en pilote à différents endroits en France. Il n&#8217;est donc pas pensable de se déplacer pour consulter ces informations, et le personnel présent a autre chose à faire que de taper des lignes de commandes ou de lancer Eclipse. <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-3668"></span></p>
<h1>Alors quoi ? Comment konfai ?</h1>
<p>J&#8217;ai donc cherché des solutions de logs en me basant sur ce qui existe déjà pour Java/JEE. Et il y a des projets portant les principaux frameworks de logs sur ces terminaux. Parfait !</p>
<p>Parmis d&#8217;autre, on retrouve donc les librairies suivantes :</p>
<ul>
<li><a href="http://code.google.com/p/android-logging-log4j/source/list">Android-logging-log4j</a></li>
<li><a href="http://www.slf4j.org/android/">SLF4J-Android</a></li>
<li><a href="http://tony19.github.com/logback-android/">Logback-Android</a></li>
</ul>
<p>Après quelques tests, je me suis rapidement orienté vers <strong>Logback-Android</strong> pour plusieurs raisons :</p>
<ul>
<li>je l&#8217;utilise déjà au quotidien ;</li>
<li>il intègre une large panoplie d&#8217;appender (dont  FileRollingAppender, DBAppender, SocketAppender) ;</li>
<li>il est configurable de plusieurs façons (AndroidManifest, logback.xml, programmatiquement) ;</li>
<li>et surtout, <a href="http://labs.excilys.com/2011/03/08/slf4j-logback-pourquoi-tout-le-monde-devrait-migrer/">Logback, c&#8217;est la vie</a>.</li>
</ul>
<p><span style="font-size: medium"><span style="line-height: 24px">Ci-dessous mon fichier logback.xml pour l&#8217;exemple. On y retrouve bien la syntaxe usuelle <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></span></p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;appender</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;FILE&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;ch.qos.logback.core.FileAppender&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/sdcard/logs/epod.log<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rollingPolicy</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- daily rollover --&gt;</span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fileNamePattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/sdcard/logs/epod.%d{yyyy-MM-dd}.log<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fileNamePattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- keep 30 days' worth of history --&gt;</span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;maxHistory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>30<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/maxHistory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/rollingPolicy<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;encoder</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}:%line - %msg%n<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/encoder<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/appender<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;root</span> <span style="color: #000066;">level</span>=<span style="color: #ff0000;">&quot;DEBUG&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;appender-ref</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;FILE&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/root<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
<h2>Et les logs on les récupère comment ?</h2>
<p>La solution la plus simple serait de configurer un SocketAppender et d&#8217;envoyer le tout sur un serveur dédié à cette tâche. Mais cela nécessite que le terminal soit toujours relié au réseau, ce qui est loin d&#8217;être évident avec des appareils mobiles.</p>
<p>Pour mon projet, les appareils en question sont des tablettes qui sont toujours reliées à un réseau interne. Elles communiquent avec le SI grâce à <a href="https://github.com/excilys/soja">Soja</a>. Pour simplifier les choses, on a donc opté pour une solution nous permettant de récupérer les logs sur la tablette, uniquement lorsque l&#8217;on en a besoin.</p>
<ol>
<li>La tablette souscrit à deux topics fixés : <em>/logs/list</em> et <em>/logs/download</em> ;</li>
<li>on envoie un message sur le topic <em>/logs/list</em> contenant le nom d&#8217;un autre topic sur lequel envoyer la réponse ;</li>
<li>la tablette renvoie la liste des fichiers de logs disponibles ;</li>
<li>on envoie un second message sur le topic <em>/logs/download</em> contenant le nom d&#8217;un topic de réponse et le fichier à envoyer.</li>
</ol>
<div class="wp-caption aligncenter" style="width: 419px"><img src="http://www.websequencediagrams.com/cgi-bin/cdraw?lz=Q2xpZW50IFNvamEtPitUYWJsZXR0ZTogL2xvZ3MvbGlzdAoADQgtLT4tACQLOiBhcHAubG9nLAAEBTEwLTA5LTEyAAcLMQAICgoKAEseZG93bmxvYWQvAE0HAFsaY29udGVudSBkdSBmaWNoaWVyIGRlIGxvZ3MuLi4&amp;s=roundgreen" alt="Communication STOMP pour récupérer les logs" width="409" height="232" /><p class="wp-caption-text">Communication STOMP pour récupérer les logs</p></div>
<h1>Conclusion</h1>
<p>Il existe donc des librairies de logs intéressantes pour Android. Pour les puristes, on peut très bien intégrer une de ces solutions avec un appender qui renvoie le tout sur LogCat et ainsi ne pas changer leurs habitudes <img src='http://labs.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://labs.excilys.com/2012/09/12/meilleure-gestion-de-logs-sur-android/" data-text="Meilleure gestion de logs sur Android"></a><a class="a2a_button_google_plusone addtoany_special_service" data-href="http://labs.excilys.com/2012/09/12/meilleure-gestion-de-logs-sur-android/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Flabs.excilys.com%2F2012%2F09%2F12%2Fmeilleure-gestion-de-logs-sur-android%2F&amp;title=Meilleure%20gestion%20de%20logs%20sur%20Android" id="wpa2a_20"><img src="http://labs.excilys.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p><img src="http://feeds.feedburner.com/~r/ExcilysLabs/~4/m9KS47Dni78" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://labs.excilys.com/2012/09/12/meilleure-gestion-de-logs-sur-android/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://labs.excilys.com/2012/09/12/meilleure-gestion-de-logs-sur-android/</feedburner:origLink></item>
	</channel>
</rss>
