Forge est un outil et un framework pour le développement rapide d'applications Java EE basées sur Maven. Il ne s'agit pas d'une nouveauté de l'éditeur de WildFly : la v1.0 du projet date de février 2012 mais aujourd'hui, avec la branche 2.x, Forge a acquis une maturité qui le rend encore plus intéressant pour tous les développeurs Java, qu'ils soient débutants ou experts, pressés ou bien bidouilleurs.
Si créer des applications est son rôle premier, JBoss Forge, de par sa construction modulaire, est très ouvert à l'imagination. Nous verrons d'abord la productivité exceptionnelle que ce framework offre, avant de le découvrir plus profondément et de jouer un peu avec. Parce que l'on aime cela, telle est notre joie.
1 Pré-requis
L'unique pré-requis technique pour utiliser Forge est d'avoir un JDK de type Java 7 ou supérieur. Comprenez bien que c'est suffisant pour utiliser Forge dans un but de découverte mais pas pour exécuter l'application Java EE que nous allons créer. Pour suivre le déroulement de cet article, des connaissances en Java EE, Maven, serveurs d'applications et base de données sont préférables.
L'application Java EE que nous allons créer nécessitera un serveur d'applications pour son exécution et une base de données pour conserver en base les informations portées par les entités JPA (Java Persistence API) utilisées. Par conséquent, il vous faudra une base de données et un serveur d'applications accessibles à votre projet pour tester le résultat, soit installer l'environnement intégré. Ceci n'est pas obligatoire et l'installation d'une base de données et d'un serveur d'applications est en dehors du cadre de cet article.
2 Installation
Le premier pas de ce voyage initiatique dans les territoires de la génération de code est l'installation du logiciel. Trois types d'installations sont proposés :
- Télécharger JBoss Developper Studio, une version d'Eclipse version Java EE augmentée des JBoss Tools, packagée par Red Hat JBoss ;
- Télécharger les JBoss Tools pour les installer dans un Eclipse pré-existant ;
- Télécharger une version utilisable en ligne de commande.
La suite de cet article utilisera d'abord la version en ligne de commande puis JBoss Developper Studio. Pour télécharger ces deux versions, rendez-vous sur http://forge.jboss.org/download.
Si vous n'avez pas encore de serveur d'applications et de base de données installés sur votre machine, ou simplement pas l'envie de les configurer, je vous conseille d'utiliser JBoss Developper Studio car il est accompagné de WildFly, un serveur full Java EE et de H2, une base de données simple et rapide, adaptée à ce que nous allons faire. Ainsi, environnement de code, serveur et base seront déjà configurés... c'est toujours 2 jours-homme de gagnés :)
Pour l'Installation de la version en ligne de commandes, décompressez l'archive dans un répertoire de votre choix et ouvrez un shell pour déclarer ce répertoire comme valeur de la variable d'environnement FORGE_HOME en éditant le fichier .profile ou .bashrc de votre répertoire personnel. Ajoutez $FORGE_HOME/bin à votre variable PATH, puis exécutez :
$ source nomDuFichierModifié
Sur Ubuntu et ses variantes, cela correspond aux commandes suivantes si vous utilisez le bash :
$ nano .bashrc
$ source .bashrc
Voilà, cela en est fini pour l'installation, votre base de registre n'est pas polluée de nouvelles clefs inutiles :)
3 Et maintenant, créons une application Java EE
Maintenant, positionnez-vous dans le répertoire où vous souhaitez créer votre projet Java EE le plus rapidement de toute votre vie de codeur jusque là.
Dans votre terminal, tapez
$ forge
Un nouveau prompt s'affiche, encore plus puissant que Bash. Et avec lui aussi, la touche de tabulation <Tab> est votre fidèle second.
jerome@bosphore ~ $ forge
_____
| ___|__ _ __ __ _ ___
| |_ / _ \| `__/ _` |/ _ \ \\
| _ | (_) | | | (_| | __/ //
|_| \___/|_| \__, |\___|
|___/
JBoss Forge, version [ 2.9.2.Final ] - JBoss, by Red Hat, Inc. [ http://forge.jboss.org ]
[jerome]$
Parce que, comme on peut le lire et l'entendre dire à longueur de temps, c'est très long et très très lourd de faire du Java EE, nous allons donc voir le contraire dans le but de vous faire apprécier la puissance de cet outil. Les heureux lecteurs présents lors de l'événement Devoxx France 2014 auront déjà pu voir le Java Champion Antonio Goncalves en faire la démonstration avec son calme légendaire.
Dans le prompt de Forge, tapez ce que vous êtes : un pro !
[jerome]$ pro
Puis appuyez sur <Tab> et la commande se complète en :
[jerome]$ project-new
Inattendu. Forge vous fait revivre ce moment de bonheur où vous êtes passés du prompt DOS à un vrai shell. Appuyez à nouveau sur <Tab> et ce sont les paramètres de la commande qui vous sont proposés. Magique.
[jerome]$ project-new
--named --version --targetLocation --buildSystem
--topLevelPackage --finalName --type
Dans votre shell, sauf à utiliser un moniteur monochrome parce que vous poussez la « hipsteritude » un peu loin, le paramètre --named sera en couleur pour indiquer qu'il est obligatoire. Il apparaît ci-dessus en gras pour le démarquer. Comme il se doit, les autres paramètres prendront les valeurs par défaut si vous ne les renseignez pas.
Saisissez ensuite :
[jerome]$ project-new --named mesNews --topLevelPackage org.moi --type
Appuyez sur <Tab>, et ce sont les valeurs possibles pour le type qui s'affichent :
war addon from-archetype
jar resource-jar from-archetype-catalog
parent ear
Formidable ! Pas besoin de trouver la documentation en ligne. J'adore. Vous aussi, j'en suis certain. Prenons-en de la graine pour nos projets.
Choisissons le type war pour continuer notre guerre aux idées reçues. La commande finale est :
[jerome]$ project-new --named mesNews --topLevelPackage org.moi --type war --finalName newsAngularJs
***SUCCESS*** Project named 'mesNews' has been created.
Petit aparté, maintenant qu'un projet est créé, pour une commande à essayer, qui porte bien son nom : command-list. Je vous invite à jeter un œil sur la sortie écran qu'elle génère avant de passer aux prochaines commandes. Ne l'oubliez pas, elle vous servira ultérieurement à vérifier la disponibilité de commandes supplémentaires que vous aurez installées. Aparté dans l'aparté, les commandes de Forge visibles à un instant t dépendent du contexte (ici, il faut qu'un projet soit créé). Surprenant, on peut filtrer avec more :
[jerome]$ command-list | more
Maintenant, faites exécuter les commandes suivantes une à une :
[jerome]$ jpa-setup --provider Hibernate --container JBOSS_EAP6
[jerome]$ jpa-new-entity --named News --targetPackage org.moi.model --idStrategy AUTO
[jerome]$ jpa-new-field --named titre --type String
[jerome]$ jpa-new-field --named texte --type String
[jerome]$ jpa-new-field --named quand --type java.util.Date
Les paramètres de la commande jpa-setup sont optionnels, par défaut Forge créera une base H2 en mémoire. Ces paramètres sont assurés de fonctionner pour un déploiement vers WildFly.
En quelques lignes de commandes, vous avez généré la classe suivante :
package org.moi.model;
import javax.persistence.Entity;
import java.io.Serializable;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Column;
import javax.persistence.Version;
import java.lang.Override;
import java.util.Date;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;
@Entity
@XmlRootElement
public class News implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
@Version
@Column(name = "version")
private int version;
@Column
private String titre;
@Column
private String texte;
@Column
@Temporal(TemporalType.DATE)
private Date quand;
public Long getId() {
return this.id;
}
public void setId(final Long id) {
this.id = id;
}
public int getVersion() {
return this.version;
}
public void setVersion(final int version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
{
return true;
}
if (!(obj instanceof News))
{
return false;
}
News other = (News) obj;
if (id != null)
{
if (!id.equals(other.id))
{
return false;
}
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public String toString() {
String result = getClass().getSimpleName() + " ";
if (id != null)
result += "id: " + id;
result += ", version: " + version;
if (titre != null && !titre.trim().isEmpty())
result += ", titre: " + titre;
if (texte != null && !texte.trim().isEmpty())
result += ", texte: " + texte;
if (quand != null)
result += ", quand: " + quand;
return result;
}
// Getters et setters supprimés pour un minimum de concision
}
Excellent. Un peu verbeux.
Les méthodes hashCode et toString sont générées aussi. Bien.
Je vous invite à jeter un coup d’œil au fichier pom.xml également.
Maintenant, nous allons faire générer une interface Web pour nos news, par la technique du scaffolding, et pour céder à la mode, elle sera basée sur AngularJS.
Le scaffolding consiste en de la génération automatique de code. Le logiciel utilise les informations à sa disposition pour créer une application de type CRUD basique. Généralement, c'est une base de données existante qui sert …. de base :)
Ce n'est pas dans les capacités initiales de Forge mais grâce à son extensibilité et au travail de la communauté, il existe un addon de scaffolding AngularJS. Pour l'installer directement à partir de Github, saisissez cette commande :
[jerome]$ addon-install-from-git --url https://github.com/forge/angularjs-addon.git --coordinate org.jboss.forge.addon:angularjs
Bienvenue dans un monde nouveau ! Cette installation va prendre un certain temps, par un effet de pelote typique de Maven, qui va remplir un peu plus votre dépôt M2.
Coupez le chrono et allez prendre une pause ; heureusement, que cette installation n'est à faire qu'une seule fois...
Passons maintenant à la génération de l'interface utilisateur à proprement parler :
[jerome]$ scaffold-setup --provider AngularJS
[jerome]$ scaffold-generate --provider AngularJS --targets org.moi.model.News
Puis, on lance la construction avec, je vous le donne en mille, Émile :
[jerome]$ build
L'application est générée et est prête à être déployée. Le war se trouve dans le répertoire target sous le nom newsAngularJs.war, ce qui est la valeur du paramètre finalName donnée lors de la création du projet. Rien ne se perd. Allez jeter un œil dans le répertoire du projet pour satisfaire votre curiosité.
L'artefact déployable généré est basé sur des fichiers source qui ont été générés aussi et constituent donc un projet de type Maven. Vous pouvez importer le projet dans Eclipse/JBoss Developper Studio par Import > Existing Maven Project pour effectuer toute modification ou ajout que vous jugerez nécessaire. Et puis, bien entendu, vous pouvez l'ajouter à votre serveur d'application Java EE pour l'exécuter.
L'application que vous venez de générer ressemble à celle présentée en figure 1.
Fig. 1 : Page d'accueil de l'application générée
En cliquant sur « News », sous l'enclume, on arrive à un écran d'administration visible en figure 2.
Fig. 2 : Page de création d'une nouvelle
Impressionnant, mais il faut admettre que l'on ne peut pas mettre cela en ligne sans quelques retouches pour rebrander le résultat, comme mettre son logo et enlever quelques liens. Certes, mais cela a été généré en quelques minutes. Et un pro du front pourra embellir ce premier jet, un peu brut de fonderie.
Si vous avez eu le souffle coupé, reprenez votre respiration avant de devenir bleu et essayez d'estimer le temps qu'il vous serait nécessaire pour créer l'équivalent. Fascinant outil à mon humble avis.
Si vous déployez cette archive et que la création d'une news ne fonctionne pas, pas d'inquiétude, c'est normal. Utilisez le scaffolding JSF, redéployez et cela marchera. L'application AngularJS utilise des points d'entrée REST que nous n'avons pas encore créés.
3.1 Bonus : point d'accès REST
Pour générer un point d'accès REST à nos news, les commandes sont :
[jerome]$ rest-setup --applicationPath rest --targetPackage org.moi.rest --config APP_CLASS
[jerome]$ rest-generate-endpoints-from-entities --targets org.moi.model.News --persistenceUnit mesNews-persistence-unit --generator JPA_ENTITY
Et là, Forge a créé le paquet org.moi.rest, dans lequel se trouvent deux classes. La première est la classique RestApplication qui permet de définir le point d'entrée de l'interface REST de toute l'application :
@ApplicationPath("rest")
public class RestApplication extends Application { }
Et la deuxième classe, NewsEndpoint est le point d'entrée vers nos news.
Voici une version expurgée du code source, sans aucun corps de méthode, qui montre le respect du paradigme REST, avec l'utilisation conforme des méthodes HTTP GET, POST, PUT et DELETE pour la manipulation de cette entité :
@Stateless
@Path("/news")
public class NewsEndpoint
{
@PersistenceContext(unitName = "mesNews-persistence-unit")
private EntityManager em;
@POST
@Consumes("application/json")
public Response create(News entity)
@DELETE
@Path("/{id:[0-9][0-9]*}")
public Response deleteById(@PathParam("id") Long id)
@GET
@Path("/{id:[0-9][0-9]*}")
@Produces("application/json")
public Response findById(@PathParam("id") Long id)
@GET
@Produces("application/json")
public List<News> listAll(@QueryParam("start") Integer startPosition, @QueryParam("max") Integer maxResult)
@PUT
@Path("/{id:[0-9][0-9]*}")
@Consumes("application/json")
public Response update(News entity)
}
Comme vous le voyez, ce code est très classique et vous auriez certainement écrit au moins la même chose. Il faut voir ce code comme une base de travail à laquelle il est possible d'ajouter ce que vous souhaitez comme des annotations pour définir les autorisations par exemple.
La méthode listAll, qui retournera au format JSON la liste (paramétrée) de toutes les news pourra être accessible par votre navigateur préféré à l'adresse suivante : http://localhost:8080/newsAngularJs/rest/news?start=0&max=1610. Mais à priori, et à fortiori aussi, cela ne renverra rien si vous n'avez pas joué à créer des entrées avec l'interface utilisateur Web.
D'ailleurs, il est probable que vous obteniez des erreurs en voulant créer des news (au moment du clic sur le bouton Save). Pas d'affolement, c'est normal, ne rejetez pas la forge, c'est uniquement de la configuration à revoir en fonction de ce sur quoi vous l'avez déployé. Votre environnement ne possède peut-être pas de datasource au nom par défaut utilisé par Forge. Et, sans points d'entrée REST, l'application en AngularJS, qui s'exécute dans votre navigateur, n'a aucune communication possible avec le serveur.
C'est quand cela ne fonctionne pas que toutes vos compétences Java EE s'avèrent nécessaires.
Voilà pour l'utilisation de Forge en mode ligne de commande.
Les téléchargements divers de la première utilisation ayant (fortement) ralenti le processus de création de l'application, je vous propose de recommencer un nouveau projet afin d'apprécier pleinement la rapidité de cet outil. Pourquoi ne pas créer un projet de blagues, avec un texte, un auteur, une date, un booléen pour indiquer si elle est destinée aux adultes,… et les informations qui vous semblent pertinentes. Nous générerons ensuite une version JSF (scaffolding Faces) et une version AngularJS.
3.2 Scripting
Il est possible de faire exécuter un script de commandes Forge à la console Forge. Pour cela, utilisez la commande run, suivie du nom du fichier.
Pour obtenir la liste des commandes exécutées et en faire un script, tournez-vous vers le fichier ~/.forge/history.
Mais Forge, ce n'est pas seulement un prompt puissant.
3.3 Texte, GUI, faites votre choix !
Vous vous souvenez de la promesse de Java, « Écrire une fois, exécuter partout » : écrire un code qui sera exécuté identiquement sur différentes plate-formes matérielles. C'est une des forces de Java et de son moteur d'exécution (runtime) : la machine virtuelle Java (JVM) et hormis des cas limites, cela est vrai.
Dans le même esprit que Java, Forge possède deux plate-formes d'exécution pour ses plugins (addons), l'une est textuelle comme nous venons de le voir, l'autre est graphique, fondue dans Eclipse. Faites votre choix, vous ne serez pas pris entre le marteau et l'enclume. La première façon d'utiliser Forge de façon graphique est d'ajouter les JBoss Tools à son IDE. La deuxième façon est d'utiliser JBoss Developper Studio.
4 JBoss Developper Studio (JDS)
À l'heure de l'écriture de cet article, la version 7 est la version stable mais elle intègre Forge 1.x, aussi préférez une version 8 (en bêta à cette date) pour bénéficier de Forge 2.x
Fussiez-vous adorateur d'Emacs ou apôtre d'IntelliJ, cette mouture d'Eclipse va vous étonner.
Pour la comparaison, nous allons recréer l'application MesNews de façon graphique. Une fois JDS lancé, appuyez sur la combinaison de touches <Ctrl> + <4> (enfin,<Ctrl> + <Shift> + <'>).
Vous devriez voir s'afficher la fenêtre présentée en figure 3 qui est le wizard (assistant) de Forge.
Fig. 3 : La fenêtre Forge
La fenêtre Forge n'est pas la console Forge (dans Eclipse) qui n'est pas Forge en mode console (shell).
Si ce n'est pas le cas, c'est que le raccourci clavier a encore changé (j'ai expérimenté le fait qu'il diffère entre deux versions sur deux OS différents). Dans ce cas, il faut aller à la pêche à l'information : allez dans le menu Window/Preferences puis dans le choix General/Keys. Dans le champ Filter, saisissez forge, puis cliquez sur la ligne Run a Forge Command dont la colonne Binding vous indiquera la combinaison de touches à réaliser. Si cette combinaison n'a aucune valeur, à vous de la définir selon votre envie et les disponibilités.
Cette fenêtre est votre interface avec Forge au sein d'Eclipse. Elle affiche l'équivalent de la commande command-list disponible en ligne de commandes. Il faut cliquer sur les commandes pour les exécuter : simple.
Voilà pour la configuration, reprenons la création de l'application. Dans la zone de filtrage (avec la loupe), tapez new puis cliquez sur New Project. Vous allez voir apparaître la fenêtre présentée en figure 4 qu'il vous faudra compléter.
Fig. 4 : Création du projet
Relancez la fenêtre de commande de Forge (<Ctrl> + <Shift> + <'> ) et, dans le filtre, saisissez entity puis cliquez sur JPA:New Entity et choisissez WildFly et Java EE comme le montre la figure 5.
Fig. 5 : Configuration de JPA
Cliquez ensuite sur Next et laissez les valeurs par défaut dans la fenêtre suivante (voir figure 6). Jetez quand même un œil à Database Type pour voir l'ensemble des bases supportées. Gardez le choix par défaut (H2) et cliquez sur Next.
Fig. 6 : Configuration de JPA
Laissez les valeurs par défaut. Notamment le nom de la source de données. Mais jetez un œil à Database Type pour voir l'ensemble des bases supportées. Gardez le choix du presque voyageur galactique. Cliquez sur Next.
Dans la fenêtre suivante reprenons ensuite le nom News pour la classe puis cliquez sur Finish pour créer l'entité. Il faut désormais lui ajouter des champs.
Dans le filtre de la fenêtre de commande, saisissez field pour afficher le choix JPA : New Field (voir figure 7) et ajoutez le champ texte.
Fig. 7 : Création d'un champ de l'entité JPA
Faites de même pour le champ titre, puis pour le champ quand il faudra utiliser le type java.util.Date.
Pour le scaffolding, à ré-exécuter à chaque changement devant être visible dans l'interface, c'est la commande Scaffold : Generate. Pour le build, sans surprise, c'est aussi la commande build.
Si comme moi, vous trouvez que c'est beaucoup trop de clics pour créer un bête champ, sachez qu'il est possible d'utiliser la « Forge Console », un shell Forge dans JDS. MAIS, et c'est un gros « mais », cette console n'est pas synchronisée sur l'éditeur actif d'Eclipse. Ils sont indépendants l'un de l'autre. Aussi, il vous faudra « cd » jusque dans la classe Entity voulue pour exécuter une commande jpa-new-field.
Et là, c'est le drame... Nous venons de créer une application géniale mais comment la déployer ?
Au début de l'article, j'écrivais que JDS offrait un environnement complet, mais en fait il n'y a pas de serveur configuré dans la nouvelle version que j'utilise. J'espère que la vôtre en dispose. Pour le cas où votre version serait également sans aucun serveur pré-configuré, voyons comment ajouter un serveur WildFly 8.
Si l'onglet Servers de votre installation n'est pas vide, chanceux que vous êtes, vous pouvez passer à la section suivante. Sinon, cliquez sur le lien indiqué dans la fenêtre (voir figure 8).
Fig. 8 : L'onglet Servers
Vous devrez ensuite définir un nouveau serveur (sélectionnez WildFly 8.x), configurer l'adaptateur pour WildFly (serveur Local contrôlé par Filesystem and shell operation), choisissez le téléchargement et l'installation de la version la plus élevée de WildFly, comme d'habitude, faites comme si vous aviez lu la licence et acceptez-la puis lancez l'installation en choisissant un chemin clair pour vous y retrouver ultérieurement (une longue attente se dessine à l'horizon). Enfin vous pourrez cliquer sur Finish !
Il faut désormais ajouter l'application au serveur nouvellement créé. Dans l'onglet Servers, faites un clic droit et sélectionnez Add and remove. Vous pourrez alors faire basculer votre application de la liste Available vers Configured en cliquant sur le bouton Add, puis cliquez sur Finish (voir figure 9).
Fig. 9 : Publication de l'application
Maintenant démarrez le serveur (clic droit sur le serveur puis Start) et naviguez à l'URL correspondante : http://localhost:8080/MesNewsGui/.
5 Et il y en a encore
Je ne peux pas finir cet article sans évoquer les collections. Nous allons ajouter un auteur pour plusieurs news par exemple. À cet auteur, donnons lui un nom et un prénom (vous savez comment faire). Ensuite il faut lier la classe Auteur et la classe News. Dans la classe Auteur, ajoutez :
@OneToMany(mappedBy = "auteur", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<News> news = new HashSet<News>();
Il faut ensuite ajouter dans la classe News :
@ManyToOne(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="auteur")
private Auteur auteur;
Puis, pour chacun de ces deux fichiers, faites générer les getters et les setters correspondants. Relancez le scaffolding, le build. Vous obtiendrez un meilleur résultat avec le scaffolding JSF (Faces) qu'avec celui produisant l'application AngularJS. Cette dernière étant assez avare d'informations en n'affichant que l'identifiant pour choisir l'auteur de la News dans une liste déroulante. Essayez les deux et comparez les.
Vous remarquerez que le produit des deux scaffolding est disponible dans l'application. Le dernier utilisé est celui actif mais les artefacts produits par l'autre scaffolder restent présents dans le projet.
6 Et maintenant ?
Et maintenant que vous êtes abasourdi par cet outil, vous vous demandez ce que vous allez pouvoir faire de toute la puissance qui vous est offerte.
Parce que le quotidien de la majorité de nous autres, développeurs Java, est plutôt fait de maintenance (quelqu'un d'autre fait aussi de la maintenance sur des projets Struts 1.x ?) que de démarrage de projets avec les dernières nouvelles technos, à quoi peut bien servir Forge au quotidien ?
Mis à part prototyper une application comme nous venons de le faire, Forge peut aussi être utilisé pour
- faire générer dans un projet de brouillon un bout de code que l'on a la flemme d'écrire pour son projet parce qu'on l'a déjà écrit vingt fois avec dix frameworks différents ;
- démarrer sa startup, en allant chercher des capitaux avec un prototype à montrer aux investisseurs ;
- créer ses outils ;
- créer ses usages.
6.1 Démarrer sa startup ?
Vous avez une idée à même de faire des millions de bénéfice ? Bien, avec Forge et sa productivité, vous pouvez créer et recréer à l'envie le backend pour votre startup.
Créez les beans entities qui portent le métier de votre site, modifiez-les, recréez-les puis faites (re)générer les API REST (attention au versioning). Un peu de scaffolding comme vu précédemment, et vous avez un site Web à montrer à des investisseurs, ou à votre responsable (dans le cas « prototyper une application »).
Petit conseil : trouvez-vous un(e) ami(e) designer pour améliorer le design par défaut.
Testez et déployez. Vous pouvez utiliser JDS pour déployer votre application vers le cloud de Red Hat : OpenShift. Naturellement, cela est intégré à l'outil. Le déploiement vers d'autres nuages est tout à fait possible également mais il faudra prévoir du temps de re-configuration.
6.2 Créer ses outils ?
Oui, créer ses outils. Wow. Rien que cela. Vaste programme. Parce que nous, programmeurs, sommes parfois fainéants (surtout les jours en -di) et que nous n'aimons pas changer de fenêtre à répétition, il existe pléthore d'extensions pour Eclipse. De l'alarme à thé au modeleur UML en passant par le prompt shell, ces extensions couvrent un large pourcentage des besoins de la majorité des développeurs.
Seulement voilà, il reste un pourcentage de tâches qui sont locales à votre environnement de projet, votre projet. Et un vrai développeur n'aime pas les tâches répétitives puisque c'est pour les réaliser que l'on a inventé les ordinateurs. Et chacun, dans nos bureaux, nous avons des choses à faire qui sont « locales » (sans pour autant impliquer de l'UTF-8). Et pour ces tâches, on a tous nos astuces. Que cela soit une feuille de tableur qui permet de générer du SQL pour initialiser sa base, un script shell qui lance une classe Java qui va scraper un site pour augmenter un fichier des fortunes ou une base de données, ou même une page AngularJS qui affiche le code Java pour des classes et un DAO complet à partir du nom d'une procédure stockée (juré je l'ai fait), on a tous nos trucs pour nous aider dans notre boulot quotidien, celui qui est closed-source, se fait derrière les portes de nos clients et qui paye les factures.
Seulement, ces exemples peuvent ressembler à du bricolage et interpeller quant à leurs maintenabilités les gens de peu de foi, un peu plus haut dans la hiérarchie. Alors, un meilleur type de solution serait de créer un plugin pour Eclipse et de le mettre sur le gestionnaire de sources de la boite. Seulement voilà, les plugins Eclipse sont (très) loin d'être simples à développer pour le peu de ce que j'ai pu en voir avant de fuir vite et loin. Tant le démarrage d'un projet d'application RCP que l'ordonnancement de ses menus dans l'ordre désiré m'ont semblé dingues de complexité et par conséquent, cette plate-forme très perfectible.
Alors Forge met à votre disposition un cadre (framework) qui permet de créer des actions personnalisées, utilisables sans quitter l'IDE. Ce qui est génial si votre client, comme cela m'est souvent arrivé, vous met à disposition une machine sous-dimensionnée avec un OS lourd et propriétaire plombé par un antivirus troué et sous-doté en RAM. Ainsi vous évitez un changement de contexte, des accès disque, etc...
Avec ces actions personnalisées, vous pourrez programmer ce que vous seul utilisez, que cela soit propre à votre projet ou à votre entreprise. Et comme ces actions (plugins) s'écrivent en Java, c'est dire que vous disposez de nombreuses API pour effectuer toute tâche imaginable. Bien entendu, vous pouvez aussi développer des addons utiles à tous et les partager avec vos pairs. L'open source, il ne faut pas seulement en profiter.
6.3 Philosophie
Forge se base réellement sur son mécanisme d'addons et de ce fait, les commandes disponibles après l'installation sont elles-mêmes des addons. Je rappelle aux plus curieux que les sources sont disponibles ;) Il est aussi possible d'utiliser ces addons dans nos addons. Inception. Collaboration.
7 Le premier addon
Parce que c'est en forgeant que l'on devient forgeron, pour ce premier addon, souscrivons à la tradition du Hello World et écrivons un « Bonjour Dennis Ritchie. Merci pour les jouets que tu as offert au monde. Entre le C, Unix et ta barbe, tu étais le père noël des geeks ! », pour honorer ce géant, pas assez idolâtré à mon avis, sur les épaules duquel nous sommes tous assis.
Comme le sujet est vaste, la création d'un addon sera survolée avec un exemple simple qui n'a pour but que vous donner envie de lire le prochain article.
Après avoir fermé tous les projets ouverts dans JDS, affichez la fenêtre Forge et choisissez Project : New. Cela permet d'avoir le choix pour utiliser des addons disponibles (voir figure 10). Dans un premier temps, il ne nous faut que core et UI.
Fig. 10 : Choix des addons utilisés par l'addon
Sinon, pour créer un projet d'addon dans la console Forge, exécutez :
[jerome]$ project-new --named addonDR --type addon
Cette commande créera le projet et le fera apparaître automatiquement dans JDS (mais il faudra ajouter les addons en tant que dépendance Maven).
Créez ensuite une classe, et copiez-y le code suivant :
package addonDR;
import org.jboss.forge.addon.ui.annotation.Command;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;
public class AddonDR {
public static String COUCOU = "Bonjour Dennis Ritchie. Merci pour les jouets que tu as offert au monde. Entre le C, Unix et ta barbe, tu étais le père noël des geeks !";
@Command(categories="LeKiff")
public Result coucouDR(){
return Results.success(COUCOU);
}
}
Maintenant, dans la fenêtre Forge, choisissez Build and Install an Addon. Sélectionnez le chemin du projet et patientez un (long) moment pendant le build.
Voilà, votre addon est créé et disponible sous le nom de coucouDR. Dans la fenêtre Forge, choisissez coucouDR et à l'exécution, vous obtiendrez votre message dans le coin en bas à droite de l'écran (voir figure 11).
Fig. 11 : Affichage de la popup avec l'hommage
Et là, vous pouvez légitimement vous dire que le message était trop long pour la popup. Certes.
Mais cet exemple simple et concis représente la porte ouverte à toutes les fenêtres de commandes que vous voudrez vous créer. Vous pouvez aussi exécuter cette commande dans la console Forge pour relire le texte dans son intégralité et toute sa splendeur.
Conclusion
Il est indéniable que Forge vous offre une productivité impressionnante. Il fait le boulot, le slogan annoncé est tenu. En très peu de temps, un projet Maven est initialisé, câblé, JPA et REST sont configurés, les fichiers obligatoires ne sont pas oubliés. Aucune bête erreur de syntaxe ou d'oubli. Le tout en un minimum de commandes et d'informations transmises au programme.
Même s'il n'est pas parfait, je juge cet outil excellent. Sa disponibilité en mode texte et en mode graphique est un vrai plus. La version graphique peut se révéler plus lente d'utilisation que la version en mode texte, notamment pour l'ajout de champs à une entité JPA. Mais, redevenons autonome, il est possible de les ajouter à la main ou même par copier/coller pour encore plus de rapidité :)
Si les interfaces graphiques générées en JSF ou AngularJS ne conviennent pas, il est possible de créer son propre générateur ou bien de les créer séparément tout en exploitant les points d'entrée REST générés.
À défaut de prendre l'ensemble de ce qui est généré, il est aussi possible de n'utiliser que des parties et de les assembler dans un autre projet.
Forge n'est pas la silver bullet du développement Java EE, il arrive que cela ne marche pas comme on le voudrait notamment avec les collections. Pire, j'ai essayé des versions de JDS qui n'ouvraient pas du tout la fenêtre Forge. Ma solution de contournement rapide a été de me tourner vers une version précédente de JDS.
Au-delà des projets simplistes, avoir des compétences Java EE est obligatoire pour utiliser le projet produit. Néanmoins, Forge est un pas supplémentaire sur le chemin de la simplification de la programmation qui, après les cartes perforées, a commencé par l'assembleur, et a continué avec le C, le Java à la main et finira pourquoi pas demain, avec de la programmation « parlée » en discutant avec un avatar anthropomorphe du cloud de notre hébergeur.
Cela en est fini pour ce premier article introductif à Forge, nous creuserons plus profondément la création d'un addon plus ambitieux dans un prochain article.
Pour me permettre d'avoir votre feedback sur cet article, vous pouvez répondre au sondage http://goo.gl/ijqi1r.
Je remercie Antonio Goncalves (@agoncal), Philippe Prados et Alexis Maillot pour leur travail de relecture de cet article.