Squelette de projet python pour Maemo5

Le projet Pyjama est aujourd’hui dans un état presque utilisable. Pyjama est un outil écrit en python pour générer un squelette de projet python pour Maemo5. Il s’agit d’un “bootstrapper” à la manière du plugin archetype de maven.

Le principal objectif de Pyjama est atteint puisque la version disponible sous forme de source permet de générer un embryon d’application exécutable. Les sources générés comprennent des outils afin de gérer le messages d’informations, la remontée de bug via googlecode et les tâches asynchrones.

Le prochaine étape est la création d’une interface de saisie des paramètres du projet ainsi que d’une IHM pour Maemo5. Ainsi on pourra créer le squelette sur PC ou bien directement sur le terminal.

Astuces pour faire des tests unitaires en Java

Bug
Image by Ecyrd via Flickr

Les tests unitaires ont pour but de tester le fonctionnement de chaque module, objet indépendamment de l’environnement qui dans lequel il sera utilisé par la suite. L’objectif est de garantir que le contrat de de module ou de la classe est bien respecté.

Le développeur inexpérimenté aura tendance à coder tous les modules avant des les assembler puis de constater que cela fonctionne ou pas. Ce test dit d’intégration ne permet pas de trouver rapidement l’origine du problème.

Pour autant est-ce que le test d’intégration doit être négligé ? En effet une bonne pratique est l’analyse descendante illustrant le vieille adage “diviser pour mieux régner”. En partant du haut, les premières méthodes utilisent alors des modules ou classes non encore écrites. Doit-on tester ces grosses briques ? Si oui comment ?

Le test doit être un acquis dogmatique. Un code non testé est un code sans valeur. La réticence première à tester est souvent justifiée par l’impossibilité à ce stade du développement d’avoir l’écosystème pour tester. Par exemple le développeur va dire “je n’ai pas encore tel ou tel module qui doit me fournir des données” ou bien “je n’ai pas encore la couche de persistance”. Il faut être clair. On test ce qui est utile et ce qui est utile c’est l’implémentation des fonctionnalités, des spécifications. Si on ne peut pas tester un code terminé c’est signe d’une mauvais;e conception: on mélange dans une même méthode ou classe des responsabilités différentes. Un code bien écrit est un code testable !

voyons comment écrire du code testable à travers des exemples.

Utilisation de classe non encore implémentée

Supposons que l’on ait une classe A qui fait des choses intéressantes mais qui doit les algorithmes sont paramétrés. Bien sûr la mécanique de paramétrage avec fichier de configuration ou configuration en base n’existe pas encore..
Si on code en due la configuration dans A, il va falloir revenir sur A pour y mettre le code définitif d’accès à la configuration. Or il y a une règle qui dit un code bien conçu doit marcher avec du code non encore écrit. Pour y parvenir on utilise le vielle adage diviser pour mieux régner qui sera incarné par une interface. La classe A sera paramétrée par une interface IAConfig passée au constructeur pour faire simple. Dès lors le test unitaire ne pose plus de problème puisqu’il va porter la configuration en dur et le code de A fonctionnera dans son utilisation réelle au sein de l’application.

Signature de méthode incompatible

Ce cas peut s’illustrer par une méthode m qui prend en argument un type la rendant difficile à tester. Par exemple disons une méthode qui prend un java.io.File en argument. Le développeur pourra se plaindre qu’il n’est pas aisé de faire un test unitaire fonctionnant sur n’importe quelle machine. Il a raison. Référencer un File dans un test JUnit sous Maven demande quelques lignes de code. Il faut filtrer un fichier de propriété contenant project.basedir=${project.basedir} qui sera placé en resource de test. Puis dans le test unitaire charger le fichier de propriétes avec un getResourceAsStream() et enfin construire le chemin vers le fichier. Pas direct mais faisable.

D’ailleurs pourquoi faire compliqué quand on peut faire simple? Un code bien écrit est un code testable. A-t-on vraiment besoin d’un File en paramètre? Utilise-t-on des propriétés ou des méthodes spécifiques au File? Sans doute non, donc un InputStream devrait être suffisant. L’idée est de changer la signature de la méthode pour la rendre le moins spécifique possible, ainsi elle sera plus facilement testable. Dans son utilisation réelle l’appelant peut manipuler un File s’il le souhaite et passer un FileInpuStream à la méthode dûment testée.

Cas de la base de données avec des DAO

Une dernière raison invoquée pour refouler les tests est la présence d’une base de données. Le premier point est d’éviter de mettre de la logique dans le traitement SQL. Si ce n’est pas passible il faut investir dans du DBUnit parce que cela signifie que la valeur ajoutée, l’implémentation des spécifications est dans le code SQL… Vraiment? La plupart du temps le code métier dans le SQL est un signe de médiocrité.

Le deuxième point est que l’absence de code métier dans la couche de persistance fait qu’il n’est pas vraiment besoin de la tester. Par exemple si on utilise un pattern DAO, on ne va pas tester les DAO si ils ne font que CRUD.

Le 3e point est que le code à tester se trouve au dessus de la couche de persistance donc testable en bouchonnant les DAO : on ne se mock pas.

L’utilisation de DAO permet de substituer facilement les implémentation SQL avec des implémentations de test. En effet le bon pattern DAO ne signifie pas seulement isoler le code SQL dans des classdes DAO mais aussi rendre les DAO interchangeable. On obtient cela on utilisant une fabrique abstraite de DAO que j’appelle DAOFactoryManager, classe intermédiaire entre le code métier et les DAO. Le DAOFactoryManager est configurable avec le type d’implémentation. Dans son utilisation réelle il renvoit par exemple une fabrique de DAO pour MySQL et en test une fabrique de mock. Le code métier doit y voir que du feux en ne manipulant qu’une interface IDAOFactory obtenue auprès du DAOFactoryManager et des interface pour chaque DAO obtenus depuis le IDAOFactory.
Cela semble lourd mais les bienfaits valent le coût. En effet le code métier est testable sans implémentation de la couche de persistance. Le developpeur peut à loisir paramétrer un MockDAOFactory dans la phase de préparation des acteurs du test, puis appeler la méthode métier qui va lors de son execution appeler le DAOFactorManager configurer en mode test, et finalement utiliser des DAO “mockés”.

On prendra juste soin de ne pas liée le DAOFactoryManager avec les objets mocké. En effet le manager de DAO est une classe qui ira en production, alors que les mock qui sont des classes de tests ne le devraient pas. En java il suffit d’utiliser la réflexion pour charger la classe dynamiquement avec un :

Class.forName("com.acme,app.dao.MockDAOFactory").newInstance()

Lors de la phase de test la classe sera disponible mais pas en production.

Tests d’intégrations

Nous entendons pas test d’intégration les tests des méthodes de façades. Ce sont celles qui orchestre les appels aux objets métiers pour accomplir les services attendus de l’application. Oublions un instant toute la pollution intellectuelle apportée par les EJB. Dans un contexte uniquement objet, on doit avoir des façades qui constituent les points d’entrées sur les fonctions du système: ce sont les implémentations informatiques des cas d’utilisations. Par exemple une application qui va tous les soirs lire une base de données puis envoyer des mails de rappel  à tous les utilisateurs portera une méthode dédié à ce cas d’utilisation dans sa façade. Cette façade pourra être appelé en ligne de commande ou par une IHM Swig ou web. Le métier ne changeant pas, le fait de garantir le fonctionnement de la façade est aussi important que de garantir le fonctionnement unitaire. ll faut tester la façade et ce n’est pas faire une entorse à la définition de test unitaire. Quand on teste une méthode qui utilise la classe ArrayList, on suppose que celle-ci n’est pas boguée et on ne la ” mock” pas. De même une fois que les briques de bases sont développées et testés unitairement, on doit les considérer comme des instructions de base et les utiliser dans la façade que l’on va tester “unitairement”.

Ce niveau de test d’intégration est pour moi pas moins que nécessaire. Alors gardons à l’esprit qu’un code non testé est un code sans valeur. Tester doit être une seconde nature qui oblige à vérifier que le code fonctionne et en les automatisant ils deviennent répétables sans effort permettant ainsi de détecter les régressions. Alors testons, testons, nos utilisateurs nous le rendront !

Un environnement de developpement Java: mise en place d’Archiva

Un concept fondamental de maven est celle du dépôt de librairie qui met à disposition des projets toutes les librairies dont ils dépendent. Cela permet de ne jamais copier une librairies tiers dans l’arborescence du projet comme on peut le voir dans certains projets fait avec ant. Avec maven on ne met dans le serveur de source uniquement des…sources et tout ce qui est fabriqué à partir de sources doit être mis à disposition dans un dépôt de librairie : le repository. Il y a 2 types de repository: l’un local à l’utilisateur qui est en train de faire un build, l’aute dit distant qui permet à tout utilisateur de bénéficier de librairies produites par d’autre build. Le repository local va accueillir une copie des librairies (dites artefacts) provenant des repository distants mais il ne  s’agit là que d’un mécanisme technique pour accélérer le build. Grâce à maven sur la machine de l’utlisateur une librairies n’est jamais dupliquée entre les projets: tous vont utiliser la librairie qui se trouve dans le repository local.

Le repository distant peut être multiple: une organisation va avoir son  dépôt maven 2 pour accueillir ces propres librairies issues de ces propres projets. Mais ces projets vont sans doute utiliser des librairies tierces en provenance d’internet ne serait-ce que pour avoir les librairies dont dépend maven 2 lui-même. L’accès du build à internet pose un premier problème à certains réseaux d’entreprises. Il faut alors avoir un miroir interne des librairies publiques. En plus la simple fonction de mirroir, le repository distant doit aussi être celui qui contient les différentes librairies interne produite par l’organisation. Dans de larges projets ou quand la gestions des dépendances doit être contrôlée par projet entier, il faut que le serveur de librairies ait une gestion des droits. Par exemple un projet donné va utiliser un repository qui ne va lui fournir que des librairies autorisées. Un autre projet aura droit à d’autres librairies. On peut répondre à ce besoin par l’utilisation de plusieurs repository mais on utilisera avantageusement Archiva qui est un serveur de repository.

Nouc choisissons la version standalone d’archiva. Après avoir décompresser l’archive, aller modifier le fichier <archiva_dir>/conf/jetty.xml afin de spécifier le port http 9090 au lieu de 8080 déjà utilisé par continuum. Modifier aussi le port https en 9443 au lieu de 8443. Installer ensuite archiva en tant que service à l’aide des commandes suivantes

sudo ln -s /home/thierry/Programmes/apache-archiva-1.2-M1/bin/archiva /etc/init.d/archiva

sudo update-rc.d archiva defaults 80

sudo /etc/init.d/archiva start

Maintenant nous allons créer un repository virtuel dédié à notre projet. Le principe est d’avoir une entrée unique dans la définition du repository distant pour tous les artefacts possibles afin de simplifier la configuration dans le projet et de déporter le recensement des repository distant dans archiva. Pour ce faire on déclare dans le projet un seul repository en mettant dans le fichier pom.xml

<repositories>
<repository>
<id>project</id>
<name>Archiva Managed Unified Repository</name>
<url>//localhost:9090/archiva/repository/vroom/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

Cette déclaration dit que le projet doit aller chercher es dépendances dans le repository qui porte le même nom que le projet. En fait il s’agira d’un repository virtuel qui va regrouper tous les repository autorisé pour le projet. Nous le créeront plus tard. Pour l’instant définissons le repository de déploiement des artefacts produit. Ainsi dans la section <distributionManagement> du fichier pom.xml ajouter les déclarations suivantes:

<snapshotRepository>
<id>snapshots</id>
<url>//localhost:9090/archiva/repository/vroom-snapshots</url>
</snapshotRepository>
<repository>
<id>internal</id>
<url>//localhost:9090/archiva/repository/vroom-internal/</url>
</repository>

On voit que le nom du repository de déploiement ne respecte pas la convention mais archiva utilise l’identifiant du repository comme suffixe de l’url. Je propose donc un contournement <nom_repo>-snaphots en <nom_repo>-internal. Dans déclaration on indique 2 repository distincts pour les snapshots et les versions finales. Dans le cadre de notre article l’usage dun repository pour le projet peut paraître surfait mais cette pratique prend son sens quand on veux regrouper dans un repository des projets ayant un lien et que l’on ne veux pas partager avec d’autres projets.

Maintenant on peut créer le repository virtuel pour le projet vroom qui va regrouper

  • les repository des ibrairies tierces
  • les repository du projet (ou du groupe)

Tout d’abord il faurt créer les repository spécifiques au projet. Aller dans le menu de gauche pour sélectionner repositories puis cliquer sur l’icone Add. Voici une capture montrant la création du repositoy vroom-internal :

Archiva repository creation Archiva repository creation snapshot

Enfin il reste à les regrouper dans le repository virtuel: aller dans le menu de gauche pour sélectionner Repositories Group. Dans le champs n haut à droite saisir vroom comme identifiant puis cliquer sur Add group. Dans le groupe qui vient d’être créé, ajouter les repository réels: il suffit à ce stade d’ajouter tous les repository pour mettre dans le groupe les repository par défaut de continuum (internal et snapshots) ainsi que les 2 spécifiques au projet vroom (vroom-internal et vroom-snapshots).

Archiva virtual repository

Archiva offre un mécanisme de gestion de droit, il nous faudra créer un utilisateur ayant le rôle Observer pour la lecture et Manager pour le déploiement d’artefact. Comme nous utilisons un repository virtuel il est judicieux de choisir un rôle Global Repository Observer afin de ne pas avoir à ajouter de droits à chaque fois qu’on ajoute un nouveau repository réel dans le repository virtuel. Les identifiants et mots de passes sont à renseigner dans le fichier settings.xml :

<server>
<id>snapshots</id>
<username>thierry</username>
<password>xxxxxxx</password>
</server>
<server>
<id>internal</id>
<username>thierry</username>
<password>
xxxxxxx</password>
</server>
<server>
<id>project</id>
<username>thierry</username>
<password>
xxxxxxx</password>
</server>
</servers>

En plus de la centralisation des repository, archiva peut aussi servir de proxy.Nous allons rediriger toute les requêtes vers des repository externes (les différents plugin de maven vont être téléchargé par ce biais) vers archiva qui va alors les stocker pour les prochaines fois. Cela est extrêmement bénéfique quand un autre utiisateur (local à la machine ou dans l’intranet de l’entreprise) lance le même build. Pour cela il faut indiquer un repository virtuel comme miroir dans le fichier settings.xml

<mirror>
<id>archiva.mirror</id>
<url>//localhost:9090/archiva/repository/mirror</url>
<mirrorOf>*,!project</mirrorOf>
</mirror>

Dans cette déclaration on dit que pour tous les repository autre que project (qui lui est définit dans le projet comme un repository archiva), maven va utiliser le repository archiva appelé mirror. Dans archiva il faudra créer le repository mirror comme repository virtuel (groupe) qui contiendra les repository standard de continuum : internal et snapshot.

Archiva mirror repository

Nous avons vu comment utiliser archiva pour centraliser l’administration des repository distant ainsi que pour mettre en cache les artefacts issus des repository distants pour les partager via archiva avec les autres builds.

Un environnement de developpement Java: mise en place d’Archiva

Un concept fondamental de maven est celle du dépôt de librairie qui met à disposition des projets toutes les librairies dont ils dépendent. Cela permet de ne jamais copier une librairies tiers dans l’arborescence du projet comme on peut le voir dans certains projets fait avec ant. Avec maven on ne met dans le serveur de source uniquement des…sources et tout ce qui est fabriqué à partir de sources doit être mis à disposition dans un dépôt de librairie : le repository. Il y a 2 types de repository: l’un local à l’utilisateur qui est en train de faire un build, l’aute dit distant qui permet à tout utilisateur de bénéficier de librairies produites par d’autre build. Le repository local va accueillir une copie des librairies (dites artefacts) provenant des repository distants mais il ne  s’agit là que d’un mécanisme technique pour accélérer le build. Grâce à maven sur la machine de l’utlisateur une librairies n’est jamais dupliquée entre les projets: tous vont utiliser la librairie qui se trouve dans le repository local.

Le repository distant peut être multiple: une organisation va avoir son  dépôt maven 2 pour accueillir ces propres librairies issues de ces propres projets. Mais ces projets vont sans doute utiliser des librairies tierces en provenance d’internet ne serait-ce que pour avoir les librairies dont dépend maven 2 lui-même. L’accès du build à internet pose un premier problème à certains réseaux d’entreprises. Il faut alors avoir un miroir interne des librairies publiques. En plus la simple fonction de mirroir, le repository distant doit aussi être celui qui contient les différentes librairies interne produite par l’organisation. Dans de larges projets ou quand la gestions des dépendances doit être contrôlée par projet entier, il faut que le serveur de librairies ait une gestion des droits. Par exemple un projet donné va utiliser un repository qui ne va lui fournir que des librairies autorisées. Un autre projet aura droit à d’autres librairies. On peut répondre à ce besoin par l’utilisation de plusieurs repository mais on utilisera avantageusement Archiva qui est un serveur de repository.

Nouc choisissons la version standalone d’archiva. Après avoir décompresser l’archive, aller modifier le fichier <archiva_dir>/conf/jetty.xml afin de spécifier le port http 9090 au lieu de 8080 déjà utilisé par continuum. Modifier aussi le port https en 9443 au lieu de 8443. Installer ensuite archiva en tant que service à l’aide des commandes suivantes

sudo ln -s /home/thierry/Programmes/apache-archiva-1.2-M1/bin/archiva /etc/init.d/archiva

sudo update-rc.d archiva defaults 80

sudo /etc/init.d/archiva start

Maintenant nous allons créer un repository virtuel dédié à notre projet. Le principe est d’avoir une entrée unique dans la définition du repository distant pour tous les artefacts possibles afin de simplifier la configuration dans le projet et de déporter le recensement des repository distant dans archiva. Pour ce faire on déclare dans le projet un seul repository en mettant dans le fichier pom.xml

<repositories>
<repository>
<id>project</id>
<name>Archiva Managed Unified Repository</name>
<url>//localhost:9090/archiva/repository/vroom/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

Cette déclaration dit que le projet doit aller chercher es dépendances dans le repository qui porte le même nom que le projet. En fait il s’agira d’un repository virtuel qui va regrouper tous les repository autorisé pour le projet. Nous le créeront plus tard. Pour l’instant définissons le repository de déploiement des artefacts produit. Ainsi dans la section <distributionManagement> du fichier pom.xml ajouter les déclarations suivantes:

<snapshotRepository>
<id>snapshots</id>
<url>//localhost:9090/archiva/repository/vroom-snapshots</url>
</snapshotRepository>
<repository>
<id>internal</id>
<url>//localhost:9090/archiva/repository/vroom-internal/</url>
</repository>

On voit que le nom du repository de déploiement ne respecte pas la convention mais archiva utilise l’identifiant du repository comme suffixe de l’url. Je propose donc un contournement <nom_repo>-snaphots en <nom_repo>-internal. Dans déclaration on indique 2 repository distincts pour les snapshots et les versions finales. Dans le cadre de notre article l’usage dun repository pour le projet peut paraître surfait mais cette pratique prend son sens quand on veux regrouper dans un repository des projets ayant un lien et que l’on ne veux pas partager avec d’autres projets.

Maintenant on peut créer le repository virtuel pour le projet vroom qui va regrouper

  • les repository des ibrairies tierces
  • les repository du projet (ou du groupe)

Tout d’abord il faurt créer les repository spécifiques au projet. Aller dans le menu de gauche pour sélectionner repositories puis cliquer sur l’icone Add. Voici une capture montrant la création du repositoy vroom-internal :

Archiva repository creation Archiva repository creation snapshot

Enfin il reste à les regrouper dans le repository virtuel: aller dans le menu de gauche pour sélectionner Repositories Group. Dans le champs n haut à droite saisir vroom comme identifiant puis cliquer sur Add group. Dans le groupe qui vient d’être créé, ajouter les repository réels: il suffit à ce stade d’ajouter tous les repository pour mettre dans le groupe les repository par défaut de continuum (internal et snapshots) ainsi que les 2 spécifiques au projet vroom (vroom-internal et vroom-snapshots).

Archiva virtual repository

Archiva offre un mécanisme de gestion de droit, il nous faudra créer un utilisateur ayant le rôle Observer pour la lecture et Manager pour le déploiement d’artefact. Comme nous utilisons un repository virtuel il est judicieux de choisir un rôle Global Repository Observer afin de ne pas avoir à ajouter de droits à chaque fois qu’on ajoute un nouveau repository réel dans le repository virtuel. Les identifiants et mots de passes sont à renseigner dans le fichier settings.xml :

<server>
<id>snapshots</id>
<username>thierry</username>
<password>xxxxxxx</password>
</server>
<server>
<id>internal</id>
<username>thierry</username>
<password>
xxxxxxx</password>
</server>
<server>
<id>project</id>
<username>thierry</username>
<password>
xxxxxxx</password>
</server>
</servers>

En plus de la centralisation des repository, archiva peut aussi servir de proxy.Nous allons rediriger toute les requêtes vers des repository externes (les différents plugin de maven vont être téléchargé par ce biais) vers archiva qui va alors les stocker pour les prochaines fois. Cela est extrêmement bénéfique quand un autre utiisateur (local à la machine ou dans l’intranet de l’entreprise) lance le même build. Pour cela il faut indiquer un repository virtuel comme miroir dans le fichier settings.xml

<mirror>
<id>archiva.mirror</id>
<url>//localhost:9090/archiva/repository/mirror</url>
<mirrorOf>*,!project</mirrorOf>
</mirror>

Dans cette déclaration on dit que pour tous les repository autre que project (qui lui est définit dans le projet comme un repository archiva), maven va utiliser le repository archiva appelé mirror. Dans archiva il faudra créer le repository mirror comme repository virtuel (groupe) qui contiendra les repository standard de continuum : internal et snapshot.

Archiva mirror repository

Nous avons vu comment utiliser archiva pour centraliser l’administration des repository distant ainsi que pour mettre en cache les artefacts issus des repository distants pour les partager via archiva avec les autres builds.

Un environnement de developpement Java: la communication

Nous avons mis en place l’intégration continue dans sa forme primitive. Elle permet de lancer la construction du projet régulièrement afin de s’assurer que tout compile parfaitement. SI l’intégration continue est essentielle dans un environnement collaboratif, il existe d’autres outils à disposition du chef de projet ou du responsable Software Factory pour renforcer l’esprit d’équipe et l’échange d’information. En fonction de la taille de l’équipe il conviendra de bien choisir la fréquence et le canal de diffusion de l’information.

Le canal le plus courant est .. la parole. C’est une évidence mais qui trouve sa limite quand l’équipe dépasse 3 à 5 personnes ou quand elle est distribuée géographiquement. Des dispositifs comme la messagerie instantanée peuvent alors prendre le relais ou bien la messagerie électronique quand le décalage horaire entre les membres de l’équipe empêche la communication en temps réel. Communiquer mais pour dire quoi ? Dans le cas particulier d’échange d’information du genre “tiens j’ai envie d’ajouter une classe ici pour faire ceci ou cela”, l’esprit d’initiative de chacun sera mis à contribution. Par contre il y a un certain nombre de cas où il est tout à fait possible d’automatiser le flux d’information.

Signaler les modifications des sources

Les modifications de sources est le premier cas. Il est important que tout membre de l’équipe sache les évolutions qui surviennent dans les sources du projet. Cette idée de propriété collective du code prônée par Extreme Programming permet à tous d’avoir un regard sur l’ensemble du code. Nous allons donc mettre en place un envoi de mail automatique dés qu’une modification survient dans le référentiel de source.

L’implémentation de cette fonctionnalité avec subversion peut se faire par le biais des “hook” qui sont des scripts appeler par subversion quand des opérations sont effectuée comme par exemple à chaque commit. Il suffit d’installer le paquet subversion-tools qui fournit le script /usr/share/subversion/hook-scripts/commit-email.pl. Aller dans le répertoire qui contient le référentiel de source pour effectuer les actions suivantes:

  1. renommer le fichier <mon_repo>/hooks/post-commit.tmpl en post-commit
  2. activer le droit d’execution au fichier post-commit
  3. ajouter les adresses mails à la fin de la commande qui se trouve à la fin du fichier pos-commit : il sera bon d’utiliser une liste de diffusion

Cette configuration est spécifique au référentiel, donc si on a dans le même référentiel plusieurs projets, des mails vont être envoyés aux adresses quelque soit le projet sur lequel intervient le commit.

Subversion peut soit utiliser sendmail ou un serveur smtp. Cela se configure dans le fichier /usr/share/subversion/hook-scripts/mailer/mailer.conf:

  1. renommer le fichier /usr/share/subversion/hook-scripts/mailer/mailer.conf.example en mailer.conf
  2. dans le fichier mailer.conf décommenter soit mail_command soit smtp_hostname,smtp_username, smtp_password

Cette configuration basique peut être améliorée en ajoutant des filtres sur les projets, les utilisateurs etc.

Rapport de construction

Tandis que les mails de commit permettent un suivi très fin des activités sur le projet, le rapport de construction donne une vision un peu plus haute en étant moins fréquente et en offrant potentiellement des rapports d’audit de code.

Continuum est fournit avec plusieurs connecteurs (mail, IRC, MSN…) pour notifier le résultat des constructions. L’envoi de mail est le connecteur le plus facile à utiliser ne nécessitant qu’une adresse mail principale que l’on pourra choisir comme une liste de diffusion.

Continuum utilise le protocole SMTP pour envoyer les mails, il faudra configurer le serveur dans le fichier <continuum>/conf/jetty.xml

Continuum - mail notifier settings continuum - mail de notification

Le site vitrine du projet

Ce canal de communication  permet de faire la promotion du projet au sein de l’organisation ou même au niveau de tout interne en offrant toutes les informations sur le projet pour toutes les audiences: utilisateurs, développeurs, assurance qualité. Le site du projet est l’élément primordiale de la documentation d’un projet gérée avec Maven. Il s’agit même pour moi de l’unique source de toute documentation sur un projet puisqu’il offre la documentation technique du projet ainsi que tout les rapports d’audit sur le code.

La mise en place du site vitrine suppose au moins l’existence d’un serveur web. Le choix du serveur web se fait naturellement en prenant apache qui s’installe avec synaptique : choisir le paquet apache2.

Notre environnement de développement devant simuler au environnement réelle multi-developpeur, nous allons mettre en place le site vitrine comme si il devait être déployer à distance. Une fois le serveur apache installé,il faut choisir le chemin (local à l’hôte de apache) vers le site du projet. Pour simplifier ce choix nous allons dire que le site ira dans /urs/share/doc accessible par //localhost/doc/etc/ mais il est possible de choisir un autre chemin en ajoutant un alias dans le fichier /etc/apache2/sites-enabled/000-default

Pour avois un site minimal il suffit d’ajouter au projet le fichier suivant <mon_projet>/src/site/site.xml contenant

<?xml version="1.0" encoding="UTF-8"?>
 <project name="Maven">
 <bannerLeft>
 <name>Maven</name>
 <src>//maven.apache.org/images/apache-maven-project.png</src>
 <href>//maven.apache.org/</href>
 </bannerLeft>
 <bannerRight>
 <src>//maven.apache.org/images/maven-small.gif</src>
 </bannerRight>
 <body>
 <links>
 <item name="Apache" href="//www.apache.org/" />
 <item name="Maven 1.x" href="//maven.apache.org/maven-1.x/"/>
 <item name="Maven 2" href="//maven.apache.org/"/>
 </links>
<menu ref="reports"/>
 </body>
 </project>

Cette simple configuration permet d’obtenir un site de documentation que vous pouvez tester en lançant

mvn site

Aller voir le résultat dans <mon_projet>/target/site

Nous reviendrons plus en détails sur les possibilités de génération du site par maven. Pour l’instant essayons d’automatiser la génération du site en chargeant l’intégration continue de mettre à jour le site. A ce stade le projet mis en place est minimaliste et la génération de son site est très rapide. Cependant, un véritable projet contenant plusieurs dizaine ou centaines de milliers de lignes de code peut voir sont temps de génération dépasser la demie-heure. C’ets pourquoi il est préférable de séparer les constructions dites de “pure build” qui doivent vérifier que le projet compile et devant intervenir dès que possible, des constructions plus lourdes qui peuvent se faire un fois par jour, la nuit par exemple. La génération du site fait partie du build nocturne.

Pour ajouter un build nocturne dans continuum, il faut d’abord ajourer une planification. Contnuum est livré avec une seule planification qui permet de lancer un build toutes les heures. Nous allons ajouter une planification pour le build nocturne. Dans le menu de gauche sélectionner “planification”. Puis cliquer sur “ajouter”.

continuum_planification_settings.1226397751.png continuum_ightly_build_definition.1226350137.png

Nous pouvons maintenant ajouter la construction qui va utiliser cette planification. Dans le menu du gauche choisir “Groupe de projet” pour sélectionner ensuite le groupe qui nous intéresse, puis le projet sur lequel on veut ajouter la construction du site.

continuum_project_information.1226350099.png continuum_site_build_definition.1226398348.png

A ce stade le build va échouer au moment du déploiement. Il nous faut définir dans le projet vie le pom.xml l’endroit où maven doit déployer le site. Pour cela ajouter les ligne suivante dans le fichier pom.xml:

<distributionManagement>
      <site>
          <id>public.site</id>
          <name>public site served by apache</name>
          <url>scp://localhost/usr/share/doc/${pom.groupId}/${pom.artifactId}</url>
      </site>
  </distributionManagement>

Pour les besoins de l’article nous utilisons la méthode de transfert SCP pour être le plus général possible. Dans un environnement réel, le site étant sans doute hébergé sur une autre machine que celle du serveur d’intégration continue. Ce choix nous permet d’aborder la question de la sécurité. Seule l’intégration continue est officiellement autorisée à déployer le site vitrine. L’identifiant du site (<id>) permettra de définir pour un site donné les paramètres de connexion (login et mot de passe) pour accéder à l’url.

Le répertoire qui va accueillir le site vitrine est  /usr/share/doc. Par défaut ce répertoire n’est accessible en écriture que par l’utilisateur “root”. Nous allons élargir le droit au groupe “root” dans le quel on va ensuite mettre un nouvel utilisateur “continuum”. Pour cela ouvrir un terminal en admiinistrateur et changer les droit sur /user/share/doc :

>sudo sh

>nautilus

add_root_group_write_on_doc.1226401611.png

Maintenant nous allons définir un utilisateur “continuum” ayant le droit d’écrire dans le répertoire  /usr/share/doc. Dans Ubuntu allr dans le menu System > Administration/Utilisateurs et groupes> pour ouvrir l’outil intitulé “réglage des utilisateurs”.. Cliquer sur “Déverrouiller” pour  pouvoir  créer un utilsateur “continuum” et définit son mot de passe.Puis toujours dans l’outil “réglage des utilisateurs” cliquer sur “gérer les groupes. Choisir le groupe “root” puis sélectionner l’utilisateur “continuum” afin de l’jouter dans le groupe “root”. Maintenant nous avons un utilisateur privilégié qui va pouvoir écrire dans le répertoire  /usr/share/doc.

Afin d’indiquer à maven l’utilisateur et le mot de passe à utiliser pour faire le deploiement par le méthode SCP, nous utilisons le fichier settings.xml qui permet de definir le paramétrage spécific. L’installation de maven ayant été faite par Ubuntu via le paquet maven, il faut modifier le fichier /usr/share/maven2/conf/settings.xml pour y ajouter le paramétrage associé  au site “public.site”

<server>
      <id>public.site</id>
      <username>continuum</username>
      <password>continuum</password>
    </server>

Nous avons successivement mis en place des mécanismes automatisant les flux d’informations suivants:

  1. alerte des modifications des sources
  2. alertes des constructions
  3. documentation du projet

Dans un prochain article nous approfondirons les possibilités offertes par la génération du site.

Un environnement de developpement Java: Mise en place de l’intégration continue

Le concept d’intégration continue est central dans l’élaboration d’une Software Factory. En effet la Software Factory prend tout son sens quand il y a plusieurs projets à intégrer. Sans l’intégration continue on ne dispose pas d’un moyen automatisé pour construire les différents projet et s’assurer de la correcte intégration des uns avec les autres… en continue. Un serveur d’intégration continue a donc pour mission de prendre les sources du projet en provenance du gestionnaire de source, de lancer une construction du projet et de mettre à disposition des membres de l’équipe de développement le résultat qui va contenir le statut du build (succès ou échec) ainsi que les artéfacts résultants (binaires, statistiques des builds….).

Plusieurs serveur de sources existent sur la place dont CruiseControl, Hudson et le nouveau Continuum. J’ai choisi ce dernier pour son intégration naturelle avec maven. Nous allons en faire la démonstration.

L’installation de continuum peut se limiter à une simple décompression d’une archive si on emploie la méthode standalone. Il est cependant indispensable que le serveur d’intégration soit automatiquement démarré donc il faudra passer par une étape supplémentaire pour le configurer en service

sudo ln -s /home/thierry/Programmes/apache-continuum-1.2/bin/continuum /etc/init.d/continuum

sudo update-rc.d -n continuum defaults 80

Lancer alors continuum avec

sudo /etc/init.d/continuum start

Continuum se présente comme un application web dont l’url est //localhost:8080/continuum

La première fois où on accède à cette url il faudra choisir le mot de passe administrateur du serveur continuum puis il faudra s’authentifier en tant que administrateur pour pouvoir ajouter d’autres utilisateurs.

Dans le cas de cet article nous allons simplement détailler l’ajout d’un projet.Utiliser le menu Ajouter un projet > projet maven 2 :

.Continuum - Ajout projet maven 2

Comme à ce stade notre Sofware Factory ne dispose pas d’accès HTTP aux sources nous allons sélectionner le pom.xml de notre copie locale du projet. En maven 2, le pom.xml est le fichier unique qui définit les caractéristiques propres d’un projet: son nom, ses dépendances propres, l’url de son dépôt de source…

Pour que continuum trouve le projet dans Subversion nous devons renseigner cette information dans le fichier pom.xml. Voici un exemple de définition de scm.

<scm>
<connection>scm:svn:svn://thierry:thierry@localhost/vroom/trunk</connection>
</scm>

Sauver le fichier pom.xml et commiter dans subversion.

Cliquer ensuite  sur le bouton browse pour choisir le fichier pom.xml

Continuum - Groupe de projet

Après quelque secondes le projet est ajouté dans le groupe par défaut avec la programmation de construction par défaut : toutes les heures.

La configuration de continuum permet de définir plusieurs patrons de construction (build par heure, build journalier), de rassembler les projets dans des groupes de construction (utile pour builder des modules faisants partie d’un projet ou de projets disjoints mais faisant partie d’une suite logicielle), de définir des environnement de constructions différents (o peut avoir sur le même serveur Continuum plusieurs projets utilisant des JDK ou des versions de maven différentes) et enfin les utilisateurs du serveurs peuvent avoirs des rôles et donc des droits différents. Ce paramétrage pourra être détaillé dans un article futur ainsi que le reporting  automatique des builds. Le prochain article traitera de la mise en place du serveur de repository Archiva.

Un environnement de developpement Java: Mise en place de l’intégration continue

Le concept d’intégration continue est central dans l’élaboration d’une Software Factory. En effet la Software Factory prend tout son sens quand il y a plusieurs projets à intégrer. Sans l’intégration continue on ne dispose pas d’un moyen automatisé pour construire les différents projet et s’assurer de la correcte intégration des uns avec les autres… en continue. Un serveur d’intégration continue a donc pour mission de prendre les sources du projet en provenance du gestionnaire de source, de lancer une construction du projet et de mettre à disposition des membres de l’équipe de développement le résultat qui va contenir le statut du build (succès ou échec) ainsi que les artéfacts résultants (binaires, statistiques des builds….).

Plusieurs serveur de sources existent sur la place dont CruiseControl, Hudson et le nouveau Continuum. J’ai choisi ce dernier pour son intégration naturelle avec maven. Nous allons en faire la démonstration.

L’installation de continuum peut se limiter à une simple décompression d’une archive si on emploie la méthode standalone. Il est cependant indispensable que le serveur d’intégration soit automatiquement démarré donc il faudra passer par une étape supplémentaire pour le configurer en service

sudo ln -s /home/thierry/Programmes/apache-continuum-1.2/bin/continuum /etc/init.d/continuum

sudo update-rc.d -n continuum defaults 80

Lancer alors continuum avec

sudo /etc/init.d/continuum start

Continuum se présente comme un application web dont l’url est //localhost:8080/continuum

La première fois où on accède à cette url il faudra choisir le mot de passe administrateur du serveur continuum puis il faudra s’authentifier en tant que administrateur pour pouvoir ajouter d’autres utilisateurs.

Dans le cas de cet article nous allons simplement détailler l’ajout d’un projet.Utiliser le menu Ajouter un projet > projet maven 2 :

.Continuum - Ajout projet maven 2

Comme à ce stade notre Sofware Factory ne dispose pas d’accès HTTP aux sources nous allons sélectionner le pom.xml de notre copie locale du projet. En maven 2, le pom.xml est le fichier unique qui définit les caractéristiques propres d’un projet: son nom, ses dépendances propres, l’url de son dépôt de source…

Pour que continuum trouve le projet dans Subversion nous devons renseigner cette information dans le fichier pom.xml. Voici un exemple de définition de scm.

<scm>
<connection>scm:svn:svn://thierry:thierry@localhost/vroom/trunk</connection>
</scm>

Sauver le fichier pom.xml et commiter dans subversion.

Cliquer ensuite  sur le bouton browse pour choisir le fichier pom.xml

Continuum - Groupe de projet

Après quelque secondes le projet est ajouté dans le groupe par défaut avec la programmation de construction par défaut : toutes les heures.

La configuration de continuum permet de définir plusieurs patrons de construction (build par heure, build journalier), de rassembler les projets dans des groupes de construction (utile pour builder des modules faisants partie d’un projet ou de projets disjoints mais faisant partie d’une suite logicielle), de définir des environnement de constructions différents (o peut avoir sur le même serveur Continuum plusieurs projets utilisant des JDK ou des versions de maven différentes) et enfin les utilisateurs du serveurs peuvent avoirs des rôles et donc des droits différents. Ce paramétrage pourra être détaillé dans un article futur ainsi que le reporting  automatique des builds. Le prochain article traitera de la mise en place du serveur de repository Archiva.

Un environnement de developpement Java: Création de l’arborescence du projet

Le gestionnaire de source installé et paramétré, il est maintenant possible d’y importer la première mouture de l’arborescence du projet. Il s’agit de l’étape sine-qua-none d’un développement distribué et multi-utilisateur. Comme nous utilisons un gestionnaire de source gérant le renommage et le déplacement de fichier, il n’est pas nécessaire d’avoir la structure de répertoire définitive. Il suffit d’ajouter au repository une structure fonctionnel c’est-à-dire qui compile au moins et nous pourrons toujours la modifier par la suite.

Nous adoptons l’arborescence de projet définie par Maven 2 et l”DE utilisé Netbeans, va nous simplifier la tâche en nous apportant une intégration poussée avec Maven. Pour cela aller dans le menu Tools > plugin puis l’onglet Available Plugins. Sélectionner Maven puis cliquer sur Installer.

Netbeans > Menu Tools > PLugin Ajout duplugin Maven

Le plugin maven permet d’ajouter dans Netbeans des menus pour lancer des goals maven et une intégration poussée des concepts de Maven dans les fenêtres d’éditions.

La création d’un projet Maven dans Netbeans est alors très simplifiée. Aller dans le menu File > New Project puis choisir la catégorie Maven et le type Maven Project. Cela donne accès à une liste d’archetype c’est-à-dire de modèle de projet Maven. Il en existe de trés nombreux et le chargement de cette liste est un peu long  la première fois qu’on l’utilise (En effet sont contenu est rapatrié depuis internet). Pour les besoins de l’article nous allons simplement choisir Maven Quickstart Archetype. Il permet de créer un projet qui génère un jar. Il en existe de beaucoup plus complexe et Maven nous  permet d’en créer nous même afin de répondre à tous les besoins. Le dernier écran permet de renseigner les informations primordiales du nouveau projet: nom, paquet, version.

Fênetre de création de projet de Netbeans Fenêtre de selection de l'archetype utilisé dans la création de projet Maven Fenetre de personnalisation du projet qui va être créé par un archetype Maven

La création du projet va prendre quelque seconde la première fois que vous utilisez cette fonction. En effet le principe de maven est de ne pas inclure les dépendances d’un projet. L’éxecution de l’archétype pour le création d’un projet est un cas particulier de build maven. Les dépendances sont donc téléchargées depuis le repository central de Maven. Ce téléchargement n’interviendra qu’une seule fois et les dépendances seront conservées dans le repository maven 2 du plugin Netbeans i.e. quelque part dans les fichiers internes de Netbeans.

Voici un exemple de log d’éxecution quand il n’est pas nécessaire de résoudre par internet les dépendances manquantes:

Scanning for projects…
project-execute
Setting property: classpath.resource.loader.class => ‘org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader’.
Setting property: velocimacro.messages.on => ‘false’.
Setting property: resource.loader => ‘classpath’.
Setting property: resource.manager.logwhenfound => ‘false’.
**************************************************************
Starting Jakarta Velocity v1.4
RuntimeInstance initializing.
Default Properties File: org/apache/velocity/runtime/defaults/velocity.properties
Default ResourceManager initializing. (class org.apache.velocity.runtime.resource.ResourceManagerImpl)
Resource Loader Instantiated: org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader
ClasspathResourceLoader : initialization starting.
ClasspathResourceLoader : initialization complete.
ResourceCache : initialized. (class org.apache.velocity.runtime.resource.ResourceCacheImpl)
Default ResourceManager initialization complete.
Loaded System Directive: org.apache.velocity.runtime.directive.Literal
Loaded System Directive: org.apache.velocity.runtime.directive.Macro
Loaded System Directive: org.apache.velocity.runtime.directive.Parse
Loaded System Directive: org.apache.velocity.runtime.directive.Include
Loaded System Directive: org.apache.velocity.runtime.directive.Foreach
Created: 20 parsers.
Velocimacro : initialization starting.
Velocimacro : adding VMs from VM library template : VM_global_library.vm
[ERROR]ResourceManager : unable to find resource ‘VM_global_library.vm’ in any resource loader.
Velocimacro : error using  VM library template VM_global_library.vm : org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource ‘VM_global_library.vm’
Velocimacro :  VM library template macro registration complete.
Velocimacro : allowInline = true : VMs can be defined inline in templates
Velocimacro : allowInlineToOverride = false : VMs defined inline may NOT replace previous VM definitions
Velocimacro : allowInlineLocal = false : VMs defined inline will be  global in scope if allowed.
Velocimacro : initialization complete.
Velocity successfully started.
[archetype:create]
—————————————————————————-
Using following parameters for creating Archetype: maven-archetype-quickstart:1.0
—————————————————————————-
Parameter: groupId, Value: net.bressure
Parameter: packageName, Value: net.bressure.vroom
Parameter: package, Value: net.bressure.vroom
Parameter: artifactId, Value: vroom
Parameter: basedir, Value: /home/thierry/NetBeansProjects
Parameter: version, Value: 1.0-SNAPSHOT
********************* End of debug info from resources from generated POM ***********************
Archetype created in dir: /home/thierry/NetBeansProjects/vroom
————————————————————————
BUILD SUCCESSFUL
————————————————————————
Total time: < 1 second
Finished at: Mon Oct 06 12:50:15 CEST 2008
Final Memory: 66M/69M
————————————————————————

Le projet qui vien d’être créé est compilable et comporte déjà les prémices de l’atelier de développement Java agile. Le build du projet passe par une phase d’éxécution des tests unitaires. Voici un exemple de sortie en faisant un clic-droit sur le projet et sélectionnant build :

Scanning for projects…
project-execute
[#process-resources]
[resources:resources]
Using default encoding to copy filtered resources.
[#compile]
[compiler:compile]
Nothing to compile – all classes are up to date
[#process-test-resources]
[resources:testResources]
Using default encoding to copy filtered resources.
[#test-compile]
[compiler:testCompile]
Nothing to compile – all classes are up to date
[#test]
[surefire:test]
Surefire report directory: /home/thierry/NetBeansProjects/vroom/target/surefire-reports
——————————————————-
T E S T S
——————————————————-
Running net.bressure.vroom.AppTest
Results :
[#package]
[jar:jar]
[#install]
[install:install]
Installing /home/thierry/NetBeansProjects/vroom/target/vroom-1.0-SNAPSHOT.jar to /home/thierry/.m2/repository/net/bressure/vroom/1.0-SNAPSHOT/vroom-1.0-SNAPSHOT.jar
————————————————————————
BUILD SUCCESSFUL
————————————————————————
Total time: 1 second
Finished at: Mon Oct 06 16:23:49 CEST 2008
Final Memory: 18M/56M
————————————————————————

Un projet qui build est un projet qui doit être partagé. Nous allons importer dans le repository l’arborescence du projet. Pour ce faire Netbeans s’interface avec Subversion à merveille. Sur le projet utiliser un clic droit > Versionning > Import to Subversion Repository pour accéder à la fenêtre de dialogue pour choisir l’emplacement sur le serveur subversion.

Nebeans Menu d'import de nouveau sources dans Subversion Netbeans Dialogue d'import de sources dans subversion

L’url à renseignée est de la forme svn://<serveur>/<projet>/trunk et dans le cas de l’article cela donne svn://localhost/vroom/trunk

Dans la boite de dialogue suivante supprimer le dernier répertoire pour ne garder que <projet>/trunk

Le trunk final est important car cela respecte l’arborescence classique des projets sous Subversion. Le trunk est l’équivalent de la HEAD sous CVS.

Nous avons créé un projet maven 2 en utilisant un archétype. Le projet est disponible dans le référentiel de source Subversion. La prochaine étape va être la mise en place de l’intégration continue.

Un environnement de developpement Java: Création de l’arborescence du projet

Le gestionnaire de source installé et paramétré, il est maintenant possible d’y importer la première mouture de l’arborescence du projet. Il s’agit de l’étape sine-qua-none d’un développement distribué et multi-utilisateur. Comme nous utilisons un gestionnaire de source gérant le renommage et le déplacement de fichier, il n’est pas nécessaire d’avoir la structure de répertoire définitive. Il suffit d’ajouter au repository une structure fonctionnel c’est-à-dire qui compile au moins et nous pourrons toujours la modifier par la suite.

Nous adoptons l’arborescence de projet définie par Maven 2 et l”DE utilisé Netbeans, va nous simplifier la tâche en nous apportant une intégration poussée avec Maven. Pour cela aller dans le menu Tools > plugin puis l’onglet Available Plugins. Sélectionner Maven puis cliquer sur Installer.

Netbeans > Menu Tools > PLugin Ajout duplugin Maven

Le plugin maven permet d’ajouter dans Netbeans des menus pour lancer des goals maven et une intégration poussée des concepts de Maven dans les fenêtres d’éditions.

La création d’un projet Maven dans Netbeans est alors très simplifiée. Aller dans le menu File > New Project puis choisir la catégorie Maven et le type Maven Project. Cela donne accès à une liste d’archetype c’est-à-dire de modèle de projet Maven. Il en existe de trés nombreux et le chargement de cette liste est un peu long  la première fois qu’on l’utilise (En effet sont contenu est rapatrié depuis internet). Pour les besoins de l’article nous allons simplement choisir Maven Quickstart Archetype. Il permet de créer un projet qui génère un jar. Il en existe de beaucoup plus complexe et Maven nous  permet d’en créer nous même afin de répondre à tous les besoins. Le dernier écran permet de renseigner les informations primordiales du nouveau projet: nom, paquet, version.

Fênetre de création de projet de Netbeans Fenêtre de selection de l'archetype utilisé dans la création de projet Maven Fenetre de personnalisation du projet qui va être créé par un archetype Maven

La création du projet va prendre quelque seconde la première fois que vous utilisez cette fonction. En effet le principe de maven est de ne pas inclure les dépendances d’un projet. L’éxecution de l’archétype pour le création d’un projet est un cas particulier de build maven. Les dépendances sont donc téléchargées depuis le repository central de Maven. Ce téléchargement n’interviendra qu’une seule fois et les dépendances seront conservées dans le repository maven 2 du plugin Netbeans i.e. quelque part dans les fichiers internes de Netbeans.

Voici un exemple de log d’éxecution quand il n’est pas nécessaire de résoudre par internet les dépendances manquantes:

Scanning for projects…
project-execute
Setting property: classpath.resource.loader.class => ‘org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader’.
Setting property: velocimacro.messages.on => ‘false’.
Setting property: resource.loader => ‘classpath’.
Setting property: resource.manager.logwhenfound => ‘false’.
**************************************************************
Starting Jakarta Velocity v1.4
RuntimeInstance initializing.
Default Properties File: org/apache/velocity/runtime/defaults/velocity.properties
Default ResourceManager initializing. (class org.apache.velocity.runtime.resource.ResourceManagerImpl)
Resource Loader Instantiated: org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader
ClasspathResourceLoader : initialization starting.
ClasspathResourceLoader : initialization complete.
ResourceCache : initialized. (class org.apache.velocity.runtime.resource.ResourceCacheImpl)
Default ResourceManager initialization complete.
Loaded System Directive: org.apache.velocity.runtime.directive.Literal
Loaded System Directive: org.apache.velocity.runtime.directive.Macro
Loaded System Directive: org.apache.velocity.runtime.directive.Parse
Loaded System Directive: org.apache.velocity.runtime.directive.Include
Loaded System Directive: org.apache.velocity.runtime.directive.Foreach
Created: 20 parsers.
Velocimacro : initialization starting.
Velocimacro : adding VMs from VM library template : VM_global_library.vm
[ERROR]ResourceManager : unable to find resource ‘VM_global_library.vm’ in any resource loader.
Velocimacro : error using  VM library template VM_global_library.vm : org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource ‘VM_global_library.vm’
Velocimacro :  VM library template macro registration complete.
Velocimacro : allowInline = true : VMs can be defined inline in templates
Velocimacro : allowInlineToOverride = false : VMs defined inline may NOT replace previous VM definitions
Velocimacro : allowInlineLocal = false : VMs defined inline will be  global in scope if allowed.
Velocimacro : initialization complete.
Velocity successfully started.
[archetype:create]
—————————————————————————-
Using following parameters for creating Archetype: maven-archetype-quickstart:1.0
—————————————————————————-
Parameter: groupId, Value: net.bressure
Parameter: packageName, Value: net.bressure.vroom
Parameter: package, Value: net.bressure.vroom
Parameter: artifactId, Value: vroom
Parameter: basedir, Value: /home/thierry/NetBeansProjects
Parameter: version, Value: 1.0-SNAPSHOT
********************* End of debug info from resources from generated POM ***********************
Archetype created in dir: /home/thierry/NetBeansProjects/vroom
————————————————————————
BUILD SUCCESSFUL
————————————————————————
Total time: < 1 second
Finished at: Mon Oct 06 12:50:15 CEST 2008
Final Memory: 66M/69M
————————————————————————

Le projet qui vien d’être créé est compilable et comporte déjà les prémices de l’atelier de développement Java agile. Le build du projet passe par une phase d’éxécution des tests unitaires. Voici un exemple de sortie en faisant un clic-droit sur le projet et sélectionnant build :

Scanning for projects…
project-execute
[#process-resources]
[resources:resources]
Using default encoding to copy filtered resources.
[#compile]
[compiler:compile]
Nothing to compile – all classes are up to date
[#process-test-resources]
[resources:testResources]
Using default encoding to copy filtered resources.
[#test-compile]
[compiler:testCompile]
Nothing to compile – all classes are up to date
[#test]
[surefire:test]
Surefire report directory: /home/thierry/NetBeansProjects/vroom/target/surefire-reports
——————————————————-
T E S T S
——————————————————-
Running net.bressure.vroom.AppTest
Results :
[#package]
[jar:jar]
[#install]
[install:install]
Installing /home/thierry/NetBeansProjects/vroom/target/vroom-1.0-SNAPSHOT.jar to /home/thierry/.m2/repository/net/bressure/vroom/1.0-SNAPSHOT/vroom-1.0-SNAPSHOT.jar
————————————————————————
BUILD SUCCESSFUL
————————————————————————
Total time: 1 second
Finished at: Mon Oct 06 16:23:49 CEST 2008
Final Memory: 18M/56M
————————————————————————

Un projet qui build est un projet qui doit être partagé. Nous allons importer dans le repository l’arborescence du projet. Pour ce faire Netbeans s’interface avec Subversion à merveille. Sur le projet utiliser un clic droit > Versionning > Import to Subversion Repository pour accéder à la fenêtre de dialogue pour choisir l’emplacement sur le serveur subversion.

Nebeans Menu d'import de nouveau sources dans Subversion Netbeans Dialogue d'import de sources dans subversion

L’url à renseignée est de la forme svn://<serveur>/<projet>/trunk et dans le cas de l’article cela donne svn://localhost/vroom/trunk

Dans la boite de dialogue suivante supprimer le dernier répertoire pour ne garder que <projet>/trunk

Le trunk final est important car cela respecte l’arborescence classique des projets sous Subversion. Le trunk est l’équivalent de la HEAD sous CVS.

Nous avons créé un projet maven 2 en utilisant un archétype. Le projet est disponible dans le référentiel de source Subversion. La prochaine étape va être la mise en place de l’intégration continue.

Un environnement de developpement Java

J’ai eu envie de faire un petit développement personnel en Java et comme j’avais réinstallé mon ordinateur, je devais refaire mon environnement depuis le début. Ce n’est d’ailleurs pas un si grand mal et l’exercice serait même intéressant car il arrive que nous devions le faire quand par exemple une défaillance de notre IDE survient comme un crash d’Eclipse réduisant à néant la configuration du workspace.

En partant d’une distribution classique Ubuntu 64 bit avec les dépôts officiels, peut-on monter un environnement de développement Java ? Est-il nécessaire d’installer des logiciels manuellement et donc maintenir par soi-même les mise-à-jour ? Est-ce que l’installation est accessible ou nécessite-t-elle une équipe système ? Pour réponde à ces questions il faut commencer par définir ce dont nous avons besoin.

Le système d’exploitation est un Linux abordable: Ubuntu. Nous supposons qu’il est déjà installé et fonctionnel. C’est une supposition très raisonnable. A partir de là il nous faut obtenir un environnement de développement Java complet comprenant :

  • un outils de modélisation
  • un éditeur de source
  • un compilateur
  • un outils de versionnage
  • un outils d’intégration continue

L’outil de modélisation sera bien pratique pour les phases préliminaires avant tout codage et devra permettre au moins la génération de code. L’opération inverse sera aussi utile car une fois emporté dans le code on risque bien d’oublier l’architecture générale et voire même la galvauder dans notre élan. Nous pouvons soit opter pour outils dédié  comme BOUML ou bien se contenter des fonctions UML de l’IDE. LEs 2 IDE open-source majeurs propose de l’UML.

L’IDE doit permettre d’écrire du code, d’apporter la coloration syntaxique, l’assistance à la frappe, le debogguage et le support de plusieurs JVM. L’IDE ne doit pas nous enfermé dans un système propriétaire de build et devra donc s’interfacer simplement avec notre outil de build préféré : Maven. Nous porterons notre choix sur Netbeans dont l’offre “packagée” estplus complète que Eclipse et mieux adapté que ce dernier pour une utilisation avec Maven.  La version 6.0 est installable directement depuis Ubuntu en utilisant Synaptic. Il faudra ajouter les plugins Subversion, Maven et UML pour completer l’installation de base. Cela ce fait directement depuis l’ID.

La partie compilateur dans le cas de java se compose du JDK  qui est l’ensemble des outils pour compiler et debugger des programmes écrit en Java. Le JDK contient aussi un JRE qui permet d’éxécuter les programmes Java. C’est le point de départ de notre environnement. Les dépots officiels d’Ubuntu propose OpenJDK 1.6 donc son installation se fera le plus simplement du monde via le gestionnaire de paquet Synaptic.

L’outils de versionnage devra permettre un refactoring constant du code et devra gérer le renommage les déplacements de fichiers sans perte d’historique sans avoir recours à l’administration du serveur. On choisira naturellement subversion dont l’installation est possible depuis les dépôt Ubuntu.

L’intégration continue est une pratique obligatoire dans les projets nécessitant plusieurs développeurs ou plusieurs module devant être assemblés. Cependant même dans le cas d’un seul développeur il aura besoin de découper le projet en modules qui devront être assemblés. Un outils permettant d’assurer le que l’ensemble “fonctionnent” correctement est nécessaire. Afin de simplifier l’intégration nous allons choisir Continuum qui se marie à merveille avec Maven. Son installation se fera manuellement en décompressant l’archive trouvé sur le site officiel de continuum

Enfin pour terminer la liste des outils nous mentionnerons l’outils de build maven qui est avec l’intégration continue les éléments le splus importants de l’environnement de developpement d’un point de vue structurel. Nous allons installer maven par le biais de Synaptic. Pour simplifier et offrir une évolutivité maximal dans l’utilisation de maven nous allons utiliser le gestionnaire de repository Apache Archiva

Maintenant que tout est installé, il faut s’assurer que tout fonctionne bien ensemble. Pour cela l’article suivant traitera de la création initiale du projet.