<?xml version="1.0"?>
<!-- name="generator" content="blojsom v2.30" -->
<rss version="2.0" xmlns:wfw="http://wellformedweb.org/CommentAPI/">
    <channel>
        <title>Expertise Java & J2EE</title>
        <link>http://java.craven.fr/blog/java/</link>
        <description>Astuces et conseils pour le programmeur raffiné</description>
        <language>fr</language>
        <image>
            <url>http://java.craven.fr/favicon.ico</url>
            <title>Expertise Java & J2EE</title>
            <link>http://java.craven.fr/blog/java/</link>
        </image>
        <docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<generator>blojsom v2.30</generator>
		<managingEditor>blog@jonathan.craven.fr</managingEditor>
		<webMaster>blog@jonathan.craven.fr</webMaster>
		<pubDate>Thu, 28 May 2009 20:45:45 +0200</pubDate>

                <item>
            <title>Sélectionner les premiers N rangées dans MS SQL, Oracle et DB2</title>
            <link>http://java.craven.fr/blog/java/SQL/?permalink=Selectionner-les-premiers-N-rangees-dans-MS-SQL-Oracle-et-DB2.html</link>
            <description>&lt;p&gt;&lt;img src=&quot;http://www.craven.fr/blojsom/resources/default/database.png&quot; align=&quot;left&quot; style=&quot;margin:8px;&quot; /&gt;
Comment faire les requêtes SQL qui ne retournent que les premiers &lt;i&gt;n&lt;/i&gt; rangées?
&lt;/p&gt;
&lt;p&gt;
Déjà il faut comprendre que les rangées ne sont pas stockées physiquement dans un ordre quelconque. Il est donc essentiel de spécifier un ORDER BY dans la requête. Cela dit, regardons comment faire un SELECT qui ne retourne que les premiers &lt;i&gt;n&lt;/i&gt; résultats trouvés (dans tous ces exemples, &lt;i&gt;n&lt;/i&gt; = 10):
&lt;/p&gt;
&lt;h4&gt;MS SQL Server&lt;/h4&gt;
&lt;blockquote&gt;
&lt;pre&gt;
SELECT TOP 10 NOM, DESCRIPTION
FROM MATABLE
ORDER BY NOM ASC
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Il y a des fortes chances que cela marche sous Sybase aussi, mais je n&#39;ai pas eu l&#39;occasion de tester.&lt;/p&gt;
&lt;h4&gt;Oracle&lt;/h4&gt;
&lt;blockquote&gt;
&lt;pre&gt;
SELECT * FROM
(SELECT NOM, DESCRIPTION
FROM MATABLE
ORDER BY NOM ASC)
WHERE ROWNUM &lt;=10
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;
(On doit imbriquer la requête dans Oracle, car si on suivait directement la clause WHERE par la clause ORDER BY, sans parenthèses, la BDD prendra les premiers résultats, aléatoires, et ensuite les triera. Ce qui n&#39;est pas ce qu&#39;on veut faire.)
&lt;/p&gt;
&lt;h4&gt;DB2&lt;/h4&gt;
&lt;blockquote&gt;
&lt;pre&gt;
SELECT NOM, DESCRIPTION
FROM MATABLE
ORDER BY NOM
FETCH FIRST 10 ROWS ONLY
OPTIMIZE FOR 10 ROWS
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Et voilà. C&#39;est dommage qu&#39;il n&#39;y a pas de façon uniforme de faire ces requêtes, mais ce n&#39;est pas trop compliqué une fois qu&#39;on connaît les variantes.
&lt;/p&gt;
</description>
            <guid>http://java.craven.fr/blog/java/SQL/?permalink=Selectionner-les-premiers-N-rangees-dans-MS-SQL-Oracle-et-DB2.html</guid>
			<pubDate>Thu, 28 May 2009 20:45:45 +0200</pubDate>
            <category>/SQL/</category>
                                </item>
                <item>
            <title>Les trois plugins Firefox les plus incontournables</title>
            <link>http://java.craven.fr/blog/java/AJAX/?permalink=Les-trois-plugins-Firefox-les-plus-incontournables.html</link>
            <description>&lt;p&gt;
Grâce à son architecture extensible et son licence open source, le navigateur Firefox est devenu un des outils les plus utiles pour les développeurs web.  Nul autre outil permet tellement facilement de tester des sites web, et de diagnostiquer ce qui ne va pas en cas de mauvais affichage, et tout cela gratuitement.  En voici les trois plug-ins qu&#39;il vous faut installer pour transformer votre navigateur Firefox dans un outil puissant de développement.
&lt;/p&gt;
&lt;center&gt;
&lt;a href=&quot;http://getfirebug.com/&quot; target=&quot;_blank&quot;&gt;
&lt;img src=&quot;http://www.craven.fr/blojsom/resources/default/firebug.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;
&lt;p&gt;&lt;a href=&quot;http://getfirebug.com/&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;1.  Firebug&lt;/b&gt;&lt;/a&gt;.  La transition de HTML classique vers CSS nous a permis de séparer contenu et présentation.  Tout cela est génial, mais comment est-ce qu&#39;on s&#39;en sort quand on a plusieurs feuilles de style avec des centaines de classes, et on doit trouver pourquoi tel &lt;tt&gt;&amp;lt;div&amp;gt;&lt;/tt&gt; se trouve pas au bon endroit?  Firebug permet de voir, simplement en passant le souris sur la page, toutes les classes css qui s&#39;y appliquent, et lesquelles sont priorisées au-dessous des autres.  Débugger le css serait un cauchemar si on n&#39;avait pas Firebug.
&lt;/p&gt;
&lt;center&gt;
&lt;a href=&quot;http://seleniumhq.org&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://www.craven.fr/blojsom/resources/default/selenium.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;
&lt;p&gt;&lt;a href=&quot;http://seleniumhq.org&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;2. Selenium&lt;/b&gt;&lt;/a&gt;.  Marre de remplir les formulaires pour tester les différents parcours de votre application?  Selenium permet, à la manière de jUnit, de sauvegarder vos parcours et de les rejouer automatiquement.  Un outil très mûr et facile à adapter à vos besoins (exportation des tests en java, intégration ant, etc.), Selenium est indispensable pour tester vos applications web.
&lt;/p&gt;
&lt;center&gt;
&lt;a href=&quot;http://livehttpheaders.mozdev.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://www.craven.fr/blojsom/resources/default/livehttpheaders.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;
&lt;p&gt;&lt;a href=&quot;http://livehttpheaders.mozdev.org/&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;3. LiveHttpHeaders&lt;/b&gt;&lt;/a&gt;.  Des fois, le serveur ne se comporte pas comme on s&#39;y attend et on a du mal à comprendre pourquoi.  Le plugin LiveHttpHeaders permet de voir, pour n&#39;importe laquelle page internet, les en-têtes HTTP que votre navigateur a envoyé avec sa requête, et aussi les en-têtes de la réponse serveur.  C&#39;est rare qu&#39;on en a besoin, mais c&#39;est extrêmement utile à avoir lorsque, par exemple, on a des comportements différents en recette et en production et qu&#39;on soupçonne qu&#39;une configuration WebSphere ou Apache est derrière le problème...
&lt;/p&gt;
</description>
            <guid>http://java.craven.fr/blog/java/AJAX/?permalink=Les-trois-plugins-Firefox-les-plus-incontournables.html</guid>
			<pubDate>Thu, 2 Apr 2009 07:07:07 +0200</pubDate>
            <category>/AJAX/</category>
                                </item>
                <item>
            <title>Garder les fichiers generes de vos JSP dans WebLogic</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=Garder-les-fichiers-g%C3%A9n%C3%A9r%C3%A9s-de-vos-JSP-dans-WebLogic.html</link>
            <description>&lt;p&gt;
Par défaut Weblogic supprime les fichiers .jsp qui sont générés lors de la phase de traduction d&#39;un JSP.  Il ne garde que les fichiers .class qui sont compilés par la suite.  Néanmoins, en développement ces fichiers .java peuvent s&#39;averer très utiles. Par exemple, lors d&#39;une exception dans le JSP, la trace donnera la ligne exact du fichier .java où l&#39;exception a eu lieu.  Si on a le fichier .java, on peut souvent trouver plus rapidement qu&#39;est-ce qui s&#39;est passé, ce qui est plus facile que de relire tout le JSP en essayant de voir qu&#39;est-ce qui a pu tourner mal (sans numéro de ligne).
&lt;/p&gt;
&lt;p&gt;
Pour dire à Weblo de ne pas supprimer ces fichiers .java, donc, on ajoute le texte suivant dans le weblogic.xml de votre application :
&lt;/p&gt;
&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
    &amp;lt;jsp-descriptor&amp;gt;    
        &amp;lt;precompile&amp;gt;false&amp;lt;/precompile&amp;gt;
        &amp;lt;precompile-continue&amp;gt;false&amp;lt;/precompile-continue&amp;gt;  
        &amp;lt;keepgenerated&amp;gt;true&amp;lt;/keepgenerated&amp;gt;  
        &amp;lt;verbose&amp;gt;true&amp;lt;/verbose&amp;gt;     
        &amp;lt;working-dir&amp;gt;/tmp/bea&amp;lt;/working-dir&amp;gt;  
    &amp;lt;/jsp-descriptor&amp;gt;
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Notez bien que vous pouvez spécifier le dossier où vous voulez stocker les fichiers .java avec la balise &amp;lt;working-dir&amp;gt;.
&lt;/p&gt;
</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=Garder-les-fichiers-g%C3%A9n%C3%A9r%C3%A9s-de-vos-JSP-dans-WebLogic.html</guid>
			<pubDate>Fri, 13 Feb 2009 20:02:02 +0100</pubDate>
            <category>/Java/</category>
                                </item>
                <item>
            <title>Garder les fichiers générés de vos JSP dans WebLogic</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=01FCD40A6C36F497A5DE88CC50DA01BA.html</link>
            <description>&lt;p&gt;
Par défaut Weblogic supprime les fichiers .jsp qui sont générés lors de la phase de traduction d&#39;un JSP.  Il ne garde que les fichiers .class qui sont compilés par la suite.  Néanmoins, en développement ces fichiers .java peuvent s&#39;averer très utiles. Par exemple, lors d&#39;une exception dans le JSP, la trace donnera la ligne exact du fichier .java où l&#39;exception a eu lieu.  Si on a le fichier .java, on peut souvent trouver plus rapidement qu&#39;est-ce qui s&#39;est passé, ce qui est plus facile que de relire tout le JSP en essayant de voir qu&#39;est-ce qui a pu tourner mal (sans numéro de ligne).
&lt;/p&gt;
&lt;p&gt;
Pour dire à Weblo de ne pas supprimer ces fichiers .java, donc, on ajoute le texte suivant dans le weblogic.xml de votre application :
&lt;/p&gt;
&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
    &amp;lt;jsp-descriptor&amp;gt;    
        &amp;lt;precompile&amp;gt;false&amp;lt;/precompile&amp;gt;
        &amp;lt;precompile-continue&amp;gt;false&amp;lt;/precompile-continue&amp;gt;  
        &amp;lt;keepgenerated&amp;gt;true&amp;lt;/keepgenerated&amp;gt;  
        &amp;lt;verbose&amp;gt;true&amp;lt;/verbose&amp;gt;     
        &amp;lt;working-dir&amp;gt;/tmp/bea&amp;lt;/working-dir&amp;gt;  
    &amp;lt;/jsp-descriptor&amp;gt;
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Notez bien que vous pouvez spécifier le dossier où vous voulez stocker les fichiers .java avec la balise &amp;lt;working-dir&amp;gt;.
&lt;/p&gt;
</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=01FCD40A6C36F497A5DE88CC50DA01BA.html</guid>
			<pubDate>Fri, 13 Feb 2009 07:02:02 +0100</pubDate>
            <category>/Java/</category>
                                </item>
                <item>
            <title>html:checkbox ne marche pas</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=html-checkbox-ne-marche-pas.html</link>
            <description>&lt;p&gt;
Si vous travailler assez longtemps avec Struts, tôt ou tard vous allez le constater : &lt;tt&gt;&amp;lt;html:checkbox&amp;gt;&lt;/tt&gt; ne marche pas.  Ou bien s&#39;il marche, son comportement est trop complexe et non-intuitif pour qu&#39;il soit utile.
&lt;/p&gt;
&lt;p&gt;
Que faire ? La solution peut sembler radical, mais je vous le conseille vivement : &lt;b&gt;il faut s&#39;en passer tout simplement&lt;/b&gt;.  Avec un peu de JavaScript, ce n&#39;est pas si brutal que ça.  Au lieu de mettre :
&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
    &amp;lt;html:checkbox property=&quot;champs&quot; /&amp;gt;
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;
On met :
&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
&amp;lt;input
    type=&quot;checkbox&quot;
    id=&quot;champs2&quot;
    onchange=&quot;Util.setValue(&#39;champs&#39;, $(&#39;champs2&#39;).checked);&quot; /&amp;gt;
&amp;lt;html:hidden property=&quot;champs&quot; /&amp;gt;
&amp;lt;script&amp;gt;
    Util.setValue(&#39;champs2&#39;, Util.getValue(&#39;champs&#39;));
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;
Et c&#39;est tout.  (J&#39;utilise mon propre classe &quot;Util&quot; pour le JavaScript, mais son fonctionnement est clair.)  Nos actions récupèrent le champs pareil, qu&#39;il soit dans un &lt;tt&gt;checkbox&lt;/tt&gt; ou un &lt;tt&gt;hidden&lt;/tt&gt;, et la champs s&#39;initialise et garde sa valeur comme on le voudrait.
&lt;/p&gt;
</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=html-checkbox-ne-marche-pas.html</guid>
			<pubDate>Fri, 1 Aug 2008 00:01:01 +0200</pubDate>
            <category>/Java/</category>
                                </item>
                <item>
            <title>Un look and feel Swing pas comme les autres</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=Un-look-and-feel-Swing-pas-comme-les-autres.html</link>
            <description>&lt;p&gt;
&lt;a href=&quot;http://napkinlaf.sourceforge.net/&quot; target=&quot;_blank&quot;&gt;Napkin&lt;/a&gt; est un &quot;Look and Feel&quot; (LAF, synonyme de skin ou thème) qu&#39;on peut installer pour Swing qui répond à un besoin tout à fait original:  souvent en tant que développeurs, on veut présenter aux clients une maquette de ce qu&#39;on pense réaliser comme intérface graphique de leur logiciel.  Mais les clients, ne connaissant pas l&#39;informatique, voient une maquette qui ressemble à ce qu&#39;ils veulent, et disent &quot;on le prend comme ça!&quot;  Après il est difficile de leur faire comprendre que ce n&#39;est qu&#39;une maquette, et il reste beaucoup de développement encore derrière à réaliser.
&lt;/p&gt;
&lt;p&gt;
Napkin nous permet de montrer clairement que l&#39;intérface qu&#39;on est en train d&#39;utiliser n&#39;est qu&#39;un prototype.  Et comment le communique-t-il?  Le plus naturellement possible!  &lt;b&gt;Napkin permet de dessiner n&#39;importe lequel interface Swing comme si c&#39;était dessiné sur une serviette en papier!&lt;/b&gt;  Une capture d&#39;écran parle plus fort que les mots : &lt;/p&gt;
&lt;a href=&quot;http://napkinlaf.sourceforge.net/NapkinSliders.jpg&quot;&gt;&lt;img src=&quot;http://napkinlaf.sourceforge.net/NapkinSliders.jpg&quot; title=&quot;Cliquer pour aggrandir&quot; width=&quot;100%&quot; /&gt;&lt;/a&gt;

&lt;p&gt;
Et le plus beau dans tout ça?  Ce n&#39;est qu&#39;un Look and Feel, donc l&#39;application reste 100% fonctionnel.  On peut même faire tourner NetBeans sur une serviette en papier :
&lt;/p&gt;
&lt;a href=&quot;http://napkinlaf.sourceforge.net/NetBeans2.jpg&quot;&gt;&lt;img src=&quot;http://napkinlaf.sourceforge.net/NetBeans2.jpg&quot; title=&quot;Cliquer pour aggrandir&quot; width=&quot;100%&quot; /&gt;&lt;/a&gt;
&lt;p&gt;
Pour un prototype, donc, ce LAF permet de montrer clairement qu&#39;il ne s&#39;agit que d&#39;un prototype&amp;mdash;mais, une fois le prototypage fini, il suffit d&#39;enlever le LAF et on a notre application, toute sage et professionnelle avec le Look and Feel par défaut.  C&#39;est malin!
&lt;/p&gt; 
</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=Un-look-and-feel-Swing-pas-comme-les-autres.html</guid>
			<pubDate>Thu, 31 Jul 2008 07:07:03 +0200</pubDate>
            <category>/Java/</category>
                                </item>
                <item>
            <title>Astuce: utiliser extends avec les génériques</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=Astuce-utiliser-extends-avec-les-generiques.html</link>
            <description>&lt;p&gt;
(L&#39;idée pour cet article vient d&#39;&lt;a href=&quot;http://blogs.sun.com/CoreJavaTechTips/entry/using_generics_with_wildcards_and&quot; target=&quot;_top&quot;&gt;un blog en anglais de John Zukowski&lt;/a&gt;.)
&lt;/p&gt;
&lt;p&gt;
Java 5 a introduit au langage Java les génériques, et depuis il est devenu beaucoup plus agréable de coder en Java.  Alors qu&#39;avant on avait un objet &lt;tt&gt;List&lt;/tt&gt;, et chaque fois qu&#39;on itérait dessus il fallait se souvenir du type des objets qu&#39;on avait mis dedans pour faire un cast (&quot;String s = (String) s.iterator().next();&quot;), maintenant on peut simplement déclarer qu&#39;on a un &lt;tt&gt;List&amp;lt;String&amp;gt;&lt;/tt&gt; et ce n&#39;est plus nécessaire d&#39;avoir des casts partout.
&lt;/p&gt;
&lt;p&gt;
Cependant, il y a un comportement bizarre qu&#39;on constate avec ces génériques lorsqu&#39;on veut en utiliser comme paramètre à une méthode.  Regardons un petit exemple&amp;nbsp;:
&lt;p&gt;
&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
    public static void main(String[] args) {
        List&lt;String[]&gt; arg = new ArrayList&amp;lt;String[]&amp;gt;();
        String[] a = {&quot;a&quot;, &quot;b&quot;, &quot;c&quot;};
        String[] b = {&quot;d&quot;, &quot;e&quot;, &quot;f&quot;};
        arg.add(a);
        arg.add(b);
        System.out.println(&quot;Notre liste applati a &quot; + applatirList(arg).size() + &quot; éléments&quot;);
        return;
    }

    private static List applatirList(List&amp;lt;Object[]&amp;gt; list) {
        List result = new ArrayList();
        for (Object[] array : list)
            result.addAll(Arrays.asList(array));
        return result;
    }
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;

&lt;p&gt;
Mais quand on compile ce programme, on a l&#39;erreur &quot;&lt;tt&gt;Test.java:19: applatirList(java.util.List&amp;lt;java.lang.Object[]&amp;gt;) in Test cannot be applied to (java.util.List&amp;lt;java.lang.String[]&amp;gt;)&lt;/tt&gt;&quot;.
En effet, contrairement au comportément des objets en général, les génériques par défaut ne sont valables &lt;i&gt;que pour le classe même, mais pas forcément ses classes filles&lt;/i&gt; !  (J&#39;avoue que je trouve ce comportement un peu illogique, mais c&#39;est le compilateur qui décide.)
&lt;/p&gt;

&lt;p&gt;
La solution, c&#39;est de modifier notre signature de méthode comme suit :
&lt;blockquote&gt;
&lt;tt&gt;
    private static List applatirList(&lt;b&gt;List&amp;lt;? extends Object[]&amp;gt;&lt;/b&gt; list)
&lt;/tt&gt;
&lt;/blockquote&gt;
Maintenant la méthode acceptera n&#39;importe lequel type de liste, de moment que son type générique est Object[] &lt;i&gt;ou une classe fille de Object[]&lt;/i&gt;.
&lt;/p&gt;
&lt;p&gt;
Pensez donc à utiliser &lt;b&gt;&lt;tt&gt;? extends&lt;/tt&gt;&lt;/b&gt; avec vos génériques pour rendre plus souple vos interfaces!
&lt;/p&gt; 
</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=Astuce-utiliser-extends-avec-les-generiques.html</guid>
			<pubDate>Wed, 21 May 2008 22:51:21 +0200</pubDate>
            <category>/Java/</category>
                                </item>
                <item>
            <title>Diagrammes de séquence UML : percer le mystère</title>
            <link>http://java.craven.fr/blog/java/UML/?permalink=Diagrammes-de-sequence-UML-percer-le-mystere.html</link>
            <description>&lt;p&gt;

Très répandus, mais aussi très mal compris, les diagrammes de séquence sont pour moi une des parties le moins bien compris de l&#39;UML.  Cette mécompréhension mène beaucoup d&#39;analystes d&#39;études à finir par s&#39;en passer complètement, en préférences d&#39;un usage exclusif des diagrammes d&#39;activité pour modéliser le comportement de leurs projets.

&lt;/p&gt;

&lt;p&gt;

Ce phénomène révèle une première mauvaise idée reçu, car &lt;b&gt;les diagrammes d&#39;activité et les diagrammes de séquence devraient intervenir dans le projet à des stades complètement différentes&amp;nbsp;!&lt;/b&gt;.  En effet, le diagramme d&#39;activité, plus générale, sert à définir le déroulement d&#39;un cas d&#39;utilisation.  Il est donc utile au moment de la spécification où les besoin fonctionnels deviennent figés pour les acteurs techniques&amp;nbsp;on concrétise ce que le logiciel va faire.  (&quot;Voici ce qui va se dérouler dans le programme.)  Et, effectivement, pour modéliser ces déroulements les diagrammes d&#39;activité sont faciles à lire et très utiles.

&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blojsom/resources/java/seq1.png&quot; align=&quot;left&quot; style=&quot;margin-right:7px;&quot; /&gt; 

Les diagrammes de séquence n&#39;ont rien à faire à ce stade.  Les acteurs fonctionnels dans le projet n&#39;y comprendront rien, et ceci pour une bonne raison: &lt;b&gt;les diagrammes de séquence existent pour modéliser le comportement &lt;i&gt;technique&lt;/i&gt;&lt;/b&gt;.  Ils doivent donc intervenir lors de la conception technique de l&#39;application: les diagrammes de séquences sont étroitement liés à la code source de projet, et non pas aux cas d&#39;utilisation au sens métier.

&lt;/p&gt;

&lt;p&gt;

La deuxième chose qu&#39;il faut donc comprendre c&#39;est que, comme le diagramme de séquence est un modélisation technique et non pas fonctionnel, cette modélisation revient à faire de la &lt;i&gt;programmation visuelle&lt;/i&gt;.  Et comme telle, pour bien faire un diagramme de séquence, il faut avoir une connaissance profonde de la programmation orienté objet.

&lt;/p&gt;

&lt;p&gt;

Déjà pour poser le premier élément du diagramme, l&#39;objet, il faut comprendre le cycle de vie de l&#39;objet, car il est modéliser par la ligne pointillé: il descend, non pas systématiquement du haut en bas du diagramme comme on voit souvent, mais uniquement aussi loin que l&#39;objet modélisé n&#39;existe.  Le début represente la création de l&#39;objet&amp;nbsp;; lorsqu&#39;il est détruit (manuellement dans des langages comme C++, ou bien conceptuellement dans tous les cas), son trait s&#39;arrête.

&lt;/p&gt;

&lt;p&gt;

Le deuxième chose que beaucoup d&#39;analystes comprennent mal c&#39;est les rectangles qui se posent sur ces lignes de vie.  Alors que, pour un programmeur, il n&#39;y a rien de plus simple: ça veut dire que la méthode est en train d&#39;exécuter.  Quelle méthode?  Mais la méthode indiqué sur la flèche stimulus, bien sûr!  En effet, ces flèches doivent être utilisées pour définir les appels des méthodes eux-mêmes, et les blocs sur l&#39;objet montrent l&#39;espace de temps où il est en train de s’exécuter activement.  C&#39;est donc pour ça que ces diagrammes sont étroitement liés à la code source&amp;nbsp;:

&lt;/p&gt;

&lt;img src=&quot;/blojsom/resources/java/seq2.png&quot;  /&gt;

&lt;p&gt;

Je peux dire ça dans d&#39;autres mots pour ceux qui sont peut-être plus orienté développement: imaginez le diagramme de séquence comme un schéma visuel de ce qui se passe lorsque vous passez sur un point de débogue.  Chaque flèche représente un appel de méthode que vous suivez, et le rectangle représente l&#39;espace de temps que le méthode s’exécute jusqu&#39;à son &lt;tt&gt;return&lt;/tt&gt;.  Ce rectangle s’agrandira, donc, si notre méthode appelle d&#39;autres méthodes (sur ce même objet ou un autre).  Le rectangle finit lorsque notre appel se retire du call stack.

&lt;/p&gt;

&lt;p&gt;

Lu comme ça, on voit qu&#39;un diagramme de séquence n&#39;est pas du tout un diagramme d&#39;activité difficile à lire!  Au contraire, c&#39;est une représentation très lisible des détails au niveau du code qui ne seraient jamais modélisables sur les diagrammes de classes, et qui ne sont pas spécifiés par les diagrammes d&#39;activité.  C&#39;est un diagramme qui répond à la question:  quel est l&#39;enchaînement des appels des méthodes, sur quels objets, et dans quel ordre?

&lt;/p&gt;

&lt;p&gt;

J&#39;espère que ces points aideront à mieux comprendre ce diagramme et son rôle utile dans la documentation d&#39;un projet informatique.  Si vous avez des questions ou si vous n&#39;êtes pas d&#39;accord avec mon point de vue, n&#39;hésitez pas à laisser un commentaire ci-dessous).

&lt;/p&gt; 

 
</description>
            <guid>http://java.craven.fr/blog/java/UML/?permalink=Diagrammes-de-sequence-UML-percer-le-mystere.html</guid>
			<pubDate>Sun, 18 May 2008 10:35:16 +0200</pubDate>
            <category>/UML/</category>
                                </item>
                <item>
            <title>Tester des Web Services avec une interface graphique</title>
            <link>http://java.craven.fr/blog/java/?permalink=Tester-des-Web-Services-avec-une-interface-graphique.html</link>
            <description>&lt;p&gt;&lt;a href=&quot;/blojsom/resources/java/soapUI.PNG&quot;&gt;&lt;img src=&quot;/blojsom/resources/java/soapUI.PNG&quot; align=&quot;right&quot; title=&quot;Cliquer pour aggrandir&quot; style=&quot;margin-left:7px;&quot; width=&quot;550&quot; /&gt;&lt;/a&gt;
Comme un Web Service n&#39;a par définition aucune interface utilisateur, on ne peut pas facilement interagir avec lui sans avoir un outil spécial. Idéalement cet outil devrait permettre de composer des requêtes SOAP directement en XML, et de visualiser les réponses SOAP que le serveur nous renvoie.  Un outil excellent, et gratuit, que j&#39;ai déjà eu l&#39;occasion d&#39;utiliser est &lt;a href=&quot;http://www.soapui.org/&quot; target=&quot;_top&quot;&gt;SoapUI&lt;/a&gt;.  Voici rapidement ce que ce logiciel permet de faire :
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Inspecter les Web services (en local ou sur le réseau)&lt;/li&gt;
&lt;li&gt;Invoquer des Web services&lt;/li&gt;
&lt;li&gt;Développer des Web services (directement dans l&#39;outil)&lt;/li&gt;
&lt;li&gt;Tester des Web services (y compris des testes de capacité)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
En plus, c&#39;est un logiciel Java et donc disponible sur Linux, Windows, et Mac OS X.  Et encore mieux, en plus du logiciel à part, des plugins existent pour l&#39;intégrer dans Eclipse, NetBeans, et IntelliJ.  Donc, quel que soit votre EDI préféré, SoapUI peut s&#39;intégrer dedans.
&lt;/p&gt;
</description>
            <guid>http://java.craven.fr/blog/java/?permalink=Tester-des-Web-Services-avec-une-interface-graphique.html</guid>
			<pubDate>Fri, 21 Mar 2008 07:02:32 +0100</pubDate>
            <category>/</category>
                                </item>
                <item>
            <title>La clause IN dans un PreparedStatement</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=La-clause-IN-dans-un-PreparedStatement.html</link>
            <description>&lt;p&gt;
Récemment un lecteur m&#39;a posé la question suivante: &amp;laquo;Je veux saisir un argument pour une clause IN dans une requête SQL.  Mais je ne sais pas dans quel format il faut mettre la chaîne.  J&#39;ai essayé :
&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;&lt;pre&gt;
 public ResultSet executerSQL(String[] arg) {
    PreparedStatement ps = conn.prepareStatement(
        &quot;SELECT * FROM TAB WHERE TAB.LIBELLE IN (?) &quot;);
    ps.setArray(1, arg);
    ...
&lt;/pre&gt;&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;
Mais ça ne marche pas! Qu&#39;est-ce qu&#39;il faut faire ? &amp;raquo;
&lt;/p&gt;
&lt;p&gt;
Ce qu&#39;il faut comprendre, c&#39;est que le &quot;?&quot; dans un &lt;tt&gt;PreparedStatement&lt;/tt&gt; ne peut pas &amp;ecirc;tre employé pour remplacer n&#39;importe laquelle chaîne plus tard.  Chaque &quot;?&quot; doit correspondre à une donnée qui sera liée à un valeur avant de lancer la requête.  (&lt;tt&gt;conn.prepareStatement()&lt;/tt&gt; va compiler l&#39;SQL fourni, alors le nombre d&#39;arguments doit être fixe.)&lt;/p&gt;
&lt;p&gt;
Il en résulte qu&#39;il est impossible d&#39;avoir un nombre variable d&#39;arguments pour un &lt;tt&gt;PreparedStatement&lt;/tt&gt; une fois que celui-ci est créé.  La seule solution est de générer le SQL dynamiquement.  Imaginons que notre méthode reçoit en argument un &lt;tt&gt;String[]&lt;/tt&gt; pour la clause IN.  On peut donc écrire la requête de l&#39;exemple précédent comme ça:
&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;&lt;pre&gt;
 public ResultSet executerSQL(String[] arg) {
    PreparedStatement ps = conn.prepareStatement(
        &quot;SELECT * FROM TAB WHERE TAB.LIBELLE IN &quot; + getInClause(arg.length));
    for (int i = 0; i &lt; arg.length; i++)
        ps.setString(i + 1, arg[i]);
    ...
}

private String getInClause(int length) {
    StringBuffer sb = new StringBuffer(&quot;(&quot;);
    for (int i = 0; i &lt; length; i++)
        sb.append(i + 1 == length ? &quot;?)&quot; : &quot;?,&quot;);
    return sb.toString();
}
&lt;/pre&gt;&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;
Certes, ce n&#39;est pas aussi beau que ça n&#39;aurait été si on pouvait utiliser &lt;tt&gt;setArray()&lt;/tt&gt;, mais c&#39;est la seule façon qui est permise.
&lt;/p&gt;
</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=La-clause-IN-dans-un-PreparedStatement.html</guid>
			<pubDate>Thu, 20 Mar 2008 22:20:03 +0100</pubDate>
            <category>/Java/</category>
                                </item>
                <item>
            <title>Comment intéroger un répertoire LDAP avec Java</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=Comment-interoger-un-repertoire-LDAP-avec-Java.html</link>
            <description>&lt;p&gt;&lt;i&gt;Lightweight directory access protocol&lt;/i&gt; (LDAP) est une technologie extr&amp;ecirc;mement repandu en entreprise pour les annuaires.  Typiquement, lorsque l&#39;autentification des utilisateurs sur une application intranet passe par l&#39;annuaire LDAP, on configure celui-ci avec JAAS dans le web.xml.  Mais ceci n&#39;est pas le sujet de cet article.  Ici je veux traiter du cas o&amp;ugrave; l&#39;on veut int&amp;eacute;rogger &lt;i&gt;directement&lt;/i&gt; un serveur LDAP et y lancer des recherches, ce qui peut &amp;ecirc;tre le cas quand on veut afficher des donn&amp;eacute;es qui sont dans l&#39;annuaire, par exemple.&lt;/p&gt;

&lt;p&gt;
Il se trouve que c&#39;est extr&amp;ecirc;mement simple de communiquer avec LDAP en Java, surtout parce que toutes les librairies n&amp;eacute;cessaires sont d&amp;eacute;j&amp;agrave; pr&amp;eacute;sents dans le JVM, dans les packages &lt;tt&gt;javax.naming&lt;/tt&gt;.  Il n&#39;y a donc rien &amp;agrave; installer, même dans une application Java SE.
&lt;/p&gt;

&lt;p&gt;
Une connexion LDAP est repr&amp;eacute;sent&amp;eacute; par un objet &lt;tt&gt;DirContext&lt;/tt&gt;, typiquement instanti&amp;eacute; par un &lt;tt&gt;InitialDirContext&lt;/tt&gt; qui prend dans son constructeur un &lt;tt&gt;Hashtable&lt;/tt&gt; contenant les param&amp;egrave;tres de connexion.  Voici l&#39;incantation magique&amp;nbsp;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY,
        &quot;com.sun.jndi.ldap.LdapCtxFactory&quot;);
    env.put(Context.PROVIDER_URL, &quot;ldap://example.com:3060/&quot;);
    env.put(Context.SECURITY_AUTHENTICATION, &quot;simple&quot;);
    env.put(Context.SECURITY_PRINCIPAL, &quot;cn=test,cn=Users&quot;);
    env.put(Context.SECURITY_CREDENTIALS, &quot;password&quot;);
    DirContext ctx = new InitialDirContext(env);
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cet exemple connecte un utilisateur appel&amp;eacute; &quot;test&quot; avec un mot de passe &quot;password&quot; au serveur &quot;example.com&quot;.  Il assume aussi que les utilisateurs se trouvent dans un dossier qui s&#39;appelle &quot;Users&quot;.  Evidemment ces param&amp;egrave;tres sont &amp;agrave; modifier en fonction de l&#39;annuaire qu&#39;on veut consulter et sa structure.&lt;/p&gt;

&lt;p&gt;Ensuite, on peut passer des requ&amp;ecirc;tes &amp;agrave; notre objet &lt;tt&gt;ctx&lt;/tt&gt;.  Le syntaxe pour une requ&amp;ecirc;te LDAP sera facile &amp;agrave; comprendre pour ceux qui connaissent bien le langage Lisp&amp;nbsp;; malheureusement cette connaissance est de plus en plus rare alors une explication sera peut-&amp;ecirc;tre n&amp;eacute;cessaire...&lt;/p&gt;

&lt;p&gt;Les parties de la requ&amp;ecirc;te sont regroup&amp;eacute;s entre parenth&amp;egrave;ses, avec un opérateur tout de suite après le parenthèse d&#39;ouverture, et les arguments après.  Alors là où dans Java ou C on écrit &lt;blockquote&gt;&lt;tt&gt;(a &amp;amp;&amp;amp; b &amp;amp;&amp;amp; (c || d))&lt;/tt&gt;&lt;/blockquote&gt; en LDAP ça devient &lt;blockquote&gt;&lt;tt&gt;(&amp;amp; a b (| c d))&lt;/tt&gt;&lt;/blockquote&gt;  Les opérateurs sont &amp;amp; (AND), | (OR), et ! (NOT).  Les arguments sont de forme &quot;clef=valeur&quot;, où &quot;valeur&quot; peut contenir des étoiles (par exemple, &quot;nom=Dup*&quot;).  Les arguments sont eux-même entourés des parenthèses.  Voici un exemple complet d&#39;une recherche lancé sur notre &lt;tt&gt;ctx&lt;/tt&gt;, qui est le &lt;tt&gt;DirContext&lt;/tt&gt; qu&#39;on a créé dans le premier exemple&amp;nbsp;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
    SearchControls controls = new SearchControls();
    controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    NamingEnumeration results = ctx.search(&quot;&quot;, 
        &quot;(&amp;amp;(uniquemember=cn=test,*)(objectclass=groupofUniqueNames))&quot;,
        controls);
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;

&lt;p&gt;
La recherche retourne un &lt;tt&gt;NamingEnumeration&lt;/tt&gt;, qui implémente &lt;tt&gt;Enumeration&lt;/tt&gt; et qui est donc facile à itérer. &lt;/p&gt;&lt;p&gt; Et voilà, à vous d&#39;employer les données retrouvés comme bon vous semble dans votre application.  N&#39;oubliez pas d&#39;appeler un &lt;tt&gt;ctx.close()&lt;/tt&gt; pour fermer votre connexion quand vous n&#39;en aurez plus besoin!
&lt;/p&gt;
 
</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=Comment-interoger-un-repertoire-LDAP-avec-Java.html</guid>
			<pubDate>Fri, 14 Mar 2008 23:38:30 +0100</pubDate>
            <category>/Java/</category>
                                </item>
                <item>
            <title>Gestion des trunk, branch, et tags dans Subversion</title>
            <link>http://java.craven.fr/blog/java/?permalink=Gestion-des-trunk-branch-et-tags-dans-Subversion.html</link>
            <description>&lt;p&gt;
Subversion est actuellement parmi les solutions de gestion de versions les plus employ&amp;eacute;s de nos jours.  Une organisation typique de projet avec Subversion utilise ce qu&#39;on appelle un &quot;trunk&quot;, des &quot;branches&quot;, et des &quot;tags&quot;.  Dans cet article j&#39;explique bri&amp;egrave;vement ces termes.
&lt;/p&gt;

&lt;p&gt;
Le &lt;b&gt;trunk&lt;/b&gt; (&lt;i&gt;tronc&lt;/i&gt; en fran&amp;ccedil;ais) est, comme son nom l&#39;indique, le projet principal.  Si on veut faire du développement en parall&amp;egrave;e (ce qui arrive souvent, par exemple, quand on a livr&amp;eacute; une version, qu&#39;on continue &amp;agrave; maintenir pour corriger des éventuels bogues, mais on pr&amp;eacute;pare en parallèle  une version 2.0 avec plein de nouvelle fonctionnalit&amp;eacute;s), on met ces &quot;branches&quot; dans, comme on pourrait le deviner, un &lt;b&gt;branch&lt;/b&gt;.

&lt;/p&gt;

&lt;p&gt;Un &lt;b&gt;tag&lt;/b&gt;, quant &amp;agrave; lui, est une balise, qu&#39;on peut appliquer &amp;agrave; une révision pour l&#39;identifier plus facilement&amp;mdash;pour dire, &amp;laquo;&amp;ccedil;a, c&#39;est la version 1.2&amp;raquo;, par exemple.  Un tag n&#39;est en r&amp;eacute;alit&amp;eacute; qu&#39;un branch qu&#39;on ne modifie jamais, mais on les met &amp;agrave; part parce que conceptuellement les deux sont tr&amp;egrave;s diff&amp;eacute;rents.

&lt;/p&gt;

&lt;p&gt;
Un dossier subversion aura donc typiquement trois dossiers &amp;agrave; la racine, &lt;i&gt;branch, tags, &lt;/i&gt;et&lt;i&gt; trunk&lt;/i&gt;, avec une copie du projet dans &lt;i&gt;trunk&lt;/i&gt;, et d&#39;autres copies dans des sous dossiers de &lt;i&gt;branch&lt;/i&gt; et/ou &lt;i&gt;tag&lt;/i&gt; selon les besoins et l&#39;&amp;eacute;volution du projet.

&lt;/p&gt;
 
</description>
            <guid>http://java.craven.fr/blog/java/?permalink=Gestion-des-trunk-branch-et-tags-dans-Subversion.html</guid>
			<pubDate>Tue, 11 Mar 2008 07:27:17 +0100</pubDate>
            <category>/</category>
                                </item>
                <item>
            <title>Comment générer des PDFs très longs avec JasperReports</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=Comment-generer-des-PDFs-tres-longs-avec-JasperReports.html</link>
            <description>&lt;p&gt;
La solution Open Source JasperReports est déjà bien connu et bien respecté dans l&#39;informatique d&#39;entreprise pour générer des reports, sous format .pdf, Excel, html, et autres.  Sur un projet récent, on avait cependant un problème: nous nous retrouvions avec un pdf à générer qui faisait plus de 700 pages, et le pauvre serveur chargé de le produire plantait en &lt;tt&gt;OutOfMemoryError&lt;/tt&gt;.  
Après débogage, on a vu que le coupable était JasperReports lui-même, qui plantait lors de la création du JasperPrint.  Ma première réaction était donc d&#39;éviter de créer un JasperPrint, et d&#39;utiliser des méthodes qui permettent de créer un report directement avec des &lt;tt&gt;InputStream&lt;/tt&gt; et &lt;tt&gt;OutputStream&lt;/tt&gt;.  Mais l&#39;utilisation d&#39;un &lt;tt&gt;PipedInputStream&lt;/tt&gt; oblige déjà l&#39;utilisation des Threads, ce qui n&#39;est pas strictement permis dans une application J2EE (la gestion des threads étant le domaine du serveur).  Mais même avec ces modifications, les problèmes des &lt;tt&gt;OutOfMemoryError&lt;/tt&gt; persistaient.  Heureusement la solution s&#39;est ensuite présentée, et donc dans ce petit article, je vais expliquer comment on peut utiliser JasperReports pour créer des documents de n&#39;importe laquelle taille, sans avoir des soucis de mémoire.
&lt;/p&gt;

&lt;p&gt;
La solution qui a finalement marché était moins radicale que cette première idée.  En fait on continue à utiliser un JasperPrint, alors les effets sur le reste notre code étaient minimes.  Il suffisait en effet d&#39;ajouter les lignes suivantes juste avant sa création:
&lt;/p&gt;


&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
JRSwapFile swapFile = new JRSwapFile(&quot;/tmp/&quot;, 0x400, 0x400);
JRAbstractLRUVirtualizer virtualizer = 
  new JRSwapFileVirtualizer(0x40, swapFile, true);
parametres.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
JasperPrint print = JasperFillManager.fillReport(
  jasper, /* notre fichier .jasper compilé */
  parametres, /* notre Map des paramètres */
  new JRBeanCollectionDataSource(donnees)); /* notre Collection des données */
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;

&lt;p&gt;
(La dernière ligne est inchangée de notre classe d&#39;origine, mais je l&#39;inclus pour vous donner le contexte.)  Que font ces trois nouvelles lignes?  En fait, notre ancienne solution plantait parce que le JasperPrint qu&#39;on gardait en mémoire était trop grand. Les Virtualizer de JasperReports permettent de déclarer des fichiers tampons, qui sont utilisés par Jasper pour écrire une partie de ses données sur disque.  En ajoutant un virtualizer dans le Map des paramètres, Jasper va automatiquement se servir de cette fonctionnalité (dans notre cas, en écrivant un fichier tampon dans le dossier temporaire &lt;tt&gt;/tmp/&lt;/tt&gt;; il existe aussi d&#39;autres types de Virtualizer).
&lt;/p&gt;

&lt;p&gt;
Dans notre projet, le simple ajout de ces trois lignes supplémentaires a suffit pour qu&#39;on sorte nos .pdf de plus de 700 pages sans problème.  Les vrais experts de JasperReports remarqueront quand même qu&#39;on utilise un &lt;tt&gt;JRBeanCollectionDataSource&lt;/tt&gt;, ce qui implique que nous avons une Collection en mémoire avec nos données.  On peut imaginer que, si notre rapport était vraiment énorme (disons 7000 pages), on n&#39;aurait pas assez de mémoire pour stocker toutes ces données en mémoire.  En effet, si le volume des données est trop important, il faut implémenter un &lt;tt&gt;JRDataSource&lt;/tt&gt; qui permet de lire les données un à un, au lieu de tout prendre en mémoire à l&#39;avance. (&lt;tt&gt;JRResultSetDataSource&lt;/tt&gt; répond déjà à ce critère.)
&lt;/p&gt;

&lt;p&gt;
Si on fait attention sur ces deux points, d’utiliser un &lt;tt&gt;JRDataSource&lt;/tt&gt; extensible, et d’inclure un &lt;tt&gt;REPORT_VIRTUALIZER&lt;/tt&gt; dans les paramètres fournis au &lt;tt&gt;JasperFillManager&lt;/tt&gt;, on pourra créer des JasperReports extrêmement volumineux sans avoir à se soucier de l&#39;utilisation de mémoire. 
&lt;/p&gt;

</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=Comment-generer-des-PDFs-tres-longs-avec-JasperReports.html</guid>
			<pubDate>Sat, 9 Feb 2008 07:37:36 +0100</pubDate>
            <category>/Java/</category>
                                </item>
                <item>
            <title>Comment déclencher du JavaScript après n secondes</title>
            <link>http://java.craven.fr/blog/java/AJAX/?permalink=Comment-declencher-du-JavaScript-apres-n-secondes.html</link>
            <description>&lt;p&gt;
Dans certains cas, on peut avoir une bonne raison de vouloir déclencher du JavaScript après un délai de 10 secondes, par exemple.  On sait, j&#39;espère, qu&#39;il ne faut jamais utiliser un boucle qui ne fait rien pour compter le passage du temps&amp;nbsp;!  Mais alors, comment faire ça correctement?  Heureusement il existe en JavaScript un moyen très facile et propre de le faire:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;tt&gt;
&lt;pre&gt;
var delai = 5; /* Cinq secondes */

var apres = function () {
  alert(delai + &#39;secondes se sont pass\351es!&#39;);
}

setTimeout(apres, delai * 1000);
&lt;/pre&gt;
&lt;/tt&gt;
&lt;/blockquote&gt;

&lt;p&gt;
Et voila, c&#39;est tout ce qu&#39;il faut pour que notre fonction &lt;tt&gt;apres&lt;/tt&gt; se déclenche après 5 secondes.  Pour résumer, la fonction JavaScript &lt;tt&gt;setTimeout&lt;/tt&gt; prend donc une fonction en premier argument, et un délai en second argument, exprimé en millisecondes. Facile! &lt;a href=&quot;#herePO&quot;  onclick=&quot;setTimeout(function(){alert(&#39;5 secondes se sont pass\351es!&#39;);}, 5000);&quot;&gt;Cliquez ici pour le voir en action&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Voir aussi&amp;nbsp;:&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Besoin de vous rappeler des accents comme le \351 dans l&#39;exemple?  &lt;a href=&quot;http://www2.craven.fr/blojsom/blog/default/Work/Programming/2007/07/04/Tableau-des-accents-pour-JavaScript-et-HTML.html?page=comments&quot;&gt;Trouver un tableau complet ici&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&amp;Agrave; la recherche d&#39;un bon plugin JavaScript pour Eclipse? &lt;a href=&quot;http://www2.craven.fr/blojsom/blog/default/Work/Programming/2007/05/29/Edition-de-JavaScript-sous-Eclipse.html?page=comments&quot;&gt;Essayez JSEclipse&lt;/a&gt;.&lt;/p&gt; 
</description>
            <guid>http://java.craven.fr/blog/java/AJAX/?permalink=Comment-declencher-du-JavaScript-apres-n-secondes.html</guid>
			<pubDate>Fri, 8 Feb 2008 18:41:32 +0100</pubDate>
            <category>/AJAX/</category>
                                </item>
                <item>
            <title>NetBeans 6 est sorti</title>
            <link>http://java.craven.fr/blog/java/Java/?permalink=Netbeans-6-est-sorti.html</link>
            <description>&lt;a href=&quot;http://www.netbeans.org&quot; target=&quot;_top&quot;&gt;&lt;img src=&quot;/blojsom/resources/default/netbeans_logo.gif&quot; align=&quot;left&quot; style=&quot;margin-right:7px;&quot; /&gt;&lt;/a&gt;

&lt;p&gt;La nouvelle version de NetBeans, mon EDI préféré, est maintenant &lt;a href=&quot;http://www.netbeans.org/&quot; target=&quot;_top&quot;&gt;disponible&lt;/a&gt;.  La nouvelle version comporte plein de nouvelles fonctionnalités et améliore beaucoup de choses par rapport à la version 5.5.  Un des plus grandes nouveautés est l’inclusion des modes pour travailler avec le langage du moment &lt;a href=&quot;http://www.ruby-lang.org/fr/&quot; target=&quot;_top&quot;&gt;Ruby&lt;/a&gt; et son framework &lt;a href=&quot;http://www.rubyonrails.org/&quot; target=&quot;_top&quot;&gt;Rails&lt;/a&gt;.&lt;p&gt;

&lt;p&gt;La seule chose qui m’embête encore chez NetBeans, c’est que la Moblity Pack, qui permet de développer pour des téléphones portables, n’est pas disponible sur Mac OS X, même avec un processeur Intel.  J’espère que cela changera un jour car tout mon developpement personnel se fait sur mon iMac maintenant et je ne peux plus donc faire du developpement mobile du tout à la maison.  Mais bon, c’est le cas pour Eclipse aussi alors ce n’est pas vraiment la faute de NetBeans.&lt;/p&gt;
</description>
            <guid>http://java.craven.fr/blog/java/Java/?permalink=Netbeans-6-est-sorti.html</guid>
			<pubDate>Mon, 10 Dec 2007 18:22:22 +0100</pubDate>
            <category>/Java/</category>
                                </item>
            </channel>
</rss>
