• Shortcuts : 'n' next unread feed - 'p' previous unread feed • Styles : 1 2
aA :  -   + pdf Infos Unsubscribe

» Publishers, Monetize your RSS feeds with FeedShow:  More infos  (Show/Hide Ads)


Date: Sunday, 30 Dec 2007 11:55

Après 4 ans de services plus ou moins bons ou loyaux, darkBlog ferme boutique. Cela fait trop longtemps que je ne prends plus vraiment de plaisir à écrire ici. Ce blog est devenu au fil du temps plus une forme de contrainte qu'autre chose, donc autant y mettre un terme plutôt que de le maintenir en état de mort clinique, mû par quelques spasmes de temps à autres lorsque la culpabilité de ne plus écrire devient trop forte. Merci à vous de l'avoir lu occasionnellement ou régulièrement. Kenavo !

Author: "YoGi" Tags: "Humeur"
Send by mail Print  Save  Delicious 
Date: Tuesday, 18 Dec 2007 09:13

Voilà un sujet qui est souvent revenu autour de la toile ces derniers temps : la compression gzip avec Domino. Et avec la multiplication des frameworks javascript plus puissants mais aussi plus lourds les uns que les autres (Ext, YUI, Dojo, etc), on comprend aisément pourquoi ce sujet est devenu critique. Initialement prévue pour la R7, puis finalement non (et voici peut-être pourquoi), plusieurs solutions personnalisées de compression gzip ont vu le jour ; en substance :

La solution que je vais vous décrire est un peu un amalgame des deux dernières ; une servlet pour compresser à la volée les fichiers, mais (et c'est là toute la magie) avec des règles de sites web spécifiques pour réécrire les URL et compresser de manière transparente, sans toucher aux liens existants.

J'attire votre attention sur le fait que le peu de tests réalisés dans des environnements de production ne se sont pas révélés à la hauteur des attentes, et en outre, après quelques jours d'activité, la tâche HTTP a commencé à montrer des signes de faiblesses et une consommation mémoire anormalement élevée. C'est peut-être dû à l'utilisation intensive de la servlet, c'est peut-être dû à autre chose (mauvais paramétrage ?). Cette première expérience me laisse perplexe car j'utilise des servlets pour d'autres applis à fort taux de visite sans le moindre problème. Néanmoins, je reste convaincu que le concept est bon et c'est pourquoi je vous le présente, en attendant de trouver le fin mot de l'histoire. Gardez tout de même ceci en tête avant de le déployer sur vos serveurs !

La servlet de proxy

Vous vous souvenez de l'agent de proxy Domino ? Vous ne l'avez certainement pas vu puisque cela n'apparaissait que dans les commentaires, mais à l'époque je l'avais également codé sous forme de servlet. Et bien j'ai ajouté quelques fonctionnalités à cette dernière, et notamment celle de gzipper le contenu avant de le renvoyer vers le client (paramètre &gzip=1).

Vous pouvez la chopper ici :

Pour ce qui est de l'installation de la servlet, je vous renvoie à cet article un peu vieux mais plus ou moins toujours d'actualité : Domino development with servlets, ou sinon, en quelques mots, vous déposez le fichier ProxyServlet.class dans votre répertoire data\domino\servlets, et vous vous assurez que le gestionnaire de servlets de Domino est activé (document serveur > Internet protocols > Domino web engine).

Les règles de sites web

Vient ensuite la partie plus amusante : les règles de sites web1. Les règles de substitutions et de redirections font un peu penser à une sorte de mod_rewrite du pauvre, mais avec un peu d'astuce on peut arriver malgré tout à faire des choses sympathiques.

L'idée va être la suivante : pour tous les fichiers ayant l'extension .js ou .css, on redirige (en interne) vers la servlet de proxy avec en paramètre l'URL du fichier susnommé. Le tout est alors totalement transparent pour l'utilisateur. Simple, non ? En réalité, un peu moins que ça, car les possibilités de réécriture des règles de sites web sont limitées et il va falloir mettre en place 2 règles de substitution par extension pour arriver proprement à nos fins.

La première règle va transformer les appels vers les fichiers *.js vers la servlet de proxy avec pour extension de fichier *.js2gzip, tandis que la seconde va intercepter les appels aux fichiers *.js2gzip pour les retransformer en *.js, ce afin de conserver le bon type MIME. Et de même pour les fichiers *.css. Sans cela, la tâche HTTP chercherait à invoquer la servlet indéfiniment (boucle infinie), jusqu'au plantage de la tâche.

*.js -> /servlet/ProxyServlet?url=*.js2gzip&gzip=1&expires=0
*.js2gzip -> *.js

Extrait de ma config :

Règles de réécriture de sites web

Attention, notez bien que les règles définies dans la partie Global web settings ne s'appliquent pas pour le site par défaut, avec Domino 7.0.2 FP2 du moins. Cela relève probablement du bug.

Conclusion

A l'heure où j'écris ceci, je ne ne peux vous fournir de chiffre, mais les résultats lors de mes tests se sont montrés sans appels, et les temps d'affichage des applications massives (remplies de fichiers js et de css) nettement réduits au premier chargement. Et ce - c'est là l'intérêt - sans changer la moindre ligne de code des applis. Un simple test avec Firebug et YSlow le prouve.
Je n'explique cependant toujours pas pourquoi les performances de la tâche HTTP se sont dégradées avec le temps, mais je vais continuer à chercher. La solution est peut-être un tuning plus fin du côté des entêtes HTTP d'expiration (voir le premier point de ce billet de Julian Robichaux) afin de soulager un peu la tâche HTTP. Quoi qu'il en soit, si jamais vous essayez de votre côté, n'hésitez pas à me dire ce que cela donne.

Edit : Voilà quelques stats pour illustrer ces propos :

Stats de compression gzip

Edit #2 : La solution été a priori trouvée (merci Smicky) ; utiliser d'un côté des connexions "fermées" entre le proxy et le serveur Domino, et conserver des connexions persistantes entre le proxy et le navigateur (ce qui implique de retourner la taille du contenu gzippé via l'entête Content-Length). Le hic, c'est que ça pose des tas de problèmes dans IE ; les CSS ou les JS se perdent très souvent dans la nature. C'est un problème connu, il y a des tas de références là dessus sur Google, et presque autant de patchs chez Microsoft selon les versions de Windows et/ou d'IE. La solution globalement préconisée : ne pas utiliser la compression gzip avec IE. Super. N'ayant pas trouvé de workaround malgré un bon paquet d'heures perdues passées sur le sujet, j'abandonne. C'était pourtant une belle idée.

1 : Pour cela, vous devez nécessairement utiliser les documents de sites internet (document serveur > onglet Basics > Load Internet configurations from Server\Internet Sites documents).

Author: "YoGi" Tags: "Lotus Notes / Domino"
Send by mail Print  Save  Delicious 
Date: Thursday, 08 Nov 2007 22:49

Récemment, le camarade Julien a eu la curieuse idée de se lancer dans la vente en ligne de skins pour iPod avec skinizi. Généralement assez peu intéressé par ce type de gadget, mais malgré tout de nature curieuse, je lui ai demandé de m'en faire parvenir un exemplaire pour mon iPod Nano 2G : le modèle Swirl. Ce qui est maintenant chose faite, puisse que je dipose du fameux skin depuis quelques jours et l'ai expérimenté hier soir. Impressions :

Le contenu du package
Contenu du package : un skin, une protection écran, et un manuel
(iPod et nappe rouge ornée de grappes de raisin non fournis)

Le package, très pro, est composé du skin, d'une protection écran ainsi que d'un manuel succint mais clair. La pose du skin est franchement facile, sa texture légèrement alvéolée évite les bulles d'air. Le toucher de l'iPod est agréable et, contrairement à ce que j'aurais pu croire, la molette tactile reste très sensible malgré les adhésifs. La pose de la protection écran quant à elle est plus délicate, et je me suis lamentablement vautré en laissant une bulle d'air en plein milieu. Mais en même temps, il m'est arrivé la même chose à deux reprises (puis abandon) sur Nintendo DS, manipulation qui ne semble par ailleurs pas poser de problème à la plupart des gens, donc je ne dois pas vraiment être une référence en la matière.

Au final, je suis agréablement surpris par le produit, tant par sa qualité que par son attrait. J'avais demandé à Julien un modèle plus par curiosité qu'autre chose, mais au final je crois bien que je vais l'adopter. Une très bonne impression, donc.


Mais quel rapport avec le titre, me diriez-vous ? J'y arrive, j'y arrive. Mettez-vous d'abord en situation : une soirée entre amis, votre iPod en poche. Une situation assez courante somme toute. Imaginez maintenant qu'une charmante demoiselle célibataire (chose rare en soirée) vous apporte une bière (chose encore plus rare), et là, paf, pas de décapsuleur ni de briquet. Mais que faire, et comment rester en ces lieux le mâle dominant face à une telle adversité ? Et bien fort de la protection anti-rayure de votre skin, déboucher une bière avec votre iPod n'est désormais plus un problème. Et la péronnelle, surprise comme charmée, de prendre un malin plaisir à s'y exercer. La soirée commence bien.

Décapsulation de bière avec un Pod skinné

Mais il y a mieux. En fin connaisseur de la gent féminine, vous savez que les femmes sont attirées par tout ce qui est frivole et chatoyant. Sans attendre, vous lui proposez d'observer de plus près l'objet nouveau de ses fantasmes (votre iPod skinné, pas vous). Après quelques hésitations, vous remarquez que ses réactions se font plus franches. Ne vous montrez pas trop hâtif, laissez la poésie du skin agir. C'est alors que la fougue s'empare d'elle. Passion, frénésie ; toute inhibition a soudainement disparu. Il ne vous reste plus qu'à transformer l'essai et lui mettre une cartouche, comme il est d'usage de dire dans le milieu du rugby. La soirée s'annonce décidemment de bonne augure.

Léchouillage d'iPod skinné

Pour toute remarque sur les femmes et ces deux derniers paragraphes, n'hésitez pas à m'écrire. Du reste, si les skins vous intéressent, ça se passe sur skinizi. Et un grand merci à mon assistante photo.

PS : Toute ma considération à celui qui arrive à retrouver l'album qui passe sur la dernière photo (indice : c'est français).

Author: "YoGi" Tags: "Divers"
Send by mail Print  Save  Delicious 
Date: Friday, 19 Oct 2007 13:27

Vous l'avez peut-être remarqué, étrangement, il n'y a pas d'instruction Exit while en LotusScript (du moins avec Domino 7), permattant de sortir d'une boucle While ... Wend. Une solution simple à ce problème est d'utiliser une boucle Do While ... Loop à la place puis l'instruction Exit do. J'aime quand un plan se déroule sans accroc.

Author: "YoGi" Tags: "Lotus Notes / Domino"
Send by mail Print  Save  Delicious 
Date: Monday, 15 Oct 2007 22:18

Je ne sais pas si vous vous rappelez, mais il y a quelques mois, je me suis fendu d'un billet particulièrement assassin sur Lotus Sametime 7.0, dans lequel je relatais les nombreux déboires que nous avons rencontré lors de la migration de Sametime 6.5.1 en 7.0. Pour le coup, je gardais une image fondamentalement négative du produit.

Cet été, je me suis déplacé dans la filliale américaine d'un de nos clients pour établir une connexion entre les serveurs Sametime américain et européen (ce dont je viens de parler quelques lignes plus bas). Figurez-vous que j'ai été très surpris, en discutant avec les administrateurs locaux, d'apprendre que ceux-ci n'ont jamais rencontré le moindre problème avec le produit. Celui-ci tourne sur iSeries, alors que l'européen (celui sur lequel je suis intervenu pour la migration) tourne sur Windows 2003.

Lors de l'opération de rapprochement des deux serveurs, il est apparu que cela ne fonctionnait pas car les serveurs n'utilisaient pas la même nature de connexion vers l'annuaire. Je me suis alors orienté vers l'infocenter de Sametime en quête de la procédure de changement de type de connexion. Et j'ai été frappé par l'étape suivante : Copy and rename the .DLL files, edit the Notes.ini file, or edit the Sametime.ini file. En substance, pour mener à bien cette opération, sur Windows, il est nécessaire de renommer tout un tas de DLL ainsi que d'écraser d'autres fichiers plus ou moins obscurs, alors que sur les autres systèmes, il suffit de modifier un simple paramètre dans le fichier sametime.ini (DirectoryType=LDAP).

Et a bien y réfléchir à posteriori, tous les problèmes que nous avons recontré lors de la migration sont propres à Windows : crash de la tâche HTTP avec la JVM de Domino 7.0.2, services qui ne démarrent pas quand Sametime est lancé depuis Remote Desktop, les meetings qui peuvent ne pas fonctionner quand le processeur utilise l'hyperthreading, le partage d'écran qui nécessite plus de 256 couleurs, etc. Je crois que ça en dit long sur la stabilité de Lotus Sametime sur Windows. J'avais conclu par "C'est bien dommage, car Sametime est un beau produit quand il marche.". Aujourd'hui, je suis convaincu que Lotus Sametime est un beau produit, et qu'il marche très bien. Mais par sur Windows.

Author: "YoGi" Tags: "Lotus Sametime"
Send by mail Print  Save  Delicious 
Date: Monday, 15 Oct 2007 21:37

Disposer de deux serveurs Sametime dans deux organisations différentes, c'est bien, mais les connecter ensemble pour permettre aux utilisateurs de l'un de communiquer avec ceux de l'autre, c'est encore bien mieux. Et (curieusement ?), c'est quelque chose d'assez simple à mettre en oeuvre1, et qui est très bien détaillée dans les deux articles suivants : How to enable communication between multiple Lotus Sametime servers et Getting two Sametime servers in the same community.

Ce que ces deux articles ne précisent pas toutefois, c'est qu'outre le fait que ces deux serveurs doivent partager le même annuaire, la connexion à ces annuaires doit être de même nature. Plus clairement : si vos deux serveurs Sametime pointent vers le même annuaire, mais que l'un utilise une connexion native à l'annuaire Domino, et que l'autre accède à l'annuaire Domino via LDAP, la connexion entre les deux serveurs ne fonctionnera pas. Et cela est aisément compréhensible ; respectivement l'un verra CN=Obiwan Kenobi/O=Ordre Jedi quand l'autre verra CN=Obiwan Kenobi,O=Ordre Jedi. Evident ? Peut-être, mais pas tant que ça quand on est dans le vif du sujet. La solution est bien évidemment de paramétrer les serveurs Sametime pour qu'ils utilisent le même protocole pour accéder à l'annuaire (et à ce sujet, je conseille vivement LDAP plutôt que les connexions natives à l'annuaire Domino).

1 : en dehors des problématiques liées au réseau si les organisations ne sont pas en LAN : autorisation des IP, ports, reverse proxy, DMZ, etc.

Author: "YoGi" Tags: "Lotus Notes / Domino"
Send by mail Print  Save  Delicious 
Date: Monday, 15 Oct 2007 20:13

Déjà évoqué dans le second billet traitant du développement de portlets avec Jetspeed et Eclipse, les informations que l'on retrouve dans WebSphere Portal à l'issue du déploiement d'un portlet JSR 168 proviennent du descripteur de déploiement portlet.xml dudit portlet. Cela dit, comme ce fichier peut se montrer plutôt verbeux, et que sa représentation XMLAccess l'est encore davantage, difficile de déterminer le rôle et l'impact précis de chacune des données du descripteur de déploiement.

C'est pourquoi je me suis livré à une petite expérience visant précisément à lever le voile sur cette zone d'ombre. En ressort que peu d'informations sont réellement utilisées, mais qu'elles sont essentielles et qu'il convient de les manipuler avec précaution (j'y reviendrai plus loin). Voici deux extraits de ces fichiers, volontairement épurés :

Descripteur de déploiement du portlet :

<portlet-app id="FOO">
    <portlet>
        <portlet-name>BAR</portlet-name>
        <portlet-info>
            <title>PLOP</title>
        </portlet-info>
    </portlet>
</portlet-app>

Puis l'export XMLAccess du portlet :

<web-app uid="FOO.webmod">
    <servlet referenceid="BAR.servlet">
    <portlet-app name="FOO" uid="FOO">
        <localedata locale="fr">
            <title>FOO</title>
        </localedata>
        <portlet name="BAR">
            <localedata locale="fr">
                <title>PLOP</title>
            </localedata>
        </portlet>
    </portlet-app>
</web-app>

Il apparaît que les deux données majeures sont la balise portlet-name ainsi que l'attribut id de la balise portlet-app : à elles seules, elles déterminent les données vitales du portlet déployé dans WPS.

Pourquoi tout ceci est important et que je vous bassine avec ? Parce qu'une mauvaise manipulation, même motivée par de très bonnes intentions, peut avoir des conséquences dramatiques. Un exemple ? Imaginez que pour une quelconque histoire de suivi de conventions de nommage (ce qui est tout à votre honneur), vous décidiez de modifier la balise portlet-name du descripteur de déploiement. Redéployez votre module web, et vous perdez tous les portlets issus du module dans votre portail1.

Bug de WPS ? Non, en réalité, la modification du portlet-name a entrainé des modifications de la servlet sous-jascente ; en effet celle-ci se voit attribuée un nouveau referenceid (celui-ci étant basé sur la valeur du portlet-name), et du coup, d'un nouvel objectid, WPS devant considérer que la servlet a changé (et ça semble compréhensible, le referenceid étant le seul attribut utilisé pour l'opération de lookup). Et vos portlets existants, liés à cette servlet par l'attribut servletref, disparaissent soudainement de la surface de votre portail. Oui, c'est sournois, mais ça peut arriver, et très facilement. Les exports XMLAccess sont formels.

Que retenir de tout ceci ? Que le portlet-name comme l'attribut id de la balise portlet-app sont les données les plus importantes du descripteur de déploiement, et qu'une fois un module déployé, mieux vaut ne jamais toucher à ces valeurs.

1 : c'est du vécu. Et ce comportement est reproductible avec WPS 5.1 et 6

Author: "YoGi" Tags: "WebSphere Portal"
Send by mail Print  Save  Delicious 
Date: Saturday, 25 Aug 2007 19:01

Ayant un peu de temps devant moi en ce début d'après-midi (GMT-5), j'en ai profité pour migrer le blog vers dotclear 1.2.7 (je tournais sur l'obsolète 1.2.3 depuis plus de 2 ans & demi, je sais, c'est mal). Ce fut aussi l'occasion de faire un peu de ménage dans les plugins et d'installer spamclear, en espérant que celui-ci me rende la vie un peu plus facile (peu avant que je ferme les commentaires, je me prenais dans la tronche environ 150 spams par nuit).
Au sujet de spamclear, celui-ci n'est pas tout à fait compatible avec les nouvelles mesures de sécurité de dotclear 1.2.7, mais le patch suivant permet de rendre fonctionnel les fonctionnalités d'entrainement du filtre. De même pour dcBlogmark, mais la mise à jour est facile (voir à ce sujet les conventions de codage de dotclear).

Les commentaires sont désormais réouverts (et toujours soumis à approbation en attendant que le filtre s'entraine un peu), n'hésitez pas à me signaler tout problème.

Author: "YoGi" Tags: "Divers"
Send by mail Print  Save  Delicious 
Date: Monday, 06 Aug 2007 17:54

Demain je pars pour 11 jours avec quelques amis (dont Tetert l'expatrié) pour l'édition 2007 du Sziget Festival, qui se déroule à Budapest, Hongrie, pour 8 jours de concerts & autres activités sympathiques, puis 3 jours de découverte de la capitale hongroise. Musicalement ça risque d'être nettement différent du très humide Hellfest 2007 ; il y en aura pour tous les goûts (rock, pop, électro, musique du monde, tsigane, etc) - et même un peu pour moi, avec la présence de quelques groupes sympathiques comme Napalm Death (4ème fois que je vais les voir en moins d'un an !) ou encore Satyricon. Mais la majorité des groupes me sont totalement inconnus, à part quelques têtes d'affiches (Nine Inch Nails, The Chemichal Brothers, et quelques autres que je ne connais que de nom...). Il s'agit donc de vacances clairement placées sous le signe de l'ouverture (et je vois déjà certaines mauvaises langues de mon entourage dire que cela ne me fera pas de mal).

Sziget Festival 2007

Bref, comme je ne pourrai pas surveiller l'activité de ce blog d'une part, et comme en ce moment je me fais harceler de spams d'autre part (1200 spams en moins de 48 heures -- il faut vraiment que j'installe spamclear et/ou du captcha), les commentaires sont coupés jusqu'à nouvel ordre. D'ici là, amusez-vous bien et pas de bêtise.

Author: "YoGi" Tags: "Ma vie"
Send by mail Print  Save  Delicious 
Date: Thursday, 02 Aug 2007 16:55

Les deux méthodes classiques d'exécution de scripts XMLAccess sont d'une part l'importation depuis l'interface d'administration du portail (Paramètres du portail > Importation XML), d'autre part l'outil en ligne de commande xmlaccess.sh (ou .bat) que l'on lance directement depuis le serveur. Mais il en existe une troisième, vraissemblablement moins connue - en tout cas non mentionnée dans l'infocenter - qui consister à communiquer avec le serveur directement via le protocole HTTP.

Le principe est simple :

  • Une requête HTTP de type POST est effectuée sur /wps/config (ex : http://wps.ftel.lan:9081/wps/config)
  • Les accréditations de l'administrateur sont transmises via les entêtes HTTP WPS-User et WPS-Password (pour les versions de WPS plus anciennes, l'unique entête WPS-Authorization, concaténation du login et du mot de passe séparés par un ':', était de vigueur. Le plus simple est de mettre les deux.).
  • Le script XMLAccess à proprement parler est transmis en tant que contenu "brut" de la requête.

En guise de réponse, le portail retourne une page HTML dont le contenu est le résultat de l'exécution du script XMLAccess. Petite démonstration.

Tout d'abord, la requête HTTP :

http://wps.ftel.lan:9081/wps/config

POST /wps/config HTTP/1.1
Host: wps.ftel.lan:9081
WPS-User: wpsadmin
WPS-Password: mypassword
WPS-Authorization: wpsadmin:mypassword
Content-Type: text/xml
<?xml version="1.0" encoding="UTF-8"?>
<request
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="PortalConfig_1.3.xsd"
type="export">
  <portal action="locate">
  <skin uniquename="ftel.skins.BlackSkin" action="export"/>
</portal>
</request>

A titre purement informatif, la réponse du portail :

HTTP/1.x 200 OK
Server: WebSphere Application Server/5.1
Content-Type: text/html; charset=ISO-8859-1
Content-Language: en
Transfer-Encoding: chunked

Nettement plus intéressant, le résultat de l'exécution du script XMLAccess :

<?xml version="1.0" encoding="UTF-8"?>
<request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" build="wp5102_032" type="update" version="5.1.0.2" xsi:noNamespaceSchemaLocation="PortalConfig_1.3.1.xsd">
  <portal action="locate">
    <skin action="update" active="true" default="false" objectid="_K_002C1DBG030CI830_IP" resourceroot="BlackSkin" type="default" uniquename="ftel.skins.BlackSkin">
      <localedata locale="fr"><title>FTEL : Black Skin</title></localedata>
    </skin>
  </portal>
  <status element="all" result="ok"/>
</request>

Et voilà ! Quel intérêt me diriez-vous ? Et bien ceci rend possible l'exécution de scripts XMLAccess à distance (ce qui reste possible avec l'outil xmlaccess.sh sous réserve de l'avoir installé), mais aussi - plus intéressant - par programmation. Une des premières applications qui me vienne à l'esprit est de combler les manques et/ou palier aux lourdeurs de l'interface d'administration par de petits scripts PHP, par exemple pour faire du nettoyage (suppression des portlets applications qui n'ont plus de portlets), ou encore effectuer rapidement des tâches coûteuses en clicks (changer toutes les langues d'une page ou d'un portlet). C'est d'ailleurs ce que nous sommes en train de faire chez mon client, et c'est très prometteur.

Pour ceux qui se demanderaient pourquoi PHP, ce choix s'impose de lui même : PHP possède une extension à la fois simple et très puissante de traitement de données XML (SimpleXML), et le Zend Framework propose un client HTTP bien commode (Zend_Http_Client). Ces deux éléments réunis, exécuter scripts XMLAccess puis en analyser les résultats en PHP est un jeu d'enfant.

Pour la route et en guise de conclusion, voici un exemple d'export complet d'un portail avec Zend_Http_Client :

$script = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n
  <request xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"PortalConfig_1.3.xsd\" type=\"export\">\n
    <portal action=\"export\"/>\n
  </request>";

$client = new Zend_Http_Client("http://wps.ftel.lan:9081/wps/config");

$client->setHeaders(array(
  'WPS-User' => $username,
  'WPS-Password' => $password,
  'WPS-Authorization' => $username . ":" . $password
));
$client->setRawData($script, 'text/xml');
$client->setMethod(Zend_Http_Client::POST);

$response = $client->request();

$result = $response->getBody();
Author: "YoGi" Tags: "WebSphere Portal"
Send by mail Print  Save  Delicious 
Date: Thursday, 26 Jul 2007 20:50

Difficile d'y échapper, en ce moment, c'est les promos, et à ce titre, Ytria, éditeur qui propose une large gamme de logiciels dédiés aux développeurs Lotus Notes, reconduit cette année son offre de licences gratuites jusqu'à la fin de l'été. Si j'en parle, ce n'est pas parce que Jérôme me l'a gentiment demandé, ni même parce qu'il s'agit d'une équipe fort sympathique que j'ai eu le plaisir de rencontrer à l'occasion de la LotusSphere 2007, mais bien parce que leurs produits sont tout simplement du bonheur en barre, dont mes collègues (hein, Renaud) comme moi sommes fans et bénissons chaque jour ses géniteurs.

Alors si vous avez un peu de temps devant vous - ce qui est souvent le cas en été, généralement signe d'activité réduite - je ne saurais que trop vous conseiller d'y jeter un oeil. Et si vous ne devez tester qu'un logiciel, essayez ScanEZ, un explorateur / éditeur de documents d'une puissance telle qu'on en vient à se demander pourquoi IBM n'a jamais intégré quelque chose de similaire à Lotus Designer. Leur slogan "Addiction may occur" est on ne peut plus juste ; une fois qu'on y a goûté, difficile de s'en passer.
Les plus démunis d'entre-vous seront ravis d'apprendre qu'une version en lecture seule de ScanEZ (une expérience qui devient vite frustrante, toutefois) reste disponible tout au long de l'année.

Author: "YoGi" Tags: "Lotus Notes / Domino"
Send by mail Print  Save  Delicious 
Date: Monday, 23 Jul 2007 20:00

Après le permis voiture (2000) et le permis moto (2001), me voici depuis quelques jours l'heureux titulaire du permis côtier, permis qui autorise son propriétaire à naviguer avec tout batiment à moteur jusqu'à 6 milles1 des côtes ou d'un abri. Son obtention a représenté 1 mois & demi d'apprentissage de la partie théorique (assez dense) dont 5 jours quasi-complets, ainsi que 3 heures de pratique (ça peut paraître peu, mais c'est suffisant pour passer l'épreuve). Un investissement somme toute conséquent qui s'est traduit en parti par un certain silence sur ces quelques pages, tout comme des vacances finalement très studieuses et peu reposantes. Mais bon ; c'est désormais derrière moi, je suis ravi et c'est une bonne chose de faite.

Modèle de navire sur lequel j'ai passé mon examen
Modèle de navire sur lequel j'ai passé mon examen.
115 chevaux au cul, des pointes à 27 noeuds2
avec 5 personnes à bord, y'a pas à dire, ça décoiffe !
(photo : bateauxdepeche.com)

J'invite d'ailleurs tous ceux qui sont intéressés par ce permis à s'y pencher au plus vite, la nouvelle réforme de cette année, qui devrait entrer en vigueur dans les mois à venir, rend la partie théorique sensiblement plus difficile (25 questions au lieu de 20, temps limité pour les réponses [utilisation d'un boitier électronique au lieu d'un QCM papier], questions à réponses multiples, nouvelles connaissances requises [lecture des cartes marines], etc).

Sinon, que puis-je bien faire de beau avec tout ces permis, me demanderiez-vous ? Et bien comme tout le monde : m'entasser tous les matins dans la ligne 1 direction la Défense, quelle question.

1 : environ 11 km. Les 6 milles, c'est nouveau, avant c'était 5 milles.

2 : 50 km/h. Sur l'eau, c'est beaucoup.

Author: "YoGi" Tags: "Ma vie"
Send by mail Print  Save  Delicious 
Date: Monday, 23 Jul 2007 10:18

Dans l'indifférence la plus complète (serait-ce dû à l'effervescence Notes 8 / Quickr / Connections ?), le Fix pack 2 de Domino 7.0.2 est sorti il y a un bon mois & demi maintenant. D'après la fix list, il règlerait (entre autre) les nombreux problèmes de crash de la tâche HTTP que l'on rencontrait avec la 7.0.2 et 7.0.2 FP1. Je l'installe de ce pas sur nos serveurs de développement. De votre côté, des retours ?

Author: "YoGi" Tags: "Lotus Notes / Domino"
Send by mail Print  Save  Delicious 
Date: Tuesday, 03 Jul 2007 18:25

Lorsqu'on réalise un import XMLAccess1 qui contient de nouveaux skins2 dans WebSphere Portal 5.1(.0.2), selon toute vraissemblance ceux-ci ne sont pas disponibles de suite. Ce qui est très perturbant car tout le reste de ce qui a pu être importé l'est instantanément (thèmes, modules web, portlets, instances de portlets, pages, mappings d'URL, etc). Les skins sont bien listés dans l'interface d'administration, mais on ne peut pas les affecter aux instances de portlets (retour au skin par défaut). Et c'est d'autant plus perturbant qu'un skin aux paramètres identiques installé à la main (et donc utilisant les mêmes ressources JSP, CSS, etc) depuis l'interface d'administration suscitée marche quant à lui du premier coup.

Donc pas la peine perdre passer l'après-midi à triturer dans tous les sens les 3000 lignes du script d'import, suffit d'attendre un peu (enfin, beaucoup), ou de redémarrer le portail (ce qui peut être très long aussi, notez), et le tour est joué. Sans doute une sombre histoire de cache dont je ne préfère pas vraiment en savoir plus.

1 : j'en ai déjà un peu parlé ici. XMLAccess est un dialecte XML qui décrit l'ensemble de la configuration d'un portail WebSphere ; ce qu'est DXL à Domino, en somme.

2 : un skin est l'habillage d'un portlet. C'est le fragment qui contient le cadre, le titre du portlet, les actions (configurer, éditer, minimiser, maximiser), etc.

Author: "YoGi" Tags: "WebSphere Portal"
Send by mail Print  Save  Delicious 
Date: Thursday, 21 Jun 2007 06:45

Et voilà, l'événement tant attendu est sur le point d'ouvrir ses portes ! Peu de changement par rapport à l'affiche initiale : Mayhem, dont le batteur Hellhammer s'est cassé le bras récemment, sera remplacé par Enslaved (du vu et revu, mais du bon quand même). Ca s'annonce donc toujours aussi excellent. Et mouillé aussi, ce qui pour le coup était moins prévu au programme, mais les prévisions météo pour les 3 jours à venir parlent tristement d'elles-mêmes :

Prévisions météo Hellfest : que de la pluie
21 juin, début de l'été... su-per

Mais bon, le breton d'origine que je suis ne va pas se laisser abattre par quelques gouttes d'eau, et a bien entendu tout l'attirail requis dans le placard (cirés, k-way...). Retour prévu lundi après-midi, avec des images plein les yeux et du son plein les oreilles (et probablement une bonne crève, aussi, histoire de changer de la grippe dont je peine à sortir). En attendant, je file faire mes bagages, décollage pour Nantes prévu à 14h00. J'espère pouvoir vous ramener quelques photos sympathiques.

Author: "YoGi" Tags: "Ma vie"
Send by mail Print  Save  Delicious 
Date: Wednesday, 06 Jun 2007 11:15

IBM met à disposition une barre d'outils de support de l'ensemble de leurs gammes de produits (Lotus, WebSphere, Tivoli, Rational) pour Internet Explorer et Firefox. Cette barre d'outils, entièrement paramétrable, offre des accès directs aux différentes rubriques les plus utiles de chacune des gammes de produits (téléchargements, documentation, forums, technotes, etc), tout comme la possibilité de rechercher directement parmi celles-ci grâce à un champ de recherche.

Voilà une excellente initiative que l'on ne peut que féliciter, et de fait une extension à installer de toute urgence.

Recherche de @Dblookup et 64k sur les technotes de Lotus

Author: "YoGi" Tags: "Lotus Notes / Domino"
Send by mail Print  Save  Delicious 
Date: Wednesday, 23 May 2007 22:25

C'est en lisant l'excellent article Coding faster lookups in IBM Lotus Notes and Domino publié il y a quelques temps déjà sur developerWorks (oui, j'ai du retard dans mes feeds) que je suis tombé sur l'astuce suivante : Use "Generate unique keys in index" to eliminate duplicate entries", que l'on pourrait traduire par : Utiliser l'option "Générer clés uniques dans l'index" pour éliminer les doublons.

Sous cet intitulé plutôt mystérieux se cache une fonctionnalité redoutable, que j'ignorais par ailleurs totalement : la possibilité de ne lister que les entrées uniques d'une vue, sur base de comparaison de chaînes de caractères. Exactement comme on le fait avec les catégories, sauf que là, point de catégorisation encombrante, la vue reste plate2.

Sans: 7 entrées, avec: 3 entrées
A gauche sans, à droite avec

L'une des principales applications de cette option s'impose d'elle même : plutôt que de faire systématiquement un @Unique derrière un @DbLookup pour supprimer les doublons tout en priant pour que la limite des 64k ne soit jamais atteinte (ou alors une fois que vous aurez changé de job), l'idée devient alors d'utiliser une vue spéciale dotée de cette propriété. Les avantages sont multiples : plus rapide (pas de @Unique à calculer à chaque exécution de la formule, mais au contraire directement calculé dans l'index de la vue), et surtout la garantie que votre appli n'explosera pas en cours de route à cause d'un trop grand nombre de documents (et du coup vous pouvez songer à faire carrière dans votre boite, et par exemple commencer par demander une augmentation).

Propriété de la vue : ODBC Access, generate unique keys in index

Petite mise en garde toutefois, en R6, cela ne fonctionne pas sur les champs multi-valués (l'article conseille alors de faire un @Implode dans la colonne puis un @Explode derrière). En R7, le problème est réglé. Et en R5 ou inférieur, je présume que cette option n'existe pas. MAJ : Cette option semble également exister en R5 et même en R4.6.

Quoi qu'il en soit, je n'en reviens toujours pas de ne découvrir un truc aussi fondamental qu'aujourd'hui, après 3 ans & demi de travail dans l'univers de Lotus Notes / Domino. Un truc qui m'aurait sauvé la mise bien des fois par le passé. Force est d'avouer que l'intitulé de section "ODBC Access" est bien trompeur, et est certainement la raison pour laquelle je ne me suis jamais attardé sur cette option. Ce qui est sûr, maintenant, c'est que je ne suis pas près de l'oublier.

2 : à défaut d'être catégorisée, la colonne en question doit tout de même être triée.

Author: "YoGi" Tags: "Lotus Notes / Domino"
Send by mail Print  Save  Delicious 
Date: Monday, 07 May 2007 20:12

Il y a quelques temps, j'ai évoqué la recherche d'un nouveau téléphone. Et bien c'est désormais chose faite, et depuis quelques jours je suis l'heureux utilisateur d'un Nokia E65. Il s'agit d'un smartphone de la gamme orientée entreprise de Nokia (E-Series) qui présente l'avantage (ou l'inconvénient, tout dépend de ce que l'on souhaite en faire) de rester dans les dimensions d'un téléphone classique. Aussi, au menu on retrouve S60 3ème édition, du Bluetooth, du Wifi (avec support de la VoIP), du VPN, push email et synchronisation avec Exchange ou Domino (support de POP / IMAP / SMTP), une suite bureautique (Quickoffice) et un Acrobat Reader allégé, un écran QVGA de franchement bonne qualité, mais aussi les fonctionnalités que l'on retrouve dans les téléphones grands publics de nos jours : lecteur audio/vidéo, capteur 2 Mpixels (de qualité honnête sans être exceptionnel), slot microSD, etc.

Le navigateur web de S60 3rd (basé sur KHTML), même s'il n'a probablement pas grand chose à envier à Opera mini (que je n'ai pas encore essayé) ou IE Pocket PC, est franchement bluffant de rapidité comme de qualité de rendu par rapport à ce que j'avais déjà eu entre les mains, et c'est un vrai régal que de surfer depuis ce téléphone. Reste malheureusement quelques désagréments qui risquent de se montrer bien pénibles à l'usage, comme l'impossibilité de gérer les identités (et retaper les noms d'utilisateur et mots de passe à chaque fois sur un clavier de téléphone, c'est lourd). Le plus regrettable est que le navigateur de la nouvelle mouture de l'OS (S60 3rd FP1) intègre (entre autre) cette fonctionnalité, mais que Nokia a manifestement préféré intégrer dans ce modèle presque tout neuf un OS âgé de 10 mois plutôt que la dernière itération. A en croire la littérature, il est peu probable de voir apparaître une mise à jour. Peut-être me tournerai-je avec le temps vers Opera Mini, à voir.

Mais s'il y a quelque chose qui m'a encore plus bluffé que le navigateur web, c'est bien la foule d'applications (dont beaucoup de gratuites) que l'on peut trouver pour S60, et pas des moindres : Google Maps, Recherche Yahoo! et Pages Jaunes, Messagerie instantanée (Skype, MSN, ICQ, etc), WidSets, un moteur de widgets hallucinant, et bien d'autres encore (si vous suivez mes blogmarks, vous avez dû voir défiler quelques liens sur le sujet dernièrement). Cela amène l'expérience de la mobilité a un tout autre niveau que ce que j'ai connu jusque là, et il y a fort à parier que, sans pour autant le remplacer, mon laptop va désormais rester bien plus souvent au placard.

Le revers de la médaille de tout ça, si on écarte les coûts de communication, c'est bien l'autonomie de l'appareil. Car si en usage classique de téléphone elle semble tout à fait honorable, dès lors qu'on commence à jouer avec plusieurs applications en multitâche, comme transférer des données en Bluetooth tout en surfant via du Wifi en écoutant un Mp3 en fond, celle-ci semble alors bien réduite (quelques heures ?). Les utilisateurs de PDA semblent s'accorder pour dire que celle-ci reste très respectable, n'empêche, il vaut mieux conserver un chargeur sur soi. Au rayon des doléances, j'ajouterai le pavé de navigation comme les touches latérales qui ne sont pas bien pratiques quand on a des mains de bûcheron comme les miennes, et une des touches qui déconne un peu (et c'est vraissemblablement un défaut du modèle puisque ce point a été relevé dans de nombreuses revues).

Quoi qu'il en soit, pour le moment j'en suis ravi, et ce modèle correspond précisément à ce que je désirais : un téléphone "intelligent" sans l'encombrement d'un PDA ou d'un Blackberry. Reste que celui-ci ne s'adresse pas à ceux qui comptent écrire dessus de manière intensive, et j'aurais plutôt tendance à les orienter vers le nouveau Nokia E61i (ou le plus ancien Nokia E61 que l'on trouve désormais à peu près au même prix que le E65), ou le Nokia E90 si vous ne savez vraiment plus quoi faire de vos sous.

Plein de captures d'écran de la bête (prises avec Screenshot for Symbian) dans la suite.

Ecran d'accueil : accès direct à certaines applis et rappels de l'agenda
Ecran d'accueil : accès direct à certaines applis et
rappels de l'agenda

Menu général
Menu général

Aperçu de l'agenda
Aperçu de l'agenda (assez mauvais, il faut l'avouer)

Navigateur web : le webmail Squirrelmail
Navigateur web : le webmail Squirrelmail.
Notez que les frames sont gérées,
et admirez la mini-map ingénieuse !

Navigateur web : votre site préféré, sensiblement plus complexe (positionnement CSS, javascript, iframes)
Navigateur web : votre site préféré, sensiblement plus
complexe (positionnement CSS, javascript, iframes)

Navigateur web : la très sympathique fonctionnalité 'aperçu'
Navigateur web : la très sympathique fonctionnalité 'aperçu'

Programmes tiers installés
Programmes tiers installés

Application recherche : Pages Jaunes (recherche)
Application recherche : Pages Jaunes (recherche)

Application recherche : Pages Jaunes (résultats)
Application recherche : Pages Jaunes (résultats)

Application recherche : Yahoo! Images
Application recherche : Yahoo! Images

Application Google Maps : parcours d'un itinéraire, en mode plan...
Application Google Maps : parcours d'un itinéraire, en mode plan...

Application Google Maps : ... et en mode satellite !
Application Google Maps : ... et en mode satellite !

Application WidSets : écran d'accueil
Application WidSets : écran d'accueil

Application WidSets : dernières publications de Digg
Application WidSets : dernières publications de Digg

Application EQO Mobile : choix du protocole
Application EQO Mobile : choix du protocole

Application EQO Mobile : liste des contacts
Application EQO Mobile : liste des contacts
(normalement c'est pas pixellisé hein)

Compteur de données après 3 jours d'utilisation. 13.42 Mo envoyés, 917 reçus.
Compteur de données après 3 jours d'utilisation.
Tâchez d'avoir un bon forfait !

Author: "YoGi" Tags: "Matériel"
Send by mail Print  Save  Delicious 
Date: Saturday, 05 May 2007 12:03

Ce billet fait suite à Développement de portlets pour WebSphere Portal avec Jetspeed et Eclipse (1/2), dont je vous conseille grandement la lecture si vous souhaitez comprendre ce qui va suivre. Sont ici abordés quelques aspects de la spécification JSR-168, le développement puis le déploiement du portlet dans Jetspeed et WebSphere Portal.

Spécification JSR-168 101

Je ne vais pas rentrer dans les arcanes de la spécification JSR-168 - si le sujet vous intéresse, vous trouverez plein de liens très intéressants par là -, mais en substance, c'est très proche du développement web classique à base de JSP et de servlets (même approche MVC, objets "request" et "response" similaires, etc) et si vous êtes à l'aise dans ce domaine, vous ne rencontrerez vraissemblablement aucune difficulté avec le développement de portlets JSR-168.

Ce qu'il est nécessaire de préciser, avant d'aller plus loin, est que la spécification définit trois états pour un portlet : normal, réduit, maximisé. En fonction de ces états, le portlet peut délivrer du contenu différent et adapté à sa représentation visuelle dans le portail. Pas de surprise, il s'agit des mêmes états que n'importe quelle fenêtre dans un window manager.

Beaucoup plus intéressant, la spécification définit aussi trois modes pour un portlet : view, edit et help :

  • Le mode view correspond au mode normal d'un portlet : il délivre le contenu et/ou réalise les actions attendues par les utilisateurs.
  • Le mode edit, optionnel, correspond au mode de personnalisation d'un portlet. Typiquement, ce mode présente un formulaire dont les paramètres vont influencer le résultat du mode view (par exemple, pour un portlet de connexion FTP, il pourrait s'agir de l'hôte, du nom d'utilisateur et du mot de passe). Il est important de noter que ces paramétrages sont propres à chaque utilisateur.
  • Enfin, le mode help, également optionnel, a pour rôle de présenter aux utilisateurs un écran d'aide sur l'utilisation du portlet.

La spécification JSR-168 offre la possibilité aux vendeurs de proposer de nouveaux modes (via la balise custom-portlet-mode du descripteur de déploiement des portlets), et comme on pouvait s'y attendre, WPS dispose d'un quatrième mode : le mode config, identique au mode edit à la différence près que les paramétrages définis sont communs à tous les utilisateurs (note : les modes edit et config peuvent présenter des écrans de personnalisation différents). Et c'est en réalité bien pratique car on imagine aisément que l'administrateur d'un portlet puisse vouloir définir des paramètres pour tous les utilisateurs dudit portlet (par exemple, l'adresse d'un annuaire LDAP). En JSR-168 pur, c'est typiquement le genre de donnée que l'on définirait en paramètre d'initialisation (balise init-param du descripteur de déploiement des portlets).
Aussi, dans la phase de développement sur Jetspeed, pour tester le mode config, le mieux est de l'associer au mode edit, quitte à désactiver ce dernier par la suite avant de passer sur WPS (et c'est d'ailleurs ce que nous allons faire ici-même avec notre portlet). Gardez toutefois à l'esprit que les paramètres saisis ne seront accessibles que pour l'utilisateur courant.

Aspect des actions d'un portlet avec les thèmes par défaut respectivement dans Jetspeed, WPS 6, WPS 5.1
Aspect des actions d'un portlet avec les thèmes par défaut,
respectivement dans Jetspeed, WPS 6 et WPS 5.1

Ces précisions étant faites, nous allons pouvoir passer au développement à proprement parler du portlet.

Développement du portlet

Pour ceux qui n'auraient pas envie de recopier le code dans Eclipse et souhaitent directement passer à l'étape suivante, le fichier WAR tout prêt à être importé ou déployé dans Jetspeed est disponible ici : L33tSpeakPortlet.war. La version finale, adaptée pour WPS, est quant à elle disponible ici : L33tSpeakPortlet-wps.war. Autre précision : le code du portlet qui va être présenté sous peu vise le minimalisme et ne respecte pas nécessairement les bonnes pratiques en vigueur (séparation de la présentation et de la logique métier, usage de JSTL au lieu des scriplets, etc). Ne pas reproduire à la maison !

Bien. Pour commencer, on va créer notre contrôleur L33tSpeakPortlet, héritant de javax.portlet.GenericPortlet et appartenant au package fr.ftel.portlets.L33tSpeak à l'aide de l'assistant (click droit sur Java Resources dans le Project Explorer d'Eclipse, puis new -> Class).

Eclipse : nouvelle classe

Le code du fichier est le suivant :

package fr.ftel.portlets.L33tSpeak;

import java.io.IOException ;
import java.io.PrintWriter;
import javax.portlet.*;

public class L33tSpeakPortlet extends GenericPortlet {
    private static String PAGE_EDIT = "/jsp/edit.jsp";

    // piqué sur http://hellboundhackers.org/code/readcode.php?id=202
    private static char [] textKey = new char[] {'a', 'b', 'c', 'd', 'e', 'f', 'g',
            'h', 'i', 'j', 'k', 'l', 'm', 'n',
            'o', 'p', 'q', 'r', 's', 't', 'u',
            'v', 'w', 'x', 'y', 'z'};

    private static char [] leetKey = new char[] {'4', 'b', 'c', 'd', '3', 'f', 'g',
    'h', '|', 'j', 'k', '1', 'm', 'n',
    '0', 'p', 'q', 'r', '5', '7', 'u',
    'v', 'w', 'x', 'y', 'z'};
    
    public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
        PortletPreferences prefs = request.getPreferences();
        String clearText = prefs.getValue("clearText", "") ;
        String leetText = clearText ;
        
        if (clearText.length() > 0) {
            for (int i=0 ; i<textKey.length ; i++) {
                leetText = leetText.replace(textKey[i], leetKey[i]);
            }
        }
        else {
            leetText = "<i>Le portlet doit être configuré !</i>";
        }
        
        response.setContentType("text/html");
        
        PrintWriter out = response.getWriter();
        out.println(leetText);
    }
    
    public void doEdit(RenderRequest request, RenderResponse response)throws PortletException, IOException {
        PortletPreferences prefs = request.getPreferences();

        request.setAttribute("clearText", prefs.getValue("clearText", "")) ;
        
        PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher(L33tSpeakPortlet.PAGE_EDIT);
        dispatcher.include(request,response);
    }
    
    public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {
        PortletMode mode = request.getPortletMode();

        if (mode.equals(PortletMode.EDIT)) {
            PortletPreferences prefs = request.getPreferences();
            prefs.setValue("clearText", request.getParameter("clearText"));
            prefs.store();
        }
    }
}

Celui-ci définit ici 3 méthodes, en plus de celles héritées de GenericPortlet : doView(), doEdit() et processAction(). A la manière des doGet() et doPost() pour les servlets, les deux premières méthodes sont invoquées par le conteneur de portlets respectivement lors du rendu du portlet en mode view et edit. Vous l'aurez deviné, il existe une troisième méthode que nous n'utilisons pas ici : doHelp(). Enfin, processAction() est la méthode invoquée pour traiter les actions effectuées sur le portlet (soumission d'un formulaire par exemple).

Ici, dans le doView(), nous récupérons une chaîne de caractères nommée clearText stockée dans les préférences du portlet (PortletPreferences), nous encodons cette chaîne en l33t speak, puis nous l'affichons directement dans le portlet via la sortie (PrintWriter) de l'objet de réponse (RenderResponse).
Cette chaîne de caractères doit être définie quelque part, et c'est précisément l'objet de la méthode doEdit(), qui récupère cette valeur des préférences, l'ajoute en tant qu'attribut de requête (un peu de découplage ne fait pas de mal), puis transmet la requête vers une page JSP edit.jsp que nous allons très bientôt définir et qui va correspondre à un formulaire de saisie de la chaîne à encoder.
Enfin, la méthode processAction(), invoquée ici à la validation du formulaire de saisie, se charge de récupérer la valeur des paramètres de la requête et de la stocker dans les préférences du portlet. Notons que les problématiques de stockage ne sont pas du tout à la charge du développeur (le conteneur de portlets est là pour ça), et que cette même méthode processAction() pourrait très bien être appelée en mode view, et c'est pourquoi nous nous vérifions que nous sommes bien dans le mode edit avant tout.

Le contenu du fichier edit.jsp, que l'on aura préalablement créé dans le répertoire WebContent/jsp/ (qui n'existe pas initialement non plus), est le suivant :

<%@ page contentType="text/html; charset=UTF-8" session="true" %>
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet"%>

<portlet:defineObjects />

<form action="<portlet:actionURL />" method="POST" name="L33tSpeakPortletEdit">
    <p>
        <label for="clearText">Texte :</label>
        <input type="text" name="clearText" id="clearText" value="<%=((String)renderRequest.getAttribute("clearText")).replaceAll("\"", "&quot;")%>"/>
    </p>
    <p>
        <input type="button" value="Retour" onclick="window.location.href = '<portlet:renderURL windowState="normal" portletMode="view"/>'"/>
        <input type="submit" value="Sauvegarde"/>
    </p>
<form>

Il s'agit d'un formulaire de saisie HTML dans toute sa simplicité. Notons l'usage assez intensif de la librairie de tags portlet. Celle-ci permet d'accéder aux objets spécifiques du portlet (renderRequest, renderResponse et portletConfig) et offre des mécanismes de création d'URL (actionURL, renderURL) et d'espace de nommage (utile pour les id des éléments HTML, pour les fonctions javascript, etc - gardez à l'esprit qu'il peut y avoir plusieurs instances d'un portlet sur une même page !).

Et c'est tout en ce qui concerne le code à proprement parler du portlet !

Déploiement du portlet dans Jetspeed

Codé, c'est bien, déployé, c'est encore mieux. Et justement, s'il y a quelque chose que nous n'avons pas encore traité pour le moment, c'est bien le descripteur de déploiement du portlet (WEB-INF/portlet.xml), dont le contenu est le suivant :

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="1.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
                                 http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
             id="L33tSpeakPortlet PortletApp">
   <portlet>
      <portlet-name>L33tSpeakPortlet Portlet</portlet-name>
      <display-name>L33tSpeakPortlet Portlet</display-name>
      <portlet-class>fr.ftel.portlets.L33tSpeak.L33tSpeakPortlet</portlet-class>
      <supports>
         <mime-type>text/html</mime-type>
         <portlet-mode>view</portlet-mode>
         <portlet-mode>edit</portlet-mode>
      </supports>
      <supported-locale>en</supported-locale>
      <portlet-info>
         <title>d0 y0u 5p34k 1337 ?</title>
      </portlet-info>
      <portlet-preferences>
        <preference>
            <name>clearText</name> 
            <value></value> 
        </preference>
      </portlet-preferences>
   </portlet>
</portlet-app>

Attardons-nous un instant sur le descripteur de déploiement du portlet car il y a plusieurs choses à préciser :

  • Jetspeed utilise le nom physique du fichier (sans l'extension .war) pour déterminer le nom du portlet application
  • WPS utilise la valeur de l'attribut id de la balise portlet-app pour déterminer le nom du portlet application
  • Jetspeed utilise les balises portlet-name et display-name pour déterminer le nom du portlet (display-name pour les utilisateurs, portlet-name en interne)
  • WPS utilise (pourquoi, mais pourquoi ?!) le titre du portlet (balise portlet-info > title) pour déterminer le nom du portlet.
  • La valeur de la balise portlet-class correspond à l'objet contrôleur du portlet (héritant de GenericPortlet)
  • Dans la balise supports, on définit les modes supportés par le portlet (balise portlet-mode). Ici, view et edit. Comme il n'y a pas de mode help, le portail n'affichera pas l'action.
  • Pour qu'une valeur puisse être stockée en préférences du portlet (comme nous l'avons fait avec clearText), elle doit être déclarée dans la section portlet-preferences. On peut également y adjoindre une valeur par défaut.

Ceci fait, il ne reste plus qu'à déployer le portlet, ce qui se fait très simplement avec Jetspeed : il suffit d'exporter le projet sous forme de fichier WAR puis de déposer celui-ci dans le répertoire webapps\jetspeed\WEB-INF\deploy. Celui-ci sera alors aspiré puis déployé automatiquement (rechargement automatique activé par défaut) :

Found web.xml
Found WEB-INF/portlet.xml
Attempting to add portlet.tld to war...
Adding portlet.tld to war...
Creating war C:\dev\Jetspeed-2.1\webapps\L33tSpeakPortlet.war ...
War C:\dev\Jetspeed-2.1\webapps\L33tSpeakPortlet.war created
JetspeedContainerServlet: starting initialization of Portlet Application at: L33tSpeakPortlet
JetspeedContainerServlet: initialization done for Portlet Application at: L33tSpeakPortlet

Le portlet est déployé, il est désormais possible d'en ajouter des instances sur des pages. Pour ce faire, il faut vous logger avec le compte admin, puis éditer une page via le bouton d'action edit. Vous tombez alors sur un panneau de contrôle de personnalisation de la page (thème de la page, skins des portlets, etc) qui contient un lien "add a portlet", qui vous amène pour sa part à une page de recherche de portlets particulièrement agréable et intuitive. Dans l'exemple ci-dessous, j'ai tout d'abord créé une nouvelle page "sandbox" pour mes essais. Cela peut se faire dans la partie d'administration.

2 instances du portlet (avec des skins différents) sur une page dans Jetspeed
2 instances du portlet (avec skins différents) sur une page dans Jetspeed

Déploiement du portlet dans WPS

Nous venons de déployer le portlet dans Jetspeed, et c'est très bien, mais l'objectif final est de pouvoir le publier dans WPS. En fait, en l'état, le portlet fonctionne d'ores et déjà parfaitement dans WPS, seulement rappelez-vous, nous souhaitions mettre en place le mode config, et non le mode edit. Quelques menues adaptations sont donc nécessaires.

Descripteur de déploiement du portlet

A commencer par le descripteur de déploiement du portlet. En effet, si on veut utiliser le mode config, il faut bien le déclarer en tant que mode supporté. Et aussi le définir tout court, à l'aide de la balise custom-portlet-mode :

<portlet-app ...>
   <portlet>
      ...
      <supports>
         <mime-type>text/html</mime-type>
         <portlet-mode>view</portlet-mode>
         <!-- <portlet-mode>edit</portlet-mode> -->
         <portlet-mode>config</portlet-mode> 
      </supports>
      ...
   </portlet>
  <custom-portlet-mode>
    <portlet-mode>config</portlet-mode> 
  </custom-portlet-mode>
</portlet-app>

Contrôleur L33tSpeakPortlet

De même, en l'état, le mode config n'est pas géré dans le contrôleur. Et il n'y a pas de doConfig() non plus, ce mode n'étant pas standard. La solution est en réalité très simple : on va réécrire le dispatcher (méthode doDispatch() héritée de GenericPortlet), puis on va router les invocations du mode config vers le mode edit. Le reste du code reste (presque) identique :

public class L33tSpeakPortlet extends GenericPortlet {
    private static final PortletMode MODE_CONFIG = new PortletMode("config");
    ...
    public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {
        PortletMode mode = request.getPortletMode();

        if (mode.equals(PortletMode.EDIT) || mode.equals(L33tSpeakPortlet.MODE_CONFIG)) {
           ...
        }
    }

    protected void doDispatch(RenderRequest request, RenderResponse response) throws PortletException, IOException {
        if (request.getPortletMode().equals(L33tSpeakPortlet.MODE_CONFIG)) {
            doEdit(request,response);
            return;
        }
        
        super.doDispatch(request, response);
    }
}

Et voilà le travail :

2 instances du portlet sur une page dans WPS
2 instances du portlet sur une page dans WPS

Conclusion

Nous avons donc vu comment développer des portlets pour WebSphere Portal en utilisant des logiciels open-source comme Eclipse et Apache Jetspeed. Et bien ce que duo concurrence difficilement RAD en terme de fonctionnalités (bien qu'avec les plugins adéquats on peut en reproduire certaines, comme Subclipse en remplacement de ClearCase) ou d'efficacité (click droit -> deploy pour déployer sur un environnement de test local ou un serveur distant, difficile de faire plus court), j'ai tendance à le préférer pour la rapidité et simplicité des logiciels mis en oeuvre. A l'usage, le gain de temps me paraît indéniable. Plus de clicks, mais tellement moins de temps à attendre bêtement derrière l'écran !

Reste qu'il est nécessaire d'avoir de bonnes bases de Java, et que tout est développé à la main et à partir de zéro, ce qui va à l'encontre d'une logique industrielle de développement. Aussi, les deux produits cités en introduction, Lotus Component Designer et WebSphere Portlet Factory, ne sont pas à écarter pour autant, selon votre profil comme vos besoins.

Author: "YoGi" Tags: "WebSphere Portal"
Send by mail Print  Save  Delicious 
Date: Tuesday, 01 May 2007 21:57

Pour développer des portlets pour WebSphere Portal, IBM propose toute une gamme de logiciels s'adressant à des publics, des besoins, et des budgets différents, tels que Rational Application Developer, l'environnement de développement étendu à destination des développeurs Java chevronnés, Lotus Component Designer s'adressant à la population des développeurs Lotus/Domino et qui a été évoqué récemment ici-même, ou encore WebSphere Portlet Factory qui permet le développement et le déploiement accéléré et grandement automatisé de portlets à l'aide d'assistants visuels et d'un grand nombre de connecteurs vers les systèmes d'entreprise (Domino, SAP, etc).

Mais les portlets répondent désormais à un standard (actuellement la spécification JSR-168 ou Portlet-1.0, la relève JSR-286, Portlet-2.0, étant toujours à l'état de brouillon), standard supporté par WebSphere Portal depuis la version 5.02. Et pour des besoins modestes - ou même complexes, du moment qu'ils ne fassent pas intervenir des spécificités de WPS comme les thèmes, le modèle de navigation ou encore la sécurité (cf le modèle SPI) - il est tout à fait possible de développer des portlets intégralement à l'aide de logiciels open-source comme Apache Jetspeed, le portail d'entreprise de la fondation Apache, et Eclipse, le couteau suisse communautaire qui reste au demeurant un excellent environnement intégré de développement. Bien sûr, ils n'adressent pas les mêmes problématiques, mais outre leur gratuité, ils ont l'avantage d'être légers et rapides, et pour le développeur Java, ceux-ci se posent en sérieuse alternative au mastodonte RAD et ses environnements de test (UTE) aussi pratiques que gourmands en mémoire. C'est ce que je vais vous présenter dans ce billet en deux parties1, de l'installation de ces outils jusqu'à la publication d'un portlet dans WPS 6.

1 : La deuxième partie est presque terminée et sera publiée dans la semaine, histoire d'éviter la blague des suites 3 mois après.

Prérequis

Il est très facile de se noyer dans l'océan de versions et de déclinaisons différentes de Java, d'autant plus que celles-ci ont changé plus d'une fois de nomenclature (pour des raisons probablement marketing qui échapperont à jamais au commun des mortels - voir l'historique chez wikipedia), alors mettons les choses au clair de suite. Pour le développement que nous allons effectuer, il va vous falloir les 3 choses suivantes :

  • Java Runtime Environment (JRE) 5.0, requis pour faire tourner Jetspeed 2.1. Il s'agit de l'environnement d'exécution, et ne permet pas le développement d'applications Java (pas de compilateur, etc). Si vous disposez déjà du JRE 5.0 ou supérieur (ce qui est fort probable), vous pouvez passer cette étape. Assurez-vous tout de même d'avoir une variable d'environnement JAVA_HOME ou JRE_HOME qui pointe sur le répertoire d'installation de votre JRE.
  • Java 2 Standard Edition 1.4.2 SDK, le kit de développement standard Java 1.4 (historiquement appelé JDK, avant d'évoluer vers J2SE, pour finalement devenir Java SE avec la version 6), nécessaire pour le développement Java de base.
  • Java 2 Enterprise Edition 1.3.1, le fameux J2EE que l'on voit sur la moitié des offres d'emploi d'informatique en ce moment (et qu'il convient désormais d'appeler Java EE ; ne perdez pas une opportunité de faire la nique aux recruteurs !), nécessaire pour le développement orienté entreprise (EJB), applications web et tout le tintouin (fournit le support des JSP, Servlets, etc).

Je propose ici des versions volontairement obsolètes des kits de développement afin d'assurer la plus grande compatibilité possible avec le WebSphere Portal que vous pourriez avoir sous la main, la compatibilité ascendante ne posant (à ma connaissance) pas de problème. En outre, si vous avez un WPS 5.1, il y a de fortes chances pour que les versions plus récentes (JDK 5.0 et J2EE 1.4) ne soient pas supportées (ça dépend en réalité du WAS sur lequel tourne WPS, mais on ne va pas s'encombrer avec des détails superflus).
Sinon, vous installez ça où vous voulez, cela n'a pas d'importance, mais souvenez-vous quand même des répertoires d'installation car vous allez avoir besoin de les référencer dans Eclipse par la suite.

Installation de Jetspeed

Direction Download Jetspeed-2 Distribution, et téléchargez le fichier jetspeed-2.1-installer.jar (32.9 Mo). Lancez l'installation avec la commande suivante :

java -jar jetspeed-2.1-installer.jar

Si vous commencez à avoir des erreurs à ce niveau, c'est probablement que la version du JRE invoquée n'est pas la bonne, et un coup de java -version vous confirmera ces propos. C'est peut-être aussi parce que vous êtes derrière un firewall ou un proxy (et dans ce cas, vous trouverez un workaround ici). Sinon, suivez la procédure d'installation comme indiqué, ce qui se résume globalement à faire next » next » next » exit. Temps d'installation : 1 minute 30 (à comparer à l'après-midi entière d'installation d'un RAD + environnements de test).

Ecran d'installation de Jetspeed
Derby est un bon choix pour une plateforme de développement

Pour permettre le partage de session entre les portlets et les servlets les accompagnant (je reviendrai là dessus dans un billet ultérieur, mais si vous voulez d'ores et déjà en savoir plus, vous pouvez aller voir par là), assurez-vous des deux points suivants :

  • Dans le fichier conf\server.xml de votre Jetspeed, ajoutez l'attribut emptySessionPath="true" à la balise Connector correspondant au connecteur que vous utilisez ; typiquement le connecteur par défaut HTTP/1.1 non SSL écoutant sur le port 8080. Ca donne quelque chose du genre :
    <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
    <Connector port="8080" maxHttpHeaderSize="8192" (...) emptySessionPath="true" />
  • Dans le fichier conf\Catalina\localhost\jetspeed.xml, vérifiez que l'attribut crossContext="true" est présent dans le contexte (balise Context). Cela devrait être le cas par défaut :
    <Context path="/jetspeed" docBase="jetspeed" crossContext="true">

Lancez ensuite le script bin\startup.bat dans le répertoire de Jetspeed, et 20 secondes plus tard, votre portail est opérationnel (à comparer à la bonne minute de démarrage d'un environnement de test dans RAD). Le port par défaut est 8080, l'adresse à taper est donc : http://localhost:8080.

Page d'accueil de Jetspeed
Les comptes système par défaut sont indiqués un peu plus bas
dans le portlet "Welcome to Jetspeed"

Installation d'Eclipse

De base, Eclipse ne supporte pas le développement d'applications J2EE/web. Pour cela, il faut installer les plugins du projet Web Tools Platform (WTP). Si vous ne disposez pas encore d'installation Eclipse, le plus simple est de télécharger un pack Eclipse + WTP tout en un. A l'heure où j'écris ces quelques lignes, le dernier pack stable en date est Eclipse 3.2.2 + WTP 1.5.3, le tout pour un peu plus de 200 Mo. Décompressez l'archive, lancez eclipse.exe, puis choisissez un nouvel espace de travail (workspace).

Maintenant, à titre didactique comme pour illustrer la configuration d'Eclipse, nous allons créer from scratch un portlet très simple qui se chargera de transformer du texte clair en l33t speak.

Configuration d'Eclipse

Il n'y a pas de type de projet "portlet" dans WTP à proprement parler, mais ce n'est pas bien dérangeant puisqu'un portlet JSR-168 est en quelques sortes une extension d'une application web traditionnelle (appelée "portlet application" dans le dialecte) ; nous allons donc pouvoir utiliser le type de projet web dynamique (dynamic web project) et y ajouter les 2 ou 3 choses requises pour en faire un vrai projet de portlet.

La présente section contient un nombre conséquent de captures d'écran qui représentent les différentes étapes de la configuration initiale d'un projet. Rassurez-vous, la vaste majorité des opérations ci-dessous consiste en la définition de l'environnement d'exécution cible (target runtime) et n'est à faire qu'une seule fois. Aux prochaines créations de projets web dynamiques, vous n'aurez qu'à choisir l'environnement d'exécution définit la première fois.

Configuration d'Eclipse : environnement d'exécution

On commence par créer un nouveau projet de type web dynamique, on indique L33tSpeakPortlet pour le nom du projet (1), puis on définit un nouvel environnement d'exécution en cliquant sur new dans le pavé target runtime (2).

Ecran de configuration du projet eclipse : nom et runtime

Choissez un environnement de type J2EE Runtime Library, qui représente un environnement J2EE standard que l'on va personnaliser par la suite.

Ecran de configuration du projet eclipse : J2EE Runtime Library

Commencez par pointer vers le répertoire d'installation de J2EE 1.3.1 que vous avez choisi (1). Pour l'aspect J2EE, c'est réglé. Reste maintenant à associer une version de Java à notre environnement d'exécution. Allons donc voir du coté des JRE installées (2).

Ecran de configuration du projet eclipse : J2EE Runtime Library

Dans les JRE installées (1), seule la JRE par défaut apparaît. Selon toutes vraissemblances, il s'agit d'une JRE 5.0 ou 6.0, celle qui en l'occurence fait tourner Jetspeed. Or, nous souhaitons ici avoir un environnement J2SE 1.4.2. On va donc ajouter une nouvelle entrée (2).

Ecran de configuration du projet eclipse : Installed JREs

En cliquant sur "parcourir" (browse), on va pointer vers le répertoire d'installation de J2SE 1.4.2. Si c'est le bon, c'est magique, tout est détecté tout seul et il n'y a rien à faire. On valide le tout.

Ecran de configuration du projet eclipse : Add JRE

Retour à l'écran des JRE installées. On peut maintenant choisir notre environnement J2SE 1.4.2. Et on valide.

Ecran de configuration du projet eclipse : Installed JREs

Retour à la configuration de l'environnement d'exécution. On choisit la JRE 1.4.2 que nous venons de définir (1), puis on attribue un nom un peu plus explicite à notre nouvel environnement (2).

Ecran de configuration du projet eclipse : J2EE Runtime Library

Retour à l'écran de création du projet web dynamique. On choisit l'environnement d'exécution que nous venons de créer (et on n'aura plus à refaire tout ça, joie), et c'est terminé, il n'y a plus qu'à valider.

Ecran de configuration du projet eclipse : New dynamic web project

Notre projet L33tSpeakPortlet tout nouveau vu au travers de la perspective J2EE : tout est déjà prêt, ou presque.

Ecran de configuration du projet eclipse : J2EE Perspective

Configuration d'Eclipse : paramètres spécifiques à chaque projet

A ce stade de la configuration, nous avons un projet web vierge pleinement opérationnel. Mais il nous manque encore quelques éléments pour en faire un projet de portlet. A commencer par la librairie Portlet-1.0 (JSR-168). Cette librairie, nous n'avons pas besoin de la fournir avec le portlet (répertoire WEB-INF/lib, exactement comme pour les applications web) puisque les conteneurs de portlets la possèdent forcément, par contre nous allons en avoir besoin dans le classpath d'Eclipse afin de pouvoir compiler les objets. Aussi, dans les propriétés du projet, on va dans la section Java Build Path, puis, histoire de faire les choses proprement, on va référencer cette librairie sous forme de variable.

Ecran de configuration du projet eclipse : Java Build Path

Ecran de configuration du projet eclipse : New Variable Classpath Entry

Ecran de configuration du projet eclipse : Classpath Variables

On ajoute une variable PORTLET_API_1.0 qui va correspondre à la librairie portlet-api-1.0.jar que l'on trouvera dans le répertoire shared/lib de Jetspeed, puis on valide toutes les boites de dialogue en cascade.

Ecran de configuration du projet eclipse : New Variable Entry : PORTLET_API_1.0

La librairie est maintenant référencée dans le projet, et sous forme de variable, ce qui permettra à des plateformes hétérogènes (dont les Jetspeed sont installés à des endroits différents par exemple) de partager bien plus facilement des sources communes (CVS, SVN, etc).
Notez qu'il n'y aura plus besoin de configurer la variable pour les projets futurs, juste de la sélectionner dans la liste.

Ecran de configuration du projet eclipse : Java Build Path

Enfin, dernière chose avant d'obtenir un projet de portlet complet : le descripteur de déploiement du portlet portlet.xml, qu'il convient de créer dans le répertoire WEB-INF/ (note : le descripteur de déploiement de l'application web web.xml a déjà été créé par l'assistant de création de projet web dynamique, et n'aura d'ailleurs pas besoin d'être modifié pour notre exemple).

Ecran de configuration du projet eclipse : New portlet.xml file

Conclusion de la première partie

Tous les éléments nécessaires pour développer et tester notre portlet sont maintenance en place. Fini les installations et la configuration, place à l'action ! Dans la seconde partie, sensiblement plus dense (moins d'images, plus de lecture), sont abordés très brièvement la spécification JSR-168, puis le code du portlet à proprement parler, pour finir sur son déploiement dans Jetspeed puis dans WPS.

Author: "YoGi" Tags: "WebSphere Portal"
Send by mail Print  Save  Delicious 
Next page
» You can also retrieve older items : Read
» © All content and copyrights belong to their respective authors.«
» © FeedShow - Online RSS Feeds Reader