<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Java - In Fine - Le Blog</title>
	<atom:link href="https://blog.infine.com/tag/java/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.infine.com</link>
	<description>Le blog des technos de demain !</description>
	<lastBuildDate>Tue, 13 Nov 2012 14:02:25 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.5.7</generator>

<image>
	<url>https://blog.infine.com/wp-content/uploads/2021/03/cropped-vignette-32x32.png</url>
	<title>Java - In Fine - Le Blog</title>
	<link>https://blog.infine.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Calcul de VWAP avec Hadoop en StandAlone</title>
		<link>https://blog.infine.com/calcul-de-vwap-avec-hadoop-en-standalone-2214?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calcul-de-vwap-avec-hadoop-en-standalone</link>
					<comments>https://blog.infine.com/calcul-de-vwap-avec-hadoop-en-standalone-2214#comments</comments>
		
		<dc:creator><![CDATA[Jonathan Blaisius]]></dc:creator>
		<pubDate>Mon, 12 Nov 2012 09:00:45 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[BigData]]></category>
		<category><![CDATA[GridComputing]]></category>
		<category><![CDATA[Hadoop]]></category>
		<category><![CDATA[Vwap]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=2214</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">6</span> <span class="rt-label rt-postfix">min.</span></span> Hadoop dans les grandes lignes  Hadoop est un framework java destiné à faciliter la création d&#8217;applications distribuées et scalables. Il permet aux applications de travailler avec des milliers de nœuds et des pétaoctets de données. Hadoop repose sur son système de fichier (HDFS) ainsi que sur son algorithme de Map/Reduce. Généralement, tous les tutoriaux ou exemples &#8230;</p>
<p>The post <a href="https://blog.infine.com/calcul-de-vwap-avec-hadoop-en-standalone-2214">Calcul de VWAP avec Hadoop en StandAlone</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">6</span> <span class="rt-label rt-postfix">min.</span></span><h1></h1>
<h1><strong>Hadoop dans les grandes lignes </strong></h1>
<p><strong><img decoding="async" class="alignleft" src="http://hadoop.apache.org/images/hadoop-logo.jpg" alt="" width="300" height="71" /></strong></p>
<p>Hadoop est un framework java destiné à faciliter la création d&#8217;applications distribuées et scalables. Il permet aux applications de travailler avec des milliers de nœuds et des pétaoctets de données.</p>
<p>Hadoop repose sur son système de fichier (HDFS) ainsi que sur son algorithme de Map/Reduce.</p>
<p>Généralement, tous les tutoriaux ou exemples d’implémentation d’Hadoop concernent un calcul basique de calcul du nombre de différents mots contenu dans des fichiers.</p>
<p>Dans cet article, je vais m’attacher à vous présenter un cas concret d’utilisation d’Hadoop pour le calcul de VWAP.</p>
<p><strong> </strong></p>
<h1>Qu&#8217;est ce qu&#8217;une VWAP et pourquoi utiliser Hadoop pour la calculer ?</h1>
<p>La VWAP (Volume-weighted average price) est un indice financier correspondant au ratio de la valeur échangée par le volume échangé. <a title="Vwap" href="http://en.wikipedia.org/wiki/Volume-weighted_average_price">Plus d&#8217;info ici</a></p>
<p>Notre but est de calculer la VWAP pour tous les titres, sur tout l&#8217;historique disponible à des heures données.</p>
<p><span id="more-2214"></span></p>
<p>Les fichiers historiques sont de la forme txt. Il y a un fichier par jour, ce fichier pèse en moyenne 1GigaOctet. Donc selon la taille de notre historique, ce calcul peut s&#8217;avérer très fastidieux et couteux en ressources.</p>
<p>Voici à quoi ressemble un fichier en entrée (enfin une infime partie) :</p>
<p><span style="font-size: x-small">C;FR0000130338;09:00:03;3;310;24.6;50;24.5</span><br />
<span style="font-size: x-small">C;FR0000130338;09:00:03;4;231;24.62;665;24.4</span><br />
<span style="font-size: x-small">C;FR0000130338;09:00:03;5;686;24.63;309;24.37</span><br />
<span style="font-size: x-small">C;BE0003796134;09:00:03;1;3360;4.51;5306;4.5</span><br />
<span style="font-size: x-small">N;FR0000120222;09:00:00;00000042;67.99</span><br />
<span style="font-size: x-small">N;FR0000120222;09:00:00;00000019;67.99</span><br />
<span style="font-size: x-small">N;FR0000120222;09:00:00;00000012;67.99</span><br />
<span style="font-size: x-small">N;FR0000120222;09:00:00;00000002;67.99</span><br />
<span style="font-size: x-small">N;FR0000120222;09:00:00;00000041;67.99</span></p>
<p>En séparant par &#8220;;&#8221;</p>
<ol>
<li>C ou N, C pour carnet d&#8217;ordre N pour une transaction</li>
<li>Code ISIN du titre</li>
<li>Heure de la transaction</li>
<li>Volume de titres échangés</li>
<li>Prix</li>
</ol>
<p>Hadoop va donc être utilisé pour ces fonctionnalitées de calcul distribués afin de répartir la charge de parsing et calcul sur différentes machines et tout aggréger pour donner en sortie un fichier avec les vwap demandées.</p>
<p>Voici un extrait du fichier de sortie :</p>
<p><span style="font-size: x-small">FR0010112524-20100104-09:00:00     25.656256</span><br />
<span style="font-size: x-small"> FR0010112524-20100104-12:00:00     26.125364</span><br />
<span style="font-size: x-small"> FR0010112524-20100104-17:00:00     26.28817</span><br />
<span style="font-size: x-small"> FR0010112524-20100106-09:00:00     26.560003</span><br />
<span style="font-size: x-small"> FR0010112524-20100106-12:00:00     26.684067</span><br />
<span style="font-size: x-small"> FR0010112524-20100106-17:00:00     26.756487</span><br />
<span style="font-size: x-small"> FR0010112524-20100217-09:00:00     25.949999</span></p>
<h1><strong>Implémentation d&#8217;Hadoop pour un calcul de VWAP</strong></h1>
<p>En entrée, on a donc toute une série de fichiers txt. Chaque fichier correspond aux extractions Euronext des transactions d’un jour donné.</p>
<p>Seules les lignes commençant par «N;» nous intéressent, les autres correspondant aux carnets d’ordre.</p>
<p>Au niveau du Mapper, nous allons extraire toutes les lignes commençant par «N;» pour un ou plusieurs code ISIN donnés.</p>
<p>Dans le Reducer, on va vouloir récupérer toutes les lignes correspondant à notre/nos ISIN triées par jour puis heure afin de calculer la Vwap pour les heures données. Or Hadoop ne permet pas de trier directement la liste de &lt;Values&gt; reçue par le Reducer</p>
<h1></h1>
<h1><strong>Tri des &lt;Values&gt; grâce à une clé composite</strong></h1>
<p>Avec Hadoop il est impossible d’effectuer un tri sur les valeurs. Par contre, à la place on peut placer les données qu’on veut trier dans la clé et ainsi utiliser une clé composite. Ensuite on utilise une classe de Partition spécifique ainsi que deux classes RawComparator afin de trier et partitionner notre map en sortie correctement.</p>
<p>La solution est d’utiliser un système de clé composite, dans notre exemple, je la nomme <strong>IsinKey</strong>.</p>
<p>L&#8217;objet IsinKey sera utilisé comme la <strong>Clé</strong> et contient :</p>
<ul>
<li>Une String key qui est la concaténation de l’ISIN puis du jour de l’extraction (par exemple : FR0010112524-20120913)</li>
<li>Une String hour qui correspond à l’heure d’une transaction</li>
</ul>
<p>Un objet <strong>Tick</strong> sera lui utilisé comme <strong>Valeur</strong> pour stocker le volume et le prix.</p>
<p>Ensuite, il va nous falloir définir 3 réglages dans le JobConf d’Hadoop :</p>
<ul>
<li>setPartitionerClass</li>
<li>setOutputValueGroupingComparator</li>
<li>setOutputKeyComparatorClass</li>
</ul>
<h2><strong>Le Partitioner</strong></h2>
<p>La première classe qu’on doit setter étend de org.apache.hadoop.mapred.Partitioner. Cette classe a pour unique fonction de déterminer dans quelle partition notre map de sortie doit aller. On ne peut aller en dessous de 0 ou au dessus de numPartitions -1 dans notre retour. En général il est préférable de récupérer le HashCode d’une partie de la Clé et d’y appliquer un modulo du nombre de partitions.</p>
<p>Dans notre exemple, on récupère le hashcode de notre Clé qu’on module ensuite avec le numPartitions.</p>
<pre class="brush: java; title: ; notranslate">public int getPartition(IsinKey key, Tick val, int numPartitions) {
   int hash = key.getKey().hashCode();
   return hash % numPartitions;
}</pre>
<h2><strong>L&#8217; Output Value Grouping Comparator</strong></h2>
<p>L’OutputValueGroupingComparator dans les paramètres du JobConf utilise un org.apache.hadoop.io.RawComparator. Le RawComparator est utilisé pour déterminer dans quel Reducer notre ligne de sortie de mapping doit aller. Ce RawComparator ne trie pas la liste de Valeurs du Reducer, mais trie l’entrée du Reducer,  pour que le Reducer sache quand un nouveau groupe commence.</p>
<p>Dans notre exemple, le grouping comparator va trier par la «Key» de notre object IsinKey (c’est a dire «Isin-date»</p>
<pre class="brush: java; title: ; notranslate">public int compare(WritableComparable w1, WritableComparable w2) {
   IsinKey k1 = (IsinKey)w1;
   IsinKey k2 = (IsinKey)w2;
   return k1.getKey().compareTo(k2.getKey());
}</pre>
<h2><strong>L’ Output Key Comparator</strong></h2>
<p>L’outputKeyComparatorClass dans les paramètre du JobConf utilise aussi un org.apache.hadoop.io.RawComparator. Ce RawComparator est utilisé pour trier les Clés que reçoit le Reducer. Les données envoyées au comparateur sont nos objets clés (IsinKey dans notre exemple). Il est très important aussi de retenir que le KeyComparator doit comprendre la règle définie dans l’OutputValueComparator.</p>
<p>Dans notre exemple, ça veut dire qu’on va d’abord comparer la Key de l’objet IsinKey, puis, si ces Key sont égales, alors on va comparer les champs Hours de l’objet IsinKey.</p>
<pre class="brush: java; title: ; notranslate">public int compare(WritableComparable w1, WritableComparable w2) {
   IsinKey k1 = (IsinKey)w1;
   IsinKey k2 = (IsinKey)w2;
   SimpleDateFormat f = new SimpleDateFormat(&quot;HH:mm:ss&quot;);
   int result = k1.getKey().compareTo(k2.getKey());

   if(0 == result) {
      try {
         result = f.parse(k1.getDate()).compareTo(f.parse(k2.getDate()));
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
return result;
}</pre>
<p>Grâce à ces trois classes redéfinies, le Reducer sera appelé une fois par clé IsinDate, puis lorsque l’on itère sur les «values», l’heure de la «Key» prend successivement ses différentes valeurs, ce qui nous permet  de déterminer la vwap à chaque tick, et de repartir à 0 pour chaque nouvelle journée</p>
<h1></h1>
<h1>Lancement en “Stand-Alone” et reste des classes</h1>
<p>Afin de démarrer le projet en mode «Stand-Alone», il suffit d’inclure les sources d’hadoop dans un projet eclipse par exemple, puis d’inclure ce projet dans le projet courant.</p>
<h2>CalcVWAPDriver</h2>
<pre class="brush: java; title: ; notranslate">public class CalcVWAPDriver {
   public static void main(String&#x5B;] args) throws IOException, InterruptedException, ClassNotFoundException {

      Configuration conf = new Configuration();
      GenericOptionsParser parser = new GenericOptionsParser(conf, args);
      args = parser.getRemainingArgs();
      conf.setStrings(&quot;ISIN&quot;, &quot;FR0010112524&quot;);
      conf.setStrings(&quot;DATES&quot;, &quot;09:00:00&quot;, &quot;12:00:00&quot;, &quot;17:00:00&quot;);
      Job job = new Job(conf, &quot;calcVWAP&quot;);
      job.setPartitionerClass(NaturalKeyPartitioner.class);
      job.setGroupingComparatorClass(NaturalKeyGroupingComparator.class);
      job.setSortComparatorClass(CompositeKeyComparator.class);
      job.setMapOutputKeyClass(IsinKey.class);
      job.setMapOutputValueClass(Tick.class);
      job.setInputFormatClass(TextInputFormat.class);
      job.setOutputFormatClass(TextOutputFormat.class);
      job.setMapperClass(CalcVWAPMapper.class);
      job.setReducerClass(CalcVWAPReducer.class);
      FileInputFormat.setInputPaths(job, new Path(args&#x5B;0]));
      FileOutputFormat.setOutputPath(job, new Path(args&#x5B;1]));
      System.out.println(job.waitForCompletion(true));
   }
}</pre>
<p>Dans l&#8217;exemple, on attribue en dur des valeurs ISIN et DATES dans la configuration d&#8217;Hadoop (lignes 7 et 8) afin d&#8217;y avoir accès dans le Mapper et le Reducer. Il est tout à fait envisageable de le rendre paramétrable avec les arguments passés à la méthode main.</p>
<h2>CalcVWAPMapper</h2>
<pre class="brush: java; title: ; notranslate">public class CalcVWAPMapper extends Mapper&lt;LongWritable, Text, IsinKey, Tick&gt; {
   private String currFile = null;
   private String currDate = null;
   private String currHour = null;
   private String currIsin = null;
   private List&lt;String&gt; isins = null;

   public String getFileName(Context context) {
      FileSplit fileSplit = (FileSplit)context.getInputSplit();
      return fileSplit.getPath().getName().toString();
   }

   protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
      if (!getFileName(context).equals(currFile)) {
         currFile = getFileName(context);
         currDate = currFile.replace(&quot;.txt&quot;, &quot;&quot;);
      }
      if (isins == null) {
         isins = Arrays.asList(context.getConfiguration().getStrings(&quot;ISIN&quot;));
      }

      String line = value.toString();
      if (line.startsWith(&quot;N;&quot;)) {
         String&#x5B;] result = line.split(&quot;;&quot;);
         if (result.length &gt;= 5) {
            if (isins.contains(result&#x5B;1])) {
               if (!result&#x5B;1].equals(currIsin)) {
                  currIsin = result&#x5B;1];
               }
               if (!result&#x5B;2].equals(currHour)) {
                  currHour = result&#x5B;2];
               }
               String volume = result&#x5B;3];
               String price = result&#x5B;4];
               context.write(new IsinKey(currIsin+&quot;-&quot;+currDate, currHour), new Tick(volume, price));
            }
         }
      }
   }
}</pre>
<p>Le Mapper est assez simple. Si ce n&#8217;est pas déjà fait, on prend le nom du fichier traité afin d&#8217;en extraire la date. Puis pareil, on récupère la liste d&#8217;ISIN entrée  en paramètre dans la JobConf Hadoop. (lignes 14 à 20)</p>
<p>Ensuite, on lit ligne par ligne le fichier. Si la ligne commence par &#8220;N;&#8221; alors on la split (lignes 23 et 24). L&#8217;Isin est la deuxième partie, l&#8217;heure la troisième, tandis que le volume et le prix sont respectivement les quatrièmes et cinquièmes parties.</p>
<p>Enfin, on écrit dans le context nos objets. D&#8217;un côté, la <strong>Clé </strong>composé de l&#8217;Isin-Date et de l&#8217;heure, et de l&#8217;autre côté la <strong>Valeur</strong> qui est composé du volume et du prix. (ligne 35)</p>
<h2>CalcVWAPReducer</h2>
<pre class="brush: java; title: ; notranslate">public class CalcVWAPReducer extends Reducer&lt;IsinKey, Tick, IsinKey, OutputVWAP&gt; {

   private String isin = null;
   private float vwap = 0.0f;
   private long totalVolume = 0;
   private List&lt;Date&gt; hoursList = null;
   private SimpleDateFormat f = new SimpleDateFormat(&quot;HH:mm:ss&quot;);

   protected void reduce(IsinKey key, Iterable&lt;Tick&gt; values, Context context) throws IOException, InterruptedException {
      IsinKey lastKey = null;
      OutputVWAP lastOutput = null;
      int currIdx = 0;

      if (hoursList == null) {
         hoursList = new ArrayList&lt;Date&gt;();
         String &#x5B;]dates = context.getConfiguration().getStrings(&quot;DATES&quot;);
         for (int i = 0; i &lt; dates.length; i++) {
            try {
               hoursList.add(f.parse(dates&#x5B;i]));
            } catch (Exception e) {
               e.printStackTrace();
            }
         }
      }

      for (Tick value : values) {
         try {
            if (currIdx &gt;= hoursList.size()) {
               return;
            }
            if (f.parse(key.getDate()).after(hoursList.get(currIdx))) {
               context.write(lastKey, lastOutput);
               if (currIdx &lt; hoursList.size()-1) {
                  currIdx++;
               } else {
                  return;
               }
            }
            Float price = Float.parseFloat(value.getPrice());
            Integer volume = Integer.parseInt(value.getVolume());
            vwap = (volume * price + totalVolume * vwap)
               / (totalVolume + volume);
            totalVolume += volume;

            lastKey = new IsinKey(key.getKey(), f.format(hoursList.get(currIdx)));
            lastOutput = new OutputVWAP(vwap);
         } catch (Exception e) {
            e.printStackTrace();
         }
      }
   context.write(lastKey, lastOutput);
   }
}</pre>
<p>Pour le Reducer, dans un premier temps, on récupère les heures rentrés dans la configuration d&#8217;hadoop (lignes 14 à 24). Le but est d&#8217;écrire en sortie la vwap pour les heures voulues et ordonnées.</p>
<p>Puis on itère sur les &lt;Values&gt;. A chaque itération on calcule la vwap et on stocke le retour. (lignes 26 à 50)</p>
<p>Si à l&#8217;itération d&#8217;après l&#8217;heure de la clé dépasse l&#8217;heure en paramètre, alors on écrit la dernière vwap calculé dans le context. Puis on passe à l&#8217;heure d&#8217;après en paramètre. Une fois qu&#8217;on a traité toutes les heures voulues, on sort de la méthode. (lignes 28 à 38)</p>
<p>Vous pouvez récupérer les sources complètes sur le <a href="https://github.com/InfineHub/VWAP-Hadoop">GitHub Infine</a></p>
<h1>Conclusion</h1>
<p>Nous avons donc vu comment calculer les vwap en utilisant le framework Hadoop en mode Stand-Alone.<br />
Mais la où Hadoop tire toute sa puissance, c&#8217;est dans la parallélisation et le clustering.<br />
Je vous montrerai donc dans un prochain article comment monter, configurer et utiliser un cluster avec Hadoop.</p><p>The post <a href="https://blog.infine.com/calcul-de-vwap-avec-hadoop-en-standalone-2214">Calcul de VWAP avec Hadoop en StandAlone</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/calcul-de-vwap-avec-hadoop-en-standalone-2214/feed</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>L&#8217;application Devoxx France d&#8217;In Fine est disponible sur le Google Play Store</title>
		<link>https://blog.infine.com/lapplication-devoxx-france-din-fine-est-disponible-sur-le-google-play-store-1954?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=lapplication-devoxx-france-din-fine-est-disponible-sur-le-google-play-store</link>
					<comments>https://blog.infine.com/lapplication-devoxx-france-din-fine-est-disponible-sur-le-google-play-store-1954#comments</comments>
		
		<dc:creator><![CDATA[Florian Boulay]]></dc:creator>
		<pubDate>Fri, 30 Mar 2012 11:21:45 +0000</pubDate>
				<category><![CDATA[Conférence]]></category>
		<category><![CDATA[Mobile (Android/iOS)]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[play framework]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=1954</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">2</span> <span class="rt-label rt-postfix">min.</span></span> In Fine, en tant que partenaire de l&#8217;évènement majeur qu&#8217;est Devoxx France, a le plaisir de mettre à disposition une application pour Devoxx France sur Android. Cette première version permet : De mettre en favoris vos sessions préférées De consulter le planning des sessions, et le détail des speakers De voir ce qui se passe &#8230;</p>
<p>The post <a href="https://blog.infine.com/lapplication-devoxx-france-din-fine-est-disponible-sur-le-google-play-store-1954">L’application Devoxx France d’In Fine est disponible sur le Google Play Store</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">2</span> <span class="rt-label rt-postfix">min.</span></span><p><a href="https://blog.infine.com/wp-content/uploads/2012/03/logo_devoxx_fr_negate.jpg" class="fancyboxgroup" rel="gallery-1954" title="Logo Devoxx France"><img decoding="async" src="https://blog.infine.com/wp-content/uploads/2012/03/logo_devoxx_fr_negate-300x154.jpg" alt="Logo Devoxx France" title="Logo Devoxx France" width="300" height="154" class="alignright size-medium wp-image-1984" srcset="https://blog.infine.com/wp-content/uploads/2012/03/logo_devoxx_fr_negate-300x154.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/03/logo_devoxx_fr_negate.jpg 400w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>In Fine, en tant que partenaire de l&#8217;évènement majeur qu&#8217;est Devoxx France, a le plaisir de mettre à disposition une application pour Devoxx France sur Android. Cette première version permet :</p>
<ul>
<li>De mettre en favoris vos sessions préférées</li>
<li>De consulter le planning des sessions, et le détail des speakers</li>
<li>De voir ce qui se passe sur Twitter avec le tag <em>devoxxfr</em></li>
<li>D&#8217;avoir accès au plan des 2 étages de l&#8217;hôtel où se déroulera la conférence</li>
<li>Et d&#8217;autres fonctionnalités&#8230;</li>
</ul>
<p><span id="more-1954"></span></p>
<p>Cette application fonctionne parfaitement sur téléphone , mais n&#8217;est pas encore totalement adaptée pour les tablettes. Dans les semaines qui viennent, nous allons continuer à mettre à jour l&#8217;application pour qu&#8217;elle soit la plus simple à utiliser possible. Voici une prévision des futures évolutions  :</p>
<ul>
<li>Complète adaptation de l&#8217;ergonomie de l&#8217;application aux tablettes</li>
<li>Ajout de la recherche sur les speakers. Actuellement elle ne fonctionne que sur les sessions</li>
<li>Quand on clique sur une salle, afficher la carte de l&#8217;étage correspondant</li>
<li>Pouvoir mettre en favori des speakers</li>
<li>Et bien d&#8217;autres choses qui dépendront des retours que nous aurons</li>
</ul>
<p>Nous sommes très fiers de mettre à disposition cette application. Elle sera mise en open source au moment de la conférence Devoxx France, certainement en licence Apache 2.<br />
Si vous rencontrez des problèmes ou avez des suggestions, écrivez un commentaire ici, ou envoyer un mail au compte indiqué sur la fiche du Google Play Store.</p>
<p>Dans la suite de l&#8217;article, nous allons approfondir l&#8217;aspect technique de l&#8217;application. Si au contraire vous souhaitez directement aller télécharger l&#8217;application, alors il faut aller ici : <a href="https://play.google.com/store/apps/details?id=com.infine.android.devoxx">Play Store</a></p>
<h2>Architecture technique</h2>
<figure id="attachment_1964" aria-describedby="caption-attachment-1964" style="width: 300px" class="wp-caption aligncenter"><a href="https://blog.infine.com/wp-content/uploads/2012/03/archi_appli_android_devoxx1.png" class="fancyboxgroup" rel="gallery-1954"><img decoding="async" class="size-medium wp-image-1964" src="https://blog.infine.com/wp-content/uploads/2012/03/archi_appli_android_devoxx1-300x164.png" alt="Architecture applicative de l'application Devoxx France In Fine" width="300" height="164" srcset="https://blog.infine.com/wp-content/uploads/2012/03/archi_appli_android_devoxx1-300x164.png 300w, https://blog.infine.com/wp-content/uploads/2012/03/archi_appli_android_devoxx1.png 660w" sizes="(max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-1964" class="wp-caption-text"><em>Architecture applicative de l&#039;application Devoxx France In Fine</em></figcaption></figure>
<p>Comme le montre le schéma ci-dessus, nous n&#8217;avons pas directement connecté l&#8217;application Android avec les API RESTful fournies par le site Devoxx. En effet les temps de réponse sont très variables, certains service ont déjà mis plus de 5 minutes à répondre. D&#8217;autre part, certains service renvoient des données en double ou incomplètes.<br />
Le serveur intérmédiaire permet donc de mieux maîtriser les données. Grâce à Play et à Mongo DB, les temps de réponse sont excellents et la charge que peut encaisser le serveur est bien au dessus de ce que nous atteindrons. Un test JMeter a mesuré que le serveur pouvait encaisser 300 requêtes par secondes. La plupart des requêtes répondent en moins de 0.1 seconde. Nous estimons que le serveur aurait à supporter, au maximum de son activité, 25 requêtes par minute</p><p>The post <a href="https://blog.infine.com/lapplication-devoxx-france-din-fine-est-disponible-sur-le-google-play-store-1954">L’application Devoxx France d’In Fine est disponible sur le Google Play Store</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/lapplication-devoxx-france-din-fine-est-disponible-sur-le-google-play-store-1954/feed</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Tomcat 6 &#8211; JNDI &#8211; password crypté et pool de connexion V7</title>
		<link>https://blog.infine.com/tomcat-6-jndi-password-crypte-et-pool-de-connexion-v7-1275?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tomcat-6-jndi-password-crypte-et-pool-de-connexion-v7</link>
					<comments>https://blog.infine.com/tomcat-6-jndi-password-crypte-et-pool-de-connexion-v7-1275#respond</comments>
		
		<dc:creator><![CDATA[Christian Nguyen Van Than]]></dc:creator>
		<pubDate>Thu, 02 Feb 2012 09:00:11 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[jndi]]></category>
		<category><![CDATA[pool]]></category>
		<category><![CDATA[tomcat]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=1275</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">3</span> <span class="rt-label rt-postfix">min.</span></span> Cet article est destiné à ceux qui ont la &#8216;chance&#8217; d&#8217;avoir Tomcat 6 comme serveur pour leurs applications et qui doivent paramétrer le pool de connexions par JNDI. Voici un petit article issu d&#8217;une demande d&#8217;un client. Le client : C&#8217;est bien la configuration par JNDI, ça serait mieux si on ne voyait pas le &#8230;</p>
<p>The post <a href="https://blog.infine.com/tomcat-6-jndi-password-crypte-et-pool-de-connexion-v7-1275">Tomcat 6 – JNDI – password crypté et pool de connexion V7</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">3</span> <span class="rt-label rt-postfix">min.</span></span><p>Cet article est destiné à ceux qui ont la &#8216;chance&#8217; d&#8217;avoir Tomcat 6 comme serveur pour leurs applications et qui doivent paramétrer le pool de connexions par JNDI.</p>
<p>Voici un petit article issu d&#8217;une demande d&#8217;un client.</p>
<p><strong><em>Le client</em></strong> : <em>C&#8217;est bien la configuration par JNDI, ça serait mieux si on ne voyait pas le mot de passe en clair <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f641.png" alt="🙁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> &#8230;</em></p>
<p><em><strong>Moi</strong>: No problem, everything is possible (enfin je crois) &#8230;</em></p>
<p>Effectivement c&#8217;est possible. D&#8217;après la documentation, il suffit d&#8217;implémenter une classe de type &#8216;factory&#8217; pour instancier les connexions avec la base de données.</p>
<p>Dans cet article, vous verrez comment crypter facilement un mot de passe ou autre mais aussi comment remplacer le pool de connexion DBCP  par le pool de connexion de Tomcat 7 (plus performant à  mon goût).</p>
<p>Tout ceci se fait en 3 étapes :</p>
<ul>
<li>Codage d&#8217;une classe &#8216;Factory&#8217;</li>
<li>Configuration de la ressource JNDI</li>
<li>Copier les jar dans le répertoire lib de Tomcat</li>
</ul>
<p><span id="more-1275"></span></p>
<p>Le processus de cryptage ne sera pas détaillé ici.<br />
Pour plus d&#8217;information, vous avez une classe &#8220;EncryptHelper&#8221; dans les sources (voir à la fin).</p>
<ul></ul>
<h2>1° La classe Factory</h2>
<p>Ici j&#8217;utilise le pool de connexion de Tomcat 7 :</p>
<pre class="brush: java; title: ; notranslate">
public class Tomcat7EncryptedFactory extends org.apache.tomcat.jdbc.pool.DataSourceFactory implements SecuredFactory{

	@SuppressWarnings(&quot;rawtypes&quot;)
	@Override
	public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
		Object o = super.getObjectInstance(obj, name, nameCtx, environment);
		if (o != null &amp;&amp; o instanceof org.apache.tomcat.jdbc.pool.DataSource) {
			org.apache.tomcat.jdbc.pool.DataSource ds = (org.apache.tomcat.jdbc.pool.DataSource) o;
			// recuperation du login et mot de passe cryptes
			String cryptedUsername = ds.getUsername();
			String cryptedPassword = ds.getDbProperties().getProperty(&quot;password&quot;);
			// on decrypte le password
			if (cryptedPassword != null &amp;&amp; cryptedPassword.length() &gt; 0) {
				String pwd = EncryptHelper.decryptData(secretKeyPassword, cryptedPassword);
				ds.setPassword(pwd);
			}
			// on decrypte le login
			if (cryptedUsername != null &amp;&amp; cryptedUsername.length() &gt; 0) {
				String username = EncryptHelper.decryptData(secretKeyUser, cryptedUsername);
				ds.setUsername(username);
			}
			// on set la taille initiale avec le minimum idle
			// on doit laisser le initialSize a 0 car il ne faut pas cree de connexion tout de suite car on a les identifiants cryptes.
			int minIdleSize = ds.getMinIdle();
			ds.setInitialSize(minIdleSize);
			ds.setConnectionProperties(ds.getConnectionProperties());

			// on ferme le pool deja parametre
			ds.close();
			// on recree le pool avec les nouveaux parametres
			ds.createPool();
			System.out.println(&quot;Initialisation de la datasource JNDI : OK&quot;);
			return ds;
		} else {
			System.out.println(&quot;Initialisation de la datasource JNDI : KO&quot;);
			return null;
		}
	}
}
</pre>
<p>Juste que la rien de difficile ^_^</p>
<h2 style="font-size: 1.5em">2° Configuration JNDI</h2>
<p>Extrait du fichier de configuration des ressources de Tomcat 6 (conf/context.xml)</p>
<div><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace;line-height: 18px">&lt;Resource name=&#8221;jdbc/mydatabase&#8221;</span></div>
<pre>    auth="Container" type="javax.sql.DataSource"
    factory="fr.cnvt.tomcat.Tomcat7EncryptedFactory"
    username="sD20tsCeFQPP3HuQV17yXw=="
    password="LoPCUiDWD47S6wIOTZWvBX7X9XTLt2vS9Sv52csoEGo="
    driverClassName="my.driver.class"
    url="my.jdbc.url"
    initialSize="0" maxActive="20" minIdle="5" maxIdle="10"
    validationQuery="SELECT 1 FROM Dual" validationQueryTimeout="300"
    maxWait="30000"
    removeAbandoned="true" removeAbandonedTimeout="600" logAbandoned="true"
    timeBetweenEvictionRunsMillis="20000"
    testWhileIdle="true"
    connectionProperties="CHARSET=utf8;" /&gt;</pre>
<p>Comme vous pouvez le voir, le login (username) et le mot de passe (password) sont cryptés.</p>
<p>Vous pouvez avoir le même login et mot de passe (c&#8217;est bizarre comme c&#8217;est fréquent&#8230;) , les 2 chaines cryptés seront différentes (normal j&#8217;utilise 2 clés de cryptage différentes ^_^)</p>
<h2>3° Librairies dans Tomcat</h2>
<p>Dernières étapes, il suffit de copier les fichiers tomcat-datasource-factory-1.0.0.jar et tomcat-jdbc-7.0.22.jar(dans le répertoire lib du zip) dans le répertoire &#8220;lib&#8221; de Tomcat 6.</p>
<p>Voila en 3 copié-collé, vous avez un pool de connexion sans mot de passe en clair ^_^</p>
<p>Pour générer vos propres login et password cryptés, il suffit d&#8217;utiliser la classe EncryptHelper comme ceci:</p>
<pre class="brush: java; title: ; notranslate">
	@Test
	public void generateEncryptedValues(){
		String login = &quot;monsupertest&quot;;
		String password = &quot;monsupertestaussi&quot;;
		String cryptedLogin = EncryptHelper.encryptData(SecuredFactory.secretKeyUser, login);
		String cryptedPassword = EncryptHelper.encryptData(SecuredFactory.secretKeyPassword, password);
		String decryptedLogin = EncryptHelper.decryptData(SecuredFactory.secretKeyUser, cryptedLogin);
		String decryptedPassword = EncryptHelper.decryptData(SecuredFactory.secretKeyPassword, cryptedPassword);
		assertEquals(login, decryptedLogin);
		assertEquals(password, decryptedPassword);
		System.out.println(&quot;Login crypte : &quot; + cryptedLogin);
		System.out.println(&quot;Mot de passe crypte : &quot; + cryptedPassword);
	}
</pre>
<p>Pour les curieux, le fichier zip contient également un pool DBCP et C3P0 qui gèrent aussi le login et mot de passe cryptés. Les clés de cryptages sont dans l&#8217;interface SecuredFactory.</p>
<p>Enjoy <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Les sources sont disponibles <a href="https://github.com/nguyenvanthan/Tomcat-Datasource-Factory" target="_blank">ici</a></p><p>The post <a href="https://blog.infine.com/tomcat-6-jndi-password-crypte-et-pool-de-connexion-v7-1275">Tomcat 6 – JNDI – password crypté et pool de connexion V7</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/tomcat-6-jndi-password-crypte-et-pool-de-connexion-v7-1275/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Devoxx 2011 &#8211; Comparatif de performances des frameworks web Java et plus encore &#8230;</title>
		<link>https://blog.infine.com/devoxx-2011-comparatif-de-performances-des-frameworks-web-java-et-plus-encore-1411?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=devoxx-2011-comparatif-de-performances-des-frameworks-web-java-et-plus-encore</link>
					<comments>https://blog.infine.com/devoxx-2011-comparatif-de-performances-des-frameworks-web-java-et-plus-encore-1411#respond</comments>
		
		<dc:creator><![CDATA[Christian Nguyen Van Than]]></dc:creator>
		<pubDate>Thu, 26 Jan 2012 11:00:56 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[devoxx]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[Spring MVC]]></category>
		<category><![CDATA[web]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=1411</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">3</span> <span class="rt-label rt-postfix">min.</span></span> Comparatifs de frameworks web à Devoxx 2011 Cet article a pour but de présenter brièvement la présentation de Stijn Van den Enden, lors du Devoxx 2011, sur les performances brutes de plusieurs frameworks connus et de partager quelques impressions sur ce sujet. Dans la première partie, il présente la méthodologie de tests ainsi que les &#8230;</p>
<p>The post <a href="https://blog.infine.com/devoxx-2011-comparatif-de-performances-des-frameworks-web-java-et-plus-encore-1411">Devoxx 2011 – Comparatif de performances des frameworks web Java et plus encore …</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">3</span> <span class="rt-label rt-postfix">min.</span></span><h1>Comparatifs de frameworks web à Devoxx 2011</h1>
<p>Cet article a pour but de présenter brièvement la présentation de  Stijn Van den Enden, lors du Devoxx 2011, sur les performances brutes de  plusieurs frameworks connus et de partager quelques impressions sur ce  sujet.</p>
<p>Dans la première partie, il présente la méthodologie de tests ainsi que les outils : le coté test.<br />
Dans la seconde partie, il nous montre les résultats qu&#8217;il a obtenu : le coté performance.<br />
Les slides de la présentation sont disponibles <a href="http://prezi.com/dr3on1qcajzw/www-world-wide-wait-devoxx-edition/">ici<br />
</a><br />
En résumé, on y voit la mise en place de la plateforme de tests ainsi que les outils utilisés.</p>
<p><span id="more-1411"></span></p>
<p><span style="text-decoration: underline">Plateforme de tests :</span></p>
<p><a href="https://blog.infine.com/wp-content/uploads/2011/11/plateforme-de-test1.png" class="fancyboxgroup" rel="gallery-1411"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-1450" src="https://blog.infine.com/wp-content/uploads/2011/11/plateforme-de-test1-1024x646.png" alt="plateforme de test" width="807" height="509" srcset="https://blog.infine.com/wp-content/uploads/2011/11/plateforme-de-test1-1024x646.png 1024w, https://blog.infine.com/wp-content/uploads/2011/11/plateforme-de-test1-300x189.png 300w, https://blog.infine.com/wp-content/uploads/2011/11/plateforme-de-test1.png 1439w" sizes="(max-width: 807px) 100vw, 807px" /></a></p>
<p><span style="text-decoration: underline">Conclusion :</span></p>
<p><a href="https://blog.infine.com/wp-content/uploads/2011/11/conclusion.png" class="fancyboxgroup" rel="gallery-1411"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-1449" src="https://blog.infine.com/wp-content/uploads/2011/11/conclusion-1024x283.png" alt="conclusion des tests" width="778" height="215" srcset="https://blog.infine.com/wp-content/uploads/2011/11/conclusion-1024x283.png 1024w, https://blog.infine.com/wp-content/uploads/2011/11/conclusion-300x82.png 300w, https://blog.infine.com/wp-content/uploads/2011/11/conclusion.png 1172w" sizes="(max-width: 778px) 100vw, 778px" /></a></p>
<p>Sa conclusion étant qu&#8217;en terme de performance brute, on a :</p>
<ol>
<li>GWT</li>
<li>Spring MVC</li>
<li>JSF 2.1.2 (Implementation Mojarra) ou Wicket</li>
<li>MyFaces (n&#8217;apparait pas dans le slide)</li>
</ol>
<p>Dans sa conclusion, qui n&#8217;apparait pas dans les slides, il dit aussi que  souvent, ce n&#8217;est pas le framework web qui est la principale cause de  la mauvaise performance d&#8217;une application.<br />
Pendant sa présentation,  il a souligné que le seul framework qui a posé problème est JSF 2  (problème de mémoire, ce qui ne m&#8217;étonne pas).<br />
Enfin, il nous rappelle qu&#8217;il faut aussi penser à la facilité de développement pour garder une bonne productivité.</p>
<h1>Avis personnel</h1>
<p>Pour ma part, la conclusion de Stijn Van den Enden ne doit pas tenir  compte du temps de rendu de la page, sinon Spring MVC serait 1er avec  GWT voire même devant.</p>
<p>Sur le point où il faut privilégier la  facilité de développement, on regrettera l&#8217;absence du comparatif des  frameworks Grails et Play qui sont tous deux excellents sur ce point.</p>
<p>Si  vous avez envie de changer de framework, d&#8217;après plusieurs  présentations vu sur le même sujet (par exemple l&#8217;article de Peter  Thomas), il faut se fixer un prototype de page à faire et si cela vous  parait trop difficile, c&#8217;est que celui-ci n&#8217;est surement pas adapté à  vos besoins.</p>
<p>Personnellement, je me demande pourquoi il y a tant  de personnes qui démarrent un projet encore avec JSF pour le web alors  qu&#8217;il a autant de problèmes de performance et qu&#8217;il est parfois si  compliqué de faire des choses simples avec (exemple pagination coté  serveur&#8230;).</p>
<p>Pour finir, son approche de Spring MVC est  intéressante car elle tend vers une pratique que j&#8217;ai adopté. Pour ma  part, j&#8217;ai abandonné l&#8217;idée que le Java était fait pour le web, car  c&#8217;est loin d&#8217;être le cas. Je préfère juste garder Java pour la partie  serveur et utiliser essentiellement des langages du web pour la vue :  très peu de JSP et EL(Expression Language) avec beaucoup de HTML, CSS et  JQuery (avec des données fournies au format JSON, d&#8217;ailleurs Spring MVC  fait très bien cela).</p>
<p>S&#8217;il fallait choisir un framework pour le  web en ce moment, je prendrai Grails pour un projet &#8216;from scratch&#8217; ou  Spring MVC pour un projet existant. Je n&#8217;ai pas assez d&#8217;expérience sur  GWT mais sa génération du javascript me fait hésiter&#8230; Je garderai dans  les deux cas, JQuery pour les composants riches car il existe  énormément de plugins pour ce framework javascript ou ExtJS ou voir même  du flash (flex).</p>
<p>En ce qui concerne Wicket, sa programmation  ressemble un peu à du Swing (client lourd) qui pourrait dérouter un  développeur web. Tapestry est intéressant mais le temps d&#8217;apprentissage  est assez important.</p>
<h1>Comparatif plus étendu</h1>
<p>Pour ceux qui comme moi ont regretté l&#8217;absence de Grails et Play, voici  un article intéressant avec un comparatif des deux et surtout une légère  &#8216;customisation&#8217; pour gagner en performance.<br />
Notez que l&#8217;utilisation de Japid pour Play booste grandement ses performances et que Netty semble plus rapide que Tomcat.</p>
<p><em>Extrait du site JT Dev (vous pouvez cliquer sur les images pour les agrandir)</em></p>
<p><em><br />
</em></p>
<p><a href="https://blog.infine.com/wp-content/uploads/2011/12/results_numbers.jpg" class="fancyboxgroup" rel="gallery-1411"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1838" src="https://blog.infine.com/wp-content/uploads/2011/12/results_numbers.jpg" alt="" width="511" height="445" srcset="https://blog.infine.com/wp-content/uploads/2011/12/results_numbers.jpg 511w, https://blog.infine.com/wp-content/uploads/2011/12/results_numbers-300x261.jpg 300w" sizes="(max-width: 511px) 100vw, 511px" /></a></p>
<p><a href="https://blog.infine.com/wp-content/uploads/2011/12/conc_users_graph.jpg" class="fancyboxgroup" rel="gallery-1411"><img loading="lazy" decoding="async" class="alignnone size-large wp-image-1839" src="https://blog.infine.com/wp-content/uploads/2011/12/conc_users_graph-1024x615.jpg" alt="" width="1024" height="615" srcset="https://blog.infine.com/wp-content/uploads/2011/12/conc_users_graph-1024x615.jpg 1024w, https://blog.infine.com/wp-content/uploads/2011/12/conc_users_graph-300x180.jpg 300w, https://blog.infine.com/wp-content/uploads/2011/12/conc_users_graph.jpg 1596w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p><a href="http://www.jtict.com/blog/rails-wicket-grails-play-lift-jsp/">Plus de détails ici</a></p><p>The post <a href="https://blog.infine.com/devoxx-2011-comparatif-de-performances-des-frameworks-web-java-et-plus-encore-1411">Devoxx 2011 – Comparatif de performances des frameworks web Java et plus encore …</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/devoxx-2011-comparatif-de-performances-des-frameworks-web-java-et-plus-encore-1411/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Devoxx 2011 &#8211; Ceylon</title>
		<link>https://blog.infine.com/devoxx-2011-ceylon-1414?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=devoxx-2011-ceylon</link>
					<comments>https://blog.infine.com/devoxx-2011-ceylon-1414#respond</comments>
		
		<dc:creator><![CDATA[Florian Boulay]]></dc:creator>
		<pubDate>Wed, 30 Nov 2011 15:00:49 +0000</pubDate>
				<category><![CDATA[Conférence]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[devoxx]]></category>
		<category><![CDATA[jvm]]></category>
		<category><![CDATA[language]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=1414</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">5</span> <span class="rt-label rt-postfix">min.</span></span> Ceylon est un nouveau langage s&#8217;exécutant sur la JVM. Il rejoint une liste désormais assez longue qui comprend notamment : Groovy Jython Jruby Scala Kotlin Fantom Gosu &#8230; Gavin King a créé Ceylon parce qu&#8217;il était frustré par les limitations de Java. Cette session a été animée par deux français, Emmanuel Bernard et Stéphane Epardaud &#8230;</p>
<p>The post <a href="https://blog.infine.com/devoxx-2011-ceylon-1414">Devoxx 2011 – Ceylon</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">5</span> <span class="rt-label rt-postfix">min.</span></span><p><a href="https://blog.infine.com/wp-content/uploads/2011/11/ceylon-logo.png" class="fancyboxgroup" rel="gallery-1414" title="ceylon logo"><img loading="lazy" decoding="async" src="https://blog.infine.com/wp-content/uploads/2011/11/ceylon-logo.png" alt="ceylon logo" title="ceylon logo" width="325" height="100" class="alignright size-full wp-image-1417" srcset="https://blog.infine.com/wp-content/uploads/2011/11/ceylon-logo.png 325w, https://blog.infine.com/wp-content/uploads/2011/11/ceylon-logo-300x92.png 300w" sizes="(max-width: 325px) 100vw, 325px" /></a></p>
<p>Ceylon est un nouveau langage s&#8217;exécutant sur la JVM. Il rejoint une liste désormais assez longue qui comprend notamment :</p>
<ul>
<li>Groovy</li>
<li>Jython</li>
<li>Jruby</li>
<li>Scala</li>
<li>Kotlin</li>
<li>Fantom</li>
<li>Gosu</li>
<li>&#8230;</li>
</ul>
<p>Gavin King a créé Ceylon parce qu&#8217;il était frustré par les limitations de Java. Cette session a été animée par deux français, Emmanuel Bernard et Stéphane Epardaud qui sont commiters sur le projet. Ils ont débuté la session en définissant les objectifs de Ceylon, avant de continuer sur ses fonctionnalités à l&#8217;aide de code. Je ne vais pas reproduire le code qu&#8217;ils ont utilisé pendant la présentation dans cet article, je vais essayer d&#8217;être plus concis.</p>
<p><span id="more-1414"></span></p>
<p>Emmanuel commence par nous indiquer les objectifs de Ceylon :</p>
<ul>
<li>Permettre d&#8217;écrire du code plus simple que l&#8217;équivalent en java</li>
<li>Éviter au développeur de tomber dans les principaux pièges de java</li>
</ul>
<p>Ceylon est pensé pour être lu facilement par des développeurs venant du monde Java. Emmanuel insiste bien sur ce point : Ceylon doit être simple à utiliser mais également simple à lire. Le code ne doit pas soulever d’ambiguïté. </p>
<h1>Principes de base</h1>
<h2>Classe simple</h2>
<pre class="brush: java; title: ; notranslate">
shared class User(String username, Natural age) {
    shared String username = username;
    shared Natural age = age;

    shared void printUser() {
        print(&quot;User name : &quot; username &quot; with age &quot; age &quot; is printed&quot;);
    }
}
</pre>
<p>Cette classe est courte, mais il y a déjà plusieurs choses à dire dessus :</p>
<ul>
<li>Le mot-clé <code>class</code> indique évidemment qu&#8217;il s&#8217;agit d&#8217;une déclaration de classe</li>
<li>Le mot-clé <code>shared</code> est l&#8217;équivalent du <code>public</code> de Java. Si le mot-clé <code>shared</code> est omis, alors la visibilité est privée (visibilité par défaut en Ceylon)</li>
<li>A la suite de la déclaration de la classe <code>User</code> se trouvent des paramètres <code>(String username, Natural age)</code>, il s&#8217;agit de la déclaration du constructeur. Je dis bien <strong>du</strong> car une Ceylon interdit la surcharge de méthode et donc un seul constructeur est autorisé</li>
<li><code>Natural</code> est l&#8217;objet représentant un nombre entier naturel. En Ceylon, il n&#8217;y a pas de type primitif</li>
<li>Les attributs de la classe sont obligatoirement initialisés, il n&#8217;y a pas de valeur par défaut, même <code>null</code> n&#8217;est pas implicite. Ici, les valeurs sont celles fournies au constructeur</li>
<li>La déclaration de la méthode <code>printUser</code> se fait comme en Java, le mot-clé <code>shared</code> en plus si on souhaite l&#8217;exposer</li>
<li>La concaténation de chaîne de caractère peut se faire sans le caractère <strong>+</strong>. La concaténation avec le caractère <strong>+</strong> fonctionne également</li>
</ul>
<h2>Méthodes</h2>
<pre class="brush: java; highlight: [2,6,12,22]; title: ; notranslate">
shared class Parent() {
    shared default void printMe() {
         print(&quot;I'm in parent class&quot;);
    }

    shared void printMessage(String messageToPrint = &quot;default argument value&quot;) {
         print(&quot;I'm in parent class and I print &quot; + messageToPrint);
    }
}

shared class Child() extends Parent() {
    shared actual void printMe() {
         print(&quot;I'm in child class&quot;);
    }
}

void testCeylon() {
    // appel de méthodes
    Parent p = Parent();
    p.printMe();
    p.printMessage(); // default value of parameter used - will work on milestone 2
    p.printMessage(&quot;message given as argument&quot;);  // classic call
    p.printMessage {  // name argument used
        messageToPrint = &quot;message with named arguments&quot;;
    };
}
</pre>
<p>Encore une fois, malgré la petite taille de code et sa lisibilité, plusieurs fonctionnalités sont à décrire :</p>
<ul>
<li>Comme dit plus haut, les méthodes ne sont pas surchargeables. Pour palier à cette obligation les paramètres peuvent avoir des valeurs par défaut (ligne 6), des <em>varargs</em> peuvent être utilisés (comme en java), ou des <em>union types</em> peuvent être utilisés (voir la doc pour plus de détails)</li>
<li>Les paramètres des méthodes sont nommés &#8211; ligne 22</li>
<li>Les méthodes peuvent être redéfinies dans les classes filles mais il faut l&#8217;autoriser explicitement grâce au mot clé <code>default</code> dans la classe parent (équivalent du <code>virtual</code> du C++ utilisé dans la classe parent) &#8211; ligne 2</li>
<li>Lors de la rédéfinition de la méthode dans une classe fille, il faut obligatoirement utiliser le mot-clé <code>actual</code> (équivalent à l&#8217;annotation <code>@Override</code> de Java) &#8211; ligne 12</li>
</ul>
<h2>null et immuabilité</h2>
<p>Par défaut toutes les variables sont immuables en Ceylon. Afin de les rendre modifiables il faut explicitement adapter la syntaxe de déclaration d&#8217;une variable en ajoutant le mot-clé <code>variable</code> et effectuer l&#8217;affectation avec l&#8217;opérateur <strong>:=</strong> : </p>
<pre class="brush: java; title: ; notranslate">
shared class ImmutableExample(Natural year) {
    // immutable
    Natural year = year;
    // Mutable
    variable Natural writableYear := year;
}
</pre>
<p>Afin d&#8217;éviter les trop nombreux <code>NullPointerException</code> de Java, une variable qui pourrait contenir la valeur  <code>null</code> doit être déclaré à l&#8217;aide d&#8217;un <code>?</code>. Ceci a des conséquences sur la manière d&#8217;utiliser ces variables comme le montre le code ci-dessous :</p>
<pre class="brush: java; title: ; notranslate">
// myBestVariable can be null
String? myBestVariable = functionThatCanReturnNull();
// to work on myBestVariable, a null check must be done
if (exists myBestVariable) {
    functionThatNeedAString(myBestVariable);
}
else {
    functionThatNeedAString(&quot;default value&quot;);
}
</pre>
<h2>Autres fonctionnalités</h2>
<p>Emmanuel et Stéphane ont présenté d&#8217;autres fonctionnalités importantes de Ceylon telles que les <em>union type</em> et les <em>intersection type</em>. Pour plus de détails, reportez vous à la <a href="http://ceylon-lang.org/documentation/tour/types/">documentation officielle.</a><br />
Malgré les arguments nommés, il est possible d&#8217;utiliser les generics. Les annotations sont également disponibles.<br />
La compatibilité entre Java et Ceylon est également disponible. Ceylon peut utiliser du code écrit en Java, et Java peut appeler du code Ceylon.</p>
<h1>En pratique</h1>
<p>Emmanuel et Stéphane, après avoir transmis les bases à l&#8217;auditoire, effectuent une démo en live de Ceylon dans Eclipse. Un plugin Eclipse a été développé et est déjà fontionnel. L&#8217;autocomplétion fonctionne bien, la coloration syntaxique et le refactoring également. Plus d&#8217;infos sur le <a href="https://github.com/ceylon/ceylon-ide-eclipse">repo git</a> associé.</p>
<p>Aucune version de Ceylon n&#8217;a encore été releasée. La prochaine version à sortir sera la milestone 1 qui ne comprendra pas encore toutes les fonctionnalités de la spécification. Trois milestones sont prévues avant que la version 1.0 ne sorte.</p>
<h2>Test de Ceylon</h2>
<p>Il est évidemment possible aujourd&#8217;hui de tester dès aujourd&#8217;hui Ceylon et pour cela, j&#8217;ai réalisé un petit screencast afin de vous montrer qu&#8217;avoir le compilateur Ceylon utilisable sur son poste est vraiment simple et rapide.</p>
<p>Les prérequis sont d&#8217;avoir sur sa machine Java 6, Ant et Git. Dans le screencast, je clone les trois repositories Git nécessaires à la création du compilateur. Chacun nécessite Ant afin d&#8217;être compilé. Une fois le compilateur généré, je le teste en compilant l&#8217;exemple de code que j&#8217;ai donné ci-dessus dans le paragraphe <em>Méthodes</em>, et je l&#8217;exécute.</p>
<p><iframe loading="lazy" src="http://player.vimeo.com/video/32661574?title=0&amp;portrait=0&amp;color=ff9933" width="660" height="371" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p>
<p>Pour ceux qui veulent tester, je vous retranscrits les commandes utilisées dans le screencast afin de faciliter le copier coller</p>

<table id="wp-table-reloaded-id-1-no-1" class="wp-table-reloaded wp-table-reloaded-id-1">
<thead>
	<tr class="row-1 odd">
		<th class="column-1">Repository Git</th><th class="column-2">Commande pour compiler le repository</th>
	</tr>
</thead>
<tbody class="row-hover">
	<tr class="row-2 even">
		<td class="column-1">git://github.com/ceylon/ceylon.language.git</td><td class="column-2">ant clean publish</td>
	</tr>
	<tr class="row-3 odd">
		<td class="column-1">git://github.com/ceylon/ceylon-spec.git</td><td class="column-2">ant clean tree publish</td>
	</tr>
	<tr class="row-4 even">
		<td class="column-1">git://github.com/ceylon/ceylon-compiler.git</td><td class="column-2">ant clean build</td>
	</tr>
</tbody>
</table>

<p>Une fois le compilateur généré, je l&#8217;ai testé. Mon fichier source se nomme <em>florian_boulay.ceylon</em> et se trouve dans le répertoire <em>samples</em>. Le répertoire <em>build</em> contient les fichiers Ceylon compilés. <em>testCeylon</em> correspond au nom de la fonction appelée pour lancer le programme.</p>

<table id="wp-table-reloaded-id-2-no-1" class="wp-table-reloaded wp-table-reloaded-id-2">
<tbody class="row-hover">
	<tr class="row-1 odd">
		<td class="column-1">Compilation du fichier Ceylon</td><td class="column-2">~/ceylon/ceylon-compiler/bin/ceylonc -src samples -out build samples/florian_boulay.ceylon</td>
	</tr>
	<tr class="row-2 even">
		<td class="column-1">Exécution du fichier Ceylon</td><td class="column-2">~/ceylon/ceylon-compiler/bin/ceylon -cp build/unversioned/default_module-unversioned.car testCeylon</td>
	</tr>
</tbody>
</table>

<p>Ceylon est un langage simple à comprendre pour qui vient de Java. En écrire est également à la portée de tous. Jusque là les objectifs de Gavin King sont atteints.</p>
<h2> Fin de la session</h2>
<p>Pour finir, Emmanuel nous indique que Ceylon a enfin sont site web : <a href="http://ceylon-lang.org">http://ceylon-lang.org</a></p>
<p>Il contient une documentation très complète, la spécification du langage écrite par Gavin King, un blog et tout ce qu&#8217;il faut pour contribuer au développement du langage. C&#8217;est là bas qu&#8217;il faut aller si vous souhaitez tester le langage qui n&#8217;a pas encore été releasé, mais peut être testé via la récupération du code source sur Github.</p>
<p>Comme vous le voyez, le logo de Ceylon est un éléphant, est-ce un hommage à PHP ? On peut lui souhaiter qu&#8217;il ait le même succès que PHP</p>
<p>De nombreux nouveaux langages ont émergé ces derniers mois fonctionnant sur la JVM (Eclipse Xtend, JetBrains Kotlin). Comme dit plus haut, Ceylon veut rester accessible à tout le monde en restant simple et facilement compréhensible. Est-ce que ces atouts seront suffisants pour faire de Ceylon une alternative à Java réellement utilisée, comme l&#8217;est Scala aujourd&#8217;hui ? Faites vous votre propre opinion et essayez le.</p><p>The post <a href="https://blog.infine.com/devoxx-2011-ceylon-1414">Devoxx 2011 – Ceylon</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/devoxx-2011-ceylon-1414/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>&#8220;==&#8221;.equals(&#8220;equals()&#8221;)</title>
		<link>https://blog.infine.com/equalsequals-8?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=equalsequals</link>
					<comments>https://blog.infine.com/equalsequals-8#respond</comments>
		
		<dc:creator><![CDATA[Florian Boulay]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 18:00:08 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[equals]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[performance]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=8</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">2</span> <span class="rt-label rt-postfix">min.</span></span> Les fondamentaux En java, la comparaison s&#8217;effectue principalement en utilisant 3 méthodes qui n&#8217;ont pas les mêmes buts : L&#8217;opérateur == est utilisé pour comparer les types primitifs et les objets. Il compare uniquement les références. Cela signifie que l&#8217;opérateur retournera &#8220;true&#8221; uniquement si les 2 objets comparés sont les mêmes en mémoire. La méthode &#8230;</p>
<p>The post <a href="https://blog.infine.com/equalsequals-8">“==”.equals(“equals()”)</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">2</span> <span class="rt-label rt-postfix">min.</span></span><h1>Les fondamentaux</h1>
<p>En java, la comparaison s&#8217;effectue principalement en utilisant 3 méthodes qui n&#8217;ont pas les mêmes buts :</p>
<ol>
<li>L&#8217;opérateur == est utilisé pour comparer les types primitifs et les objets. Il compare uniquement les références. Cela signifie que l&#8217;opérateur retournera &#8220;true&#8221; uniquement si les 2 objets comparés sont les mêmes en mémoire.</li>
<li>La méthode &#8216;equals()&#8217; permet de comparer 2 objets. Toutes les classes ont une méthode &#8216;equals()&#8217; héritée de la classe Object. Cette méthode compare la valeur de 2 objets. S&#8217;ils représentent la même chose, alors la méthode doit renvoyer &#8220;true&#8221;. Cette méthode est plus difficile qu&#8217;il n&#8217;y paraît à implémenter. Je pourrais revenir dessus ultérieurement dans un prochain article.</li>
<li>La méthode &#8216;compareTo()&#8217; permet de comparer 2 objets comme la méthode &#8216;equals()&#8217;. Contrairement à &#8216;equals()&#8217;, les classes ne définissent pas toutes cette méthode. Pour cela il faut hériter de l&#8217;interface Comparable. Cette méthode est utilisée pour pouvoir trier les objets l&#8217;implémentant. Si les 2 objets sont égaux, alors la méthode doit renvoyer 0 ; si un object O1 est considéré précédent un autre object O2 alors il faut renvoyer -1, si O2 précède O1 alors il faut renvoyer 1.</li>
</ol>
<pre class="brush: java; title: ; notranslate">
int i = 5, j = 5, k=8;
Integer int1 = new Integer(42) ;
Integer int2 = new Integer(42) ;
String str1 = &quot;Blog&quot;;

java.util.Date t1 = new java.util.Date();
Thread.sleep(1000l);
java.util.Date t2 = new java.util.Date();

System.out.println (i == j); // print true
System.out.println (int1 == int2); // print false
System.out.println (&quot;Blog&quot;.equals(str1)); // print true
System.out.println (str1 == &quot;Blog&quot;); // déconseillé mais écrit true
System.out.println (t1.compareTo(t2)); // print -1
</pre>
<p>Les comparaisons faites avec &#8216;equals()&#8217; ou &#8216;compareTo()&#8217; entre une variable et une constante doivent être réalisées comme à la ligne 13 de l&#8217;exemple précédent, c&#8217;est-à-dire qu&#8217;il faut comparer la constante avec la variable à tester. Ceci permet d&#8217;éviter une potentielle NullPointerException si l&#8217;on faisait &#8216;str1.equals(&#8220;Blog&#8221;)&#8217;.</p>
<h3>Le cas particuliers des enum</h3>
<p>Depuis java 5, les enum ont été introduits dans java. Les enum pourraient faire l&#8217;objet d&#8217;un article complet, mais il est bon de savoir que les enum ont été créés pour être comparés avec l&#8217;opérateur &#8216;==&#8217;. N&#8217;hésitez donc pas à les utiliser ! En plus d&#8217;être très lisibles, ils sont performants à l&#8217;usage.</p>
<p><span id="more-8"></span></p>
<h2>Les performances unitaires</h2>
<p>Si on a le choix, quel opérateur/méthode utiliser pour faire la comparaison ? Un des critères de choix peut être la performance. Sur une application où les comparaisons sont très nombreuses, il peut être judicieux d&#8217;optimiser les comparaisons et donc de choisir en connaissance de cause.</p>
<p>Voici le petit programme qui m&#8217;a permis de tester les performances de chacun. Dans la boucle j&#8217;ai utilisé une des instructions en commentaire à chaque test :</p>
<pre class="brush: java; title: ; notranslate">
long start = System.currentTimeMillis();
for (long l = 0; l &lt; 2 &lt;&lt; 60; l++) {
    // &quot;1&quot;.equals(&quot;1&quot;);
    // if (&quot;1&quot; == &quot;1&quot;) ;
    // &quot;1&quot;.compareTo(&quot;1&quot;);
}
long end = System.currentTimeMillis();
long timePassedInMs = end - start;
&amp;#91;/sourcecode&amp;#93;

Sans surprise les résultats sont les suivants :
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;==&lt;/strong&gt; : 978 ms de moyenne&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;equals()&lt;/strong&gt; : 991 ms de moyenne, soit 1.35 % que ==&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;compareTo()&lt;/strong&gt; : 1004 ms de moyenne, soit 2.62% de plus que ==&lt;/li&gt;
&lt;/ul&gt;
Quelques remarques sur ces résultats :
&lt;ol&gt;
	&lt;li&gt;La première instruction de la méthode 'equals()' de la classe String est de tester que les 2 objets comparés ont la même référence grâce à l'opérateur ==. La différence de temps entre == et 'equals()' s'explique donc uniquement par l'appel de la méthode et le retour de cette méthode. La différence vient aussi en partie du fait que la JVM va inliner la méthode 'equals()' et que ceci prend un certain temps.&lt;/li&gt;
	&lt;li&gt;'compareTo()' de la classe String effectue plusieurs boucles et de nombreux tests. Il est tout à fait logique qu'elle soit plus lente que les 2 autres comparateurs. Elle n'est pas optimisée pour gagner du temps comme l'est 'equals()'.&lt;/li&gt;
&lt;/ol&gt;
Ces quelques tests montrent bien que faire un == est plus rapide que l'appel d'un 'equals()', même si dans le cas de la classe String la différence est faible. Si vous avez le choix, privilégiez donc le == à 'equals()', même si les performances ont l'air très proches. Il peut arriver que vous utilisiez du code que vous ne pouvez pas modifier (API, framework, librairie partagée...) et dans ce cas la méthode 'equals()' peut être mal écrite et donc bien plus lente qu'elle ne l'est pour la classe String. Mais la question est la suivante : comment faire pour avoir le choix entre == et 'equals()' ? Je vais essayer de vous montrer une manière d'avoir le choix un peu plus loin dans ce post, après vous avoir expliqué un peu plus en détail comment fonctionne la classe String.

Nous laissons de côté 'compareTo()' pour la fin du post, car elle n'a pas la même utilité que les 2 autres méthodes de comparaison.
&lt;h2&gt;Le cas de la classe String&lt;/h2&gt;
Comme nous l'avons vu au début du post, les String doivent être comparés à l'aide de la méthode 'equals()'. Cependant il est tentant de vouloir utiliser l'opérateur == plus rapide et renvoyant quasiment tout le temps le même résultat que la méthode 'equals()'.

La classe String a beaucoup de particularités : c'est la seule classe que l'on peut initialiser sans appel explicite à un constructeur ou méthode statique ; elle possède des opérateurs surchargés... et d'autres spécificités encore. Une de ses particularité est que la JVM garde un pool d'instances des objets String. Ainsi, si deux String sont initialisés avec la même valeur, alors la JVM utilisera le même objet. Mais ce n'est pas vrai dans tous les cas. Regardons cet exemple :

&#x5B;sourcecode language=&quot;java&quot;]
final String TEST_VALUE = &quot;infine&quot;;

String inPool = &quot;infine&quot;;
String inPool2 = &quot;in&quot; + &quot;fine&quot;;
String noPool = new String(&quot;infine&quot;);
String suffix = &quot;fine&quot;;
String noPool2 = &quot;in&quot; + suffix;

System.out.println(inPool == TEST_VALUE);  // true
System.out.println(inPool2 == TEST_VALUE);  // true
System.out.println(noPool == TEST_VALUE);  // false
System.out.println(noPool2 == TEST_VALUE);  // false
</pre>
<p>En voyant les résultats, vous comprenez pourquoi il ne faut pas utiliser l&#8217;opérateur == pour la comparaison de String, le résultat est trop incertain. Lorsqu&#8217;un objet String est créé en utilisant l&#8217;opérateur new (comme pour un objet &#8220;normal&#8221; en fait), alors la JVM ne renvoie pas un objet String du pool, mais crée un nouvel objet (cas de l&#8217;objet &#8220;noPool&#8221;). De plus, si un objet String est calculé à l&#8217;exécution, par une concaténation par exemple, alors il n&#8217;est pas créé à partir du pool (cas de l&#8217;objet &#8220;noPool2&#8221;).</p>
<p>Pour se rendre compte de la manière dont le compilateur gère les String, voici un extrait du bytecode généré obtenu avec la commande <em>javap</em> :</p>
<pre class="brush: java; title: ; notranslate">
0:	ldc	#16; //String infine
2:	astore_1
3:	ldc	#16; //String infine
5:	astore_2
6:	ldc	#16; //String infine
8:	astore_3
</pre>
<p>Dans cet extrait, nous voyons que 3 variables font référence au même objet String valant &#8220;infine&#8221; (matérialisé par la référence #16). Ces 3 variables sont dans le code précédent TEST_VALUE, inPool et inPool2. Elles sont déclarées différemment mais le compilateur ne crée qu&#8217;une seul référence dans le pool de String de la JVM.</p>
<p>Si on souhaite forcer la récupération d&#8217;un objet String à partir du pool, alors il faut utiliser la méthode &#8216;intern()&#8217;. Reprenons l&#8217;exemple ci-dessus, mais en utilisant la méthode &#8216;intern()&#8217; :</p>
<pre class="brush: java; title: ; notranslate">
final String TEST_VALUE = &quot;infine&quot;;

String inPool = &quot;infine&quot;;
String inPool2 = &quot;in&quot; + &quot;fine&quot;;
String noPool = new String(&quot;infine&quot;);
String suffix = &quot;fine&quot;;
String notPool2 = &quot;in&quot; + suffix;

System.out.println(inPool == TEST_VALUE);  // true
System.out.println(inPool2 == TEST_VALUE);  // true
System.out.println(noPool.intern() == TEST_VALUE);  // true !
System.out.println(notPool2.intern() == TEST_VALUE);  // true !
</pre>
<p>Pour en savoir plus, n&#8217;hésitez pas à chercher <em>String literal pool</em> dans votre moteur de recherche préféré.</p>
<h1>Étude de cas : == doit renvoyer la même chose que equals()</h1>
<p>La classe String arrive bien à faire que dans certains cas == et &#8216;equals()&#8217; renvoient le même résultat. Nous allons donc essayer de faire mieux ! Nous allons donc partir d&#8217;un exemple simple dans lequel == et &#8216;equals()&#8217; ne sont pas interchangeables. Enfin, nous allons modifier le code afin d&#8217;utiliser == pour chaque comparaison, ceci dans le but d&#8217;avoir de bonnes performances, et une meilleure gestion de la mémoire.<br />
Bien entendu, nous pourrions gagner des performances de plein de manières différentes, mais ce n&#8217;est pas le but de cet article.</p>
<h2>Présentation du code existant</h2>
<p>Voici une classe permettant de gérer des couleurs RGB. Elle est donc composée de 3 attributs pouvant avoir une valeur comprise entre 0 et 255 chacun. Voici une partie du code de la classe avec son constructeur :</p>
<pre class="brush: java; title: ; notranslate">
public class RgbColor {

    private final int green;
    private final int red;
    private final int blue;

    public RgbColor(int green, int red, int blue) {
        super();
        this.green = green;
        this.red = red;
        this.blue = blue;
    }

    // ...other methods, including hashcode() and equals()
}
</pre>
<p>Comme nous le voyons, cette classe possède un unique constructeur. Il est donc possible de créer autant d&#8217;objet de type RgbColor que nous voulons, et s&#8217;ils sont identiques nous seront obligés de les comparer avec &#8216;Equals()&#8217; car chaque objet RgbColor sera différent.<br />
Ce constructeur est l&#8217;équivalent du &#8216;String test = new String(&#8220;test&#8221;)&#8217; vu précédemment dans ce post. Un appel crée toujours un objet.</p>
<h2>Pool de gestion des instances</h2>
<p>La version améliorée ajoute une nouvelle méthode statique. Cette méthode permet de créer un objet s&#8217;il n&#8217;existe pas encore dans le pool, ou alors de renvoyer l&#8217;objet existant si il a déjà été créé auparavant. Ce pattern est appelé static factory pattern, et est très bien décrit dans le livre <em>Effective Java</em> de <strong>Josh Bloch</strong>.</p>
<p>public class RgbColor {</p>
<p>    private final int green;<br />
    private final int red;<br />
    private final int blue;<br />
    // pooling<br />
    private static Map<Integer, RgbColor> pool = new ConcurrentHashMap<Integer, RgbColor>();</p>
<p>    /**<br />
     * Values must be between 0 and 255.<br />
     *<br />
     * @param green<br />
     * @param red<br />
     * @param blue<br />
     * @return<br />
     */<br />
    public static RgbColor getColor(int green, int red, int blue) {<br />
        if (!isAllowedColorValue(green) || !isAllowedColorValue(red) || !isAllowedColorValue(blue)) {<br />
            throw new IllegalArgumentException(&#8220;Allowed color value is between 0 and 255&#8221;);<br />
        }<br />
        // same key as hashcode<br />
        int key = green << 16 | red << 8 | blue;
        if (pool.containsKey(key)) {
            return pool.get(key);
        }
        RgbColor color = new RgbColor(green, red, blue);
        pool.put(key, color);
        return pool.get(key);
    }

    private static boolean isAllowedColorValue(int color) {
        if (color < 0 || color > 255) {<br />
            return false;<br />
        }<br />
        return true;<br />
    }</p>
<p>    private RgbColor(int green, int red, int blue) {<br />
        super();<br />
        this.green = green;<br />
        this.red = red;<br />
        this.blue = blue;<br />
    }</p>
<p>    @Override<br />
    public boolean equals(Object obj) {<br />
        if (this == obj)<br />
            return true;<br />
        if (obj == null)<br />
            return false;<br />
        if (getClass() != obj.getClass())<br />
            return false;<br />
        RgbColor other = (RgbColor) obj;<br />
        if (blue != other.blue)<br />
            return false;<br />
        if (green != other.green)<br />
            return false;<br />
        if (red != other.red)<br />
            return false;<br />
        return true;<br />
    }</p>
<p>    @Override<br />
    public int hashCode() {<br />
        return green << 16 | red << 8 | blue;
    }

    // ...other methods
}
[/sourcecode]

La méthode statique 'getColor()' permet de gérer un pool de toutes les instances de la classe RgbColor. De plus le constructeur est devenu privé, ce qui oblige l'utilisateur de cette classe à construire un object avec la méthode 'getColor()'. Contrairement à la classe String, tous les objets seront donc comparable avec l'opérateur == car un objet unique est créé par triplet rouge, vert, bleu.
Elle est l'équivalent de la construction d'un object String sans constructeur : String test = "test";

Je ne vous joins pas de classe de test, mais les performances sont désormais améliorées car toutes les instances de RgbColor sont comparables avec l'opérateur ==. La mémoire est également mieux gérée car toutes les instances se retrouvent dans le pool. On pourrait encore améliorer cette classe, en remplaçant la 'ConcurrentHashMap' par une <a href="http://www.javaspecialists.co.za/archive/Issue015.html">SoftHashMap</a> par exemple, avec un peu d&#8217;adaptation du code.</p>
<p><strong>Fichiers joints</strong><br />
Code source utilisé pour faire ce post : <a href='https://blog.infine.com/wp-content/uploads/2010/05/post-equals.zip'>Archive zip</a></p><p>The post <a href="https://blog.infine.com/equalsequals-8">“==”.equals(“equals()”)</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/equalsequals-8/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Java, enfin une roadmap !</title>
		<link>https://blog.infine.com/java-enfin-une-roadmap-157?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=java-enfin-une-roadmap</link>
					<comments>https://blog.infine.com/java-enfin-une-roadmap-157#respond</comments>
		
		<dc:creator><![CDATA[Antoine]]></dc:creator>
		<pubDate>Tue, 21 Sep 2010 18:38:47 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[j2se]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=157</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">&#60; 1</span> <span class="rt-label rt-postfix">min.</span></span> On n&#8217;y croyait plus, mais c&#8217;est arrivé ! Oracle vient de présenter à JavaOne ses projets pour Java SE et la communauté. Plusieurs points à retenir : &#8211; openJDK plus que jamais d&#8217;actualité, avec 2 releases majeures prévues en 2011 et 2012 qui seront la base pour JDK7 &#38; JDK8 &#8211; Fusion du meilleur de &#8230;</p>
<p>The post <a href="https://blog.infine.com/java-enfin-une-roadmap-157">Java, enfin une roadmap !</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">&lt; 1</span> <span class="rt-label rt-postfix">min.</span></span><p>On n&#8217;y croyait plus, mais c&#8217;est arrivé ! Oracle vient de <a href="http://www.oracle.com/us/corporate/press/173782">présenter à JavaOne</a> ses projets pour Java SE et la communauté. Plusieurs points à retenir :</p>
<p>&#8211; openJDK plus que jamais d&#8217;actualité, avec 2 releases majeures prévues en 2011 et 2012 qui seront la base pour JDK7 &amp; JDK8<br />
&#8211; Fusion du meilleur de jrockit et hotspot<br />
&#8211; JDK et JRE restent gratuit (!) avec la même license</p>
<p>Les interminables débats pour savoir si telle ou telle fonctionnalité  devait être intégrée dans la version 7 sont derrière nous. Pour ceux qui attendaient les closures (lambda expression), la modularité (jigsaw) ou encore le framework swing, on sait désormais que ça ne sera pas pour la version 7, et rien n&#8217;est promis pour la version 8.<br />
Pour la liste complètes des fonctionnalités , <a href="http://openjdk.java.net/projects/jdk7/features/">c&#8217;est par ici</a></p><p>The post <a href="https://blog.infine.com/java-enfin-une-roadmap-157">Java, enfin une roadmap !</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/java-enfin-une-roadmap-157/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
