Tous les articles par Arnaud Fonce

CSS : tous en bloque et en ligne

Voici le petit hack dont il faut se souvenir avoir une propriété « display: inline-block; » qui fonctionne sous Internet Explorer. Il faut l’ajouter les propriétés suivante :

    *display:inline; 
    zoom:1; /* "inline-block" for IE6/7 */

Et pendant que j’y suis, la valeur « auto » sur la propriété « margin » ne fonctionne sous IE que si le parent a une propriété « text-align: center » de positionné.

Sources :

http://robertnyman.com/2010/02/24/css-display-inline-block-why-it-rocks-and-why-it-sucks/

http://forum.alsacreations.com/topic-4-40741-1-Probleme-IE8—margin–0-auto-.html

Postgres et ses séquences


C’est un petit truc à savoir mais ça peut rendre chèvre si on ne le sait pas.

Lorsque vous faites un dump d’une base PostgreSQL avce par exemple PHPPGAdmin, les dernières lignes du fichier généré sont là pour mettre à jour les séquences de la base de données.

Oui mais voilà, de temps en temps, ces lignes sont de la forme :

SELECT pg_catalog.setval('seq_role', 100, true);

Et les autres fois, ça sera de la forme :

SELECT pg_catalog.setval('seq_role', 100, false);

Si vous modifiez le script à la main après l’avoir dumpé, faites attention, ce flag qui prend la valeur « true » ou « false » définit si la valeur passée en paramètre est la suivante qui sera fournie par la séuqence ou si c’est la précédente valeur.

-- le prochain appel retournera 101
SELECT pg_catalog.setval('seq_role', 100, true); 

-- le prochain appel retournera 100
SELECT pg_catalog.setval('seq_role', 100, false);

Pensez-y quand vous aurez vos prochaines violations de contraintes.

Netbeans ne passera pas à côté d’Unity

Si parmis les IDE gratuits, comme moi, votre préférence se porte sur Netbeans (déjà je vous aimes bien car, d’une part, je n’en rencontre pas si souvent, et d’autre part, comme tout être humain, j’aime ceux qui me ressemble 😉 ). Et si comme moi, vous avez abandonné le système aux « fenêtres » pour quelque chose d’un peu plus underground comme Ubuntu, alors cet article va vous intéresser.

Vous n’êtes pas sans savoir que le bureau officiel d’Ubuntu est maintenant, et depuis quelques versions, Unity. Et vous avez sûrement remarqué que les menus des applications sont intégrés à la barre principale de l’OS (qui fait maintenant office de barre de titre des fenêtres, menu de la fenêtre, barre de notification et menu du système). Si vous avez bien poussé la porte de la 12.04, vous devriez pas avoir loupé le nouveau système de recherche indexée HUD qui permet de rechercher dans les menus des applications sans avoir à les retenir par cœur. Bref, c’est génial mais, ça ne fonctionne pas pour les applications Java comme Netbeans.

N’étant pas le premier Java Geek, d’autres sont passé avant moi pour intégrer la barre de menu de Netbeans à HUD. Et c’est Dan Jared qui, après avoir indiqué sur son blog comment installer son plugin Java Ayatana pour Netbeans (http://danjared.wordpress.com/netbeans/), semble avoir finalement distribuer ce plugin dans l’update center d’Oracle (http://plugins.netbeans.org/plugin/41822/java-ayatana).

Pour rappel, Ayatana est le nom donné par la communauté Ubuntu pour unifier tous les efforts faits autour l’intégration d’Unity. Ca va du menu global dont on vient de parler dans le cas de Netbeans jusqu’au notifications (https://wiki.ubuntu.com/Ayatana). Notre ami maintient la librairie qui va vous permettre d’intégrer les menu Swing dans le menu global d’Unity : http://code.google.com/p/java-swing-ayatana/

 

 

Git : Le commit qui fait mal

Imaginez-vous, un soir, vous êtes mal luné et vous remonté un fichier personnel qui vous a servi à faire vos tests dans votre gestionnaire de source. Les développements avancent. D’itération en itération, votre fichier personnel est trimbalé jusqu’au jour où arrive la livraison et que votre fichier personnel se retrouve dans le livrable de votre client.

Bon, c’est vrai, je pousse la caricature un peu loin. Si votre est arrivé jusque là, c’est qu’il n’avais pas tant d’importance que ça ce fichier. Ou alors, vous vouliez parfaitement illustrer mon propos à vos collègues. Dans ce cas, je ne peux que vous en remercier.

Toujours est-il que la trace de votre fichier sera toujours visible dans ce satané commit. Et les futurs développeurs de votre projet (dont vous serez peut-être le chef dans 5-10 ans) sera toujours accessible. Heureusement, je viens de tomber sur la commande magique de Git :

git filter-branch --tree-filter 'rm -f my_file' HEAD

Le fichier my_file aura alors disparu de tous vos commits. Et la prochaine fois, vous éviterez de mélanger le boulot avec votre vie personnelle.

 

Redmine, Rails, Warbler, JBoss : la magie de JRuby

J’ai toujours regreté de ne pas trouver un outil de bug tracking Open Source et sympa dans l’écosystème Java. Certes, il y a bien Jira qui offre une licence au projet Open Source (je trouve que c’est d’ailleurs une très bonne démarche de leur part qui permet de conserver leur business model tout en soutenant la communauté). Mais c’est bien loin de mon business model personnel composé à 80% de vaporware.

De plus, j’ai toujours été attiré, intrigué, piqué au vif par Redmine. Les quelques heures de prise en main que j’ai pu en faire m’ont fait très bonne impression. Il n’a pas l’air aussi personnalisable que Jira mais l’interface respire la simplicité et l’évidence, je ne me suis jamais posé de question sur ce que je faisais.

Je désespérais donc de trouver un outil équivalent à déployer sous mon JBoss ou mon Tomcat et j’en venais à la conclusion, mainte fois partagé, que finalement on est jamais mieux servi que par soi-même. Et là, je suis tombé sur cet article et ma vie a changée :

http://www.javacodegeeks.com/2012/02/redmine-installation-getting-started.html

Et toute cette magie repose sur Warbler un gem à installer qui permet d’encapsuler les applications Rails dans un package war. Le tout utilisant JRuby pour l’exécution. Et je garantie que les explications données dans l’article ci-dessus fonctionne à merveille pour un Redmine 1.3.1 déployé sur un JBoss 7.1.0. Et pour avoir un peu plus de détail sur le fonctionnement de Warbler :

http://jrubyist.wordpress.com/2009/10/15/using-jruby-warbler-rake-to-deploy-rails-apps-to-jboss/

La performance des tests fonctionnels

Vous avez un projet Java (ou avec une autre technologie Web). Si dans votre projet, vous avez des scénarios Selenium pour vous assurer que votre projet ne présente pas de régressions fonctionnelles, c’est bien, vous êtes un bon élèves. Si en plus, vos tests sont automatisés par une plate-forme d’intégration continue (du type Jenkins), alors vous méritez une mention honorable. Mais est-ce que vous avez pensé à collecter des données de performance pendant l’exécution de ces tests ?

Cet article est doublement posté, on peut le retrouver sur le site de mon entreprise : http://blog-rd.ideotechnologies.com/?p=2432

Un outil à la rescousse

Pour nous aider dans cette tache, dynaTrace met à notre disposition un outil gratuit qui peut facilement se glisser une plate-forme existante de tests Selenium. L’outil en question se nomme « dynaTrace Ajax Edition » et vous pouvez le trouver à l’adresse suivante : http://ajax.dynatrace.com/ajax/en/

Lorsqu’on lance à la main l’outil, on alors la possibilité d’exécuter le navigateur de son choix et l’outil capturera, au cours d’une session d’analyse, toutes les requêtes qui passe par le navigateur et rendra compte du temps passé dans le réseau, celui passé dans le rendu de la page ou dans les scripts :

Chaque session est ensuite archivée. C’est donc une vision assez complète de la performance de la requête du point de vue client que nous obtenons. Si vous êtes en train de tester en lisant mes explications, vous allez surement me dire que c’est bien joli tout ça mais comment peut-on faire pour que les données soient collectées pendant l’exécution de mes tests Selenium. Rien ne l’empêche car dans les faits, dynaTrace Ajax Edition est un plugin ajouté au navigateur, il est constament présent (même lorsqu’on lance le navigateur en dehors d’une session de l’outil). Il suffit de savoir communiquer avec ce plugin ; et le langage disponible est la variable d’environnement. Pour ma part, j’en utilise 3 :

  • DT_AE_AGENTACTIVE # active la collecte des données par dynaTrace Ajax Edition ; à noter que l’outil doit être lancé pour agréger les données capturées par le plugin
  • DT_AE_AGENTNAME # donne un nom aux données collectées
  • DT_AE_CLEARCACHE # nettoie le cache avant de lancer les requêtes ou non

Dans la pratique avec Selenium, vous avez surement un script de lancement votre Remote Control qui ressemblera à :

set DT_AE_AGENTACTIVE=true
set DT_AE_AGENTNAME=IDEO_SELENIUM
set DT_AE_CLEARCACHE=true
ant -Dport=5557 -Dhost=localhost -DhubURL=http://localhost:4444 -Denvironment="ie 8 windows" launch-remote-control

Dorénavant, à chaque fois que le Remote Control lancera un navigateur et que dynaTrace Ajax sera démarré, les données de performance seront archivées dans l’outil :

Les inconvénients

C’est prometteur mais ce n’est pas parfait. En tout cas, personnellement, j’y vois quelques inconvénients :

  • Tout d’abord une limitation de la version gratuite : seul les navigateurs Internet Explorer 8, 9 et 10 et Firefox 9 et 10 sont officiellement supportés. Si vous voulez supporter de plus ancienne version, il faudra soit regarder du côté de la version payante, soit rechercher d’autres outils
  • Ce n’est pas une solution centralisée : en effet, les données ne sont visibles et archivées que sur le client lourd sur le poste où le client web s’exécute. Dans le cas d’un Grid Selenium, où il y a certainement autant de machines (certainement virtuelles) que de versions de navigateur à tester, il y aura autant de client lourd dynaTrace à lancer.
  • Le suivi des performance n’est pas aisé : ce qui est principalement interressant avec ce genre de mesure, c’est d’avoir un suivi des mesures pour voir rapidement les dégradations induites par les nouveaux développements. Ici, je ne trouve pas ça évident. Tout d’abord, le nom des données archivées est celui données dans la variable d’environnement DT_AE_AGENTNAME. Il n’est donc déterminé qu’au moment de lancer le Remote Control, autant dire que toutes les archives porteront le même nom (que ce soit pour tester l’affichage d’une liste ou d’un message d’alerte). De toute façon, la comparaison n’est pas facile, il faut ouvrir les archives prendre les mesures à la main et les comparer soit même.

Un début de solution

Nous ne sommes pas pour autant totalement dépourvu si on décide de prendre le temps de développer ses propres outils. Avec l’aide de quelques paramètres, dynaTrace peut émettre une requête HTTP avec un contenu JSON synthétisant les données enregistrées pendant une session d’analyse. Avec une simple servlet et un parser du type google-gson, il est alors possible de récupérer les valeurs et de les archiver soi-même de manière centralisée.

Les paramètres sont à ajouter dans le fichier dtajax.ini dans le répertoire d’installation de dynaTrace :

-Dcom.dynatrace.diagnostics.ajax.beacon.uploadurl=http://localhost:8080/beaconstorage/endpoint
-Dcom.dynatrace.diagnostics.ajax.beacon.portalurl=http://localhost:8080/beaconstorage/endpoint
-Dcom.dynatrace.diagnostics.ajax.beacon.autoupload=true

Et la requête JSON reçu alors par votre Servlet (ou autre technologie) sera de la forme :

{
 "version":"2.0.0",
 "url": "www.mydomain.com",
 "rank":95,
 "ranks":{
 "cache": {"rank":100, "comment":"" },
 "net": {"rank":98, "comment":"" },
 "server": {"rank":94, "comment":"2 dynamic server-requests" },
 "js": {"rank":89, "comment":"4 slow JS handlers"}
 },
 "timetoimpression":1587,
 "timetoonload":1645,
 "timetofullload":2747,
 "reqnumber":9,
 "xhrnumber":0,
 "pagesize":264562,
 "cachablesize":0,
 "noncachablesize": 264562,
 "timeonnetwork": 400,
 "timeinjs": 30,
 "timeinrendering":200
}

Vous trouverez de plus ample information sur le site officiel de dynaTrace bien sûr : http://ajax.dynatrace.com/ajax/en/ mais aussi sur le blog officiel du produit : http://blog.dynatrace.com/2010/10/30/web-performance-optimization-use-cases-part-3-automation/

Back to bascis of JSTL

En ce moment, je travaille sur une mini application permettant de collecter des données de performances de mon application mesurées pendant l’exécution de mes tests Selenium. Pour effectuer les mesures, je me base sur dynaTrace Ajax Edition qui installe un plugin sur les navigateurs contrôlés par Selenium et envoi les données à mon application qui se chargera de stocker les données et offre un écran pour les restituer.

J’ai voulu la faire simple, en utilisant un projet de Servlet et JSP tout ce qu’il y a de plus simple. Pour que ma page JSP soit belle, j’ai aussi voulu utiliser les JSTL. Et je dois bien l’avouer, cela a nécessité un rafraîchissement sur les versions de JEE et les compatibilités avec les versions de JSTL.

Qu’est ce que JSTL ?

JSTL est l’acronyme pour Java Standard Tag library. Elle offre 2 choses :

  • comme son nom le laisse entendre, une bibliothèque de taglib (pour manipuler les variables, contrôler son exécution par des tests et des boucles, …)
  • les Expression Language qui permet d’écrire des mini scripts Java dans une syntaxe ${ // mon code Java }

Les versions de JSTL

Bien entendu, JSTL est une spécification qui a évolué au cours du temps. Voici, ici les correspondances de version JEE :

Servlet JSP JSTL JEE
2.5 2.1 1.2 5
2.4 2.0 1.1 1.4
2.3 1.2 1.0 1.2

Avec la version 1.2 de JSTL les Expression Language ne pouvaient être utilisées qu’au travers de la balise c:out. Pour les versions suivantes, les EL peuvent être utilisées n’importe où dans la page JSP.

Il faut donc être vigilant. Votre projet doit être dans une bonne version. Si vous utilisez Maven, votre fichier pom doit contenir les bonnes références :

<dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>servlet-api</artifactId>
     <version>2.5</version>
     <scope>provided</scope>
</dependency>

Votre web.xml doit avoir la bonne entête. Pour une version 2.5 de Servlet :

<?xml version="1.0" encoding="UTF-8"?>
<web-app
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
...
</web-app>

Il faut également être vigilant sur la manière dont on référence les taglib dans les JSP. En version 1.0, il faut utiliser la syntaxe suivante :

<%@taglib uri="http://java.sun.com/jsp/core" prefix="c" %>

Pour les versions plus récentes, voici la ligne :

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

Implémentation de JSTL

JSTL est une spécification. Pour fonctionner, il faut disposer d’une implémentation. Heureusement la plupart des fournisseurs de serveurs d’application (comme Glassfish ou JBoss) fournisse une implémentation.

Mais ce n’est pas le cas de Tomcat. Et pour remédier à ce problème, il y a 2 solutions, soit vous récupérer des librairies d’implémentation et vous les ajouter dans le répertoire lib d’installation de votre Tomcat. Soit vous ajoutez la dépendance ci-dessous dans votre fichier pom :

<dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>jstl</artifactId>
     <version>1.2</version>
</dependency>

La plupart de mes informations proviennent de ce post : http://www.mularien.com/blog/2008/04/24/how-to-reference-and-use-jstl-in-your-web-application/

Gitblit : premier commit

Gitblit est dans la place et j’en suis pour le moment très satisfait. Il faut dire qu’avec trois dépôts à usage personnel, je ne risque pas de créer des cas compliqués d’usage 😉
Cependant, une chose ne m’a pas paru intuitive. Lorsqu’on créé un dépôt tout neuf sans repartir d’aucun code existant, la commande push pour remonter mes commits ne semblait pas fonctionner correctement. En effet, avec les commandes ci-dessous :

git clone http://127.0.0.1:8080/gitblit/git/maintest.git
cd maintest
echo "TEST" > test.txt
git add .
git commit -a -m "Commit de test"
git push

Cette dernière commande n’a jamais rien affiché de plus qu’un magnifique :

Everything up-to-date

Et rien n’est pas apparu dans mon dépôt.

Après quelques essais, ce que je comprends, c’est lors de la création du dépôt par Gitblit, aucune branche master n’existe (ou du moins, elle n’est pas correctement associée à l’origin du dépôt). Pour remettre les choses en place, la simplissime commande ci-dessous suffit à remettre les choses en place :

 git push origin master

Après ça, la branche master locale est bien reliée à la branche master sur origin (donc sur notre serveur Gitblit).

Gitblit & Jenkins : l’authentification du risque

Tout récemment, je me suis amusé avec Gitblit et Jenkins. Je ne pensais vraiment rencontrer le moindre souci pour intégrer ces 2 outils (tellement ça me paraissait être l’état de l’art du développement). Oui mais en fait si, il y a bien quelques petits soucis. Pas grand chose me diront certain.

Gitblit est une application Web permettant de créer, organiser ses dépôts Git. Elle est assez jeune et très prometteuse je trouve car elle fonctionne out of the box (comme on dit). Nullement besoin d’installer un binaire git à côté de l’application ou un serveur HTTP pour que les développeurs accèdent aux dépôts. Toutes les couches de communications, la gestion des utilisateurs et la gestion des dépôts sont dans l’application Web.

Je ne présente plus Jenkins, l’outil d’intégration continue qui se charge d’extraire le contenu du gestionnaire de source, de builder, de tester, ….

Voici le problème (qui est une intersection de 2 problèmes) :

  • Par choix, je veux des dépôts qu’on peut librement cloner mais je veux en restreindre les push. C’est génial, c’est tout à fait faisable dans Gitblit. Aïe ! Oui on peut le faire mais le clonage n’est pas vraiment libre car il demande un compte. 1er problème
  • Jenkins a un plugin pour l’intégration d’un dépôt git. Super, je ne devrais pas avoir de problème particulier. Ah mais c’est pas possible, ils m’en veulent ! Impossible de saisir un login et un mot de passe pour accéder au dépôt. Qu’est-ce que c’est que ce plugin à moitié fini.

Résultat : mes dépôts sont en libre accès (ce qui n’est pas un problème pour moi car je suis le seul participant à mes projets) mais ça m’embêterait d’avantage dans une organisation plus conséquente en équipe.