<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://blog.netapsys.fr/index.php/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Netapsys Blog</title>
  <link>http://blog.netapsys.fr/index.php/</link>
  <atom:link href="http://blog.netapsys.fr/index.php/feed/author/ludovic_chaboud/rss2" rel="self" type="application/rss+xml"/>
  <description></description>
  <language>fr</language>
  <pubDate>Mon, 20 May 2013 16:57:21 +0200</pubDate>
  <copyright>Netapsys 2008 - 2011</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>TDD : Test Driven Development 2/2 - Mise en pratique</title>
    <link>http://blog.netapsys.fr/index.php/post/2013/04/28/TDD-%3A-Test-Driven-Development-2/2-D%C3%A9monstration</link>
    <guid isPermaLink="false">urn:md5:a67dbb583dd99f1376e7dd93d00295e2</guid>
    <pubDate>Mon, 20 May 2013 08:31:00 +0200</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Méthodologies et bonnes pratiques</category>
        <category>eclemma</category><category>Mockito</category><category>TDD</category><category>Test Driven Development</category>    
    <description>&lt;p&gt;Dans le post précédent &lt;a href=&quot;http://blog.netapsys.fr/index.php/post/2013/04/28/TDD-%3A-Test-Driven-Development&quot;&gt;TDD&amp;nbsp;: Test Driven Development 1/2 - Principes&lt;/a&gt;, nous avons vu les principes théoriques du &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Test%20Driven%20Development&quot;&gt;Test Driven Development&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Nous allons maintenant mettre &lt;strong&gt;en pratique&lt;/strong&gt; le cycle de développement du &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Pour rappel, les étapes du cycle du &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt; sont&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Définir la fonctionnalité à l'aide du test&lt;/strong&gt; =&amp;gt; Le test est en échec&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implémenter&lt;/strong&gt; =&amp;gt; Le test est en succès, la couverture est à 100%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Réécrire / Simplifier&lt;/strong&gt; =&amp;gt; Le test est en succès, la couverture est à 100%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/cycle.png&quot; alt=&quot;Cycle du TDD&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Nous allons voir dans ce post une mise en pratique du &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt; avec comme exemple le workflow d'un article d'un blog.&lt;/p&gt;    &lt;h3&gt;Exemple&amp;nbsp;: workflow d'un article&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;création / enregistrement de l'article&lt;/li&gt;
&lt;li&gt;transfert pour validation&lt;/li&gt;
&lt;li&gt;publication de l'article&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voyons comment réaliser la création et l'enregistrement de l'article en &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;Fonctionnalité 1&amp;nbsp;: Création d'un article vide&lt;/h2&gt;


&lt;h3&gt;TDD - Etape 1&amp;nbsp;: Définir la fonctionnalité&lt;/h3&gt;


&lt;p&gt;La fonctionnalité est définie par le test qui doit être unitaire.&lt;/p&gt;


&lt;p&gt;Nous nous focalisons sur le but de la fonctionnalité qui est ici de créer un article. Nous nous isolons de contexte technique et des autres fonctionnalités à l'aide de &quot;bouchons&quot;.&lt;/p&gt;


&lt;p&gt;Nous commençons par écrire un test pour définir la fonctionnalité sans écrire de code d'implémentation.&lt;/p&gt;


&lt;h4&gt;Test&amp;nbsp;: création d'un article&lt;/h4&gt;

&lt;pre&gt;
public class CreationArticleTest {
 @Test
 public void testCreationDUnArticleVide() {
   // Given
   ArticleService articleService = new ArticleServiceImpl();
   // When
   Article article = articleService.creerArticleVide();
   // Then
   assertNotNull(article);
 }
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Nous avons défini le contrat de notre première fonctionnalité&amp;nbsp;: créer un article vide.&lt;/p&gt;


&lt;p&gt;Ce test ne compile car il manque les classes d'implémentation.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/cap15.png&quot; alt=&quot;test en erreur&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Dans le cycle du TDD, nous venons de terminer la première étape&amp;nbsp;: définir le contrat de l'implémentation, c'est à dire ce que doit faire notre programme.&lt;/p&gt;


&lt;h3&gt;TDD - Étape 2&amp;nbsp;: Définir l'implémentation&lt;/h3&gt;


&lt;p&gt;Nous passons à la deuxième étape&amp;nbsp;: définir l'implémentation jusqu'à ce que le test passe.&lt;/p&gt;


&lt;h4&gt;Création des classes, interfaces et méthodes manquantes&lt;/h4&gt;

&lt;p&gt;Pour cela nous allons nous servir du code écrit dans le test pour créer l'implémentation manquante.&lt;/p&gt;


&lt;p&gt;Les classes et les méthodes manquantes sont indiquées en rouge et en erreur par l'IDE eclipse.&lt;/p&gt;


&lt;p&gt;Durant cette étape, nous créons ainsi la classe Article, l'interface et la classe d'implémentation du service ArticleService.&lt;/p&gt;


&lt;h4&gt;Classe Article&lt;/h4&gt;
&lt;pre&gt;
public class Article {
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Interface ArticleService&lt;/h4&gt;
&lt;pre&gt;
public interface ArticleService {
 Article creerArticleVide();
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Classe ArticleServiceImpl&lt;/h4&gt;
&lt;pre&gt;
public class ArticleServiceImpl  implements ArticleService {
 public Article creerArticleVide() {
   return new Article();
 }
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
L'exécution du test est maintenant en succès.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/cap12.png&quot; alt=&quot;test en succès&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Le plugin &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/eclemma&quot;&gt;eclemma&lt;/a&gt; pour eclipse nous indique que la couverture du test est à 100%&amp;nbsp;: tout ce que nous venons de créer était nécessaire au test, nous n'avons rien ajouté d'inutile pour répondre au contrat de notre fonctionnalité.&lt;/p&gt;


&lt;h4&gt;Couverture du test&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/cap13.png&quot; alt=&quot;couverture du test&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;h4&gt;Couverture du projet&lt;/h4&gt;

&lt;p&gt;La couverture du projet est à 100%&amp;nbsp;:
&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/cap11.png&quot; alt=&quot;couverture à 100%&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Nous venons de terminer la deuxième étape dans le cycle du &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt;&amp;nbsp;: définir l'implémentation jusqu'à ce que le test soit en succès, avec une couverture à 100%.&lt;/p&gt;


&lt;h3&gt;TDD - Étape 3&amp;nbsp;: Réécrire le code pour simplifier et réorganiser&lt;/h3&gt;


&lt;p&gt;Cette étape consiste à simplifier ou à réorganiser le code existant avec les modifications que nous venons d'effectuer.&lt;/p&gt;


&lt;p&gt;Ceci peut être par exemple de factoriser du code dupliqué, de simplifier des boucles de traitement ou les conditions des tests.&lt;/p&gt;


&lt;p&gt;Par contre il ne s'agit pas de réécrire toute l'implémentation existante. Pour nous limiter dans cette étape, nous ne devons pas modifier les tests existants.&lt;/p&gt;


&lt;p&gt;Le code dans notre exemple étant simple, nous n'avons pas besoin d'effectuer de réécriture.&lt;/p&gt;


&lt;p&gt;Nous avons terminé la première fonctionnalité et nous pouvons passer à la fonctionnalité suivante.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;


&lt;h2&gt;Fonctionnalité 2&amp;nbsp;: Enregistrement de l'article&lt;/h2&gt;


&lt;h3&gt;TDD - Étape 1&amp;nbsp;: Définir la fonctionnalité&lt;/h3&gt;


&lt;p&gt;Suite à la fonctionnalité de création de l'article, nous souhaitons maintenant enregistrer cet article avec un nom d'auteur, un titre, un contenu. La date d'enregistrement sera définie automatiquement sur l'article.&lt;/p&gt;


&lt;p&gt;Nous imposons ce contrat dans notre test unitaire d'enregistrement d'article.&lt;/p&gt;


&lt;h4&gt;Test&amp;nbsp;: enregistrement d'un article&lt;/h4&gt;
&lt;pre&gt;
@Test
public void testEnregistrementDUnArticle() {
 // Given
 Article article = new Article();
 article.setAuteur(&amp;quot;test auteur&amp;quot;);
 article.setTitre(&amp;quot;test titre&amp;quot;);
 article.setContenu(&amp;quot;test contenu&amp;quot;);
 
 ArticleServiceImpl articleServiceImpl = new ArticleServiceImpl();
 ArticleService articleService = articleServiceImpl;

 ArticleDAO articleDAO = Mockito.mock(ArticleDAO.class);
 articleServiceImpl.setArticleDAO(articleDAO);
 
 // When
 articleService.save(article);
 
 // Then
 assertNotNull(article.getDateEnregistrement()); 
 Mockito.verify(articleDAO).save(article);
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
Nous venons d'écrire le contrat correspondant à notre fonctionnalité.&lt;/p&gt;


&lt;p&gt;Dans notre test, nous nous sommes focalisés sur l'intention de la fonctionnalité et non sur l'aspect technique. Pour cela nous avons utilisé des &quot;bouchons&quot; à l'aide de &quot;mocks&quot; via &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Mockito&quot;&gt;Mockito&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Nous nous concentrons ainsi sur le plus important&amp;nbsp;: le code métier qui répond aux règles métier. Nous verrons l'aspect technique plus tard.&lt;/p&gt;


&lt;p&gt;Ici la gestion de la persistance de l'article se fera par la DAO. En bouchonnant la DAO, nous ne nous occupons pas de l'implémentation de la DAO. Nous déléguons ceci à plus tard. Nous vérifions uniquement que nous faisons appel à la méthode d'enregistrement de l'article de la DAO avec en paramètre l'article à enregistrer. Nous écrions plus tard, toujours en mode &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt;, le contrat de la méthode d'enregistrement de la DAO.&lt;/p&gt;


&lt;p&gt;De même si nous avions eu à faire des calculs complexes. Nous aurions bouchonné la classe de calcul et nous aurions uniquement testé que nous avons effectivement fait appel à cette méthode de calcul.&lt;/p&gt;


&lt;h4&gt;Le test ne compile pas&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/cap16.png&quot; alt=&quot;test en échec&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;
Le code ne compile pas car l'implémentation n'existe pas.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;
Nous venons de terminer notre première étape dans le cycle du &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt;.&lt;/p&gt;


&lt;h3&gt;TDD - Étape 2&amp;nbsp;: Définir l'implémentation&lt;/h3&gt;


&lt;p&gt;Nous passons à la deuxième étape&amp;nbsp;: définir l'implémentation jusqu'à ce que le test passe.&lt;/p&gt;


&lt;p&gt;Pour cela nous allons de nouveau nous servir du code écrit dans le test et des fonctionnalités de l'IDE pour créer l'implémentation manquante.&lt;/p&gt;


&lt;p&gt;Nous avons ainsi de nouvelles propriétés dans la classe Article, une nouvelle interface ArticleDAO et pour le service ArticleService une nouvelle méthode ainsi que l'injection de la DAO.&lt;/p&gt;


&lt;h4&gt;Classe Article&lt;/h4&gt;
&lt;pre&gt;
public class Article {
 private String auteur;
 private String titre;
 private String contenu;
 private Date dateEnregistrement;
 ...getters / setters...
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Interface de ArticleDAO&lt;/h4&gt;

&lt;p&gt;Nous avons uniquement besoin de l'interface pour la DAO pour ne pas nous soucier de l'implémentation.&lt;/p&gt;
&lt;pre&gt;
public interface ArticleDAO {
 void save(Article article);
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Interface du service ArticleService&lt;/h4&gt;
&lt;pre&gt;
public interface ArticleService {
 Article creerArticleVide();
 void saveArticle(Article article);
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;La classe du service ArticleServiceImpl&lt;/h4&gt;
&lt;pre&gt;
public class ArticleServiceImpl implements ArticleService {
 private ArticleDAO articleDAO;

 public Article creerArticleVide() {
   return new Article();
 }
 
 public void saveArticle(Article article) {
   article.setDateEnregistrement(new Date());
   articleDAO.save(article);
 }

 public void setArticleDAO(ArticleDAO articleDAO) {
   this.articleDAO = articleDAO;
 }
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
Le code compile, les tests sont maintenant en succès.&lt;/p&gt;


&lt;h4&gt;Atteindre la couverture à 100%&lt;/h4&gt;

&lt;p&gt;Cependant la couverture n'est pas à 100% car les méthodes &quot;getXXX&quot; des propriétés de la classe Article ne sont actuellement pas utilisées. Hors, les méthodes getters / setters sur les beans métiers sont obligatoires même si elles ne sont pas utilisées dans l'immédiat.&lt;/p&gt;


&lt;p&gt;L'objectif de la couverture à 100% est de vérifier qu'aucun code n'est inutile. C'est pourquoi le test des méthodes getters / setters des beans métiers est un effort à faire pour atteindre la cible des 100%.&lt;/p&gt;


&lt;p&gt;Pour cela, les trois lignes suivantes sont ajoutées à la fin du test&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
 assertEquals(&amp;quot;test auteur&amp;quot;,article.getAuteur()); 
 assertEquals(&amp;quot;test titre&amp;quot;,article.getTitre()); 
 assertEquals(&amp;quot;test contenu&amp;quot;,article.getContenu()); 
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Notre objectif est atteint&amp;nbsp;: la couverture est maintenant à 100%.&lt;/p&gt;


&lt;h4&gt;Couverture du test&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/cap18.png&quot; alt=&quot;couverture du test&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;h4&gt;Couverture du projet&lt;/h4&gt;

&lt;p&gt;La couverture du projet est à 100%&amp;nbsp;:
&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/cap17.png&quot; alt=&quot;couverture du projet à 100%&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Nous pouvons passer à l'étape 3 du cycle du TDD.&lt;/p&gt;


&lt;h3&gt;TDD - Étape 3&amp;nbsp;: Réécrire le code pour simplifier et réorganiser&lt;/h3&gt;


&lt;p&gt;Le code étant déjà simple, nous n'avons pas besoin de réécrire le code.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;Nous avons vu un exemple de mise en pratique du &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Cette démarche change la façon de penser en se focalisant sur les règles fonctionnelles avant de réfléchir à comment les implémenter.&lt;/p&gt;


&lt;p&gt;La pratique du &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt; demande un temps d'adaptation, mais apporte de nombreux bénéfices.&lt;/p&gt;


&lt;p&gt;Vous pouvez par exemple tester le &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt; sur l'exemple de ce post pour vous entraîner.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h2&gt;Références&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eclemma.org/&quot; title=&quot;eclemma&quot;&gt;eclemma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/mockito/&quot; title=&quot;Mockito&quot;&gt;Mockito&lt;/a&gt; - &lt;a href=&quot;http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html&quot; title=&quot;Mockito - Documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Test Driven Design - &lt;a href=&quot;http://fr.wikipedia.org/wiki/Test_Driven_Development&quot; title=&quot;TDD&quot;&gt;Wikipedia Français&lt;/a&gt; - &lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot; title=&quot;TDD&quot;&gt;Wikipedia Anglais&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2013/04/28/TDD-%3A-Test-Driven-Development-2/2-D%C3%A9monstration#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2013/04/28/TDD-%3A-Test-Driven-Development-2/2-D%C3%A9monstration#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/589</wfw:commentRss>
      </item>
    
  <item>
    <title>TDD : Test Driven Development - Partie 1 - Principes</title>
    <link>http://blog.netapsys.fr/index.php/post/2013/04/28/TDD-%3A-Test-Driven-Development</link>
    <guid isPermaLink="false">urn:md5:89d18511b801ee95a90e750f0b29829e</guid>
    <pubDate>Tue, 30 Apr 2013 08:15:00 +0200</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Méthodologies et bonnes pratiques</category>
        <category>TDD</category><category>Test Driven Development</category>    
    <description>&lt;p&gt;Le développement piloté par les tests ou &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/TDD&quot;&gt;TDD&lt;/a&gt; &quot;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Test%20Driven%20Development&quot;&gt;Test Driven Development&lt;/a&gt;&quot; nous impose de commencer par écrire les tests unitaires avant le code de la vraie classe d'implémentation.&lt;/p&gt;


&lt;p&gt;Ce fonctionnement apporte de nombreux avantages, mais est difficile à appréhender car il change notre logique d'écriture du code.&lt;/p&gt;


&lt;p&gt;Nous avons à écrire le contrat que doit réaliser la méthode testée AVANT d'écrire cette méthode. Ce contrat est écrit dans le test unitaire et impose le comportement d'une méthode en fonction de données de départ.&lt;/p&gt;


&lt;p&gt;Ce post a pour objectif de vous présenter les principes du TDD ainsi que le cycle de développement en mode TDD. Un second post vous présentera une démonstration du TDD.&lt;/p&gt;    &lt;h2&gt;Règles du TDD&lt;/h2&gt;


&lt;p&gt;Le fonctionnement en mode TDD impose le respect des trois lois suivantes&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Première loi&amp;nbsp;: Toujours écrire le test avant d'écrire le code de la méthode testée.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous ne devez pas écrire le code d'implémentation cible tant que vous n'avez pas écrit le code du test associé. C'est à dire qu'il est nécessaire d'avoir imposé le contrat avant d'écrire le code cible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deuxième loi&amp;nbsp;: Définir dans le test les comportements et les résultat attendus de la méthode testée.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le code de test impose le respect d'une règle métier.
Ce test est en échec dans un premier temps&amp;nbsp;: en effet, le code d'implémentation testé n'existe pas ou ne compile pas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Troisième loi&amp;nbsp;: Ecrire dans la méthode testée le code suffisant afin que le passage du test soit en succès.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le code d'implémentation doit rester simple afin de gagner en efficacité. C'est pourquoi il est nécessaire de réécrire le code une fois que tous les tests sont en succès. De plus, les tests doivent rester en succès à la fin de la réécriture du code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quatrième loi&amp;nbsp;: La couverture du code testé est à 100%.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La couverture du code à 100% permet d'éviter d'avoir du code non testé ou inutile qui peut être source d'erreurs.&lt;/p&gt;


&lt;h2&gt;Cycle du TDD&lt;/h2&gt;

&lt;p&gt;Le TDD repose sur les règles précédentes et permet d'avoir le cycle de développement suivant&amp;nbsp;:&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/TDD/schema.png&quot; alt=&quot;TDD - Cycle&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ajout d'un nouveau test / Modification d'un test en cas de changement d'une règle existante&lt;/li&gt;
&lt;li&gt;Ecrire le contenu de ce test pour imposer le comportement à la méthode d'implémentation testée&lt;/li&gt;
&lt;li&gt;Lancer tous les tests et vérifier que seul ce test ne passe pas&lt;/li&gt;
&lt;li&gt;Ecrire le code minimal dans la méthode testée pour réussir le test&lt;/li&gt;
&lt;li&gt;Lancer tous les tests et vérifier qu'ils sont tous en succès&lt;/li&gt;
&lt;li&gt;Vérifier que la couverture du code testé est à 100%&lt;/li&gt;
&lt;li&gt;Réécrire le code d'implémentation testé pour le nettoyer et le simplifier&lt;/li&gt;
&lt;li&gt;Lancer tous les tests et vérifier qu'ils sont tous en succès&lt;/li&gt;
&lt;li&gt;Vérifier que la couverture du code testé est à 100%&lt;/li&gt;
&lt;li&gt;Recommencer ce cycle pour ajouter ou modifier un test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ce cycle est à effectuer à chaque changement dans le code de l'application.&lt;/p&gt;


&lt;p&gt;L'intégration continue permet de valider que le code d'implémentation respecte toujours les contrats imposés par les tests.&lt;/p&gt;


&lt;h2&gt;Conditions du TDD&lt;/h2&gt;


&lt;p&gt;Le développement en mode TDD impose les conditions suivantes pour être efficace&amp;nbsp;:&lt;/p&gt;


&lt;h3&gt;Couverture à 100%&lt;/h3&gt;

&lt;p&gt;La couverture du code testée doit toujours être de 100%. Ceci permet de ne pas avoir de code non testé ou inutile.
Ceci est possible dans les classes non dépendantes d'un socle technique.&lt;/p&gt;


&lt;p&gt;Dans eclipse, il est possible d'utiliser le plugin &lt;a href=&quot;http://www.eclemma.org/&quot;&gt;Eclemma&lt;/a&gt; pour vérifier la couverture du code à 100%.&lt;/p&gt;


&lt;h3&gt;Avoir des tests lisibles&lt;/h3&gt;

&lt;p&gt;Ce fonctionnement impose également de conserver du code de test propre, lisible et compréhensible en utilisant des noms de variable et une organisation compréhensibles.&lt;/p&gt;


&lt;p&gt;Les tests unitaires deviennent la documentation fonctionnelle du code métier. C'est pourquoi le nom de la méthode de test doit être le plus explicite possible afin de savoir ce qu'elle teste sans même à avoir à lire le code. Il ne faut pas hésiter à avoir écrire le nom de la méthode sous forme de phrase ou avec le code de la règle métier testée.&lt;/p&gt;


&lt;h3&gt;Le test doit être unitaire&lt;/h3&gt;

&lt;p&gt;Les tests unitaires doivent s'exécuter le plus possible en dehors du contexte applicatif, c'est à dire sans avoir besoin de lancer le contexte Spring, d'avoir accès à la base de données ou à un serveur d'envoi de mails SMTP. Ainsi les tests pourront être lancés dans n'importe quel environnement.&lt;/p&gt;


&lt;p&gt;Pour cela, le test doit rester unitaire, c'est à dire découplé du reste du contexte applicatif. Ainsi, dans le test, seule la classe testée est réellement instanciée, et toutes ses dépendances sont mockées. C'est à dire que les classes associées à la classe testée sont remplacées par des classes &quot;mock&quot; qui vont permettre de simuler le fonctionnement de leurs méthodes et de vérifier que ses méthodes sont bien appelées.&lt;/p&gt;


&lt;h3&gt;Le test doit s'exécuter rapidement&lt;/h3&gt;

&lt;p&gt;Le fait que le test est unitaire et découplé de l'environnement permet également de garantir que le test s'exécutera rapidement. En effet si l'exécution des tests est rapide, on aura plus tendance à lancer fréquemment l'intégralité des tests pour vérifier les non régressions.&lt;/p&gt;


&lt;p&gt;D'autre part, les tests ne doivent par dépendre les uns des autres afin de pouvoir être lancés unitairement dans n'importe quel ordre. Ainsi un test ne doit pas dépendre du résultat d'un test précédent.&lt;/p&gt;


&lt;h3&gt;Le test doit échouer si une condition n'est pas remplie&lt;/h3&gt;

&lt;p&gt;Il est important qu'un test échoue dès qu'un comportement ou que le résultat n'est pas cohérent ou pas celui attendu. Ceci permet de détecter les anomalies le plus tôt possible. Ainsi il est nécessaire que le test unitaire remonte les exceptions au lieu de les gérer, de les mettre dans un fichier de log ou voir de les masquer. Ceci permet de les visualiser en cas d'échec.&lt;/p&gt;


&lt;h3&gt;Toujours écrire les tests avant le code&lt;/h3&gt;

&lt;p&gt;Il est important de toujours conserver l'ordre d'écriture&amp;nbsp;: c'est à dire d'écrire les tests avant d'écrire le code d'implémentation.&lt;/p&gt;


&lt;p&gt;Cet ordre permet de garder une &lt;strong&gt;dynamique&lt;/strong&gt; dans le développement de l'application.&lt;/p&gt;


&lt;p&gt;En effet, ceci garantit que le code d'implémentation sera toujours testable et ne sera pas trop complexe pour être testé. Cela évite également le découragement dans le cas où nous avons à écrire le test après avoir écrit notre méthode d'implémentation et que ce code est devenu trop complexe.&lt;/p&gt;


&lt;p&gt;De plus, le fait d'imposer les contrats de la méthode testée rassure le développeur car le test garantit que le code développé fonctionne.&lt;/p&gt;


&lt;h2&gt;Bénéfices&lt;/h2&gt;

&lt;h3&gt;Respect constant dans le temps des règles métiers&lt;/h3&gt;

&lt;p&gt;En écrivant les tests unitaires avant d'écrire le code de la méthode cible, cela nous oblige d'écrire chaque contrat dans ce test unitaire qui devient alors le garant du respect des règles métiers. Chaque méthode du test unitaire indique qu'une règle métier sera respectée par la méthode cible. Ainsi en cas de modification du code cible entraînant une échec du test, cela permet de détecter les régressions sans même avoir besoin de lancer l'application.&lt;/p&gt;


&lt;p&gt;La plate-forme d'intégration continue permet cette détection à intervalle régulier et pour l'ensemble de l'équipe travaillant sur le projet. Le nommage de la méthode et de la classe de test doit être suffisamment lisible pour identifier la règle en échec sans même avoir besoin d'ouvrir la classe de test.&lt;/p&gt;


&lt;h3&gt;Simplification du code&lt;/h3&gt;

&lt;p&gt;D'autre part, le fait d'écrire le code minimal permettant de répondre au contrat décrit par le test permet la simplification du code.&lt;/p&gt;


&lt;p&gt;Nous n'avons plus à effectuer de programmation défensive, ainsi pas besoin de tester le fait que tel argument de la méthode est null&amp;nbsp;: les tests s'en chargent. Le seul cas où cela est nécessaire est s'il s'agit de méthodes de bibliothèques ou d'API publiques.&lt;/p&gt;


&lt;p&gt;Nous n'avons plus tendance à ajouter de méthodes ou de classes utilitaires supplémentaires. Nous allons à l'essentiel, c'est à dire les éléments offerts par le langage Java et ses bibliothèques pour répondre aux besoins du test unitaire. Nous pourrons toujours réécrire le code plus tard, de toutes façons les tests sont là pour valider que le code répond toujours aux exigences.&lt;/p&gt;


&lt;h3&gt;Mise en confiance de l'équipe&lt;/h3&gt;

&lt;p&gt;Le fait que les tests garantissent le fonctionnement du code permet à une équipe d'être en confiance sur le travail réalisé par chacun.&lt;/p&gt;


&lt;p&gt;Un membre de l'équipe pourra ainsi travailler sur le code d'un autre membre de l'équipe avec en garde fou les tests qui vont servir détecter les régressions. Ainsi cette personne sera davantage en confiance. Le fait que le test soit en erreur permet de dialoguer plus facilement entre les membres de l'équipe pour comprendre comment le code fonctionne réellement et ce qu'il est censé faire.&lt;/p&gt;


&lt;h3&gt;Amélioration technique&lt;/h3&gt;

&lt;p&gt;Les tests permettent de faciliter la réécriture et l'amélioration technique de l'application car ils permettent de lever des alertes si une modification a entraîné des régressions sur le fonctionnement interne de l'application.&lt;/p&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;Nous avons pu voir dans ce post les principes et le fonctionnement théorique du TDD qui apportent beaucoup de bénéfices notamment au niveau de la fiabilité et du respect des règles métiers.&lt;/p&gt;


&lt;p&gt;Nous verrons dans un second post, une démonstration avec la mise en pratique des principes du TDD.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2013/04/28/TDD-%3A-Test-Driven-Development#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2013/04/28/TDD-%3A-Test-Driven-Development#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/588</wfw:commentRss>
      </item>
    
  <item>
    <title>Trier efficacement les objets en Java - 2ème partie : Guava</title>
    <link>http://blog.netapsys.fr/index.php/post/2012/10/28/Trier-efficacement-les-objets-en-Java-2%C3%A8me-partie</link>
    <guid isPermaLink="false">urn:md5:f837f0f5917d67835be5f4adc81c2372</guid>
    <pubDate>Fri, 30 Nov 2012 19:14:00 +0100</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Java J2EE</category>
        <category>Collator</category><category>Comparator</category><category>ComparisonChain</category><category>Ordering</category>    
    <description>&lt;ul&gt;
&lt;li&gt;Suite du billet précédent&amp;nbsp;: &quot;&lt;a href=&quot;http://blog.netapsys.fr/index.php/post/2012/10/28/Guava-Faciliter-l-%C3%A9criture-des-comparateurs-d-objets&quot;&gt;Trier efficacement les objets en Java - 1ère partie&lt;/a&gt;&quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le tri d'objets en Java s'effectue à l'aide de méthodes et de classes de comparaisons.&lt;/p&gt;


&lt;p&gt;Cependant, l'écriture de ces méthodes peut vite devenir fastidieuse et être source d'erreurs lorsque les objets à comparer ont beaucoup de propriétés à tester.&lt;/p&gt;


&lt;p&gt;Voyons comment la bibliothèque &lt;a href=&quot;http://code.google.com/p/guava-libraries/&quot; title=&quot;Guava&quot;&gt;Guava&lt;/a&gt; de Google peut nous aider à simplifier l'écriture de ces méthodes.&lt;/p&gt;


&lt;h2&gt;Guava&amp;nbsp;: Ordering et ComparisonChain&lt;/h2&gt;

&lt;p&gt;Nous verrons ainsi l'utilisation des classes &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; et &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;Javadoc - ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt; de &lt;a href=&quot;http://code.google.com/p/guava-libraries/&quot; title=&quot;Guava&quot;&gt;Guava&lt;/a&gt;.&lt;/p&gt;    &lt;h2&gt;La classe Ordering&lt;/h2&gt;

&lt;p&gt;La classe &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; contient des méthodes qui permettent de définir plus simplement le tri d'une collection d'éléments.
Elle contient également des méthodes qui permettent de lancer le tri d'une collection d'éléments.&lt;/p&gt;


&lt;h4&gt;Ordering implémente Comparator&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; implémente l'interface Comparator ce qui permet d'utiliser une instance &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; de la même façon qu'une instance Comparator.&lt;/p&gt;


&lt;h3&gt;Définition d'une instance de Ordering&lt;/h3&gt;

&lt;p&gt;Nous pouvons définir une instance &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; des deux manières suivantes&amp;nbsp;:&lt;/p&gt;


&lt;h4&gt;Définition d'un Ordering à partir d'un Comparator existant&lt;/h4&gt;


&lt;p&gt;Nous pouvons définir un &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; à partir d'un Comparator existant.&lt;/p&gt;
&lt;pre&gt;
Ordering ordering = Ordering.from(comparator);
&lt;/pre&gt;


&lt;p&gt;Ceci permet d'étendre le comportement de ce Comparator pour modifier le tri des éléments, comme par exemple inverser l'ordre du tri.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Définition d'un Ordering à l'aide d'une méthode de tri par défaut&lt;/h4&gt;


&lt;p&gt;Nous pouvons utiliser les ordres de tri fournis par la classe &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ordre naturel&lt;/strong&gt;&amp;nbsp;: la comparaison des instances repose sur la méthode compareTo de chaque instance. Ceci implique obligatoirement que les objets triés implémentent l'interface Comparable et la méthode compareTo.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt; Ordering ordering = Ordering.natural();&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;utilisation de toString&lt;/strong&gt;&amp;nbsp;: la comparaison des instances repose sur la méthode toString de chaque instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt; Ordering ordering = Ordering.usingToString();&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;tri selon les références des instances&lt;/strong&gt;&amp;nbsp;: la comparaison des instances repose sur la comparaison des références des instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt; Ordering ordering = Ordering.arbitrary();&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Etendre le comportement du tri&lt;/h3&gt;


&lt;p&gt;&lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; contient des méthodes qui permettent d'étendre le comportement de base de la comparaison.&lt;/p&gt;


&lt;p&gt;Par exemple, nous pouvons inverser l'ordre du tri, gérer les instances non définies pour éviter les exceptions NullPointerException.&lt;/p&gt;


&lt;h4&gt;Inverser l'ordre&lt;/h4&gt;

&lt;p&gt;Pour inverser l'ordre, nous ajoutons l'appel à la méthode &lt;strong&gt;reverse&lt;/strong&gt;&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
Ordering ordering = Ordering.from(comparator).reverse();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h4&gt;Gérer le cas des objets non définis&lt;/h4&gt;

&lt;p&gt;Dans le cas où un des objets à comparer est nul, par défaut l'exception &lt;strong&gt;NullPointerException&lt;/strong&gt; est levée.&lt;/p&gt;


&lt;p&gt;Cependant ce cas peut être géré via l'appel à la méthode &lt;strong&gt;nullsFirst&lt;/strong&gt; ou &lt;strong&gt;nullsLast&lt;/strong&gt; qui indique que les instances non définies se retrouvent respectivement au début ou à la fin de la liste.&lt;/p&gt;

&lt;pre&gt;
// Les instances nulles ne sont pas gérées et un __NullPointerException__ peut être levé
Ordering.from(comparator);

// Les instances nulles sont gérées et se retrouvent au début de la liste
Ordering.from(comparator).nullsFirst();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Si nous voulons les valeurs nulles à la fin, nous avons également l'expression suivante&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
Ordering.natural().nullsLast();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h4&gt;Indiquer la propriété de l'objet sur laquelle effectuer le tri&lt;/h4&gt;

&lt;p&gt;La méthode &lt;strong&gt;onResultOf&lt;/strong&gt; permet d'indiquer sur quelle propriété de l'objet effectuer le tri.&lt;/p&gt;


&lt;p&gt;Cette méthode prend en paramètre une instance de &lt;strong&gt;Function&lt;/strong&gt; qui est une autre classe fournit par la bibliothèque et qui permet de retourner une valeur à partir de l'objet passé en paramètre.&lt;/p&gt;


&lt;p&gt;Par exemple, dans le cas d'un livre disposant de la propriété auteur, nous pouvons définir le tri sur l'ordre naturel selon cette propriété auteur&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
final Ordering&amp;lt;Livre&amp;gt; livreOrdering =
    Ordering.natural().nullsFirst().onResultOf(new Function&amp;lt;Livre, String&amp;gt;() {
        public String apply(final Livre input)
        {
            return input.getAuteur();
        }
    });

final List&amp;lt;Livre&amp;gt; livresResultat = livreOrdering.sortedCopy(livres);
&lt;/pre&gt;


&lt;p&gt;La méthode &lt;strong&gt;apply&lt;/strong&gt; de la classe &lt;strong&gt;Function&lt;/strong&gt; retourne ici la propriété &lt;strong&gt;auteur&lt;/strong&gt; à partir de l'instance de &lt;strong&gt;Livre&lt;/strong&gt;. L'auteur servira à trier les livres. De plus la méthode &lt;strong&gt;nullsFirst&lt;/strong&gt; permet de gérer les cas où la collection contient des livres non définis.&lt;/p&gt;


&lt;h3&gt;Lancer le tri des éléments&lt;/h3&gt;


&lt;h2&gt;Trier les éléments&lt;/h2&gt;

&lt;p&gt;Nous pouvons maintenant trier nos livres à l'aide notre nouveau comparateur, soit à l'aide &lt;strong&gt;Collections.sort&lt;/strong&gt;, soit à l'aide de &lt;strong&gt;Ordering.sortedCopy&lt;/strong&gt;.&lt;/p&gt;
&lt;pre&gt;
// Livres à trier
List&amp;lt;Livre&amp;gt; livres = getLivres();

// Comparaison de livres
LivreComparator livreComparator = 
    Ordering.from(new LivreComparator()).nullFirst();

// Trier les livres
List&amp;lt;Livre&amp;gt; livreTries = 
    Ordering.from(livreComparator).sortedCopy(livres);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h3&gt;Exemples d'utilisation de la classe Ordering&lt;/h3&gt;


&lt;p&gt;Nous pouvons ainsi avoir les déclarations suivantes&amp;nbsp;:&lt;/p&gt;


&lt;h4&gt;Tri naturel sur les auteurs d'un livre&amp;nbsp;:&lt;/h4&gt;

&lt;p&gt;Nous trions les livres suivant un &lt;strong&gt;Comparator&lt;/strong&gt; sur les livres en inversant l'ordre et gérant le cas des livres non définis&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
final List&amp;lt;Livre&amp;gt; livresResultat =
            Ordering.from(livreComparator).reverse().nullsFirst().sortedCopy(livres);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h4&gt;Collection triée de livres&lt;/h4&gt;

&lt;p&gt;Nous définissons une collection triée de livres avec gestion des cas des instances nulles&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
Set&amp;lt;Livre&amp;gt; livres = new TreeSet&amp;lt;Livre&amp;gt;(
            Ordering.from(livreComparator).nullFirst());
&lt;/pre&gt;


&lt;h3&gt;Conclusion sur l'utilisation d'un Ordering&lt;/h3&gt;

&lt;p&gt;La classe &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; propose d'autres fonctionnalités non détaillées ici qui permettent d'étendre davantage le comportement&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;ComparisonChain&lt;/h2&gt;

&lt;p&gt;La classe &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt; facilite l'écriture des méthodes de comparaison de type &lt;strong&gt;compareTo&lt;/strong&gt; et des &lt;strong&gt;Comparator&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;En effet, elle permet de tester à la suite chacune des propriétés des objets à comparer.&lt;/p&gt;


&lt;p&gt;Elle s'utilise de la manière suivante&amp;nbsp;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;on appelle dans un premier temps la méthode statique &lt;strong&gt;ComparisonChain.start()&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;on teste ensuite chaque propriété par une suite d'appels à la méthode ComparaisonChain.compare&lt;/li&gt;
&lt;li&gt;enfin on récupère le résultat de la comparaison à l'aide de la méthode ComparaisonChain.result&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Voici un exemple de l'utilisation de &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt; dans le cas de la comparaison de deux livres&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
public int compare(final Livre livre1,
                   final Livre livre2)
{
    return ComparisonChain
            .start()
            .compare(livre1.getAuteur(),
                     livre2.getAuteur())
            .compare(livre1.getAnnee(),
                     livre2.getAnnee())
            .compare(livre1.getTitre(),
                     livre2.getTitre())
            .result();
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Nous voyons que la logique de comparaison est simplifiée.&lt;/p&gt;


&lt;h3&gt;Comparaison de propriétés spécifiques&lt;/h3&gt;


&lt;p&gt;De plus, la méthode compare peut prendre un troisième paramètre de type &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Comparator&quot;&gt;Comparator&lt;/a&gt; ou &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; . Ceci permet d'indiquer un méthode de comparaison spécifique pour une propriété en indiquant un comparateur spécifique.&lt;/p&gt;


&lt;p&gt;Ainsi, si nous souhaitons ne pas prendre en compte les accents dans la comparaison de chaînes de caractères, nous pouvons définir un comparateur de type &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Collator&quot;&gt;Collator&lt;/a&gt; qui étend la classe &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Comparator&quot;&gt;Comparator&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Nous obtenons le code suivant&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
public int compare(final Livre livre1,
                   final Livre livre2)
{
    // Comparator qui ne tient pas compte des accents
    final Collator collator = Collator.getInstance(Locale.FRENCH);
    collator.setStrength(Collator.PRIMARY);

    return ComparisonChain
            .start()
            .compare(livre1.getAuteur(),
                     livre2.getAuteur(),
                     Ordering.from(collator))
            .compare(livre1.getAnnee(),
                     livre2.getAnnee())
            .compare(livre1.getTitre(),
                     livre2.getTitre(),
                     Ordering.from(collator))
            .result();
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h3&gt;Gérer les propriétés nulles pour éviter les NullPointerException&lt;/h3&gt;


&lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;&amp;nbsp;: &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt; ne gère pas les cas où une des instances à comparer est nulle.
Pour éviter d'avoir des exceptions &lt;strong&gt;NullPointerException&lt;/strong&gt;, nous devons gérer les cas des instances nulles de chaque propriété et des instances à comparer.&lt;/p&gt;


&lt;p&gt;Pour cela, il est important d'utiliser la méthode &lt;strong&gt;Ordering.nullsFirst()&lt;/strong&gt; que ce soit à la comparaison des propriétés ou lors du tri des éléments.&lt;/p&gt;


&lt;p&gt;Ainsi, nous utilisons la classe &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; pour étendre les comparateurs de la manière suivante&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
// Comparateur
Comparator comparatorWithoutNullPointerException = 
    Ordering.from(comparator).nullFirst();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Ainsi dans le code ci-dessus, le cas où deux propriétés ne sont pas définies n'est pas géré.&lt;/p&gt;


&lt;p&gt;L'expression suivante permet de gérer les valeurs nulles qui seront situées avant les valeurs non nulles&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
// Gestion des instances nulles
Ordering.natural().nullsFirst();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Dans le cas où pour comparer les propriétés le &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; repose sur un comparateur existant et que nous voulons gérer les cas où une des valeurs est nulles, nous aurons l'expression suivante&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
Ordering.from(comparator).nullFirst();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h3&gt;Méthode de comparaison gérant les valeurs nulles&lt;/h3&gt;


&lt;p&gt;Dans notre exemple, nous avons un comparateur de type &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Collator&quot;&gt;Collator&lt;/a&gt; au niveau de l'auteur et du titre, et pas de comparateur spécifique au niveau de l'année. Nous obtenons le code suivant pour gérer les valeurs nulles&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
public int compare(final Livre livre1,
                   final Livre livre2)
{
     // Comparer sans tenir compte des accents et de la casse
     final Collator collator = Collator.getInstance(Locale.FRENCH);
     collator.setStrength(Collator.PRIMARY);

     // Comparaison sur les propriétés des livres
     return ComparisonChain
             .start() 
             .compare(livre1.getAuteur(),
                      livre2.getAuteur(),
                      Ordering.from(collator).nullsFirst())
             .compare(livre1.getAnnee(),
                      livre2.getAnnee(),
                      Ordering.natural().nullsFirst())
             .compare(livre1.getTitre(),
                      livre2.getTitre(),
                      Ordering.from(collator).nullsFirst())
             .result();
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h3&gt;Lancer le tri à l'aide d'un ComparisonChain&lt;/h3&gt;


&lt;p&gt;Nous pouvons effectuer le tri à l'aide d'un &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt; à l'aide de l'appel à la méthode &lt;strong&gt;Ordering.sortedCopy&lt;/strong&gt;. Il faut également ne pas oublier d'utiliser la méthode &lt;strong&gt;Ordering.nullsFirst()&lt;/strong&gt; pour gérer les cas des instances à comparer non défini et éviter ainsi les &lt;strong&gt;NullPointerException&lt;/strong&gt;&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
// Comparateur de livres
LivreComparator livreComparator = 
    Ordering.from(new LivreComparator()).nullFirst();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;


&lt;h2&gt;Exemple complet&lt;/h2&gt;


&lt;p&gt;Voici un exemple complet de tri de livres en utilisant &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt; et &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; .&lt;/p&gt;


&lt;p&gt;Les livres sont triés suivant l'auteur, le titre puis l'année&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
public class LivreComparator
	implements Comparator&amp;lt;Livre&amp;gt; 
{	
    // Comparaison de livres
    public int compare(final Livre livre1,
                       final Livre livre2)
    {
    	 // Comparer s'en tenir compte des accents et de la casse
    	final Collator collator = Collator.getInstance(Locale.FRENCH);
        collator.setStrength(Collator.PRIMARY);
        
        // Comparaison sur les propriétés des livres
        return ComparisonChain
                .start()
                .compare(livre1.getAuteur(),
                         livre2.getAuteur(),
                         Ordering.from(collator).nullsFirst())
                .compare(livre1.getAnnee(),
                         livre2.getAnnee(),
                         Ordering.natural().nullsFirst())
                .compare(livre1.getTitre(),
                         livre2.getTitre(),
                         Ordering.from(collator).nullsFirst())
                .result();
    }    
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Nous trions les livres en utilisant ce comparateur&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
LivreComparator livreComparator = new LivreComparator();

// Gérer le cas des livres non définis (éviter les NullPointerException)
Ordering&amp;lt;Livre&amp;gt; livreOrdering =
    Ordering.from(livreComparator).nullsFirst();

// Trier la liste des livres
List&amp;lt;Livre&amp;gt; livresResultat = livreOrdering.sortedCopy(livres);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;L'utilisation des classes &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; et &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt; de &lt;a href=&quot;http://code.google.com/p/guava-libraries/&quot; title=&quot;Guava&quot;&gt;Guava&lt;/a&gt; permettent de faciliter et de réduire les bugs en diminuant les cas complexes de comparaison des propriétés multiples des objets. Ceci permet de réduire les erreurs et de rendre plus fiable les méthodes de tri sur les éléments en utilisant les méthodes de comparaisons existantes, en chaînant les comparaisons des propriétés des objets et en gérant les cas des instances non définies.&lt;/p&gt;


&lt;p&gt;Cependant, l'apprentissage de l'utilisation de ces classes demandent un peu de pratique mais qui ensuite apporte ces fruits en diminuant la complexité du code à écrire.&lt;/p&gt;


&lt;h2&gt;Référence&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Billet précédent&amp;nbsp;: &quot;&lt;a href=&quot;http://blog.netapsys.fr/index.php/post/2012/10/28/Guava-Faciliter-l-%C3%A9criture-des-comparateurs-d-objets&quot;&gt;Trier efficacement les objets en Java - 1ère partie&lt;/a&gt;&quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voici quelques références sur les classes &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Ordering&quot;&gt;Ordering&lt;/a&gt; et &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt; de la bibliothèque &lt;a href=&quot;http://code.google.com/p/guava-libraries/&quot; title=&quot;Guava&quot;&gt;Guava&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/GuavaExplained?tm=6&quot; title=&quot;Guava - Wiki&quot;&gt;Guava Wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Ordering&amp;nbsp;: &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/OrderingExplained&quot; title=&quot;Guava - Wiki - Ordering&quot;&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Comparaison avec la méthode compareTo&amp;nbsp;: &lt;a href=&quot;http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained#compare/compareTo&quot; title=&quot;Guava - Wiki - compareTo&quot;&gt;compareTo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Comparaison avec la classe ComparisonChain&amp;nbsp;: &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ComparisonChain.html&quot; title=&quot;Guava - Javadoc - ComparisonChain&quot;&gt;ComparisonChain&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2012/10/28/Trier-efficacement-les-objets-en-Java-2%C3%A8me-partie#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2012/10/28/Trier-efficacement-les-objets-en-Java-2%C3%A8me-partie#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/506</wfw:commentRss>
      </item>
    
  <item>
    <title>Trier efficacement les objets en Java - 1ère partie</title>
    <link>http://blog.netapsys.fr/index.php/post/2012/10/28/Guava-Faciliter-l-%C3%A9criture-des-comparateurs-d-objets</link>
    <guid isPermaLink="false">urn:md5:d6784f79edef755807917325b590667f</guid>
    <pubDate>Tue, 30 Oct 2012 12:00:00 +0100</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Java J2EE</category>
            
    <description>&lt;ul&gt;
&lt;li&gt;Ce billet précède&amp;nbsp;: &quot;&lt;a href=&quot;http://blog.netapsys.fr/index.php/post/2012/10/28/Trier-efficacement-les-objets-en-Java-2%C3%A8me-partie&quot;&gt;Trier efficacement les objets en Java - 2ème partie - Guava&lt;/a&gt;&quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le tri d'objets en Java est facilité par l'utilisation de méthodes de comparaison.&lt;/p&gt;


&lt;p&gt;Nous allons voir dans cette première partie quel est le contrat de ces méthodes, comment les écrire et comment s'effectue le tri d'objets en Java à l'aide de ces méthodes.&lt;/p&gt;


&lt;p&gt;Nous verrons ainsi l'utilité de l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt; et de la classe &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;Comparaison d'objets&lt;/h2&gt;

&lt;p&gt;Les méthodes de comparaison permettent de trier une liste d'objets. Pour cela, ces méthodes consistent, pour deux instances d'un même objet, à comparer chacune de leurs propriétés et à indiquer quelle instance se situe avant l'autre selon l'ordre voulu.&lt;/p&gt;


&lt;p&gt;Le contrat de ces méthodes de comparaison est défini par&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la méthode &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html#compareTo(T)&quot; title=&quot;Javadoc - Comparable.compareTo(T)&quot;&gt;compareTo&lt;/a&gt; de l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;la méthode &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html#compare(T, T)&quot; title=&quot;Javadoc - Comparator.compare(T, T)&quot;&gt;compare&lt;/a&gt; de la classe &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;    &lt;p&gt;Nous verrons que l'écriture de ces méthodes peuvent vite devenir fastidieuses et sources d'erreurs lorsque les objets à comparer ont beaucoup de propriétés à tester.&lt;/p&gt;


&lt;p&gt;Nous prendrons comme exemple le tri d'une liste de livres.&lt;/p&gt;


&lt;h3&gt;Méthode compareTo de l'interface Comparable&lt;/h3&gt;

&lt;p&gt;L'objet lui-même étend l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt;. Cette interface implique l'écriture de la méthode de comparaison entre l'instance de l'objet et une autre instance de ce même objet.&lt;/p&gt;
&lt;pre&gt;
int compareTo(T object);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Cette méthode compareTo retourne un nombre entier qui indique&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;si &amp;lt; 0&amp;nbsp;: l'instance est avant la deuxième instance&lt;/li&gt;
&lt;li&gt;si = 0&amp;nbsp;: les deux instances sont à la même position&lt;/li&gt;
&lt;li&gt;si &amp;gt; 0&amp;nbsp;: l'instance est après la deuxième instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour l'exemple des livres à trier, la classe Livre implémente &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt; et la méthode compareTo&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
public class Livre
    implements Comparable&amp;lt;Livre&amp;gt;
{
    public int compareTo(Livre livre2) {
        (...)
    }
    (...)
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Ainsi la méthode compareTo retourne un nombre entier qui indique&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;si &amp;lt; 0, le livre est avant le livre 2&lt;/li&gt;
&lt;li&gt;si = 0, le livre est à la même position que le livre 2&lt;/li&gt;
&lt;li&gt;si &amp;gt; 0, le livre est après le livre 2&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Méthode compare de la classe Comparator&lt;/h3&gt;

&lt;p&gt;La classe &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt; impose l'écriture de la méthode compare qui prend en paramètre les deux instances à comparer.&lt;/p&gt;
&lt;pre&gt;
public class Comparator&amp;lt;T extends Object&amp;gt;
{
    int compare(T o1, T o2);
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;De même que pour la méthode compareTo de l'interface Comparable, la méthode compare retourne un nombre entier qui indique&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;si &amp;lt; 0&amp;nbsp;: la première instance est avant la deuxième instance&lt;/li&gt;
&lt;li&gt;si = 0&amp;nbsp;: les deux instances sont à la même position&lt;/li&gt;
&lt;li&gt;si &amp;gt; 0&amp;nbsp;: la première instance est après la deuxième instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour un livre, nous pouvons ainsi avoir le comparateur LivreComparator qui étend &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt; et qui implémente la méthode compare:&lt;/p&gt;
&lt;pre&gt;
public class LivreComparator
    extends Comparator&amp;lt;Livre&amp;gt;
{
    public int compare(Livre livre1, Livre livre2) {
        (...)
    }
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;La méthode compare de la classe LivreComparator retourne un nombre entier qui indique&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;si &amp;lt; 0&amp;nbsp;: le livre 1 est avant le livre 2&lt;/li&gt;
&lt;li&gt;si = 0&amp;nbsp;: les deux livres sont à la même position&lt;/li&gt;
&lt;li&gt;si &amp;gt; 0&amp;nbsp;: le livre 1 est après le livre 2&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Trier une liste&lt;/h3&gt;

&lt;p&gt;A l'aide des méthodes de comparaison, nous pouvons trier une liste d'objets grâce à la méthode sort de java.util.Collections.&lt;/p&gt;


&lt;h4&gt;Via Comparable.compareTo&lt;/h4&gt;


&lt;p&gt;Dans le cas où on se base sur la méthode de comparaison compareTo via l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt; implémentée par l'objet, nous avons à appeler la méthode sort en indiquant uniquement la liste des objets.&lt;/p&gt;
&lt;pre&gt;
// Liste des livres
List&amp;lt;Livre&amp;gt; livres = getLivres();

// Tri des livres selon la méthode compareTo de Livre
Collections.sort(livres);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h4&gt;via Comparator.compare&lt;/h4&gt;


&lt;p&gt;Dans le cas où on se base sur la méthode de comparaison compare du &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt;, nous avons à appeler la méthode sort en indiquant la liste des objets et le &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;
// liste des livres
List&amp;lt;Livre&amp;gt; livres = getLivres();

// Comparaison de livres
LivreComparator livreComparator = new LivreComparator();

// Tri des livres selon le Comparator
Collections.sort(livres, livreComparator);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h3&gt;Collections triées&lt;/h3&gt;

&lt;p&gt;Les collections TreeSet et TreeMap sont des collections dont les objets sont toujours triés selon une méthode de comparaison, soit via &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt;, soit à l'aide d'un &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt;.&lt;/p&gt;


&lt;h4&gt;Comparable&lt;/h4&gt;

&lt;p&gt;Ainsi si nous souhaitons une liste de livres sans doublon et toujours triés, nous pouvons nous baser sur l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt; de l'objet Livre. Pour cela, nous définissons une instance de TreeSet. Cette implémentation va détecter que l'objet ajouté à la collection implémente l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt; et se servira alors de la méthode compareTo pour trier les objets insérés dans la collection.&lt;/p&gt;
&lt;pre&gt;
// Liste de livres triés selon la méthode compareTo de Livre
Set&amp;lt;Livre&amp;gt; livres = new TreeSet&amp;lt;Livre&amp;gt;();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h4&gt;Comparator&lt;/h4&gt;

&lt;p&gt;Pour le tri de la liste, nous pouvons également spécifier un &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt; externe.&lt;/p&gt;
&lt;pre&gt;
// Comparaison de livres
LivreComparator livreComparator = new LivreComparator();

// Liste de livres triés selon le Comparator
Set&amp;lt;Livre&amp;gt; livres = new TreeSet&amp;lt;Livre&amp;gt;(livreComparator);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h2&gt;Ecriture des méthodes de comparaison&lt;/h2&gt;

&lt;p&gt;Comme déjà dit plus haut, les méthodes de comparaisons consiste à indiquer la position d'un élément par rapport à un autre élément en comparant chacune de leurs propriétés selon l'ordre voulu.&lt;/p&gt;


&lt;p&gt;Par exemple, nous souhaitons trier une liste de livres. Chaque livre dispose d'un auteur, d'un titre et d'une année de publication.&lt;/p&gt;


&lt;p&gt;Nous souhaitons trier ces livres dans l'ordre suivant&amp;nbsp;: d'abord par auteur, puis par année de publication et enfin par titre.&lt;/p&gt;


&lt;p&gt;En pratique, nous allons d'abord comparer l'auteur de deux livres. Si les deux auteurs sont différents, on indique quel livre se situe avant l'autre suivant l'auteur dans l'ordre alphabétique. Dans le cas où les deux auteurs sont identiques, nous continuons la comparaison sur l'année de publication. Si les deux années sont différentes, on indique quel livre se situe avant l'autre suivant l'année. Enfin, dans le cas où les deux années sont égales, on compare sur le titre, en indiquant le livre qui se situe avant l'autre suivant le titre et d'après l'ordre alphabétique. Dans le cas où les deux titres sont identiques, comme il n'y a plus d'autres propriétés à comparer, on indique que les deux livres sont à la même position dans la liste.&lt;/p&gt;


&lt;h3&gt;Ecriture de la méthode compareTo de l'interface Comparable&lt;/h3&gt;

&lt;p&gt;L'écriture de la méthode de comparaison compareTo de l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt; consiste à comparer les propriétés de l'instance de l'objet avec les propriétés d'une autre instance de même type d'objet.&lt;/p&gt;
&lt;pre&gt;
int compareTo(T object);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Par exemple, nous prenons l'exemple de la classe Livre et nous voulons trier suivant l'auteur, puis l'année, puis le titre. Nous avons ainsi le code suivant&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
public class Livre
    implements Comparable&amp;lt;Livre&amp;gt;
{
    
    public int compareTo(Livre livre2)
    {
        // Comparaison sur l'auteur
        int compAuteur = this.getAuteur().compareTo(livre2.getAuteur());
        if(compAuteur != 0) { return compAuteur; }

        // Comparaison sur l'année
        int compAnnee = this.getAnnee().compareTo(livre2.getAnnee());
        if(compAnnee != 0) { return compAnnee; }

        // Comparaison sur le titre
        int compTitre = this.getTitre().compareTo(livre2.getTitre());
        if(compTitre != 0) { return compTitre; }

        // Les deux livres sont à la même position
        return 0;
    }

    (...)
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Nous avons ainsi comparer chaque propriété des deux instances. Dès qu'une des propriétés ne correspond pas entre les deux instances, on retourne le nombre entier indiquant l'ordre entre les deux instances.&lt;/p&gt;


&lt;h3&gt;Classe Comparator&lt;/h3&gt;

&lt;p&gt;L'écriture de la méthode compare qui prend en paramètre les deux instances à comparer consiste à comparer les propriétés de ces deux instances. Cette méthode est quasiment identique à la méthode compareTo de l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt;, hormis que l'on travaille sur deux instances d'objets qui ne sont pas liées au &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt;. Cette séparation permet de séparer la logique de comparaison de l'objet lui-même.&lt;/p&gt;
&lt;pre&gt;
public class LivreComparator
    extends Comparator&amp;lt;Livre&amp;gt;
{
    
    public int compare(Livre livre1, Livre livre2)
    {
        // Comparaison sur l'auteur
        int compAuteur = livre1.getAuteur().compareTo(livre2.getAuteur());
        if(compAuteur != 0) { return compAuteur; }

        // Comparaison sur l'année
        int compAnnee = livre1.getAnnee().compareTo(livre2.getAnnee());
        if(compAnnee != 0) { return compAnnee; }

        // Comparaison sur le titre
        int compTitre = livre1.getTitre().compareTo(livre2.getTitre());
        if(compTitre != 0) { return compTitre; }

        // Les deux livres sont à la même position
        return 0;
    }

    (...)
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
Ainsi la méthode compare du &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt; ressemble à la méthode compareTo précédente.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Difficultés et pièges dans l'écriture des méthodes de comparaison&lt;/h2&gt;

&lt;p&gt;Ces méthodes de comparaison bien qu'utiles sont difficiles à écrire.&lt;/p&gt;


&lt;p&gt;En effet, il est nécessaire de gérer plusieurs éléments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la comparaison de deux propriétés change suivant le type de la propriété&lt;/li&gt;
&lt;li&gt;il faut gérer le cas où un des deux objets ou une des propriétés n'est pas défini, pour ne pas avoir d'exception de type NullPointerException. Dans l'exemple, que se passe-t-il si l'auteur du livre 1 est non défini, c'est à dire null.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voici par exemple, la méthode de comparaison avec la gestion des objets et des propriétés qui peuvent être non définis&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
public class LivreComparator
    extends Comparator&amp;lt;Livre&amp;gt;
{
    
    public int compare(Livre livre1, Livre livre2)
    {
        if(livre1 == null) {
            if(livre2 == null) { 
                // Les deux livres ne sont pas définis
                return 0; 
            } else { 
                // Seul le livre 1 n'est pas défini
                return -1;
            }
        } else {
            // Seul le livre 2 n'est pas défini
            return 1;
        }

        // Comparaison sur l'auteur
        String auteurLivre1NonNull = 
            StringUtils.trimToEmpty(livre1.getAuteur());
        String auteurLivre2NonNull = 
            StringUtils.trimToEmpty(livre2.getAuteur());

        int compAuteur = 
            auteurLivre1NonNull.compareTo(auteurLivre2NonNull);
        if(compAuteur != 0) { return compAuteur; }

        // Comparaison sur l'année
        Integer anneeLivre1NonNull;
        if(livre1.getAnnee()==null) {
            anneeLivre1NonNull = 0;
        } else {
            anneeLivre1NonNull = livre1.getAnnee();
        }
        Integer anneeLivre2NonNull;
        if(livre2.getAnnee()==null) {
            anneeLivre2NonNull = 0;
        } else {
            anneeLivre2NonNull = livre2.getAnnee();
        }

        int compAnnee = 
            anneeLivre1NonNull.compareTo(anneeLivre2NonNull);
        if(compAnnee != 0) { return compAnnee; }

        // Comparaison sur le titre
        String titreLivre1NonNull = 
            StringUtils.trimToEmpty(livre1.getTitre());
        String titreLivre2NonNull = 
            StringUtils.trimToEmpty(livre2.getTitre());

        int compTitre = 
            titreLivre1NonNull.compareTo(titreLivre2NonNull);
        if(compTitre != 0) { return compTitre; }

        // Les deux livres sont à la même position
        return 0;
    }

    (...)
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;Il est important de maîtriser le tri des objets en Java avec l'utilisation de l'interface &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Comparable&lt;/a&gt; et de la classe &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Comparator&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Cependant, nous nous apercevons que l'écriture des méthodes de comparaison peut rapidement devenir un parcours du combattant où il faut déjouer tous les pièges.&lt;/p&gt;


&lt;p&gt;L'écriture de tests unitaires peuvent aider, cependant le test de tous les cas possibles devient rapidement fastidieux.&lt;/p&gt;


&lt;p&gt;C'est pourquoi je vous présenterai dans un second post des solutions pour faciliter l'écriture de ces méthodes de comparaison, notamment à l'aide de la bibliothèque Guava.&lt;/p&gt;


&lt;h2&gt;Référence&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&quot;&lt;a href=&quot;http://blog.netapsys.fr/index.php/post/2012/10/28/Trier-efficacement-les-objets-en-Java-2%C3%A8me-partie&quot;&gt;Trier efficacement les objets en Java - 2ème partie - Guava&lt;/a&gt;&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Comparable&amp;nbsp;: &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html&quot; title=&quot;Javadoc - Comparable&quot;&gt;Javadoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Comparator&amp;nbsp;: &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html&quot; title=&quot;Javadoc - Comparator&quot;&gt;Javadoc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2012/10/28/Guava-Faciliter-l-%C3%A9criture-des-comparateurs-d-objets#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2012/10/28/Guava-Faciliter-l-%C3%A9criture-des-comparateurs-d-objets#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/505</wfw:commentRss>
      </item>
    
  <item>
    <title>Guava : Classer les éléments d'une collection</title>
    <link>http://blog.netapsys.fr/index.php/post/2012/10/19/Classer-les-%C3%A9l%C3%A9ments-d-une-collection</link>
    <guid isPermaLink="false">urn:md5:eca658bd29c0944a13b6e7149ae231cf</guid>
    <pubDate>Thu, 25 Oct 2012 10:00:00 +0200</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Java J2EE</category>
            
    <description>&lt;p&gt;Pour certains algorithmes, nous avons besoin de classer des éléments selon une de leur propriété.&lt;/p&gt;


&lt;p&gt;Nous allons voir dans un premier temps comment classer une liste d'objets de manière classique, puis nous verrons comment le faire plus simplement à l'aide des bibliothèques common-collections d'Apache et guava de Google.&lt;/p&gt;


&lt;h2&gt;Cas pratique&lt;/h2&gt;


&lt;p&gt;Nous prenons comme exemple la liste de livres d'une bibliothèque.&lt;/p&gt;


&lt;p&gt;Nous souhaitons avoir le classement des ouvrages selon leur auteur de la manière suivante&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
 - Auteur : Jules Vernes
    - Cinq semaines en ballon, 1863
    - Voyage au centre de la Terre, 1864
    - De la Terre à la Lune, 1865
 - Auteur : Rudyard Kipling
    - Le livre de la jungle, 1894
    - Le second livre de la jungle, 1895
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;    &lt;h2&gt;Classer des objets&lt;/h2&gt;


&lt;p&gt;En Java, ce classement s'effectuerait de la manière suivante&amp;nbsp;:&lt;/p&gt;


&lt;p&gt;Nous avons la collection de type Map&amp;lt;clé, Collection&amp;lt;valeur&amp;gt;&amp;gt; qui permet de stocker pour chaque clé plusieurs valeurs.&lt;/p&gt;


&lt;p&gt;Ainsi dans notre exemple, nous avons pour la clé auteur un ou plusieurs livres.&lt;/p&gt;

&lt;pre&gt;
// Livres classés par auteur
Map&amp;lt;String, Collection&amp;lt;Livre&amp;gt;&amp;gt; livresParAuteurs =
    new HashMap&amp;lt;String, Collection&amp;lt;Livre&amp;gt;&amp;gt;();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h3&gt;Boucle de classement&lt;/h3&gt;


&lt;p&gt;La valorisation de ce tableau peut s'effectuer via le traitement suivant qui consiste à parcourir la liste des livres et pour chaque livre d'ajouter ce livre à la liste de ceux de l'auteur.&lt;/p&gt;

&lt;pre&gt;
// Parcourt les livres
for (Livre livre : livres)
{
    // Auteur du livre
    String auteur = livre.getAuteur();

    // Liste des livres de l'auteur
    Collection&amp;lt;Livre&amp;gt; livresParAuteur = livresParAuteurs.get(auteur);

    // Créer la liste si elle n'existe pas
    if (livresParAuteur == null)
    {
        livresParAuteur = new ArrayList&amp;lt;Livre&amp;gt;();
        livresParAuteurs.put(auteur,
                             livresParAuteur);
    }

    // Ajoute le livre à la liste des livres de l'auteur
    livresParAuteur.add(livre);
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Nous remarquons qu'une partie de ce code est redondant, il s'agit de créer la liste de livres dans le cas où elle n'existe pas déjà pour l'auteur.&lt;/p&gt;


&lt;p&gt;Nous pouvons améliorer cela à l'aide du type Multimap.&lt;/p&gt;


&lt;h2&gt;Guava&amp;nbsp;: MultiMap&lt;/h2&gt;


&lt;p&gt;L'interface Multimap&amp;lt;clé, valeur&amp;gt; correspond à la collection Map&amp;lt;clé, Collection&amp;lt;valeur&amp;gt;&amp;gt;.&lt;/p&gt;


&lt;p&gt;Elle permet de gérer la création d'une nouvelle liste d'éléments pour tout nouvel ajout dans le tableau.&lt;/p&gt;


&lt;p&gt;Il existe une implémentation de Multimap pour les bibliothèques common-collections d'Apache et guava de Google. Nous choisissons ici la bibliothèque guava de Google car elle supporte par défaut les types génériques.&lt;/p&gt;


&lt;h3&gt;Différence entre Multimap et Map&lt;/h3&gt;


&lt;p&gt;Cependant, il ne s'agit pas exactement de la collection Map&amp;lt;clé, Collection&amp;lt;valeur&amp;gt;&amp;gt;.
En effet, comme expliqué sur le wiki de Guava, Multimap ne se comporte pas exactement comme la collection Map, notamment au niveau de la gestion de la liste d'éléments dans le cas où aucune valeur n'est présente pour une clé.
Par exemple, Multimap retournera toujours une liste vide et jamais nulle dans le cas où aucun élément n'a été ajouté pour une clé du tableau.&lt;/p&gt;


&lt;p&gt;Ceci est détaillé dans la documentation&amp;nbsp;: &lt;a href=&quot;https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap_Is_Not_A_Map&quot; title=&quot;https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap_Is_Not_A_Map&quot;&gt;Multimap is not a map&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;Multimap&amp;nbsp;: Implémentations possibles&lt;/h3&gt;


&lt;p&gt;Les implémentations de Multimap&amp;lt;clé, valeur&amp;gt; correspondent à une implémentation possible Map&amp;lt;clé,Collection&amp;lt;valeur&amp;gt;&amp;gt;.&lt;/p&gt;


&lt;p&gt;Les plus communes sont&amp;nbsp;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ArrayListMultimap&lt;/strong&gt;&amp;lt;clé, valeur&amp;gt; =&amp;gt; &lt;strong&gt;HashMap&lt;/strong&gt;&amp;lt;clé, &lt;strong&gt;ArrayList&lt;/strong&gt;&amp;lt;valeur&amp;gt;&amp;gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HashMultimap&lt;/strong&gt;&amp;lt;clé, valeur&amp;gt; =&amp;gt; &lt;strong&gt;HashMap&lt;/strong&gt;&amp;lt;clé, &lt;strong&gt;HashSet&lt;/strong&gt;&amp;lt;valeur&amp;gt;&amp;gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TreeMultimap&lt;/strong&gt;&amp;lt;clé, valeur&amp;gt; =&amp;gt; &lt;strong&gt;TreeMap&lt;/strong&gt;&amp;lt;clé, &lt;strong&gt;TreeSet&lt;/strong&gt;&amp;lt;valeur&amp;gt;&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Elles sont détaillées sur le wiki de Guava&amp;nbsp;: &lt;a href=&quot;https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Implementations&quot; title=&quot;https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Implementations&quot;&gt;Implémentations&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;Instanciation de Multimap&lt;/h3&gt;


&lt;p&gt;L'instanciation s'effectue via l'interface de la classe d'implémentation de la collection, ici ArrayListMultimap&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
// Livres classés par auteur
final Multimap&amp;lt;String, Livre&amp;gt; livresParAuteurs = 
    ArrayListMultimap.create();
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Ainsi le code précédent se simplifie car le code de création de la liste n'est plus utile&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
for (final Livre livre : livres)
{
    // Auteur du livre
    final String auteur = livre.getAuteur();

    // Livres par auteur
    livresParAuteurs.put(auteur,
                         livre);
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Cependant, hormis pour la récupération de l'auteur à partir de l'objet Livre, ce code n'a pas réellement de valeur ajoutée.&lt;/p&gt;


&lt;p&gt;Nous pouvons de nouveau améliorer ce code pour ne plus avoir à parcourir nous-même, ni à gérer l'ajout des éléments dans le tableau.&lt;/p&gt;


&lt;h2&gt;Utilisation de Function&lt;/h2&gt;


&lt;p&gt;L'interface Function de guava correspond à une transformation d'un objet vers un autre objet.&lt;/p&gt;


&lt;p&gt;Ainsi cette interface a deux types génériques, le type de l'objet initial et le type de l'objet qui sera en résultat de la fonction.&lt;/p&gt;
&lt;pre&gt;
Function&amp;lt;initial, final&amp;gt;
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;L'interface impose l'implémentation de la méthode apply qui prend en paramètre l'objet à transformer et qui retourne le résultat de cette transformation.&lt;/p&gt;

&lt;pre&gt;
public interface Function&amp;lt;F, T&amp;gt; {
    T apply(@Nullable F input);
}
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h3&gt;Function&lt;/h3&gt;


&lt;p&gt;Dans notre exemple, nous allons utiliser cette interface Function pour définir une classe qui sera chargée de retourner l'auteur à partir de l'objet Livre&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
Function&amp;lt;Livre, String&amp;gt; getAuteurFromLivreFunction = 
    new Function&amp;lt;Livre, String&amp;gt;() {
        public String apply(final Livre livre)
        {
            return livre.getAuteur();
        }
};
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;h3&gt;Multimaps.index&lt;/h3&gt;


&lt;p&gt;De plus, guava dispose de la méthode index via la classe Multimaps.&lt;/p&gt;


&lt;p&gt;Cette méthode prend en paramètre la collection à traiter ainsi que la fonction qui va fournir la clé correspondant à chaque objet de la collection. Ceci permettra de définir pour une même clé tous les éléments associés de la collection.&lt;/p&gt;


&lt;p&gt;Dans notre exemple, nous avons ainsi l'appel suivant&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
final Multimap&amp;lt;String, Livre&amp;gt; livresParAuteurs =
    Multimaps.index(livres,
                    getAuteurFromLivreFunction);
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Ceci permet de ne se focaliser que sur la gestion de la clé associée à chaque élément et non sur la façon dont le tableau est alimenté.&lt;/p&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;L'utilisation de la bibliothèque Guava de Google permet de simplifier l'écriture d'algorithmes basés sur des collections en Java.&lt;/p&gt;


&lt;p&gt;Il est intéressant de lire la documentation de cette bibliothèque et de s'en inspirer pour améliorer nos pratiques et sur notre façon d'implémenter nos solutions.&lt;/p&gt;


&lt;p&gt;L'interface Function tout comme Predicate permettent d'externaliser une partie du code spécifique et de les utiliser ainsi avec les méthodes de traitement génériques déjà implémentés dans Guava. Connaître ces méthodes permet de gagner du temps, réduit les risques d'erreurs et simplifie le code à écrire.&lt;/p&gt;



&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Références&lt;/h2&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Guava de Google&lt;/h3&gt;

&lt;h4&gt;Site&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/guava-libraries/&quot; title=&quot;https://code.google.com/p/guava-libraries/&quot;&gt;https://code.google.com/p/guava-libraries/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Documentation&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/guava-libraries/wiki/FunctionalExplained#Predicates&quot; title=&quot;https://code.google.com/p/guava-libraries/wiki/FunctionalExplained#Predicates&quot;&gt;Predicate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/guava-libraries/wiki/FunctionalExplained#Functions&quot; title=&quot;https://code.google.com/p/guava-libraries/wiki/FunctionalExplained#Functions&quot;&gt;Function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap&quot; title=&quot;https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap&quot;&gt;Multimap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Dépendance Maven&lt;/h4&gt;
&lt;pre&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.google.guava&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;guava&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;13.0.1&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2012/10/19/Classer-les-%C3%A9l%C3%A9ments-d-une-collection#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2012/10/19/Classer-les-%C3%A9l%C3%A9ments-d-une-collection#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/497</wfw:commentRss>
      </item>
    
  <item>
    <title>Predicate In Action</title>
    <link>http://blog.netapsys.fr/index.php/post/2012/10/17/Commons-Collection-In-Action</link>
    <guid isPermaLink="false">urn:md5:d6472e2f0ba4d9ecd69bde555c845098</guid>
    <pubDate>Sat, 20 Oct 2012 09:55:00 +0200</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Java J2EE</category>
        <category>Apache</category><category>CollectionUtils</category><category>common-collections</category><category>commons-collection</category><category>evaluate</category><category>filter</category><category>guava</category><category>Predicate</category><category>prédicat</category><category>select</category>    
    <description>&lt;p&gt;Habituellement, la recherche d'éléments dans une liste consiste à écrire une boucle de parcours d'éléments, un test pour savoir si l'élément parcouru est un de ceux que l'on cherche, puis à ajouter cet élément dans la liste de résultats. L'écriture de ce code est redondant, source d'erreurs et peut devenir complexe à lire et à maintenir.&lt;/p&gt;


&lt;p&gt;Les prédicats permettent de simplifier l'écriture de méthodes de recherche d'éléments dans une liste.&lt;/p&gt;


&lt;p&gt;En effet, l'interface Predicate permet d'externaliser la méthode de sélection des éléments recherchés.&lt;/p&gt;


&lt;p&gt;Nous nous concentrons sur l'intention&amp;nbsp;: que les éléments trouvés correspondent bien à ce que nous cherchons.&lt;/p&gt;


&lt;p&gt;Ainsi, nous verrons une recherche classique de livres correspondant à certains critères. Ensuite nous verrons comment les bibliothèques &lt;a href=&quot;http://commons.apache.org/collections/&quot; title=&quot;http://commons.apache.org/collections/&quot;&gt;common-collections d'Apache&lt;/a&gt; et &lt;a href=&quot;https://code.google.com/p/guava-libraries/&quot; title=&quot;https://code.google.com/p/guava-libraries/&quot;&gt;guava de Google&lt;/a&gt; nous permettent de simplifier l'écriture de cette recherche à l'aide notamment de l'interface Predicate.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Exemple de recherche&lt;/h2&gt;


&lt;p&gt;Nous allons prendre comme exemple une bibliothèque qui dispose d'une liste de livre.&lt;/p&gt;


&lt;p&gt;Pour chaque livre, nous disposons des informations suivantes&amp;nbsp;: le titre, l'auteur et l'année de publication.&lt;/p&gt;


&lt;p&gt;Nous recherchons les livres répondant aux critères suivant&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;auteur&amp;nbsp;: Rudyard Kipling&lt;/li&gt;
&lt;li&gt;titre&amp;nbsp;: le titre comporte les mots &quot;jungle&quot; et &quot;grand&quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voyons comment nous pouvons effectuer cette recherche.&lt;/p&gt;    &lt;h2&gt;Recherche classique&lt;/h2&gt;


&lt;p&gt;Voici une boucle de recherche classique&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
// Livres trouvés par la recherche
List&amp;lt;Livre&amp;gt; livreTrouves = new ArrayList&amp;lt;Livre&amp;gt;();

// Boucle de recherche
for(Livre livre : livres) {

    // Test des critères
    boolean estTrouve = 
        StringUtils.containsIgnoreCase(livre.getAuteur(),
                                       &amp;quot;Kipling&amp;quot;)
     &amp;amp;&amp;amp; StringUtils.containsIgnoreCase(livre.getTitre(),
                                       &amp;quot;livre&amp;quot;)
     &amp;amp;&amp;amp; StringUtils.containsIgnoreCase(livre.getTitre(),
                                       &amp;quot;jungle&amp;quot;);

    // Le livre correspond aux critères
    if(estTrouve) {
        livreTrouves.add(livre);
    }
}
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Amélioration de la recherche classique&lt;/h3&gt;


&lt;p&gt;Dans le code précédent, nous remarquons que nous avons une forte complexité au niveau du test sur les critères.
En effet, la logique métier est concentrée dans ce test de vérification des critères.&lt;/p&gt;


&lt;p&gt;C'est pourquoi nous créons une méthode spécifiquement chargée d'effectuer ce test.&lt;/p&gt;


&lt;p&gt;Nous obtenons ainsi le code suivant&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
/**
 * Vérifier si le livre correspond aux critères de recherche.
 * @param livre Livre
 * @return Indique si le livre correspond aux critères.
 */
private boolean verifierCritere(Livre livre)
{
    boolean estTrouve = 
        StringUtils.containsIgnoreCase(livre.getAuteur(),
                                       &amp;quot;Kipling&amp;quot;)
     &amp;amp;&amp;amp; StringUtils.containsIgnoreCase(livre.getTitre(),
                                       &amp;quot;livre&amp;quot;)
     &amp;amp;&amp;amp; StringUtils.containsIgnoreCase(livre.getTitre(),
                                       &amp;quot;jungle&amp;quot;);

    return estTrouve;
}
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;
La boucle de recherche est simplifiée&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
// Livres trouvés par la recherche
List&amp;lt;Livre&amp;gt; livreTrouves = new ArrayList&amp;lt;Livre&amp;gt;();

// Boucle de recherche
for(Livre livre : livres) {

    // Le livre correspond aux critères
    if(verifierCritere(livre)) {
        livreTrouves.add(livre);
    }

}
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Prédicat de recherche&lt;/h2&gt;


&lt;p&gt;La recherche a été simplifiée en externalisant dans une nouvelle méthode le test de vérification des critères sur un des éléments de la liste.&lt;/p&gt;


&lt;p&gt;Les bibliothèques &lt;a href=&quot;http://commons.apache.org/collections/&quot; title=&quot;http://commons.apache.org/collections/&quot;&gt;commons-collection&lt;/a&gt; et &lt;a href=&quot;https://code.google.com/p/guava-libraries/&quot; title=&quot;https://code.google.com/p/guava-libraries/&quot;&gt;guava&lt;/a&gt; permettent d'effectuer cette séparation à l'aide de l'interface &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Predicate&quot;&gt;Predicate&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;L'interface &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Predicate&quot;&gt;Predicate&lt;/a&gt; impose l'écriture d'une méthode prenant en paramètre un des éléments de la liste et qui se charge de retourner un booléen indiquant si l'élément correspond à ce que l'on cherche. Dans notre exemple, il s'agissait qu'un livre corresponde à un auteur et à un titre.&lt;/p&gt;


&lt;p&gt;Cependant, la méthode principale conserve la logique de parcours des éléments de la liste et d'ajout des éléments trouvés dans la liste de résultats de la recherche. Les bibliothèques &lt;a href=&quot;http://commons.apache.org/collections/&quot; title=&quot;http://commons.apache.org/collections/&quot;&gt;common-collections&lt;/a&gt; et &lt;a href=&quot;https://code.google.com/p/guava-libraries/&quot; title=&quot;https://code.google.com/p/guava-libraries/&quot;&gt;guava&lt;/a&gt; permettent de ne plus avoir à écrire cette logique, tout simplement en fournissant à la méthode de recherche la liste des éléments et le prédicat.&lt;/p&gt;


&lt;p&gt;Voyons deux exemples d'implémentation utilisant les deux bibliothèques.&lt;/p&gt;


&lt;h2&gt;Avec common-collections d'Apache&lt;/h2&gt;


&lt;p&gt;Nous utilisons l'interface &lt;a href=&quot;http://commons.apache.org/collections/apidocs/org/apache/commons/collections/Predicate.html&quot; title=&quot;http://commons.apache.org/collections/apidocs/org/apache/commons/collections/Predicate.html&quot;&gt;Predicate&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
public interface Predicate {
    boolean evaluate(Object object);
}
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;
Voici l'implémentation de notre &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/pr%C3%A9dicat&quot;&gt;prédicat&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
Predicate predicat = new Predicate() {
    public boolean evaluate(Object o) {
        Livre livre = (Livre) o;
        boolean estTrouve = 
            StringUtils.containsIgnoreCase(livre.getAuteur(),
                                           &amp;quot;Kipling&amp;quot;)
         &amp;amp;&amp;amp; StringUtils.containsIgnoreCase(livre.getTitre(),
                                           &amp;quot;livre&amp;quot;)
         &amp;amp;&amp;amp; StringUtils.containsIgnoreCase(livre.getTitre(),
                                           &amp;quot;jungle&amp;quot;);

        return estTrouve;
    }
};
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;
La méthode &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/evaluate&quot;&gt;evaluate&lt;/a&gt; correspond à la méthode verifierCritere de notre code précédent.&lt;/p&gt;


&lt;p&gt;La version officielle des &lt;a href=&quot;http://commons.apache.org/collections/&quot; title=&quot;http://commons.apache.org/collections/&quot;&gt;commons-collection&lt;/a&gt; ne supporte pas les types génériques. Il existe cependant une version dérivée supportant les types génériques et qui sera indiquée à la fin de ce post.&lt;/p&gt;


&lt;p&gt;Voici notre boucle de recherche qui utilise maintenant le &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/pr%C3%A9dicat&quot;&gt;prédicat&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
// Livres trouvés par la recherche
List&amp;lt;Livre&amp;gt; livreTrouves = new ArrayList&amp;lt;Livre&amp;gt;();

// Boucle de recherche
for(Livre livre : livres) {
    // Test des critères
    if(predicat.evaluate(livre)) {
        // Le livre correspond aux critères
        livreTrouves.add(livre);
    }
}
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;
Cette boucle de recherche peut être remplacée par l'appel de la méthode &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/select&quot;&gt;select&lt;/a&gt; de la classe &lt;a href=&quot;http://commons.apache.org/collections/apidocs/org/apache/commons/collections/CollectionUtils.html&quot; title=&quot;http://commons.apache.org/collections/apidocs/org/apache/commons/collections/CollectionUtils.html&quot;&gt;CollectionUtils&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
// Livres trouvés par la recherche
List&amp;lt;Livre&amp;gt; livreTrouves = new ArrayList&amp;lt;Livre&amp;gt;();

// Recherche de livres
CollectionUtils.select(livres,
                       predicate,
                       livreResultats);
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Avec guava de Google&lt;/h2&gt;


&lt;p&gt;Même chose que précédemment, nous utilisons l'interface &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Predicate&quot;&gt;Predicate&lt;/a&gt;, mais cette fois-ci celle de &lt;a href=&quot;https://code.google.com/p/guava-libraries/&quot; title=&quot;https://code.google.com/p/guava-libraries/&quot;&gt;guava&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
public interface Predicate&amp;lt;T&amp;gt; {
    boolean apply(T input);
}
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;
La bibliothèque &lt;a href=&quot;https://code.google.com/p/guava-libraries/&quot; title=&quot;https://code.google.com/p/guava-libraries/&quot;&gt;guava&lt;/a&gt; supporte par défaut les types génériques ce qui simplifie l'écriture.&lt;/p&gt;


&lt;p&gt;Voici l'implémentation de notre &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/pr%C3%A9dicat&quot;&gt;prédicat&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
Predicate&amp;lt;Livre&amp;gt; predicate = new Predicate&amp;lt;Livre&amp;gt;() {
    public boolean apply(Livre livre)
        boolean estTrouve = 
            StringUtils.containsIgnoreCase(livre.getAuteur(),
                                           &amp;quot;Kipling&amp;quot;)
         &amp;amp;&amp;amp; StringUtils.containsIgnoreCase(livre.getTitre(),
                                           &amp;quot;livre&amp;quot;)
         &amp;amp;&amp;amp; StringUtils.containsIgnoreCase(livre.getTitre(),
                                           &amp;quot;jungle&amp;quot;);

        return estTrouve;
    }
};
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;
Voici notre boucle de recherche qui utilise maintenant le &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/pr%C3%A9dicat&quot;&gt;prédicat&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
// Livres trouvés par la recherche
List&amp;lt;Livre&amp;gt; livreTrouves = new ArrayList&amp;lt;Livre&amp;gt;();

// Boucle de recherche
for(Livre livre : livres) {
    // Test des critères
    if(predicat.apply(livre)) {
        // Le livre correspond aux critères
        livreTrouves.add(livre);
    }
}
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;
Cette boucle de recherche peut être remplacée par l'appel de la méthode &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/filter&quot;&gt;filter&lt;/a&gt; de la classe &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html&quot; title=&quot;http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html&quot;&gt;Collections2&lt;/a&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
// Recherche de livres
Collection&amp;lt;Livre&amp;gt; livreResultats = 
    Collections2.filter(bibliotheque.getLivres(),
                         predicate);
&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;L'utilisation des prédicats pour la recherche permet de se concentrer sur l'intention&amp;nbsp;: vérifier que les éléments trouvés correspondent bien aux critères de recherche.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Références&lt;/h2&gt;

&lt;h3&gt;Common-collections d'Apache&lt;/h3&gt;

&lt;h4&gt;Site&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://commons.apache.org/collections/&quot; title=&quot;http://commons.apache.org/collections/&quot;&gt;http://commons.apache.org/collections/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Dépendance Maven&lt;/h4&gt;
&lt;pre&gt;
&amp;lt;dependency&amp;gt;
	&amp;lt;groupId&amp;gt;commons-collections&amp;lt;/groupId&amp;gt;
	&amp;lt;artifactId&amp;gt;commons-collections&amp;lt;/artifactId&amp;gt;
	&amp;lt;version&amp;gt;3.2.1&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Common-collections avec les types génériques&lt;/h3&gt;

&lt;h4&gt;Site&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/megamattron/collections-generic&quot; title=&quot;https://github.com/megamattron/collections-generic&quot;&gt;https://github.com/megamattron/collections-generic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Dépendance Maven&lt;/h4&gt;
&lt;pre&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;net.sourceforge.collections&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;collections-generic&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;4.01&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Guava de Google&lt;/h3&gt;

&lt;h4&gt;Site&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/guava-libraries/&quot; title=&quot;https://code.google.com/p/guava-libraries/&quot;&gt;https://code.google.com/p/guava-libraries/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/guava-libraries/wiki/FunctionalExplained#Predicates&quot; title=&quot;https://code.google.com/p/guava-libraries/wiki/FunctionalExplained#Predicates&quot;&gt;Wiki&amp;nbsp;: Predicates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Dépendance Maven&lt;/h4&gt;
&lt;pre&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.google.guava&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;guava&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;13.0.1&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2012/10/17/Commons-Collection-In-Action#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2012/10/17/Commons-Collection-In-Action#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/496</wfw:commentRss>
      </item>
    
  <item>
    <title>Gestion des énumérations avec Struts</title>
    <link>http://blog.netapsys.fr/index.php/post/2012/09/28/Gestion-des-%C3%A9num%C3%A9rations-avec-Struts</link>
    <guid isPermaLink="false">urn:md5:018fdd6d9388274789e5bb5ac4391983</guid>
    <pubDate>Sun, 30 Sep 2012 14:30:00 +0200</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Java J2EE</category>
            
    <description>    &lt;p&gt;Struts en version 1 ne supporte pas, par défaut, les énumérations au niveau des valeurs postées depuis les formulaires HTML.&lt;/p&gt;


&lt;p&gt;Je vous propose une solution pour que Struts puisse convertir directement la valeur qui a été sélectionnée dans le formulaire HTML vers la valeur de l'énumération correspondante.&lt;/p&gt;


&lt;h2&gt;Exemple d’énumération&lt;/h2&gt;


&lt;p&gt;Comme exemple, nous prenons l'énumération sur les statuts d’un dossier&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
public enum DossierStatut {
  /** Statut : Brouillon. */
  BROUILLON(&amp;quot;dossier.statut.brouillon&amp;quot;),
  /** Statut : Nouveau. */
  NOUVEAU(&amp;quot;dossier.statut.nouveau&amp;quot;),
  /** Statut : En cours. */
  EN_COURS(&amp;quot;dossier.statut.encours&amp;quot;),
  /** Statut : A valider. */
  A_VALIDER(&amp;quot;dossier.statut.avalider&amp;quot;),
  /** Statut : Clos. */
  CLOS(&amp;quot;dossier.statut.clos&amp;quot;);
  
  /**
   * Clé de message du libellé du statut.
   */
  private final String libelle;
  
  /**
   * Constructeur.
   * @param libelle Libellé.
   */
  public DossierStatut(String libelle) {
    this.libelle = libelle;
  }

  /**
   * Retourne la clé de message du libellé.
   * @return Clé de message du libellé.
   */
  Public String getLibelle() {
    return this.libelle;
  }
}
&lt;/pre&gt;


&lt;h2&gt;Page de saisie d’une valeur énumérée&lt;/h2&gt;


&lt;p&gt;Nous prenons comme exemple une page de recherche de dossiers.&lt;/p&gt;


&lt;p&gt;L’utilisateur peut saisir un ou plusieurs statuts de dossier à rechercher.&lt;/p&gt;


&lt;p&gt;Cette page contient une liste de cases à cocher pour chacun des statuts.&lt;/p&gt;


&lt;h3&gt;Page JSP&lt;/h3&gt;

&lt;pre&gt;
&amp;lt;%@ page import=&amp;quot;fr.netapsys.exemple.model.DossierStatut&amp;quot;%&amp;gt;

&amp;lt;form&amp;gt;

  &amp;lt;%-- Parcourt tous les statuts possibles du dossier --%&amp;gt;
  &amp;lt;c:forEach items=&amp;quot;${rechercheForm.dossierStatuts}&amp;quot; 
             var=&amp;quot;dossierStatut&amp;quot;&amp;gt;

    &amp;lt;%-- Ne pas sélectionner par défaut --%&amp;gt;
    &amp;lt;c:set var=&amp;quot;selected&amp;quot; value=&amp;quot;&amp;quot; /&amp;gt;
    &amp;lt;%-- Tester si cette valeur a été précédemment sélectionnée --%&amp;gt;
    &amp;lt;c:set var=&amp;quot;selected&amp;quot;&amp;gt;
      &amp;lt;c:forEach items=&amp;quot;${rechercheForm.dossierStatutSelecteds}&amp;quot;
                 var=&amp;quot;dossierStatutSelected&amp;quot;&amp;gt;
        &amp;lt;c:if test=&amp;quot;${dossierStatut eq dossierStatutSelected}&amp;quot;&amp;gt;
          checked=&amp;quot;checked&amp;quot;
        &amp;lt;/c:if&amp;gt;
      &amp;lt;/c:forEach&amp;gt;
    &amp;lt;/c:set&amp;gt;

    &amp;lt;%-- Affichage de la case à cocher --%&amp;gt;
    &amp;lt;label&amp;gt;
      &amp;lt;input type=&amp;quot;checkbox&amp;quot; 
             name=&amp;quot;statuts&amp;quot; 
             value=&amp;quot;${dossierStatut}&amp;quot;
             ${selected}
      /&amp;gt;
      &amp;lt;bean message key=&amp;quot;${dossierStatut.libelle}&amp;quot; /&amp;gt;
    &amp;lt;/label&amp;gt;

  &amp;lt;/c:forEach&amp;gt;

&amp;lt;/form&amp;gt;
&lt;/pre&gt;


&lt;p&gt;La boucle «&amp;nbsp;c:forEach&amp;nbsp;» itère sur toutes les valeurs possibles de l'énumération DossierStatut. Ces valeurs ont été obtenues à l'aide de la méthode «&amp;nbsp;getDossierStatuts&amp;nbsp;» du formulaire Struts «&amp;nbsp;rechercheForm ».&lt;/p&gt;


&lt;p&gt;La variable «&amp;nbsp;selected&amp;nbsp;» permet d'indiquer si une des valeurs a été cochée précédemment. Pour cela, nous effectuons une recherche dans la liste des valeurs précédemment sélectionnées.&lt;/p&gt;



&lt;h2&gt;Formulaire Struts&lt;/h2&gt;


&lt;p&gt;La classe RechercheForm contient une propriété «&amp;nbsp;dossierStatutSelecteds&amp;nbsp;» dont le type est un tableau de valeurs de l'énumération «&amp;nbsp;DossierStatut ». Cette propriété contient les valeurs sélectionnées dans la page par l'utilisateur.&lt;/p&gt;


&lt;p&gt;La méthode «&amp;nbsp;getAllDossierStatuts&amp;nbsp;» retourne toutes les valeurs possibles de l'énumération de «&amp;nbsp;DossierStatut ».&lt;/p&gt;

&lt;pre&gt;
public RechercheForm extends ActionForm {
  /**
   * Statuts du dossier sélectionné.
   */
  private DossierStatut[] dossierStatutSelecteds;

  /**
   * {@inheritDoc}
   */
  public void reset(ActionMapping mapping,
                    HttpServletRequest request)
  {
    super.reset(mapping,
                request);
    // Réinitialiser les statuts de dossiers sélectionnés
    // à chaque soumission du formulaire de recherche
    this.dossierStatutSelecteds = null;
  }

  /**
   * Retourne les statuts de dossiers sélectionnés.
   * @return Statuts de dossiers sélectionnés.
  public DossierStatut[] getDossierStatutSelecteds() {
    return this.dossierStatutSelecteds;
  }

  /**
   * Définit les statuts de dossiers sélectionnés.
   * @param dossierStatuts Statuts de dossiers sélectionnés.
   */
  public void setDossierStatuts(DossierStatut[] dossierStatutSelecteds) {
    this.dossierStatutSelecteds = dossierStatutSelecteds;
  }

  /**
   * Retourne la liste de tous les statuts de dossier possibles.
   * @return Statuts de dossier possibles.
   */
  public List&amp;lt;DossierStatut&amp;gt; getAllDossierStatuts() {
    return DossierStatut.values();
  }
}
&lt;/pre&gt;


&lt;h2&gt;Déclarer le plugin de conversion des valeurs postées dans Struts&lt;/h2&gt;


&lt;p&gt;A l&quot;aide d'une classe de conversion, nous indiquons à Struts comment effectuer la conversion entre une des valeurs de l’énumération et la chaîne de caractères String contenant le nom correspondant dans l’énumération.&lt;/p&gt;


&lt;p&gt;Exemple&amp;nbsp;: l’utilisateur a sélectionné «&amp;nbsp;En cours », la valeur sélectionnée et postée par le formulaire HTML est la chaîne de caractères «&amp;nbsp;EN_COURS ». Le converteur va convertir cette chaîne de caractères en la valeur de l’énumération «&amp;nbsp;DossierStatut.EN_COURS ».&lt;/p&gt;


&lt;h3&gt;Plugin de conversion de données&lt;/h3&gt;


&lt;p&gt;Tout d'abord nous déclarons le plugin de conversion de données.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;struts-config&amp;gt;
(...)

  &amp;lt;!-- Conversion de données postées. --&amp;gt;
  &amp;lt;plug-in
    className=&amp;quot;fr.netapsys.exemple.web.converter.plugin.ConverterPlugin&amp;quot;
  /&amp;gt;

(...)
&amp;lt;/struts-config&amp;gt;
&lt;/pre&gt;


&lt;p&gt;La méthode «&amp;nbsp;init&amp;nbsp;» de la classe du plugin «&amp;nbsp;ConverterPlugin&amp;nbsp;» permet d’indiquer les énumérations et la classe de conversion des énumérations.&lt;/p&gt;

&lt;pre&gt;
public class ConverterPlugin
    implements PlugIn
{
  /**
   * {@inheritDoc}
   */
  public void init(final ActionServlet servlet,
                   final ModuleConfig config)
  {
    final EnumConverter enumConverter = new EnumConverter();

    // Conversion de l’énumération DossierStatut
    ConvertUtils.register(enumConverter,
                          DossierStatut.class);

    // TODO Ajouter les autres énumérations à convertir
    // ConvertUtils.register(enumConverter,
    //                       MonEnumeration.class);

  }
}
&lt;/pre&gt;


&lt;p&gt;Pour définir une nouvelle énumération à supporter, il suffit d'ajouter la ligne suivante de déclaration du Converter pour cette énumération&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
  ConvertUtils.register(enumConverter,
                        MonEnumeration.class);
&lt;/pre&gt;


&lt;h2&gt;Classe de conversion&lt;/h2&gt;


&lt;p&gt;La classe de conversion est en charge de convertir la chaîne de caractères soumise par le formulaire HTML vers la valeur de l'énumération correspondante.&lt;/p&gt;


&lt;p&gt;Cette classe permet également l'opération inverse de conversion de la valeur de l'énumération vers une chaîne de caractères.&lt;/p&gt;


&lt;p&gt;La classe de conversion suivante est générique et peut s’utiliser pour n’importe quel type d’énumération.&lt;/p&gt;

&lt;pre&gt;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.lang.StringUtils;

public class EnumConverter
    implements Converter
{

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings(&amp;quot;unchecked&amp;quot;)
  public Object convert(final Class type,
                        final Object value)
  {
        if (value == null)
        {
            return null;
        }

        // Conversion de String vers l’énumération.
        if (value instanceof String)
        {
            final String valueAsString = StringUtils.trimToNull((String) value);
            if (valueAsString == null)
            {
                return null;
            }
            else
      {
        // Recherche de la valeur de l'énumération.
        Class&amp;lt;Enum&amp;gt; enum = (Class&amp;lt;Enum&amp;gt;) type;
        for (final Enum enumeration : (enum.getEnumConstants())
        {
          if (StringUtils.equalsIgnoreCase(valueAsString,
                                           enumeration.name()))
          {
            return enumeration;
          }
        }
        return null;
      }
    }
    // Conversion de l’énumération vers String.
    else if (type.isInstance(value))
    {
      return ((Enum) value).name();
    }
    // Type non supporté.
    else
    {
      return value;
    }
  }
}
&lt;/pre&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;Vous pouvez maintenant utiliser directement les énumérations dans vos pages JSP avec Struts.&lt;/p&gt;


&lt;p&gt;La classe de conversion des énumérations permet d’accélérer le développement et facilite la compréhension de ce qui a été développé pour du futures évolutions.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2012/09/28/Gestion-des-%C3%A9num%C3%A9rations-avec-Struts#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2012/09/28/Gestion-des-%C3%A9num%C3%A9rations-avec-Struts#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/490</wfw:commentRss>
      </item>
    
  <item>
    <title>m2eclipse : Déclarez vos projets Maven dans Eclipse</title>
    <link>http://blog.netapsys.fr/index.php/post/2012/06/02/m2eclipse-%3A-Maven-dans-Eclipse</link>
    <guid isPermaLink="false">urn:md5:c2ff6596b3a68d2d7d1f9ae45fe2b4cf</guid>
    <pubDate>Fri, 15 Jun 2012 13:00:00 +0200</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Méthodologies et bonnes pratiques</category>
            
    <description>&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse.png&quot; alt=&quot;m2eclipse&quot; style=&quot;float:right; margin: 0 0 1em 1em;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;m2eclipse édité par Sonatype permet le support de Maven dans l’IDE eclipse.&lt;/p&gt;


&lt;p&gt;Ce plugin apporte des fonctionnalités notamment au niveau de l'édition des fichiers &lt;strong&gt;pom.xml&lt;/strong&gt;, de la gestion et de l'actualisation des dépendances du projet dans Eclipse et de la gestion du filtrage des fichiers de ressources.&lt;/p&gt;


&lt;p&gt;L’objectif de ce post est de vous présenter comment installer le plugin &lt;strong&gt;m2eclipse&lt;/strong&gt; et comment configurer des projets existants ou créer de nouveaux projets.&lt;/p&gt;    &lt;h2&gt;Pré-requis&lt;/h2&gt;

&lt;p&gt;Pour que le plugin m2eclipse fonctionne, il est nécessaire d'avoir installé et configuré Maven en local.
&lt;br /&gt;
&lt;br /&gt;
Le fichier &lt;strong&gt;settings.xml&lt;/strong&gt; doit exister dans le répertoire &lt;strong&gt;.m2&lt;/strong&gt; local.&lt;/p&gt;


&lt;p&gt;Les variables d'environnement doivent être ajoutées&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt; &lt;strong&gt;MAVEN_HOME&lt;/strong&gt; : répertoire d'installation de maven
 &lt;strong&gt;M2_HOME&lt;/strong&gt; : répertoire &lt;strong&gt;.m2&lt;/strong&gt; contenant le repository local de maven.&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Installation du plugin&lt;/h2&gt;

&lt;p&gt;Nous installons m2eclipse via le marketplace d'Eclipse.&lt;/p&gt;


&lt;p&gt;Pour cela, dans Eclipse, aller dans le menu &lt;strong&gt;Help&lt;/strong&gt; &amp;gt; &lt;strong&gt;Eclipse marketplace&lt;/strong&gt;.&lt;br /&gt;
Dans la nouvelle fenêtre &lt;strong&gt;Eclipse MarketPlace&lt;/strong&gt;, saisir le mot &lt;strong&gt;maven&lt;/strong&gt; dans &lt;strong&gt;Find&lt;/strong&gt; et lancer la recherche.&lt;br /&gt;
Le plugin &lt;strong&gt;Maven Integration for Eclipse&lt;/strong&gt;  de &lt;strong&gt;Eclipse.org&lt;/strong&gt; apparaît.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_marketplace.png&quot; alt=&quot;Installation de m2eclipse depuis le marketplace&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Cliquer sur le bouton &lt;strong&gt;Install&lt;/strong&gt; et sélectionner les plugins suivants :&lt;br /&gt;
&lt;strong&gt;Maven Integration for Eclipse&lt;/strong&gt; &amp;gt; &lt;strong&gt;m2e&lt;/strong&gt; et &lt;strong&gt;m2e - slf4j&lt;/strong&gt;&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_installplugin.png&quot; alt=&quot;Choix des plugins à installer&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Cliquer sur le bouton &lt;strong&gt;Previous&lt;/strong&gt; pour revenir sur l'écran de recherche du marketplace.
&lt;br /&gt;
&lt;br /&gt;Rechercher cette fois-ci &lt;strong&gt;m2eclipse wtp&lt;/strong&gt;.
&lt;br /&gt;Le plugin &lt;strong&gt;Maven Integration for Eclipse for WTP&lt;/strong&gt; apparaît:&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_installplugin2.png&quot; alt=&quot;m2eclipse - WTP&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Cliquer sur le bouton &lt;strong&gt;Install&lt;/strong&gt; et sélectionner le module &lt;strong&gt;Maven Integration for Eclipse for WTP&lt;/strong&gt; &amp;gt; &lt;strong&gt;Maven Integration for WTP&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_installplugin3.png&quot; alt=&quot;m2eclipse - WTP&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Confirmer l'installation et, à la fin de l'installation de m2eclipse, accepter le redémarrage d'eclipse.&lt;/p&gt;


&lt;p&gt;Bravo&amp;nbsp;! m2eclipse est installé dans votre Eclipse :-)&lt;/p&gt;


&lt;p&gt;Voyons comment configurer nos projets avec le plugin m2eclipse.&lt;/p&gt;


&lt;h2&gt;Configuration des projets avec m2eclipse&lt;/h2&gt;


&lt;p&gt;m2eclipse nous offre plusieurs possibilités&amp;nbsp;: nous pouvons créer un nouveau projet Maven à partir de zéro, soit à partir d'un archétype Maven existant. Il est également possible d'importer un projet déjà existant dans notre workspace ou de le récupérer directement depuis le référentiel de sources en utilisant le composant SCM de Maven.&lt;/p&gt;


&lt;p&gt;Cependant un projet doit obligatoirement disposer d'un fichier pom.xml pour être associé à m2eclipse.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Déclarer un projet existant en tant que projet Maven&lt;/h3&gt;

&lt;p&gt;Pour lier un projet existant au plugin m2eclipse, dans la vue &lt;strong&gt;Package Explorer&lt;/strong&gt; cliquer sur le projet avec le bouton droit de la souris, puis sur &lt;strong&gt;Configure&lt;/strong&gt; et &lt;strong&gt;Convert to Maven project&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_convertproject.png&quot; alt=&quot;m2eclipse - Déclarer un projet existant en tant que projet Maven&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Cependant, si le projet contient plusieurs modules Maven, aucun projet n'est pour le moment créé par le plugin m2eclipse. Il faut alors importer les projets comme indiqué dans le paragraphe suivant &lt;strong&gt;Importer des projets existants en tant que projets Maven&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;Importer des projets existants en tant que projets Maven&lt;/h3&gt;

&lt;p&gt;L'importation de projets Maven permet d'importer tous les modules d'un projet Maven en tant que projet dans Eclipse.&lt;/p&gt;


&lt;p&gt;Pour cela, dans Eclipse, aller dans le menu &lt;strong&gt;File&lt;/strong&gt; puis &lt;strong&gt;Import&lt;/strong&gt;.
&lt;br /&gt;
&lt;br /&gt;La fenêtre de sélection du type d'importation apparaît. Sélectionner &lt;strong&gt;Maven&lt;/strong&gt; &amp;gt; &lt;strong&gt;Existing Maven Projects&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_importmaven.png&quot; alt=&quot;m2eclipse - Importer des projets Maven&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;La fenêtre d'importation propose alors d'indiquer le répertoire de base à partir duquel le plugin m2eclipse recherche les projets Maven à importer.&lt;/p&gt;


&lt;p&gt;Par exemple, dans le cas d'un projet multi-modules, nous recherchons depuis la racine du projet les modules à importer dans Eclipse&amp;nbsp;:&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_importmaven2.png&quot; alt=&quot;m2eclipse - Importer des projets Maven&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Après avoir cliqué sur le bouton &lt;strong&gt;Next&lt;/strong&gt;, nous arrivons à la liste des utilitaires nécessaires au plugin m2eclipse à installer pour pouvoir exploiter les plugins de Maven. Par exemple, il aura besoin d'un connecteur pour utiliser le plugin &lt;strong&gt;maven-compiler-plugin&lt;/strong&gt; pour effectuer la compilation du projet.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_importmaven3.png&quot; alt=&quot;m2eclipse - Importer des projets Maven&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Après confirmation de l'importation, les projets détectés sont visibles dans le workspace d'Eclipse en tant que projets Maven.&lt;/p&gt;


&lt;p&gt;Si le projet contient plusieurs modules Maven, un écran de sélection de ces modules apparaît pour sélectionner les projets à déclarer dans le workspace.&lt;/p&gt;


&lt;h3&gt;Récupérer le projet depuis le référentiel de sources SVN&lt;/h3&gt;

&lt;p&gt;Nous souhaitons récupérer notre projet directement depuis le référentiel de sources, par exemple SVN, et le référencer dans m2eclipse.&lt;/p&gt;


&lt;p&gt;Pour cela, Saisir le raccourcir &lt;strong&gt;CTRL + N&lt;/strong&gt; dans eclipse pour afficher la fenêtre &lt;strong&gt;New&lt;/strong&gt;.&lt;br /&gt;
De nouvelles entrées apparaissent&amp;nbsp;:&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newfromscm.png&quot; alt=&quot;m2eclipse - Importer un projet depuis le référentiel de sources&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Sélectionner &lt;strong&gt;Maven&lt;/strong&gt; &amp;gt; &lt;strong&gt;Checkout as Maven project from SCM&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;La fenêtre &lt;strong&gt;Checkout as Maven project from SCM&lt;/strong&gt; apparaît.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newfromscm1.png&quot; alt=&quot;Récupérer le projet Maven depuis SCM&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;h4&gt;Sélection du référentiel de source&lt;/h4&gt;

&lt;p&gt;La liste déroulante à droite de &lt;strong&gt;SCM URL&lt;/strong&gt; détermine le type de référentiel, par exemple SVN ou GIT.
&lt;br /&gt;
Dans le cas où il n'est pas présent, il est nécessaire de l'installer via le lien &lt;strong&gt;Find more SCM connectors in the m2e MarketPlace&lt;/strong&gt;.&lt;br /&gt;
La fenêtre &lt;strong&gt;m2e MarketPlace / Install m2e connectors&lt;/strong&gt; apparaît et permet de rechercher le protocole souhaité.&lt;br /&gt;
Dans la liste de résultats, aller dans la section tout en bas &lt;strong&gt;m2e Team Providers&lt;/strong&gt; et sélectionner le protocole souhaité.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newfromscm_installproviders.png&quot; alt=&quot;Installer le connecteur au référentiel de sources&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Sélectionnons par exemple le connecteur &lt;strong&gt;m2e-subversive&lt;/strong&gt; pour nous connecter au référentiel de sources &lt;strong&gt;SVN&lt;/strong&gt;.&lt;br /&gt;
m2eclipse nous proposera alors d'installer &lt;strong&gt;Maven SCM Handler for Subversive&lt;/strong&gt;.&lt;br /&gt;
Confirmer ce choix et accepter de redémarrer eclipse à la fin de l'installation.&lt;/p&gt;


&lt;p&gt;Une fois Eclipse redémarré, utiliser le raccourci clavier &lt;strong&gt;CTRL + N&lt;/strong&gt; pour afficher la fenêtre de création, puis rechercher &lt;strong&gt;Maven&lt;/strong&gt; puis &lt;strong&gt;Checkout Maven Projects depuis SCM&lt;/strong&gt; pour recommencer la récupération du projet depuis le référentiel de sources.&lt;/p&gt;


&lt;p&gt;Cette fois-ci le référentiel SVN apparaît dans la liste déroulante du champ &lt;strong&gt;SCM&lt;/strong&gt;.&lt;/p&gt;


&lt;h4&gt;Définir l'URL du projet dans le référentiel de sources&lt;/h4&gt;


&lt;p&gt;&lt;br /&gt;Le sélectionner et saisir l'URL complet du projet sur le référentiel SVN.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newfromscm3.png&quot; alt=&quot;m2eclipse - Indiquer l&amp;#039;URL SVN&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Ensuite, confirmer l'importation du projet depuis le référentiel.
&lt;br /&gt;
&lt;br /&gt;Le plugin m2eclipse va importer le projet dans Eclipse en tant que projet Maven.
&lt;br /&gt;Il va également définir des projets dans Eclipse pour chacun des modules Maven.&lt;/p&gt;


&lt;h2&gt;Création d'un nouveau projet Maven&lt;/h2&gt;

&lt;p&gt;m2eclipse permet la création d'un nouveau projet Maven soit vide, soit à partir d'un archétype.&lt;/p&gt;


&lt;h3&gt;Création d'un nouveau projet vide&lt;/h3&gt;

&lt;p&gt;Dans Eclipse, utiliser le raccourci &lt;strong&gt;CTRL + N&lt;/strong&gt; pour ouvrir la fenêtre de création.
&lt;br /&gt;Sélectionner &lt;strong&gt;Maven&lt;/strong&gt; puis &lt;strong&gt;Maven Project&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newprojectempty.png&quot; alt=&quot;m2eclipse - Création d&amp;#039;un nouveau projet vide&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;La fenêtre &lt;strong&gt;New Maven Project&lt;/strong&gt; apparaît, cocher &lt;strong&gt;Create a simple project (skip archetype selection)&lt;/strong&gt; puis cliquer sur &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newprojectempty1.png&quot; alt=&quot;m2eclipse - Création d&amp;#039;un nouveau projet vide&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;La fenêtre de configuration du projet apparaît&amp;nbsp;:&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newprojectempty2.png&quot; alt=&quot;m2eclipse - Création d&amp;#039;un nouveau projet vide&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Dans la zone &lt;strong&gt;Artifact&lt;/strong&gt;, nous avons à définir les informations Maven de notre projet&amp;nbsp;: &lt;strong&gt;Group Id&lt;/strong&gt;, &lt;strong&gt;Artifact Id&lt;/strong&gt;, &lt;strong&gt;Numéro de version&lt;/strong&gt;, le type de &lt;strong&gt;packaging&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;&amp;nbsp;: le packaging est important car il va déterminer le type et le contenu de notre nouveau projet.&lt;/p&gt;


&lt;p&gt;Pour le packaging &lt;strong&gt;pom&lt;/strong&gt;, le nouveau projet sera de type &lt;strong&gt;Projet simple&lt;/strong&gt;. Il ne contiendra qu'un fichier &lt;strong&gt;pom.xml&lt;/strong&gt;. Ce projet pourra être utilisé comme projet Maven parent et y définir des modules Maven.&lt;/p&gt;


&lt;p&gt;Pour le packaging &lt;strong&gt;jar&lt;/strong&gt;, le nouveau projet sera de type &lt;strong&gt;Projet Java&lt;/strong&gt;. Il contiendra un fichier &lt;strong&gt;pom.xml&lt;/strong&gt; et les répertoires de sources et de tests.&lt;/p&gt;


&lt;p&gt;Pour le packaging &lt;strong&gt;war&lt;/strong&gt;, le nouveau projet sera de type &lt;strong&gt;Projet Web&lt;/strong&gt; et pourra être déployé avec le WTP de Eclipse. Il contiendra un fichier &lt;strong&gt;pom.xml&lt;/strong&gt;, les répertoires de sources et tests ainsi qu'un répertoire &lt;strong&gt;src/main/webapp&lt;/strong&gt;. Cependant le fichier &lt;strong&gt;web.xml&lt;/strong&gt; sera à créer manuellement.&lt;/p&gt;


&lt;p&gt;Nous pouvons également indiquer le projet parent. Le bouton &lt;strong&gt;Browse&lt;/strong&gt; permet d'accéder à la fenêtre de recherche du projet parent. Cette recherche se base sur le paramétrage de l'actefactory dans les fichiers &lt;strong&gt;settings.xml&lt;/strong&gt; de notre configuration Maven et référencés par le plugin &lt;strong&gt;m2eclipse&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;Valider la création du projet&amp;nbsp;: le projet apparaît dans le workspace d'Eclipse.&lt;/p&gt;


&lt;h3&gt;Création d'un nouveau projet depuis un archetype&lt;/h3&gt;

&lt;p&gt;Il est également possible de créer notre projet depuis un modèle de projet existant, aussi appelé &lt;strong&gt;archetype&lt;/strong&gt; dans Maven.&lt;/p&gt;


&lt;p&gt;Il existe plusieurs archetypes publics, comme appfuse. Ceci permet de partir d'un projet modèle pour tester de nouvelles technologies.&lt;/p&gt;


&lt;p&gt;Pour créer notre projet depuis un archetype, dans Eclipse, utiliser le raccourci &lt;strong&gt;CTRL + N&lt;/strong&gt; pour ouvrir la fenêtre de création. Sélectionner &lt;strong&gt;Maven&lt;/strong&gt; puis &lt;strong&gt;Maven Projects&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newprojectarchetype.png&quot; alt=&quot;m2eclipse - Création d&amp;#039;un projet depuis un archetype&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;La fenêtre &lt;strong&gt;New Maven Project&lt;/strong&gt; apparaît. &lt;br /&gt;Ne pas cocher &lt;strong&gt;Create a simple project (skip archetype selection)&lt;/strong&gt; puis cliquer sur &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newprojectarchetype1.png&quot; alt=&quot;m2eclipse - Création d&amp;#039;un projet depuis un archetype&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;La fenêtre suivante permet de rechercher le projet Archetype qui va servir de modèle pour notre nouveau projet.
&lt;br /&gt;Nous pouvons rechercher par exemple appfuse qui propose des projets pour JSF, Spring MVC, Struts 2.
&lt;br /&gt;Sélectionner le projet modèle et cliquer sur &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newprojectarchetype2.png&quot; alt=&quot;m2eclipse - Création d&amp;#039;un projet depuis un archetype&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Enfin la création de notre projet se termine par les propriétés Maven où nous définissons le &lt;strong&gt;Group Id&lt;/strong&gt;, &lt;strong&gt;Artifact Id&lt;/strong&gt;, la &lt;strong&gt;version&lt;/strong&gt; et le &lt;strong&gt;package&lt;/strong&gt; de base des classes Java de notre nouveau projet.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/m2eclipse/m2eclipse_newprojectarchetype3.png&quot; alt=&quot;m2eclipse - Création d&amp;#039;un projet depuis un archetype&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Après confirmation, notre nouveau projet apparaît dans le workspace en se basant sur le projet archetype comme modèle.&lt;/p&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;Maintenant que le plugin &lt;strong&gt;m2eclipse&lt;/strong&gt; est installé et que votre projet est déclaré en tant que projet Maven, vous pouvez utiliser les fonctionnalités offertes par ce plugin, comme l'édition des fichiers &lt;strong&gt;pom.xml&lt;/strong&gt;, la gestion des dépendances et la configuration automatique des projets dans Eclipse et avec le WTP.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2012/06/02/m2eclipse-%3A-Maven-dans-Eclipse#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2012/06/02/m2eclipse-%3A-Maven-dans-Eclipse#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/436</wfw:commentRss>
      </item>
    
  <item>
    <title>SpringSource Tool Suite (STS) - Configuration des projets</title>
    <link>http://blog.netapsys.fr/index.php/post/2012/06/12/SpringSource-Tool-Suite-%28STS%29-Configuration-des-projets</link>
    <guid isPermaLink="false">urn:md5:f7481f9ebb4b588062570896c2791c2d</guid>
    <pubDate>Thu, 14 Jun 2012 18:09:00 +0200</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Java J2EE</category>
        <category>SpringSource Tool Suite</category>    
    <description>&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/sts_logo.png&quot; alt=&quot;SpringSource Tool Suite&quot; style=&quot;float:right; margin: 0 0 1em 1em;&quot; /&gt;
Suite au post précédent où je vous présentais les fonctionnalités de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; pour l'édition des fichiers XML de Spring, je vous présente ici comment effectuer la configuration de votre projet avec ce plugin.&lt;/p&gt;    &lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Définir un projet Java comme étant un projet Spring&lt;/h2&gt;

&lt;p&gt;Maintenant, il est nécessaire de déclarer le projet en tant que projet de type Spring.&lt;/p&gt;


&lt;p&gt;Ceci permet d'activer les fonctionnalités de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; sur ce projet.&lt;/p&gt;


&lt;p&gt;Un projet de type Spring est indiqué par le petit «&amp;nbsp;S&amp;nbsp;» comme &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Spring&quot;&gt;Spring&lt;/a&gt; en haut à droite de l’icône du projet qui passe de &lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_iconeprojetsansspring.png&quot; alt=&quot;SpringSource Tool Suite - Icône du projet sans Spring&quot; /&gt; à &lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_iconeprojetavecspring.png&quot; alt=&quot;SpringSource Tool Suite - Icône du projet avec Spring&quot; /&gt;.&lt;/p&gt;


&lt;p&gt;Voici deux méthodes: soit manuellement dans eclipse, soit via le plugin &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/maven-eclipse-plugin&quot;&gt;maven-eclipse-plugin&lt;/a&gt; de Maven.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Via Eclipse&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Dans &lt;strong&gt;Eclipse&lt;/strong&gt; &amp;gt; Vue &lt;strong&gt;Package Explorer&lt;/strong&gt; ou &lt;strong&gt;Project Explorer&lt;/strong&gt; &amp;gt; Cliquer avec le bouton droit de la souris sur le nom du projet &amp;gt; &lt;strong&gt;Spring Tools&lt;/strong&gt; &amp;gt; &lt;strong&gt;Add Spring Project Nature&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_addspringnature.png&quot; alt=&quot;SpringSource Tool Suite - Déclarer le projet de type Spring&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;Maintenant votre projet est déclaré comme étant de type «&amp;nbsp;projet Spring ».&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Via le plugin maven-eclipse de Maven&lt;/h3&gt;

&lt;p&gt;L’utilisation du plugin &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/maven-eclipse-plugin&quot;&gt;maven-eclipse-plugin&lt;/a&gt; de Maven permet de définir un projet Maven comme étant de type Spring dans eclipse.&lt;/p&gt;


&lt;p&gt;La déclaration du projet Spring s’effectue en ajoutant des propriétés à la configuration du plugin &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/maven-eclipse-plugin&quot;&gt;maven-eclipse-plugin&lt;/a&gt; dans le fichier &lt;strong&gt;pom.xml&lt;/strong&gt; du projet de cette façon&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;&lt;strong&gt;maven-eclipse-plugin&lt;/strong&gt;&amp;lt;/artifactId&amp;gt;
    (…)
    &amp;lt;configuration&amp;gt;
        &amp;lt;projectnatures&amp;gt;
            &amp;lt;projectnature&amp;gt;
                &lt;strong&gt;org.springframework.ide.eclipse.core.springnature&lt;/strong&gt;
            &amp;lt;/projectnature&amp;gt;
        &amp;lt;/projectnatures&amp;gt;
        &amp;lt;additionalBuildcommands&amp;gt;
            &amp;lt;buildcommand&amp;gt;
                &lt;strong&gt;org.springframework.ide.eclipse.core.springbuilder&lt;/strong&gt;
            &amp;lt;/buildcommand&amp;gt;
        &amp;lt;/additionalBuildcommands&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;
Lancer la commande Maven pour mettre à jour la configuration des projets dans Eclipse&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;mvn eclipse:clean eclipse:eclipse&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;Une fois réactualisé dans Eclipse, le projet sera indiqué comme étant un projet de type «&amp;nbsp;Spring&amp;nbsp;» : un petit «&amp;nbsp;S&amp;nbsp;» apparaîtra sur l'icône du projet dans eclipse&amp;nbsp;: &lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_iconeprojetavecspring.png&quot; alt=&quot;SpringSource Tool Suite - Icône du projet avec Spring&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Spring Project Builder&lt;/h3&gt;

&lt;p&gt;Le &lt;strong&gt;Spring Project Builder&lt;/strong&gt;  est ajouté dans la liste des Builders dans la configuration du projet.&lt;/p&gt;


&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_builder.png&quot; alt=&quot;SpringSource Tool Suite - Builder&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;Il indique que les fichiers de configurations de Spring seront analysés par &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; à chaque compilation du projet.
&lt;br /&gt;
&lt;br /&gt;Ceci permet d’avoir &lt;strong&gt;à jour&lt;/strong&gt; les références vers les beans Spring à chaque modification du code Java ou des fichiers XML de configuration Spring.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Configuration du projet avec &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Maintenant que notre projet est de type Spring, nous abordons la partie la plus importante de la configuration du projet.&lt;/p&gt;


&lt;p&gt;Elle consiste à indiquer à &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; les fichiers Spring du projet actuel et des projets liés qui seront analysés par &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; au niveau de ce projet.&lt;/p&gt;


&lt;p&gt;Nous avons ainsi deux listes à définir&amp;nbsp;: une première liste pour indiquer les fichiers Spring du projet actuel et une seconde liste pour indiquer les fichiers Spring qui seront analysés par &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Pour cela, dans la configuration Spring du projet, l’arborescence contient le nouvel élément  &lt;strong&gt;Spring&lt;/strong&gt; &amp;gt; &lt;strong&gt;Beans Support&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;La partie droite &lt;strong&gt;Beans Support&lt;/strong&gt; contient deux onglets &lt;strong&gt;Config Files&lt;/strong&gt; et &lt;strong&gt;Config Sets&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;Onglet Config Files&lt;/h3&gt;

&lt;p&gt;L’onglet &lt;strong&gt;Config Files&lt;/strong&gt; permet de lister les fichiers XML de Spring du projet actuel. Les fichiers Spring peuvent être soit ajoutés soit manuellement, soit détectés automatiquement par «&amp;nbsp;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;&amp;nbsp;» ce qui est fort pratique&amp;nbsp;! :-)&lt;/p&gt;


&lt;p&gt;Une fois référencé, le fichier Spring est indiqué dans Eclipse avec un petit «&amp;nbsp;S&amp;nbsp;» sur son icône de fichier&amp;nbsp;: &lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_iconefichieravecspring.png&quot; alt=&quot;SpringSource Tool Suite - icône de fichier déclaré dans SpringSource Tool Suite&quot; /&gt;&lt;/p&gt;


&lt;h3&gt;Onglet Config Sets&lt;/h3&gt;

&lt;p&gt;L’onglet &lt;strong&gt;Config Sets&lt;/strong&gt; permet lui de d'indiquer les fichiers Spring qui sont réellement analysés par &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; pour le projet actuel.&lt;/p&gt;


&lt;p&gt;Nous y indiquons ainsi les fichiers Spring du projet actuel et également les fichiers Spring des autres projets liés.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Important&amp;nbsp;: pour les fichiers Spring des tests :&lt;/strong&gt; il ne faut pas référencer les fichiers Spring des tests des autres projets liés, mais uniquement ceux des tests du projet actuel. En effet, les fichiers Spring de tests des autres projets ne sont pas utilisés dans le projet actuel et les référencer serait source d'erreurs.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Configuration d’un projet&lt;/h2&gt;

&lt;p&gt;Voyons comment configurer un projet.&lt;/p&gt;


&lt;p&gt;Voici le projet &lt;strong&gt;bookstore&lt;/strong&gt; à configurer. Il s'agit d'une application Web&amp;nbsp;:&lt;/p&gt;


&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_simple_vueprojet.png&quot; alt=&quot;SpringSource Tool Suite - Organisation du projet bookstore&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Liste des fichiers Spring&lt;/h4&gt;

&lt;p&gt;Dans un premier temps, nous définissons la liste des fichiers Spring du projet.&lt;/p&gt;


&lt;p&gt;Dans la configuration du projet&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beans Support&lt;/strong&gt; &amp;gt; Onglet &lt;strong&gt;Config Files&lt;/strong&gt; &amp;gt; Cliquer sur &lt;strong&gt;Scan&lt;/strong&gt; &amp;gt; Ajouter tous les fichiers Spring détectés&amp;nbsp;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_simple_configfiles.png&quot; alt=&quot;SpringSource Tool Suite - Fichiers Spring&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Groupe des fichiers Spring analysés par &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;Dans un second temps, nous indiquons à &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; les fichiers Spring à prendre en compte pour ce projet.&lt;/p&gt;


&lt;p&gt;Dans la configuration du projet&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beans Support&lt;/strong&gt; &amp;gt; Onglet &lt;strong&gt;Config Sets&lt;/strong&gt; &amp;gt; Cliquer sur &lt;strong&gt;New&lt;/strong&gt; &amp;gt; La fenêtre d'ajouts de fichiers Spring apparaît &amp;gt; Sélectionnez tous les fichiers Spring de &lt;strong&gt;bookstore-common&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_simple_configset.png&quot; alt=&quot;SpringSource Tool Suite - Groupe de fichiers Spring&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Fin de la configuration&lt;/h2&gt;

&lt;p&gt;Voilà le projet est configuré, &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; connaît et analyse vos fichiers Spring à chaque compilation du projet.&lt;/p&gt;


&lt;p&gt;SpringSource Tool Suite va pouvoir vous assister dans l'écriture de vos fichiers Spring et dans la détection des erreurs.
Dans cette troisième partie, nous allons aborder la configuration d'un projet disposant de plusieurs modules liés entre eux.&lt;/p&gt;


&lt;p&gt;En effet, ce type de configuration est moins évident que pour un projet simple.&lt;/p&gt;


&lt;p&gt;L'objectif de ce post est de vous indiquer comment s'y prendre et d'éviter certains pièges.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Configuration d’un projet avec plusieurs modules&lt;/h2&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;Pour comprendre comment configurer des projets disposant de plusieurs modules avec SpringSource Tool Suite, nous allons prendre l’exemple d'un projet disposant des deux modules suivants&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;bookstore-common&lt;/strong&gt;&amp;nbsp;: module inclu sous forme de &lt;strong&gt;jar&lt;/strong&gt; dans le module web&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bookstore-web&lt;/strong&gt;&amp;nbsp;: module web&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous avons donc une dépendance entre le projet &lt;strong&gt;common&lt;/strong&gt; et le projet &lt;strong&gt;web&lt;/strong&gt; car le module &lt;strong&gt;common&lt;/strong&gt; est inclu sous forme de &lt;strong&gt;jar&lt;/strong&gt; dans le module &lt;strong&gt;web&lt;/strong&gt;.
&lt;br /&gt;
Avec cette dépendance, les fichiers Spring du module &lt;strong&gt;common&lt;/strong&gt; sont utilisés dans le module &lt;strong&gt;web&lt;/strong&gt;. Ainsi les beans Spring du module web référencent les beans spring du module commun. Cette complication sera détaillée ci-dessous pour pouvoir configurer des projets multi-modules.&lt;/p&gt;


&lt;p&gt;Voici l’organisation de ces deux modules&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_bookstore_vueprojet2.png&quot; alt=&quot;SpringSource Tool Suite - Vue du projet&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Définir les fichiers Spring du projet «&amp;nbsp;common&amp;nbsp;»&lt;/h3&gt;

&lt;p&gt;Le module commun ne référence aucun fichier Spring d'un autre projet.&lt;/p&gt;


&lt;p&gt;Il correspond au cas d'un projet simple&amp;nbsp;: nous référençons dans &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; uniquement les fichiers Spring de ce projet.&lt;/p&gt;


&lt;h4&gt;Lister les fichiers Spring du projet «&amp;nbsp;common&amp;nbsp;»&lt;/h4&gt;

&lt;p&gt;Dans la configuration du projet&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beans Support&lt;/strong&gt; &amp;gt; Onglet &lt;strong&gt;Config Files&lt;/strong&gt; &amp;gt; Cliquer sur &lt;strong&gt;Scan&lt;/strong&gt; &amp;gt; Ajouter tous les fichiers Spring détectés&amp;nbsp;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_common_configfiles.png&quot; alt=&quot;SpringSource Tool Suite - Configuration des fichiers du module common&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;h4&gt;Groupe des fichiers Spring analysés par SpringSource Tool Suite&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beans Support&lt;/strong&gt; &amp;gt; Onglet &lt;strong&gt;Config Sets&lt;/strong&gt; &amp;gt; Cliquer sur &lt;strong&gt;New&lt;/strong&gt; &amp;gt; La fenêtre d'ajouts de fichiers Spring apparaît &amp;gt; Sélectionnez tous les fichiers Spring de &lt;strong&gt;bookstore-common&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_common_configset_select.png&quot; alt=&quot;SpringSource Tool Suite - Sélection des fichiers Spring pour le groupe de fichiers du module common&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_common_configset.png&quot; alt=&quot;SpringSource Tool Suite - Groupe de fichiers Spring du module common&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Définir les fichiers Spring du projet «&amp;nbsp;web&amp;nbsp;»&lt;/h3&gt;

&lt;p&gt;Pour le projet &lt;strong&gt;bookstore-web&lt;/strong&gt;, nous avons à référencer les fichiers Spring &lt;strong&gt;applicationContext-web.xml&lt;/strong&gt; et &lt;strong&gt;applicationContext.xml&lt;/strong&gt; et également les fichiers Spring de &lt;strong&gt;bookstore-common&lt;/strong&gt;.&lt;/p&gt;


&lt;h4&gt;Lister les fichiers Spring du projet «&amp;nbsp;web&amp;nbsp;»&lt;/h4&gt;

&lt;p&gt;Dans la configuration du projet&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beans Support&lt;/strong&gt; &amp;gt; Onglet &lt;strong&gt;Config Files&lt;/strong&gt; &amp;gt; Cliquer sur &lt;strong&gt;Scan&lt;/strong&gt; &amp;gt; Ajouter tous les fichiers Spring détectés&amp;nbsp;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_web_configfiles.png&quot; alt=&quot;SpringSource Tool Suite - Fichiers Spring du module web&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;h4&gt;Groupe des fichiers Spring analysés par SpringSource Tool Suite&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beans Support&lt;/strong&gt; &amp;gt; Onglet &lt;strong&gt;Config Sets&lt;/strong&gt; &amp;gt; Cliquer sur &lt;strong&gt;New&lt;/strong&gt; &amp;gt; La fenêtre d'ajouts de fichiers Spring apparaît &amp;gt; Sélectionnez les fichiers Spring de &lt;strong&gt;bookstore-web&lt;/strong&gt; et de &lt;strong&gt;bookstore-common&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important&amp;nbsp;: les fichiers Spring des tests des autres projets ne doivent pas être sélectionnés&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;Ici, le fichier Spring &lt;strong&gt;applicationContext-test.xml&lt;/strong&gt; des tests du module commun ne doit pas être repris. Il est encadré ci-dessous en rouge. Ainsi son contenu n'impactera pas le module Web qui n'utilise pas ce fichier.&lt;/p&gt;


&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_web_configset_select.png&quot; alt=&quot;SpringSource Tool Suite - Sélection des fichiers Spring pour le groupe de fichiers du module web&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_web_configset.png&quot; alt=&quot;SpringSource Tool Suite - Groupe de fichiers Spring du module web&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;Au travers des exemples pour un projet simple et d'un projet multi-modules comportant des tests, vous avez pu voir comment effectuer la configuration sur votre projet.&lt;/p&gt;


&lt;p&gt;Vous pourrez ainsi gagner du temps et de l'énergie dans l'écriture de vos fichiers XML Spring à l'aide de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Références&amp;nbsp;:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://http://www.springsource.com/developer/sts&quot;&gt;SpringSource Tool Suite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.springsource.org/&quot;&gt;Spring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eclipse.org/downloads/&quot;&gt;Eclipse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://maven.apache.org/&quot;&gt;Maven&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://maven.apache.org/plugins/maven-eclipse-plugin/&quot;&gt;maven-eclipse-plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://maven.apache.org/plugins/maven-eclipse-plugin/examples/provide-project-natures-and-build-commands.html&quot;&gt;maven-eclipse-plugin - Provide Project Natures And Build Commands for Eclipse&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2012/06/12/SpringSource-Tool-Suite-%28STS%29-Configuration-des-projets#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2012/06/12/SpringSource-Tool-Suite-%28STS%29-Configuration-des-projets#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/446</wfw:commentRss>
      </item>
    
  <item>
    <title>SpringSource Tool Suite (STS) - Simplifiez-vous l'écriture des fichiers XML de Spring</title>
    <link>http://blog.netapsys.fr/index.php/post/2012/06/12/SpringSource-Tool-Suite-%28STS%29-Simplifiez-vous-l-%C3%A9criture-des-fichiers-XML-de-Spring</link>
    <guid isPermaLink="false">urn:md5:62ef088be684a768a3353abb59662453</guid>
    <pubDate>Wed, 13 Jun 2012 12:12:00 +0200</pubDate>
    <dc:creator>Ludovic Chaboud-Paupi</dc:creator>
        <category>Java J2EE</category>
            
    <description>&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/sts_logo.png&quot; alt=&quot;SpringSource Tool Suite&quot; style=&quot;float:right; margin: 0 0 1em 1em;&quot; /&gt;
&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; est un plugin qui permet le support de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Spring&quot;&gt;Spring&lt;/a&gt; dans
&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Eclipse&quot;&gt;Eclipse&lt;/a&gt;. Il se base sur le plugin &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/Spring%20IDE&quot;&gt;Spring IDE&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Je vais vous présenter dans ce post les fonctionnalités de base de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; qui sont de gérer la déclaration de beans Spring dans les fichiers XML.&lt;/p&gt;    &lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Fonctionnalités de base de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;&lt;/h2&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Rechercher un bean Spring&lt;/h3&gt;

&lt;p&gt;La recherche de beans Spring est simplifiée&amp;nbsp;: nous pouvons rechercher la définition d'un bean Spring par son id de la même façon que si nous recherchions une classe Java.&lt;/p&gt;


&lt;p&gt;La barre d’outils dans eclipse contient la nouvelle icône&amp;nbsp;:  &lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_iconerecherche.png&quot; alt=&quot;SpringSource Tool Suite - icône de recherche&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Cette icône donne accès à la fenêtre de recherche &lt;strong&gt;Open Bean&lt;/strong&gt; permettant de rechercher un bean Spring par son &lt;strong&gt;id&lt;/strong&gt;. Nous pouvons y utiliser des jokers «&amp;nbsp;&lt;strong&gt;*&lt;/strong&gt; ».&lt;/p&gt;


&lt;p&gt;Le raccourci par défaut de recherche d’un bean Spring est &lt;strong&gt;ALT + SHIFT + B&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_openbean.png&quot; alt=&quot;SpringSource Tool Suite - Recherche d&amp;#039;un bean Spring&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Auto-complétion&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; nous assiste également dans l'édition des fichiers XML en apportant l'auto-complétion au niveau des noms des classes Java, des propriétés et des beans Spring référencés.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Auto-complétion du nom des classes Java&lt;/h3&gt;

&lt;p&gt;Nous déclarons la classe Java d'un bean Spring. &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; nous aide en affichant les classes Java possibles&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_nomclassejava1.png&quot; alt=&quot;SpringSource Tool Suite - Auto-complétion du nom de la classe Java&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Auto-complétion du nom des propriétés&lt;/h3&gt;

&lt;p&gt;Nous ajoutons une nouvelle propriété, &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; liste toutes les propriétés possibles&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_nompropriete1.png&quot; alt=&quot;SpringSource Tool Suite - Auto-complétion du nom de la propriété&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Auto-complétion des références vers d’autres beans Spring&lt;/h3&gt;

&lt;p&gt;SpringSource Tool Suite nous aide également lorsque nous définissons une référence vers un bean Spring en listant les noms possibles&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_nomref1.png&quot; alt=&quot;SpringSource Tool Suite - Auto-complétion du nom du bean Spring référencé&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Navigation&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; facilite la navigation dans les fichiers XML de Spring.
&lt;br /&gt;Il est ainsi possible de naviguer vers un bean Spring référencé ou vers la méthode «&amp;nbsp;set&amp;nbsp;» correspondant au nom de la propriété du bean Spring.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Navigation vers les beans référencés&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; permet d'accéder à un bean Spring référencé en appuyant sur CTRL et en cliquant sur le nom du bean Spring&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_lienref1.png&quot; alt=&quot;SpringSource Tool Suite - Lien depuis la référence&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;

&lt;p&gt;CTRL + Clic sur le nom du bean Spring «&amp;nbsp;bookDao&amp;nbsp;» permet d’accéder à sa définition&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_lienref2.png&quot; alt=&quot;SpringSource Tool Suite - Bean pointé par la référence&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Navigation vers les méthodes «&amp;nbsp;setters&amp;nbsp;»&lt;/h3&gt;

&lt;p&gt;Il est également possible d'accéder depuis le nom de la propriété à la méthode «&amp;nbsp;set&amp;nbsp;» correspondante&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springide_liensetter1.png&quot; alt=&quot;SpringSource Tool Suite - Lien vers la méthode set&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/pre&gt;

&lt;p&gt;CTRL + Clic sur le nom de la propriété &lt;strong&gt;bookDao&lt;/strong&gt; permet d’accéder à la méthode &lt;strong&gt;setBookDao&lt;/strong&gt; de la classe. Ceci permet de voir comment est injectée la valeur de la propriété.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Gestion des erreurs&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; indique les erreurs dans les fichiers de configuration de type&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la propriété ne peut pas être définie car la méthode «&amp;nbsp;set&amp;nbsp;» n'existe pas&lt;/li&gt;
&lt;li&gt;le bean référencé n’existe pas&lt;/li&gt;
&lt;li&gt;la classe d’implémentation n’existe pas&lt;/li&gt;
&lt;li&gt;le bean à définir dans la propriété ne correspond pas au type de la propriété en question&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Installation de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; s’installe en tant que plugin via le Marketplace d'Eclipse.&lt;/p&gt;


&lt;h3&gt;Via le marketplace&lt;/h3&gt;

&lt;p&gt;Dans eclipse, aller dans le menu &lt;strong&gt;Help&lt;/strong&gt; &amp;gt; &lt;strong&gt;Eclipse marketplace&lt;/strong&gt;.&lt;br /&gt;
Dans la nouvelle fenêtre &lt;strong&gt;Eclipse MarketPlace&lt;/strong&gt;, saisir les mots &lt;strong&gt;Spring Tool&lt;/strong&gt; dans &lt;strong&gt;Find&lt;/strong&gt; et lancer la recherche.&lt;br /&gt;
&lt;br /&gt;
Le plugin &lt;strong&gt;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;&lt;/strong&gt;  de &lt;strong&gt;SpringSource&lt;/strong&gt; apparaît dans deux versions différentes. Il faut prendre la version qui correspond à la votre version d'Eclipse.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springsourcetoolsuite_install_marketplace.png&quot; alt=&quot;SpringSource Tool Suite - Installation via le marketplace&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Cliquer sur le bouton &lt;strong&gt;Install&lt;/strong&gt; et rendez-vous au chapitre &lt;strong&gt;Choix des modules du plugin&lt;/strong&gt; pour finaliser l'installation.&lt;/p&gt;


&lt;h3&gt;Choix des modules du plugin&lt;/h3&gt;

&lt;p&gt;Pour l'installation de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;, sélectionner les modules suivants&amp;nbsp;:
&lt;br /&gt;&lt;strong&gt;Spring IDE&lt;/strong&gt; &amp;gt; &lt;strong&gt;Spring IDE Core&lt;/strong&gt;
&lt;br /&gt;&lt;strong&gt;SpringSource Tool Suite&lt;/strong&gt; &amp;gt; &lt;strong&gt;SpringSource Tool Suite&lt;/strong&gt;&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://blog.netapsys.fr/public/spring-ide/springsourcetoolsuite_install_module.png&quot; alt=&quot;SpringSource Tool Suite - Installation des modules&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Confirmer l'installation et, à la fin de l'installation de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;, accepter le redémarrage d'Eclipse.&lt;/p&gt;


&lt;h3&gt;Fin de l'installation&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bravo !&lt;/strong&gt; &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; est installé dans votre Eclipse :-)&lt;/p&gt;



&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;L’atout de &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; réside dans la recherche de beans Spring, l’auto-complétion et la détection d’erreurs dans la configuration qui n'apparaissent habituellement qu’au démarrage de l’application ou dans les tests unitaires.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt; nous permet ainsi de gagner du temps et de faciliter l’écriture des fichiers XML de Spring.&lt;/p&gt;


&lt;p&gt;Si vous souhaitez ajouter ces fonctionnalités sur votre projet dans Eclipse, rendez-vous dans le second post où je vous expliquerai comment configurer votre projet avec &lt;a href=&quot;http://blog.netapsys.fr/index.php/tag/SpringSource%20Tool%20Suite&quot;&gt;SpringSource Tool Suite&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4&gt;Références&amp;nbsp;:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.springsource.com/developer/sts&quot;&gt;SpringSource Tool Suite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.springsource.org/&quot;&gt;Spring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eclipse.org/downloads/&quot;&gt;Eclipse&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    
    
    
          <comments>http://blog.netapsys.fr/index.php/post/2012/06/12/SpringSource-Tool-Suite-%28STS%29-Simplifiez-vous-l-%C3%A9criture-des-fichiers-XML-de-Spring#comment-form</comments>
      <wfw:comment>http://blog.netapsys.fr/index.php/post/2012/06/12/SpringSource-Tool-Suite-%28STS%29-Simplifiez-vous-l-%C3%A9criture-des-fichiers-XML-de-Spring#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.netapsys.fr/index.php/feed/atom/comments/445</wfw:commentRss>
      </item>
    
</channel>
</rss>