La Feuille d’Olivier

Aller au contenu | Aller au menu | Aller à la recherche

dimanche, juillet 17 2011

Installation de l'imprimante Brother DCP-7030

J'ai fait l'acquisition il y a quelque chose comme deux ans d'une imprimante Brother DCP-7030 qui répondait à mes différents critères:

  • Imprimante laser pour un coût supposé réduit sur le long terme
  • Imprimante monochrome, là aussi pour réduire les coûts et éviter la politique scandaleuse des cartouches de couleur. Pour mes principaux cas d'utilisation (documents administratifs, contre-marques, photocopies, impressions de plans), la couleur n'était pas nécessaire
  • Fonction scanner pour numériser des documents, permettre d'avoir un simili-fax à la maison et surtout avoir une photocopieuse à portée de main
  • Constructeur supportant Linux et, bonus, proposant des pilotes libres

Las! Si l'imprimante donne globalement satisfaction, l'installation s'est révélée une petite galère, avec installation de paquets extérieurs et opérations manuelles préliminaires. Ayant récemment du réinstaller le tout, il a fallu retrouver la procédure et la ré-exécuter. Pour les générations futures, voici la procédure à suivre:

  • Télécharger les paquets .deb adaptés sur le site de Brother: le driver LPR et le wrapper cups
  • Préalablement à l'installation, créer le répertoire /usr/share/cups/model (le paquet suppose, à tort, que ce répertoire existe) avec la commande:
olemerdy@lafeuille:~$ sudo mkdir /usr/share/cups/model
  • Passer cupsd en mode scrogneugneu à l'aide de la commande:
olemerdy@lafeuille:~$ sudo aa-complain cupsd
  • Installer le paquet apt://brdcp7030lpr à partir du fichier brdcp7030lpr-2.0.2-1.i386.deb en utilisant GDebi ou tout autre outil du même acabit
  • Installer le paquet apt://cupswrapperdcp7030 à partir du fichier cupswrapperDCP7030-2.0.2-1.i386.deb à l'aide de la ligne de commande:
olemerdy@lafeuille:~$ sudo dpkg -i –force-all –force-architecture cupswrapperDCP7030-2.0.2-1.i386.deb
  • Vérifier que le fichier /usr/share/cups/model/DCP7030.ppd est désormais présent.

Il est temps de brancher l'imprimante (modèle USB) qui est alors détectée, sans qu'aucun pilote ne puisse être automatiquement sélectionné. Choisissez alors l'option Choisir un fichier PPD et sélectionner le fichier désigné précédemment. Plus qu'à nommer l'imprimante et voilà! Une impression de test et un débourrage papier manuel plus tard, tout fonctionne bien au niveau de l'impression, ouf!

On verra plus tard pour la fonction scanner, à chaque nuit suffit sa peine :)

Sources:

vendredi, novembre 12 2010

Privilégier les paquets de la distribution Linux principale lorsqu'un dépôt tiers est activé

Gestionnaires de paquets et dépôts tiers

Les systèmes de paquets en général, et ceux des distributions Linux en particulier sont une chose formidable. Encourageant le découpage en modules avec une architecture de dépendances (obligatoires ou recommandées) claire, ils ont nombre de bénéfices, parmi lesquels:

  • l'uniformisation de l'installation (configuration/binaires/données, scripts de pré/post-installation)
  • la limitation de l'espace utilisé par réutilisation de bibliothèques logicielles communes
  • signalisation des nouveaux paquets disponibles, des mises à jour dans un processus unifié

La force et la faiblesse de ce système sont que l'utilisateur est a priori limité à ce que le mainteneur d'un dépôt de paquets a souhaité intégrer ou non, et dans quelle version. A priori seulement car, contrairement au système d’App Store qui fleurissent à présent (iPhone, Android et basiquement tous les acteurs s'y mettent tant le modèle doit être rentable), les systèmes de paquetages Linux autorisent l'ajout de dépôts tiers (voire la mise en place d'un dépôt personnel) qui proposent de nouveaux paquets (de nouvelles applications) ou des versions différentes de paquets existants.

Si certains dépôts comme celui de Wine proposent des mises à jour d'un ensemble de paquets bien identifiés (l'implémentation de Windows pour Unix wine en l'occurrence), d'autres proposent des groupes d'applications nouvelles comme celui de Medibuntu tandis que d'autres proposent les deux en même temps.

Et c'est là où le bât blesse! Si je peux accepter (ou plutôt chercher à ce) qu'un paquet particulier passe dans une version supérieure et si je peux certainement chercher à pouvoir installer et administrer simplement de nouvelles applications, je n'ai a priori pas envie, en cherchant à avoir ce second effet (de nouvelles applications), que des bibliothèques de base soient automatiquement mises à jour vers des versions non supportées ou instables simplement parce qu'elles sont présentes dans ce nouveau dépôt avec un numéro de version supérieure.

C'est par exemple le cas des célèbres dépôts GetDeb (applications générales) et PlayDeb (jeux) qui proposent d'alléchantes nouvelles applications (comme AstroMenace) tout en proposant des versions plus récentes de Gimp que je préférerais éviter d'installer par défaut.

Suis-je donc condamné à ne pas utiliser ces dépôts, installer les paquets des nouvelles applications et les mettre à jour manuellement comme le premier utilisateur de MS Windows venu?

Outillage graphique dans Synaptic

Je suis comme vous, j'ai horreur de me compliquer la vie et j'apprécie quand les choses marchent comme je le souhaite de manière simple. Je lance donc Synaptic Package Manager pour tenter d'y trouver le paramétrage magique. En farfouillant dans les options, on trouve deux moyens différents de modifier les versions installés

Distribution préférentielle

La première peut être trouvée dans Configuration > Préférences > Distribution et permet de préciser la stratégie de mise à jour des paquets en privilégiant au choix:

  • La version la plus élevée (comportement par défaut)
  • La version déjà installée (c'est-à-dire qu'aucune mise à jour, y compris de sécurité, ne sera installée sans action spécifique de l'utilisateur)
  • La version provenant d'un nom de distribution particulier

Synaptic -> Préférences de distribution

Las! Si cette dernière option semble pouvoir résoudre notre problème, il n'en n'est rien. En effet, par défaut, vous aurez trois noms de distribution par défaut. Pour Ubuntu Maverick, il s'agira de maverick (distribution de base), de maverick-security (correctifs de sécurité, très important), de maverick-updates (mises à jour recommandées mais non critiques) voire maverick-backports si vous l'activez (reports de paquets prévus pour la version majeure suivante). Or, vous ne pouvez mettre qu'un seul nom de distribution dans le champ:

  • Si vous utilisez maverick, les mises à jour de sécurité ne seront plus prioritaires
  • Si vous utilisez maverick-security et qu'un paquet présent dans votre dépôt Getdeb (au hasard, gimp) n'a pas de mise à jour de sécurité, celui de Getdeb sera toujours prioritaire sur celui de la distribution principale. Grogne.

Bloquer/forcer la version d'un paquet

Un autre moyen de modifier la stratégie de mise à jour par défaut est d'utiliser le menu Paquet

  • Bloquer la version bloque toute mise à jour ultérieure du paquet
  • Forcer la version... permet de sélectionner (lorsqu'il y a plusieurs versions disponibles) celle que l'on veut privilégier

Synaptic -> Forcer la version

C'est ce dernier comportement que l'on aimerait avoir de manière globale... mais ce n'est pas exactement ce que j'appelle une solution facile. Il reste néanmoins intéressant de savoir comment surcharger localement un comportement de paquet.

Synaptic ne nous est donc d'aucune aide. Mais comment faire?

Sauvé par la ligne de commandes... une fois de plus

En fouillant de droite et de gauche, on finit tout de même par se rendre compte que le système APT comprend des possibilités de configuration plus souples grâce au système de Pinning. Il permet grâce à une syntaxe relativement simple de remplir notre besoin. En effet, à la lecture de la page de manuel de apt_preferences

olemerdy@lafeuille:~$ man apt_preferences

on se rend compte que ce que l'on souhaite réaliser peut-être fait avec les trois lignes suivantes:

Package: *
Pin: release a=maverick-getdeb
Pin-Priority: 100

  • Package: * signifie que la règle que l'on écrit va impacter tous les paquets (il est possible d'écrire des règles spécifiques à des patterns de noms de paquets)
  • Pin: release a=maverick-getdeb signifie que la règle s'appliquera aux release dont l’archive name est maverick-getdeb (il eut été possible alternativement de choisir un Pin: origin archive.getdeb.net pour discriminer en fonction de l'origine physique des paquets)
  • Pin-Priority: 100 signifie que l'on ne proposera l'installation de ce paquet que s'il n'est pas installé et qu'il n'existe pas de version dans une autre distribution. Les autres niveaux de priorité sont explicités dans la page man

Formidable! C'est exactement ce que nous cherchions. La fin du calvaire?

Bug de prise en charge du /etc/preferences.d

Presque :) En effet, à la lecture de la même page man, il apparait que l'on peut choisir entre placer cette configuration dans le fichier /etc/apt/preferences ou dans un fichier arbitraire dans le répertoire /etc/apt/preferences.d pourvu que ce fichier n'ait pas d'extension ou bien l'extension .pref. Adepte des configurations modulaires, je m'empresse d'adopter cette seconde solution. Erreur!

En effet, après de longs tests, les mises à jour de Getdeb sont toujours proposées dans Synaptic et aptitude, alors qu'elles ne le sont pas dans apt-get ni dans le Gestionnaire de mises à jour. Les comportement inconsistants n'étant pas une solution cible rêvée, nous voilà repartis pour un peu plus de lecture.

Au détour d'un forum, on s'aperçoit en effet que certaines applications ne supportent pas la configuration via le répertoire /etc/apt/preferences.d. Rapatrions simplement le contenu de notre fichier dans /etc/apt/preferences et enfin tout rentre en ordre et fonctionne comme attendu. Hourra!

Seuls les nouveaux paquets des dépôts Getdeb sont proposés à l'installation même s'il est toujours possible de forcer la version paquet par paquet grâce à la manipulation décrite plus haut.

Tout travail mérite salaire

On ne le dira jamais assez, prenez le contrôle de vos outils! Il n'y a aucun problème avec un peu de magie technique à partir du moment où on comprend comment elle fonctionne. Toutefois, après tous ces efforts et l'obtention d'une solution simple et élégante en trois lignes, il est temps d'obtenir notre récompense et de découvrir tous ces belles applications.

Du côté du dépôt Getdeb:

  • ArgoUML, un modeleur UML libre bien connu (je l'utilisais en stage de fin d'études...) quoi qu'assez moche avec le LookAndFeel Swing de base
  • Gnome Connection Manager, un gestionnaire de connexions SSH plutôt puissant, permettant la création de groupes, de clusters, de tunnels imbriqués et allant donc encore plus loin que Terminal Server Client ou mRemote sous MS Windows
  • ubuntu-tweak, un outil permettant de personnaliser Ubuntu en permettant un accès facile à de multiples réglages plus ou moins cachés.

Du côté du dépôt Playdeb:

  • 0ad, un jeu de stratégie libre très proche dans son fonctionnement de Age of Empires, très prometteur
  • AstroMenace, un jeu de shoot en 3D, gratuit sous Linux, plutôt sympa
  • BloodFrontier, un FPS à la carrière hélas terminée avant l'heure
  • caph, un petit jeu demandant la résolution de puzzles en se basant sur un moteur physique réaliste
  • enemy-territory, le FPS multijoueur à succès d'id Software
  • eternallands, un Morpeug... Meuporg... MMORPG gratuit en 3D
  • goonies, un remake récent à l'occasion du 20ème anniversaire du jeu tiré du film de Spielberg
  • l-echo, un jeu de puzzle lorgnant du côté d'echochrome
  • lugaru, un jeu d'action en 3D récemment devenu libre sur les aventures d'un lapin-garou expert en kung-fu, à base de contrôles intuitifs
  • megaglest, un fork du RTS libre ayant pour modèle Warcraft III
  • openalchemist, un Tetris-like comme on en voit beaucoup sur téléphone et consoles portables
  • opensonic, un remake bluffant des premiers Sonic, particulièrement impressionnant lorsque l'on sait qu'il a été réalisé par deux personnes par rapport aux dizaines ou centaines qu'a nécessité Sonic 4 Episode 1 pour un résultat moins convainquant
  • scourge, un hack'n slash avec des airs de Diablo 2
  • speed-dreams, un simulateur de course automobile plutôt joli
  • tileracer, un jeu de courses arcade très proche de TrackMania avec de jolis effets d'accélération
  • ufoai, un jeu de gestion/stratégie en 3D directement inspiré du génial X-Com: Enemy Unknown
  • urbanterror, un clone de Counter-Strike issu d'un mod de Quake III
  • vdrift, un jeu de simulation de course automobile libre
  • worldofpadman, un FPS issu d'un mode pour Quake III sur les batailles entre de petits êtres dans nos cuisines ou salles de bain

À boire et à manger donc!

Sources

mercredi, septembre 15 2010

Éviter le vol de focus avec Compiz

Cela vous est certainement arrivé quelques fois: à l'allumage de votre ordinateur personnel, vous êtes pris d'une frénésie de lancement de programmes: navigateur, client mail (pour les quelques résistants qui en utilisent comme moi ;)), messagerie instantanée, lecteur de musique, terminal... (rayez les mentions inutiles). Soudain, alors que vous saisissez votre mot de passe principal dans votre navigateur, votre client mail vous jette une interface de saisie pour son propre mot de passe à la figure, interrompant votre saisie précédente (voire, emporté par votre élan, vous avez saisi la moitié du mot de passe du navigateur dans le nouveau champ). Je ne parle même pas des cas où, faute d'avoir regardé, vous remplacez un mot de passe enregistré par celui que vous pensiez saisir dans une autre fenêtre.

Ce phénomène pour le moins horripilant porte le joli nom de vol de focus.

Notons que cela s'applique à d'autres cas que la saisie de mot de passe: vous êtes en train de lire une vidéo de courte durée quand vous vous rappelez qu'il vous faut écrire un message. Vous lancez un client mail en arrière plan pour que tout soit prêt à la fin de votre vidéo dans deux minutes et, boum, la fenêtre de votre client tout juste lancé se place en avant-plan, voire vous jette une invite de saisie, obstruant la vidéo qui continue de se jouer derrière.

Heureusement, il existe des solutions dans certains cas. Le salut est venu de cet article sur Think Underground pour les utilisateurs de Compiz. Il convient, pour plus de facilités d'utiliser le Gestionnaire de Configuration CompizConfig (sous Gnome, accès dans Systèmes > Préférences).

En cliquant sur Options Générales puis en choisissant l'onglet Comportement de la prise de focus & de l'augmentation, on obtient l'écran suivant:

Capture-Gestionnaire_de_Configuration_CompizConfig.png

Il convient alors de régler le Niveau de sensibilité du focus à une valeur élevée (par défaut, elle est réglée à Faible). Et voilà!

Ordinateur professionnel oblige, si quelqu'un connaît une solution au vol de focus pour Windows (XP et supérieurs), je lui serai très reconnaissant de partager ses connaissances!

mercredi, décembre 16 2009

Développer avec JavaEE 6 et Maven mi-décembre 2009

JavaEE 6 est sorti en version finale il y a quelques jours à peine et la liste des améliorations est fort longue et impressionnante. Nous allons enfin pouvoir nous amuser avec les EJBs asynchrones, faire de l'injection de dépendances, de la validation, le tout de façon standard et portable (!) et sans embarquer les 200 jars comme on le voit tous les jours (une application à 500 Ko plutôt que 200 Mo, ça tente quelqu'un). Ou tout du moins nous rendre compte par nous-mêmes si ces belles promesses sont tenues.

Grand utilisateur de Maven2 qui, malgré ses évidentes faiblesses, s'avère tout de même extrêmement pratique pour prototyper / construire et déployer rapidement une application, je me demandais s'il était possible d'utiliser les APIs JavaEE 6 dans une application gérée par Maven. Cela nécessitait d'avoir les Jars à disposition dans un dépôt.

Et bien c'est le cas!

Il convient tout d'abord d'ajouter dans votre pom parent ou votre miroir Maven le dépôt Sun officiel:

<repositories>
  ...
  <repository>
    <id>maven2-repository.dev.java.net</id>
    <url>http://download.java.net/maven/2</url>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
  ...
</repositories>

Puis d'importer les dépendances suivantes (au choix suivant votre projet):

<properties>
  ...
  <javax.javaee.version>6.0</javax.javaee.version>
  ...
</properties>
...
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>javax</groupId>
	  <artifactId>javaee-api</artifactId>
	  <version>${javax.javaee.version}</version>
	  <scope>provided</scope>
    </dependency>
	<dependency>
      <groupId>javax</groupId>
	  <artifactId>javaee-endorsed-api</artifactId>
	  <version>${javax.javaee.version}</version>
	  <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
	  <artifactId>javaee-web-api</artifactId>
	  <version>${javax.javaee.version}</version>
	  <scope>provided</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

La première correspond au Profile Full, la troisième au Profile Web et la deuxième... je l'ignore (à tester). Notez que ces dépendances ne proposent que les Jars compilés, espérons que les sources arrivent prochainement pour disposer de l'assistance usuelle dans votre IDE préféré.

Dans ma lettre au Père Noël numérique de cette année, je me permets d'ajouter en hâte:

  • Lesdites sources
  • Une inclusion dans les dépôts principaux de Maven
  • Une dépendance des projets tiers (Hibernate, bibliothèques JSF) pour compilation
  • La sortie de quelques bibliothèques JSF adaptée à JSF2 (la distribution de base manquant cruellement de composant)
  • Un serveur d'applications embeddable proposant a minima le profil Web (Jetty 8?) afin de pouvoir comme aujourd'hui déployer rapidement une application d'un > mvn jetty:run
  • La mise à disposition dans les dépôts Maven de Spring 3.0 qui sort ce jour et compatible avec les APIs JavaEE 6

Allez hop, je me lance dans le grand chantier de migration de toutes mes application Samples, il y a du pain sur la planche. Codez bien!

mardi, octobre 21 2008

Mettre Apache 2 en Reverse Proxy devant Tomcat

Mise en condition

Les sites et applications Web à travers HTTP sont désormais, à tort ou à raison, une part essentielle voire prépondérante de notre écosystème informatique. Une application ou un site complexe peut fort bien se composer d'un ensemble d'applications utilisant différentes technologies:

  • Une application PHP tournant sur un serveur Apache avec le mode PHP activé
  • Des scripts CGI servis par un serveur Lighttpd
  • Une application Web Java empaquetée sous forme de fichier .war et déployée sur Tomcat
  • Une application JavaEE empaquetée sous forme de fichier .ear et déployée sur Glassfish
  • Une application .NET déployée sur IIS
  • Une application individuelle embarquant son propre serveur HTTP, telle Nexus

Chacune de ces application peut donc être accédée par un serveur HTTP différent. Qui dit serveur différent dit port différent et l'on aboutit bien vite à proposer à l'utilisateur final un ensemble d'URLs contenant lesdits ports (8080, 8081, 8180, 9080...). Cela pose un certain nombre de problèmes:

  • L'utilisateur n'est pas habitué à devoir indiquer le port dans ses URLs, le port HTTP par défaut 80 étant utilisé dans l'immense majorité des cas
  • Présenter un port par serveur expose inutilement l'architecture interne de l'application et de l'infrastructure, ainsi que les éventuelles technologies utilisées
  • Présenter de multiples ports nécessite d'ouvrir autant d'accès vers l'extérieur du réseau dans les pare-feu

Une des solutions à ce problème consiste à mettre en place un reverse proxy.

Cas d'utilisation

Nous allons dans cet exemple mettre en place un exemple simple exposant une application Web déployée sur un serveur Tomcat à travers un frontal Apache. Cet exemple est dès alors généralisable et extensible à d'autres serveurs.

Pas à pas

La première étape consiste à installer Apache 2, Tomcat et les applications d'exemple pour ce dernier.

olemerdy@lafeuille:~$ sudo aptitude install apache2 tomcat55 tomcat55-webapps

Vérifions à présent que les serveurs ont bien été installés en ouvrant votre navigateur favori sur:

À présent, il vous faut vous assurer que le mod_proxy et son rejeton, le mod_proxy_ajp sont bien activés. Pour cela, tapouillez dans votre terminal favori:

olemerdy@lafeuille:~$ sudo a2enmod proxy_ajp
  Enabling proxy as a dependency
  Module proxy_ajp installed; run /etc/init.d/apache2 force-reload to enable.
olemerdy@lafeuille:~$ sudo /etc/init.d/apache2 force-reload

Afin de valider la bonne activation du module, vérifiez que les liens symboliques /etc/apache2/mods-enabled/proxy.load, /etc/apache2/mods-enabled/proxy_ajp.load et /etc/apache2/mods-enabled/proxy.conf ont bien été créés.

Nous allons à présent personnaliser la configuration du module proxy:

olemerdy@lafeuille:~$ sudo nano /etc/apache2/mods-enabled/proxy.conf

Le fichier devrait à présent ressembler à cela:

<IfModule mod_proxy.c>

  # ProxyRequests reste à Off en mode reverse proxy
  ProxyRequests Off

  <Proxy *>
    AddDefaultCharset off
    Order deny,allow
    # Allow from all est autorisable en mode reverse proxy
    Allow from all
  </Proxy>

  # On restreint le proxy à une seule application
  <Location /jsp-examples>
    ProxyPass ajp://192.168.x.xx:8009/jsp-examples
    ProxyPassReverse ajp://192.168.x.xx:8009/jsp-examples
  </Location>

  ProxyVia On
</IfModule>

Et c'est tout! Redémarrez Apache d'un bien senti:

olemerdy@lafeuille:~$ sudo /etc/init.d/apache2 restart

C'est le moment de vérité; ouvrez votre butineur favori sur la page prévue pour la redirection. Merveille des merveilles, apparait sous vos yeux la page déjà vue précédemment.

Passage en mode balancer

La répartition de charge entre de multiples instances exige d'abord d'activer le mod_proxy_balancer d'une simple ligne de commande:

olemerdy@lafeuille:~$ sudo a2enmod proxy_balancer
  Enabling proxy as a dependency
  Module proxy_balancer installed; run /etc/init.d/apache2 force-reload to enable.
olemerdy@lafeuille:~$ sudo /etc/init.d/apache2 force-reload
<IfModule mod_proxy.c>
  ProxyRequests Off

  <Proxy *>
    AddDefaultCharset off
    Order deny,allow
    Allow from all
  </Proxy>

  <Proxy balancer://tomcat>
    BalancerMember ajp://192.168.x.xx:8009
    BalancerMember ajp://192.168.y.yy:8009
  </Proxy>

  <Location /jsp-examples>
    ProxyPass balancer://tomcat/jsp-examples stickysession=JSESSIONID|jsessionid
  </Location>

  ProxyVia On
</IfModule>

Conclusion

Nous avons vu dans cet article comment mettre en place une redirection simple du serveur HTTP d'Apache vers un serveur d'application compatible avec la norme AJP. Dans de futures évolutions de cet article, nous aborderons une personnalisation plus poussée de la redirection ainsi que des exemples de redirection HTTP.

vendredi, juillet 4 2008

Bases de données embarquées en Java

Les aventuriers de la base de données perdue

Dans le cadre d'un projet PoC utilisant, entre autres, les frameworks Spring et Hibernate, je me suis récemment penché sur le problème de la base de données. Le projet obéissait aux règles suivantes:

  • Le projet devait être extrêmement simple à déployer pour n'importe quel développeur ou testeur; une fois les sources récupérées du gestionnaire de version, un simple mvn jetty:run devait permettre de compiler et lancer une application complètement configurée.
  • Les données (au sens large) à stocker incluaient aussi bien du texte (noms d'utilisateur...) que des données binaires (fichiers image). Désireux de limiter les méthodes de stockage de données, je souhaitais également tester le stockage de données binaires en base, pratique que j'ai souvent entendu conspuer,
  • Afin de limiter au maximum la redondance d'informations et rendre plus aisée le processus de développement ainsi que celui de déploiement, je souhaitais également automatiser la création du schéma de base de données en utilisant les outils idoines (le générateur DDL d'Hibernate ici).
  • La configuration de la base de données se devait d'être d'intégration aisée avec les frameworks retenus.

Le driver SQL maudit

La première contrainte m'a amené à me pencher sur les bases de données embarquées en Java. En effet, la configuration se résume alors plus ou moins à fournir une classe de Driver et une URL de connexion (voir ci-après). J'ai successivement identifié trois bases embarquées:

  • HSQLDB, utilisée pour les tests unitaires dans certains des projets auxquels j'ai participé. Suffisante dans un premier temps, j'ai du m'en détourner du fait des limitations en taille des fichiers stockables (probablement dues au fait que les données sont entièrement chargées en mémoire), a priori d'environ 4ko par Blob. Des versions ultérieures (la 1.9.0) viendront peut-être améliorer les choses.
  • Derby de la fondation Apache, également embarquée par défaut dans Glassfish en tant que JavaDB. Autorisant le stockage de fichiers plus conséquents en utilisant le disque dur, cette base a du cependant être rapidement remplacée en raison d'un bug Hibernate/Derby dans la génération de schémas pour lequel les deux projets se renvoient la balle l'un à l'autre. Plutôt que de passer trop de temps à essayer de régler le problème ou de sacrifier de la souplesse dans la configuration du projet, j'ai préféré passer à:
  • H2 qui semble particulièrement intéressante à la lecture de la documentation (assez fournie au demeurant). La configuration est simple, les comparatifs (à prendre avec des pincettes) élogieux et les fonctionnalités au rendez-vous. De plus, les problèmes rencontrés avec le couple Hibernate/Derby ne se produisent pas ici.

La dernière configuration

Pour terminer cet article, voici un exemple de configuration de Spring avec Hibernate comme framework de persistence et H2 comme base de données embarquée. Le fichier de configuration Spring, ici /WEB-INF/applicationContext.xml, pourrait contenir les lignes suivantes:

<?xml version="1.0" encoding="UTF-8"?>
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:util="http://www.springframework.org/schema/util"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
    
  <!-- General properties -->
  <context:property-placeholder
    location="/WEB-INF/applicationContext.properties" />   
  <util:properties
    id="jpaProperties"
    location="classpath:META-INF/hibernate.properties" />
		
  <!-- Data -->
  <bean
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"
    id="dataSource"
    p:driverClassName="${jdbc.driverClassName}"
    p:url="${jdbc.url}"
    p:username="${jdbc.username}"
    p:password="${jdbc.password}" />
  <bean
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    id="entityManagerFactory"
    p:dataSource-ref="dataSource"
    p:jpaProperties-ref="jpaProperties"
    p:jpaVendorAdapter-ref="jpaVendorAdapter" />
  <bean
    class="org.springframework.orm.jpa.JpaTransactionManager"
    id="transactionManager"
    p:entityManagerFactory-ref="entityManagerFactory" />
  <bean
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    id="jpaVendorAdapter" />
  <bean
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
  <tx:annotation-driven />

</beans>

Avec le fichier de propriété /WEB-INF/applicationContext.properties contenant les clés suivantes:

jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:~/database/my-project
jdbc.username=sa
jdbc.password=sa

Et le fichier de propriétés META-INF/hibernate.properties contenant les clés suivantes:

hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=update

Conclusion

Les bases de données embarquées, en plus de fournir des commodités pour les tests unitaires et les prototypes, permettent également la réalisation de clients Java embarquant leur propre système de persistence. On peut même facilement imaginer un système d'ApplicationClient java fonctionnant en modes connecté et déconnecté, maintenant une base de données côté client et synchronisant régulièrement ses données avec une base de données partagée côté serveur (exemple: une bibliothèque musicale). L'objet d'un futur article?

lundi, mars 24 2008

Utiliser les capacités JPA/JTA de votre serveur d'applications à travers Spring

Contextualisons!

Le framework Spring connaît depuis plusieurs années un succès, à mon humble avis, mérité en mettant en avant les notions de conteneur et d'inversion de contrôle. Mais Spring se veut également un aggrégateur de nombreux frameworks externes en proposant facilités d'utilisation et homogénéité d'intégration. Si je reste sceptique des manière générale vis-à-vis des frameworks encapsulant des frameworks (l'objet d'un futur billet?), la redondance de certaines possibilités avec la norme Java Enterprise Edition (JavaEE 5 pour les intimes) est ici encore plus flagrante.

Je réalise actuellement une application d'exemple intégrant Java EE 5 et certains de ses frameworks principaux (JSF, JPA pour ne citer qu'eux) avec des frameworks externes tels que:

  • Spring apportant une très grande richesse dans la construction de l'application (n'importe quel type de ressource peut être injecté dans les entités gérées par le conteneur)
  • AspectJ, et plus spécialement son intégration à travers Spring, pour la programmation par aspects
  • Facelets pour les gabarits d'affichage et une alternative aux classiques JSPs

Une des possibilités intéressantes de cette combinaison de technologies est de pouvoir créer des Managed Beans JSF via Spring en ne configurant quasiment rien dans les fichiers faces-config (car les Managed Beans sont résolus via un SpringBeanFacesELResolver) et applicationContext (car Spring 2.5 permet de se reposer quasiment uniquement sur les annotations).

Une des contraintes de ce projet est la portabilité entre serveurs JavaEE 5 en exploitant au maximum les capacités de la norme. Le corollaire est que nous souhaitons reposer au maximum sur lesdites APIs. Malheureusement, ce qui n'aurait dû être qu'une formalité s'est révélé assez difficile.

Le problème et sa solution

Le problème rencontré vient du fait que nous créons les Managed Beans via Spring. Dans le cadre de cette application simple, les Managed Beans connaissent directement les DAOs (pas de couche façade entre les deux) également créés par Spring, qui doivent recevoir une EntityManagerFactory du conteneur. Dans une application JavaEE 5 pure, il suffit d'annoter le champ qui nous convient avec @PersistenceContext ou @PersistenceUnit pour recevoir l'objet JPA qui convient. Ici, nous avons substitué au conteneur JavaEE le conteneur Spring et nous souhaitons donc que Spring délègue directement la gestion au conteneur JavaEE.

La documentation officielle, excellente au demeurant, n'est pas très claire quant à la marche à suivre pour obtenir un environnement complètement fonctionnel. En effet, dans le cas de délégation pure et simple, il est indiqué d'utiliser la résolution JNDI mais sans véritablement être pertinente quand au nom cible. Les exemples fournis ne sont pas forcément plus utiles pour notre cas.

Le salut est venu d'un article consacré aux EJB3 et à Spring qui détaille la mécanique à mettre en place. Elle se décompose en trois étapes:

  • Déclarer notre unité de persistance dans le fichier persistence.xml
<persistence
  version="1.0"
  xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit
    name="springfaceletstest"
    transaction-type="JTA">
    [...]
  </persistence-unit>
</persistence>
  • Donner un nom JNDI à cette unité de persistance dans le descripteur de déploiement web.xml
<web-app
  version="2.5"
  xmlns="http://java.sun.com/xml/ns/javaee"
  [...]
  <persistence-unit-ref>
    <persistence-unit-ref-name>persistence/springfaceletstest</persistence-unit-ref-name>
    <persistence-unit-name>springfaceletstest</persistence-unit-name>
  </persistence-unit-ref>
  [...]
</web-app>
  • Résoudre cette unité de persistance au sein du fichier de configuration Spring applicationContext.xml
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xmlns:tx="http://www.springframework.org/schema/tx">
  [...]
  <jee:jndi-lookup
    id="entityManagerFactory"
    jndi-name="java:comp/env/persistence/springfaceletstest" />
  <tx:annotation-driven />
  <tx:jta-transaction-manager />
  [...]
</beans>

Notez que les deux dernières annotations permettent, pour la première, de se baser sur les annotations pour déclarer les méthodes transactionnelles et, pour la deuxième, de déclarer simplement un objet transactionManager utilisant JTA.

Et voilà, c'est magique, tout fonctionne correctement! Dans un prochain article, la présentation plus complète de l'intégration JSF/Facelets/Spring.

PS: En écrivant cet article, je viens de m'apercevoir que Spring 2.5.2 était sorti. À tester!

mercredi, janvier 9 2008

Créer votre certificat pour vos serveurs sous Ubuntu

Les notions de sécurité, de signature et de confiance numériques sont des principes qui vivent avec l'industrie informatique depuis des dizaines d'années déjà sans toutefois trouver l'écho large qu'elles méritent. Il est probable toutefois que l'aspiration grandissante des particuliers à plus de confidentialité quant au contenu de leurs échanges peut amener à une demande accrue envers les fournisseurs de service de moyens techniques permettant de la préserver.

Notion de chaîne de confiance numérique

TODO ;)

Étape préalable de génération de la clé et de la requête de création de certificat

La toute première étape de notre périple va être la génération de la clé privée de votre serveur. Comme son nom l'indique, cette clé est *privée* et ne devra jamais, en aucune occasion, être communiquée à quelque tiers que ce soit. Après s'être assuré que le paquet openssl est bien installée, ouvrons notre terminal préféré et tapouillons:

olemerdy@lafeuille:~$ cd /etc/ssl
olemerdy@lafeuille:/etc/ssl$ sudo openssl genrsa -out server.key 1024

L'algorithme ici choisi est RSA dont je me souviens avec émotion de la démonstration de fonctionnement en classe préparatoire, et la taille de clé est de 2048 bits, un format imposé par l'autorité de certification retenue.

Attention! Sitôt générée, sitôt protégée! Il est extrêmement important de limiter l'accès de cette clé au superutilisateur root seul en changeant ses droits d'accès à l'aide de la commande chmod, que nous utiliserons en mode octal pour changer:

olemerdy@lafeuille:/etc/ssl$ sudo chmod 400 server.key

Ouf, ça va mieux. Il est désormais temps de générer une requête de création de certificat. C'est cette requête que vous transmettrez par la suite à l'autorité de certification afin qu'elle l'utilise et génère le certificat final associé. Allons-y donc:

olemerdy@lafeuille:/etc/ssl$ sudo openssl req -new -key server.key -out server.csr

S'en suit un questionnaire vous permettant de renseigner un certain nombre d'informations qui figureront dans le certificat final. Dans notre cas particulier, cela n'a guère d'importance dans la mesure où l'autorité de certification choisie surcharge toutes ces valeurs. En fonction de votre propre choix, ces informations peuvent ou non servir. La plus critique est celle concernant le nom de domaine protégé qui doit absolument correspondre à celui pour lequel vous utiliserez le certificat. Exemples de réponse aux questions:

Country Name (2 letter code) [AU]:fr
State or Province Name (full name) [Some-State]:France
Locality Name (eg, city) []:Paris
Organization Name (eg, company) [Internet Widgits Pty Ltd]:LaFeuille.org
Organizational Unit Name (eg, section) []:LaFeuille.org
Common Name (eg, YOUR name) []:lafeuille.org
Email Address []:admin@lafeuille.org

Vous disposez de tous les éléments nécessaires, il est désormais temps de trouver un fournisseur externe.

Création du certificat avec StartSSL

L'autorité de certification que j'ai retenue est StartCom, une autorité qui a le bon goût de permettre la création de certificats de niveau 1 gratuits, tout en étant une autorité racine pour au moins Firefox et les systèmes Linux que j'ai pu tester, permettant ainsi une utilisation transparente du service pour l'utilisateur lambda. Il en existe quelques autres, comme CACert.org que je n'ai pas encore eu le loisir de tester.

Création du compte d'accès

La première étape consiste à obtenir un accès au site. En effet, StartCom a fait le choix (compréhensible étant donné son métier et que j'apprécie personnellement) de ne proposer qu'une authentification par certificat. Il convient donc de passer tout d'abord par le wizard de création:

StartSSL create account

Une fois votre certificat personnel obtenu, il ne vous reste plus qu'à cliquer sur Authenticate et à sélectionner votre certificat.

Validation du domaine

Il convient à présent de valider le domaine pour lequel vous souhaitez créer un certificat.

Dans l'onglet Validation Wizard, choisissez l'option Domain Name Validation

startssl-3-validate-domain-1.png

Entrons ensuite le nom de votre domaine à valider, le top-domain level étant à sélectionner dans une loooooooongue select box (le clavier sera notre meilleur ami).

startssl-3-validate-domain-2.png

Sur l'écran suivant, nous voyons une liste d'adresses mail apparaître dont certaines, magie, sont les nôtres, ou plus exactement celles qui sont obtenues en faisant un whois sur le nom de domaine. Sélectionnons celle où nous souhaitez recevoir notre courriel de validation.

startssl-3-validate-domain-3.png

Quelques secondes plus tard, nous recevons le courriel en question avec le code de confirmation à rentrer dans le champ de la page idoine.

startssl-3-validate-domain-4.png

Ça y est, notre domaine est validé pour une durée de 30 jours. Enchaînons immédiatement avec la création du certificat à proprement parler.

Création du certificat

Dans l'onglet Certificates Wizard, sélectionnons Web Server SSL/TLS Certificate:

startssl-2-create-cert-1.png

L'étape suivante n'est pas nécessaire dans la mesure où nous avons déjà généré clé privée et demande de certificat. Cliquons donc sur Skip:

startssl-2-create-cert-2.png

Dans le champ suivant, il convient simplement de copier/coller le contenu de notre fichier /etc/ssl/server.csr:

startssl-2-create-cert-3.png

Et voilà! Le certificat est généré. Copions le contenu affiché dans la zone de texte et collons-le dans le fichier justement intitulé /etc/ssl/server.crt

Notez que peu après la délivrance de ce certificat, StartCom viendra naviguer sur votre site pour s'assurer que le certificat a été correctement installé. Vous recevrez un mail indiquant que tout est correctement en place. C'est le second niveau de contrôle réalisé par StartCom. Mais pour que cela fonctionne, il faut déjà s'assurer d'avoir installer correctement ledit certificat.

Installation du certificat

Dernière étape, l'installation des certificats serveur StartSSL qui viendront en complément de votre propre certificat serveur afin de valider l'ensemble de la chaîne de certification. Vous pouvez le récupérer à l'adresse suivante ou simplement en le téléchargeant depuis votre terminal:

olemerdy@lafeuille:/etc/ssl$ sudo wget http://www.startssl.com/certs/sub.class1.server.ca.crt

Configuration d'Apache

Nous y sommes presque. Il reste à configurer Apache pour qu'il utilise ces certificats nouvellement créés. Il convient d'éditer le fichier du site que vous souhaitez configurer dans /etc/apache2/sites-available:

olemerdy@lafeuille:/etc/apache2/sites-available$ sudo nano 001-lafeuille.org

Et de s'insérer dans le VirtualHost consacré à la connexion sur le port 443 (port par défaut HTTPS):

<VirtualHost *:443>

        SSLEngine On
        SSLCertificateFile /etc/ssl/server.crt
        SSLCertificateKeyFile /etc/ssl/server.key
        SSLCACertificatePath /etc/ssl/certs
        SSLCertificateChainFile /etc/ssl/sub.class1.server.ca.crt

</VirtualHost>

On redémarre le serveur Apache pour s'assurer que tout va bien:

olemerdy@lafeuille:/etc/apache2/$ sudo /etc/init.d/apache2 restart

Et il ne reste plus qu'à se connecter sur la page d'accueil en HTTPS et à constater que tout se passe bien: https://lafeuille.org

Sources

dimanche, janvier 6 2008

Configurer Eclipse pour éviter les OutOfMemoryError sous Linux

Pratiquant le développement JavaEE, j'utilise depuis maintenant quelques années l'IDE Eclipse pour ses nombreuses qualités. Toutefois, lors de mon passage sous Linux, j'ai été vite confronté à des difficultés pour faire fonctionner Eclipse de manière satisfaisante, ce qui est bien le comble lorsque l'on parle de Java dont un des avantages marquants est la portabilité.

A la date d'écriture de cet article, la version proposée par défaut dans les dépôts d'Ubuntu est la 3.2.2 (Calisto) et non pas la dernière en date, la 3.3 (Europa) qui apporte de nombreuses améliorations, dont la version 1.5 de WST gérant JavaEE 5. Pour l'instant, ceci est également vrai pour la prochaine version en développement. La mort dans l'âme, j'ai du me résoudre à installer une distribution générique du site officiel. En expérimentant avec quelques projets JavaEE 5, je finis malheureusement rapidement par obtenir des erreurs de type "PermGen Space" correspondant à une mémoire insuffisante. Il me paraissait plus que douteux que ma machine principale de bureau dotée de 2 Go de mémoire échoue aussi lamentablement sous Linux alors que Eclipse sous Windows fonctionnait normalement sur un petit portable sans prétention.

Après quelques recherches sur le sujet, il semblerait que ce phénomène provienne de la JVM utilisée (celle de Sun). Pour pallier à ce problème, il faut rajouter des paramètres non standards à la JVM au lancement d'Eclipse, ce qui n'a rien de très élégant. J'ai donc effectué la modification arbitraire suivante dans le fichier eclipse.ini à la racine du dossier d'Eclipse:

-showsplash
org.eclipse.platform
-vmargs
-Xms40m
-Xmx512m
-XX:PermSize=64M
-XX:MaxPermSize=256m

J'ai donc augmenté la taille maximale allouable (Xmx) et également ajouté des paramètres augmentant la taille de la fameuse PermSize (XX:PermSize et XX:MaxPermSize). Les tailles données sont purement arbitraires et mériteraient une configuration plus fine.

Voici les références m'ayant permis de trouver la solution à mon problème:

Bon développement sous Linux!

samedi, janvier 5 2008

Configurer le mod UserDir pour Apache 2 sous Ubuntu

Le mod UserDir pour le server HTTP Apache permet aux utilisateurs du système de disposer d'un espace dans leur dossier utilisateur directement accessible par Apache 2. Ce dernier donnera accès au contenu de ce dossier par une URL intuitive du type http://domain.name/~username, dans mon cas http://lafeuille.org/~olemerdy. N'importe quel utilisateur du système peut alors de manière simple (dépôt de fichiers HTML dans son espace utilisateur) publier du contenu accessible à tous. Séduisant, non?

Activer le mod UserDir

La première chose à faire, en dehors d'installer apache2, pour que ce rêve devienne réalité est d'activer le mod UserDir si cela n'est pas déjà fait par défaut.

olemerdy@lafeuille:~$ sudo a2enmod userdir

Il faut redémarrer le serveur pour que la modification soit prise en compte, ce qui se fait très simplement:

olemerdy@lafeuille:~$ sudo /etc/init.d/apache2 restart

Préparer le dossier de réception

Première étape: créer le dossier utilisateur utilisé par Apache. C'est dans ce dossier que vous pourrez déposer du contenu. Par défaut, il s'agit de public_html

olemerdy@lafeuille:~$ mkdir public_html

Malheureusement, ce n'est pas si simple! Dans la mesure où ledit dossier se trouve dans votre espace, il faut que le processus Apache puisse y avoir accès. Or, les utilisateurs créés par défaut ont un dossier qui n'est visible que d'eux (et c'est bien!). Nous allons voir comment configurer les droits minimaux pour autoriser Apache à accéder aux fichiers. Un bref rappel:

  • Un droit d'exécution x sur un dossier permet de se positionner dans celui-ci, par exemple avec la commande cd
  • Un droit de lecture r sur ce même dossier autorisera à lister son contenu.

Il est donc possible de permettre l'accès à un répertoire sans permettre son listage, par exemple pour permettre l'accès à un fichier. C'est exactement ce que nous cherchons à faire ici pour les autres utilisateurs du système:

olemerdy@lafeuille:~$ chmod og+x public_html

Il faut bien sûr que le dossier parent de public_html soit également accessible, ce que nous nous empressons de faire d'un bien senti:

olemerdy@lafeuille:~$ cd ..
olemerdy@lafeuille:/home$ chmod og+x olemerdy

Attention ! Vous venez d'autoriser l'accès à votre dossier utilisateur. Pour peu que d'autres dossiers et fichiers soient en lecture, écriture ou exécution, ces utilisateurs vont pouvoir les utiliser. Si, comme il paraît souhaitable, vous désirez éviter ce cas de figure, il convient de retirer le maximum de ces droits sur vos fichiers. Si vous n'avez pas froid aux yeux, la commande suivante retirera tous les droits nécessaires récursivement à tous les fichiers de votre dossier utilisateur:

olemerdy@lafeuille:~$ chmod -R og-rwx *

Si vous choisissez cette solution extrême, n'oubliez pas ensuite de réexécuter les commandes autorisant l'accès à public_html! Voilà, vous êtes prêts à déposer vos fichiers dans le dossier idoine avec des droits minimaux de lecture pour tous. Bonne publication!

Note additionnelle

Historiquement, les droits des nouveaux fichiers sous Debian (dont est dérivée Ubuntu) sont paramétrés en octal à 755 (c'est-à-dire lecture et exécution pour tout le monde et écriture pour le propriétaire seul), ce qui correspond à un umask de 022. Vous pouvez décider de ne donner de droits qu'au propriétaire en réglant l'umask à 077. Il vous suffit pour cela de modifier le fichier .bashrc:

olemerdy@lafeuille:~$ echo "umask 077" >> .bashrc

Si vous souhaitez paramétrer cette préférence par défaut pour tous les utilisateurs, la modification devra être faite dans le fichier /etc/login.defs

dimanche, décembre 30 2007

Installer Maven sous Ubuntu

Mise à jour

Maven fait désormais partie des paquets officiels d'Ubuntu. Il suffit de cliquer sur le lien idoine ou de tapouiller en ligne de commandes:

olemerdy@lafeuille:~$ sudo aptitude install maven2

Article original

Maven fait partie de ces outils indispensables au développeur Java qui ne font malheureusement pas (encore?) partie des paquets disponibles dans les dépôts officiels d'Ubuntu. Cet article se propose de décrire comment installer ce logiciel pour tous les utilisateurs dans notre distribution préférée.

Si Java n'est pas encore installé, il vous faudra d'abord installer le Java Development Kit en cliquant ici ou en tapouillant en ligne de commande:

olemerdy@lafeuille:~$ sudo aptitude install sun-java6-jdk

Il convient ensuite de télécharger la version la plus récente (2.0.8 à l'écriture de cet article) de Maven sur le site dédié de la fondation Apache. Le format de l'archive importe peu mais partons du principe que vous choisissez le Zip.

Décompressez cette archive d'un joyeux:

olemerdy@lafeuille:~$ unzip apache-maven-2.0.8.zip

Si vous n'avez pas encore créé de répertoire pour les logiciels optionnels, c'est-à-dire hors dépôts, faites-le maintenant:

olemerdy@lafeuille:~$ sudo mkdir /opt

Copiez maintenant votre répertoire Maven dans son nouveau chez-lui:

olemerdy@lafeuille:~$ sudo cp -R apache-maven-2.0.8 /opt/

Vous pouvez effacer le répertoire de décompression d'un vengeur:

olemerdy@lafeuille:~$ rm -rf apache-maven-2.0.8

Maven propose une unique commande mvn pour exécuter toutes ses tâches. Liez-la par un lien symbolique afin que vous puissiez l'utiliser telle quelle en ligne de commandes:

olemerdy@lafeuille:~$ sudo ln -s /opt/apache-maven-2.0.8/bin/mvn /usr/local/bin/mvn

Il nous reste encore à définir la variable d'environnement JAVA_HOME (étrangement non créée par le processus normal d'installation) en la définissant dans le fichier général bashrc

olemerdy@lafeuille:~$ sudo nano /etc/bash.bashrc

Ajoutez à la fin de ce fichier la ligne suivante:

# set environment variables
export JAVA_HOME=/usr/lib/jvm/java-6-sun

Sauvegardez d'un joyeux Ctrl-O et quittez d'un tout aussi joyeux Ctrl-X. Ça y est, votre environnement est prêt! Il ne vous reste plus qu'à vous placer dans votre espace de travail et à taper un petit mvn install pour vérifier que tout fonctionne. Bonne compilation!