Les addons, c'est sa Forge

Magazine
Marque
GNU/Linux Magazine
Numéro
186
Mois de parution
octobre 2015
Domaines


Résumé
Dans cet article, nous allons apprendre comment créer des addons pour Forge, le framework de création rapide d'applications Java EE édité par JBoss/Red Hat, et ainsi, l'étendre.Vous avez aimé la création de projet Java EE du précédent article, alors vous allez aimer créer un addon pour produire des projets Android !

Body

JBoss Forge est un générateur de code, initialement orienté Java EE. Dans cette série d'articles, nous allons voir comment l'étendre pour générer du code Android !

Pour suivre cet article, il est préférable de connaître l'utilisation de JBoss Forge, de JBoss Developper Studio (JDS)...  bref, d'avoir lu l'article précédent consacré à Forge [1].

Le but de cet article est de vous permettre de créer vos propres outils pour vos projets en abordant des points essentiels, utilisés dans un contexte Android.
Ces outils qui vous permettront d'automatiser des tâches répétitives. Donc moins d'ennui au quotidien. Oh joie !

1 Panorama

Avant d'entrer dans le vif du sujet, sachez que désormais Forge peut s'utiliser dans Eclipse, dans IntelliJ Idea et dans NetBeans. Toujours, en sus de la console.

Il y a deux addons que je souhaite porter à votre attention afin de vous faire voir combien les addons peuvent être différents les uns des autres.
Le premier ajoute la synthèse vocale à Forge. Vous pouvez donc l'utiliser pour faire parler vos scripts Forge.
Inutile, donc indispensable :), il vous permet de suivre vos scripts les yeux fermés.
Cet addon est open source et le lien est présent à la fin de l'article [2].

Le deuxième n'est pas open source, mais c'est mon dernier exemple en date d'addon. Dans le cadre d'un projet en cours, je l'ai créé pour automatiser des tâches répétitives de création de classes.
À partir de données de connexion JDBC et d'un nom de procédure stockée, il permet de générer les classes d'entrée (input) et de sortie (output) de cette procédure ainsi que le DAO, le service et leurs interfaces Spring respectives sans oublier l'appel en JPA 2.1. Que du bonheur… une fois que cela fonctionne :)

C'est en fait assez simple. Il suffit d'écrire le code une fois à la main puis de savoir qu'il faut utiliser les metadata de JDBC et le pattern template pour générer ce code.
Comptez quelques heures à feu doux tout de même.

Fin du panorama. À partir de ce grand écart, à vous d'imaginer ce qui vous aiderait dans votre quotidien.

Puisque les addons s'écrivent en Java, et que pléthore de librairies existent, il y a tant de choses à écrire.
De la publication d'un gist directement à partir de l'IDE, ou moins sérieusement mettre à jour son statut FB, envoyer des tweets ou développer une messagerie de groupe. C'est vous qui voyez.

2 Forge, ton core !

Ceci n'est pas un appel à faire plus d'exercice physique, mais un rappel sur le noyau (en anglais core) de Forge. Dans l'article précédent, j'indiquais que Forge (la distribution) est modulaire, car lui-même constitué d'addons (réutilisables), comme Core et UI. Ces addons, vous en avez vu la liste complète lorsque vous avez créé votre premier addon lors de l'article précédent [1].

Les indispensables Core (noyau, sans lui rien n'est possible), UI (qui permet d'interagir avec l'utilisateur via les interfaces) sont les addons desquels dépendront toujours vos addons, mais il y en a d'autres tout aussi utiles :

- Configuration a pour fonction de permettre de stocker de l'information, de façon persistante ;

- Environment permet aussi de stocker des informations, à partager entre addons, mais de façon volatile ;

- Template permet d'utiliser des modèles pour créer des fichiers (voir le design pattern homonyme, ou l'outil Freemarker) ;

- Parser-Java, Parser-XML et Parser-JSON permettent de manipuler des fichiers de chacun de ces types ;

- Resources permet notamment de lire des fichiers.

Ce sont les addons principaux, nous reviendrons sur certains d'entre eux plus avant dans le fil de cet article.

La liste complète se trouve à l'adresse http://forge.jboss.org/addons (cochez la case Core).

Revenons à la création de projet Android.

3 Périmètre

Nous allons revoir comment créer un addon simple (mais non simpliste comme l'avant-goût de l'article précédent) qui créé la structure d'un projet Android.

Parce que je ne suis pas autorisé à remplir tout le magazine avec cet article, le périmètre du code à suivre ne sera pas exactement la création d'un projet identique à celui généré par l'assistant d'ADT (dans Eclipse).
Néanmoins, nous allons voir comment faire saisir des informations à l'utilisateur et les utiliser.
C'est LA brique de base pour tous vos futurs addons.
Nous utiliserons ensuite un addon préexistant, pour créer des fichiers selon un modèle.

4 Rappel – un addon simple

Comme vu dans le précédent article consacré à Forge, il est extrêmement simple d'écrire un addon de type «Au revoir Dennis Ritchie» affichant un simple message à l'écran.

Les étapes sont les suivantes :

- Création d'un projet de type addon, avec la fenêtre Forge (<Control> + <Shift> + <'> …. à priori) ;

- Ajouter les dépendances aux addons Core et UI ;

- Créer une classe ;

- Créer une méthode annotée @Command (lui mettre des attributs value et categories parlants) ;

- Lui faire retourner Results.success(« Meunier, tu dors ?») ;

- Puis, exécuter la commande addon-build-and-install ;

- Et enfin, exécuter la commande créée.

Vous trouverez le code correspondant sur le compte GitHub du magazine.

Battons le fer pendant qu'il est chaud, et commençons notre nouvel addon à partir de ces étapes simples.

Pour rappel, dans ADT, l'assistant pour créer un projet Android ressemble au contenu de la figure 1.

Forge2B1_CreaPrj1_fig1

Fig.1 : Premier écran de la création d'un projet Android avec ADT.

Comme vous le voyez, il s'agit de faire saisir quelques informations à l'utilisateur.

Avec Forge, il est très rapide d'obtenir un écran s'en approchant, tel que celui présenté en figure 2.

Forge2B1_fen_crea_prj_full_fig_02

Fig. 2 : Notre propre écran, forgé à la main. Notez l'enclume en haut à droite.

Pour arriver à ce résultat, le code est le suivant (admirez sa concision) :

public class NewAndroidProject {

 String[] PROJECT_FOLDERS = {"assets","bin","gen","libs","res","src"};

 

 @Command(categories={"AndroidSimple"},

   help="Help I need somebody",

   value="Android::Project")

 public Result new_android_project(

   

   @Option(value = "location",label="Répertoire où créer le projet",required=true, type="String",defaultValue="/tmp/projets", enabled=false) String repertoireRacine,

   @Option(value = "prjName",label="Project Name",required=true,type="String", description="Le nom du projet",requiredMessage="Il faut un nom",shortName='p') String projectName,

   @Option(value = "appName",label="Nom de l'application",required=true,type="String",defaultValue="MillionDollarProject" ) String appName,

   @Option(value="package",label="Nom du package Principal",required=true,type="String", defaultValue = "org.wadael.n.million") String packageName,

   @Option(value="minSdk", label="Minimum SDK",required=true,type="Long", defaultValue= "16") Integer minSDK,

   @Option(value="targetSdk", type="Integer",defaultValue = "21") Integer cibleSDK){

  

  File racine = new File(repertoireRacine + File.separator + projectName);

  if(!racine.mkdirs()) // création du répertoire racine du projet

   Results.fail("Impossible créer répertoire " + racine );

  else{

   File f = null;

   for(String rep : PROJECT_FOLDERS){

    f = new File( racine.getAbsolutePath()+File.separator + rep );

    f.mkdirs();

    System.out.println("creation du repertoire " + f.getAbsolutePath());

   }

  }

  return Results.success( "Waouh. " + projectName + " " + appName);

 }

}

Et là, dans ces quelques lignes, vous pouvez voir qu'il y a non seulement le code pour l'interface utilisateur, mais aussi le code pour créer l'arborescence de répertoires.

Ne nous mentons pas, ce code ne crée pas la totalité d'un projet Android, mais il crée le projet à l'endroit demandé (par défaut /tmp/projets) avec l'ensemble des répertoires de haut niveau qui constituent un projet Android. Toujours pour une question de place, cela n'aurait pas de sens de mettre ici des remplacements de chaînes dans des Strings qui iraient dans des fichiers. Pensons aux forêts. Pour le code façon simpliste, voir GitHub.

La magie qui amène le résultat que l'on vient de voir provient des annotations utilisées. Examinons ces annotations.

La première, apposée sur la classe est :

@Command(categories={"AndroidSimple"}, help="Help I need somebody", value="Android::Project")

L'attribut categories est le nom que l'on retrouve dans la première colonne de la fenêtre Forge. Il est possible d'indiquer plusieurs catégories pour un addon.

Forge2B1_capture_fenForge_AndroidSimple_fig_03

Fig. 3 : La fenêtre Forge d'Eclipse.

L'attribut value correspond à la deuxième colonne et au titre de l'assistant, qui est aussi le nom de la commande dans la console Forge !

Rappelez-vous que Forge peut s'exécuter tant en ligne de commandes que dans Eclipse. Aussi, malgré la complétion automatique de la console, évitez les majuscules, les caractères accentués et les espaces dans les valeurs de cet attribut (c’est-à-dire ne faites pas ce qu'indique la figure 3).

Sachez que la valeur sera automatiquement normalisée par Forge, ici « Android::Project » devient « android-project » dans la console Forge. Ce qui est joli dans Eclipse ne l'est pas forcément en ligne de commandes.

Enfin, l'attribut help correspond au sous-titre de l'assistant que l'on vient de forger (voir figure 2).

La deuxième annotation utilisée est @Option dont la première occurrence est :

@Option(value = "location",label="Répertoire où créer le projet",required=true, type="String",defaultValue="/tmp/projets", enabled=false) String repertoireRacine

Les paramètres sont la valeur, le libellé (label), le caractère obligatoire (required=true), le type (Chaîne), et la valeur par défaut.

Valeur et valeur par défaut ? Diantre, n'aurions-nous pas un problème de design ici ? Que nenni l'ami.

La valeur par défaut est donc, dans Eclipse, la valeur initiale du champ ET dans la console, cela sera la valeur utilisée si l'utilisateur ne valorise pas l'attribut. Logique.Tandis que value  sera le nom utilisé pour ce paramètre dans la console Forge. Oui, il est différent de label. Mais seul value est obligatoire.

Le nom value est hérité des annotations Java @Option("maValeur") correspondant à @Option(value= "maValeur") en version longue.

Si l'un des champs en required=true n'est pas renseigné, il ne sera pas possible de valider l'écran (car le bouton Finish reste grisé).

D'autres paramètres supplémentaires sont possibles comme dans cet autre exemple :

@Option(label="Project Name",required=true,type="String", value = "ProjectName",description="Le nom du projet",requiredMessage="Il faut un nom",shortName='p') String projectName,...)

Ici, description sera le texte de l'infobulle au-dessus du champ si le pointeur reste dessus.

Pour donner des instructions à l'utilisateur, renseignez l'attribut requiredMessage, qui sera utilisé dans les cas d'absence ou d'erreur de saisie.

L'attribut shortName indique la touche à combiner avec la touche <Alt> pour mettre le curseur de saisie dans le champ correspondant (dans Eclipse). Bonne idée !

Pour compiler le code, ouvrez la fenêtre Forge, et sélectionnez Build and Install an addon, puis choisissez le répertoire du projet. Patientez.

Ne vous inquiétez pas si la compilation vous semble extrêmement lente. Elle l'est ! Ce n'est pas votre machine qui est devenue particulièrement lente. En fait, la machine bosse beaucoup, car il y a beaucoup de choses à faire faire à la machine pour arriver à un tel niveau de simplicité pour les développeurs. Si vous exécutez Forge dans un Shell en dehors d'Eclipse, la commande est addon-build-and-install.

Exécutez votre addon.

Allez vérifier le contenu du répertoire /tmp/projets/. Il doit contenir un répertoire contenant des répertoires vides. Victoire. Vous voici armé pour développer vos propres addons.

5 Auto critique

En toute fausse modestie, cet addon a un aspect assez formidable. En très peu de code, nous obtenons un comportement voulu, intégré dans l'IDE. Et il est même possible d'avoir plusieurs commandes @Command dans une même classe (l'idéal pour multiplier les commandes simples sans multiplier les classes).

Mais il n'est évidemment pas parfait. Tout y est chaîne de caractères, il n'y a, par exemple, pas de choix dans une liste déroulante possible. Aucune vérification n'est possible et l'on peut saisir Lollipop à la place de 21, ce qui est certes sémantiquement équivalent, mais le projet Android que l'on obtiendrait compilerait beaucoup moins bien.

Ensuite, cette méthode permet de créer seulement un écran de saisie, pas un « assistant ».

Mais cela est possible, voir la classe org.jboss.forge.addon.ui.wizard.UIWizard ainsi que le projet MetaForgeWizard sur mon compte GitHub [3].

Prochainement

Dans un prochain article, nous apprendrons un autre moyen d'écrire des addons, une deuxième façon que je nommerai, à défaut d'un meilleur nom, de mode « moins simple, mais mieux » pour avoir accès à plus de fonctionnalités, en commençant par la validation et l'utilisation d'autres widgets d'UI (liste déroulante, sélecteur de fichier, etc.).

Références

[1] J. Baton, « JBoss Forge2, Java EE facile, très facile », GNU/Linux Magazine n° 180, mars 2015.

[2] Addon de synthèse vocale :  https://github.com/forge/forge-speech-addon

[3] Mon compte GitHub :https://github.com/wadael

Je remercie Fabien Dubail, Koen Aers, Horacio Gonzalez (@lostInBrittany) et Philippe Charrière (@k33g_org) pour leur aimable travail de relecture de cet article, ainsi qu'Antonio Goncalves (@agoncal) pour m'avoir fait découvrir l'extensibilité de cet outil, George Gastaldi (@gegastaldi) pour son aide, ma société : DRiMS (@drims_ssii), qui m'a permis de travailler avec cet outil (8h/j >> 3h/nuit) et bien sûr, Sylvie qui s'occupe de nos enfants quand je travaille sur un article.




Articles qui pourraient vous intéresser...

Mise au point à distance avec GDB

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
111
Mois de parution
novembre 2020
Domaines
Résumé

Le débogueur GDB est un outil indispensable pour la mise au point de programmes, a fortiori dans le cas du développement croisé (mise au point à distance ou « remote debug »). Dans cet article, nous allons voir comment mettre en place différentes solutions suivant plusieurs cas de figure (programme en espace utilisateur, noyau Linux statique ou pilote en espace noyau). Afin de permettre au plus grand nombre de lecteurs de tester les exemples décrits, nous utiliserons l’émulateur QEMU (et Buildroot) pour les démonstrations.

Jouons avec l'obfuscation de code

Magazine
Marque
GNU/Linux Magazine
Numéro
242
Mois de parution
novembre 2020
Domaines
Résumé

Rendre son code illisible lorsque l'on prêche pour l'open source, c'est le mal incarné. Toutefois, il est possible de concevoir que dans certains cas, on souhaite obscurcir des parties d'un code et, surtout d'un point de vue purement technique, cela peut se révéler intéressant.

Le point sur le débogage en Python

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
111
Mois de parution
novembre 2020
Domaines
Résumé

Il n'existe pas une unique façon de déboguer du code en Python. Dans cet article, nous allons faire un rapide tour des différentes techniques qui s'offrent à vous pour traquer les bugs.

Les bases de LaTeX sous GNU/Linux et Windows

Magazine
Marque
GNU/Linux Magazine
Numéro
242
Mois de parution
novembre 2020
Domaines
Résumé

Et si nous retournions aux sources ? Des articles sont régulièrement consacrés à LaTeX dans ce magazine, mais comment les utiliser si l'on part de zéro ? Dans cet article, je vous propose de voir ou revoir comment installer LaTeX, configurer un éditeur et gérer les extensions/paquets pour une utilisation sous GNU/Linux ou Windows. Une sorte de guide de survie pour prof de maths, en cas d'obligation d'enseignement à distance...

Débugage facile avec Sentry

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
111
Mois de parution
novembre 2020
Domaines
Résumé

Nous le savons tous, aucun code n’est exempt de bugs. Nous avons beau écrire tous les tests unitaires du monde, tous les tests fonctionnels, avoir une couverture du code par nos tests de 200 %, il y a toujours des bugs qui passent à travers les mailles du filet. Sentry est là pour vous aider à les trouver et à les corriger grâce à vos utilisateurs, et ce, sans qu’ils ne s’en rendent compte.