Nous allons voir comment mixer un projet Java Maven classique avec un projet frontal Yeoman à l'aide du plugin yeoman-maven-plugin de Thomas Recloux, qui est aussi utilisé dans JHipster.
Le frontal Web écrit en Javascript va utiliser les services REST du back écrit en Java. Le tout dans un seul et même projet et packagé au sein d'un même Jar ou War.
Arborescence du projet
pom.xml => Fichier Maven src => Source du projet main java resources webapp test java resources yo => Projet Yeoman package.json Gruntfile.js bower.json app/Le répertoire "yo" contient les sources du projet Yeoman qui ne sont pas inclus directement dans les sources du projet. Ceci permet de conserver un projet Yeoman indépendamment du reste du projet qui lui respecte la structure d'un projet Maven.
Maven
La construction du projet "Yeoman" s'effectuera à l'aide de la commande "grunt build" lancée par Maven via le plugin yeoman-maven-plugin.Ce build nécessite l'appel aux outils "npm", "bower" et "grunt".
Ainsi le plugin va lancer les commandes suivantes par défaut :
npm install
bower install --no-color
grunt test --no-color
grunt build --no-color
Application classique Java EE
Dans le cas d'une application Java classique (non SpringBoot) packagée sous forme de War, nous devons indiquer à Maven d'inclure les fichiers produits par Grunt à la racine du War.Pour cela, nous utilisons le plugin
maven-war-plugin
pour inclure les fichiers du répertoire yo/dist/public
produit par Grunt :
Nous obtenons le profil suivant dans le pom.xml :
Lancer la commande Maven suivante pour packager l'application sous forme d'un War :
mvn packageLes commandes
npm install
, bower install
, grunt test
et grunt build
sont alors lancés par Maven via le plugin maven-yeoman-plugin
afin de compiler le projet yeoman, ensuite Maven va packager les fichiers produits par grunt dans le fichier War.
Nous obtenons alors le packaging suivant :
- myapp.war :
à la racine : les fichiers du répertoire "yo/dist/public" produit par Grunt : index.html, etc. les fichiers du répertoire "src/main/resources" META-INF/ MANIFEST.MF maven/ pom.xml WEB-INF/ classes/ ... les classes Java du projet lib/ ... les librairies jars org/ springframework/ ... les classes de spring
SpringBoot
Dans le cas d'une application Spring Boot, nous allons voir comment configurer Maven pour intégrer les fichiers du projet Yeoman dans le packaging Jar ou War d'une application Spring Boot.Nous allons voir les packagings suivants :
- packaging final pour la mise en production
- packaging lors du développement
Profil Production : Packaging final
Spring Boot utilise par défaut les répertoires de fichiers de ressources dans le classpath de l'application :- /static
- /resources
- /public
- /META-INF/resources
Dans le cas d'un projet yeoman basé sur le générateur angular-fullstack, l'outil Grunt va produire les fichiers dans le répertoire
dist/public
.Or
public
correspond au nom d'un des répertoires de ressources gérés en standard par Spring Boot. Nous n'avons plus qu'à l'inclure dans le classpath de l'application lors de la phase de packaging via Maven.Pour cela, nous pouvons indiquons à Maven que le contenu du répertoire
yo/dist
fera parti du classpath du Jar ou du War généré :Nous obtenons donc la configuration suivante pour le profil du packaging "production" : Lancer la commande Maven suivante pour packager l'application :
mvn package -PprodNous aurons ainsi le packaging suivant dans le cas du packaging de l'application sous forme de Jar :
- myapp.jar :
public => le répertoire "public" produit par Grunt ... les autres fichiers du projet META-INF/ MANIFEST.MF maven/ pom.xmlNous aurons le packaging suivant dans le cas du packaging de l'application sous forme de War :
- myapp.war :
META-INF/ MANIFEST.MF maven/ pom.xml WEB-INF/ classes/ public => le répertoire "public" produit par Grunt ... les autres fichiers du projet lib/ ... les librairies jars org/ springframework/ ... les classes de spring
Profil Développement : utilisation de "grunt serve"
Nous n'incluons pas la partie statique dans le packaging de l'application car celle-ci sera servie par le serveur lancé par la commande "grunt serve".
C'est pourquoi nous n'avons pas besoin de lancer grunt depuis Maven, ni du plugin "maven-yeoman-plugin" pour le profil de développement.
C'est pourquoi nous n'avons pas besoin de lancer grunt depuis Maven, ni du plugin "maven-yeoman-plugin" pour le profil de développement.
Voici le profil "dev" :
Démarrer l'application Spring Boot via la commande :
mvn spring-boot:run
Démarrer le serveur des ressources statiques :
cd yo grunt serve
Nous pouvons accéder à l'application via l'URL suivante :
Les modifications apportées dans le projet yeoman seront reportées directement dans le navigateur Web lancé sur le port 9000 via le livereload ou browersync.
Nous devons maintenant définir un proxy sur le serveur lancé par Grunt :
Grunt : Définir un proxy sur le serveur de Grunt pour rediriger les requêtes REST vers le serveur Tomcat
Les requêtes lancées par AngularJS vers les services Rest sont par défaut dirigées vers le serveur lancé par Grunt qui est sur le port 9000.C'est pourquoi nous avons besoin de définir un proxy sur le serveur lancé par Grunt afin qu'il redirige les requêtes vers le serveur Tomcat sur le port 8080.
De plus, nous avons besoin d'ajouter un filtre CORS pour que le serveur accepte les requêtes des pages provenant du serveur de Grunt.
Filtre Java CORS
Nous ajoutons le filtre suivant dans l'application Java qui ne doit être actif que durant le développement, c'est à dire lorsque le profil Spring est "dev" :Ajout du proxy dans Grunt
Nous avons des configurations différentes à définir dans le fichierGruntfile.js
suivant si le plugin "connect" ou "browser-sync" est utilisé :
Dans le cas du plugin "connect"
Dans le cas où Grunt lance son serveur de fichiers statiques via le plugin "grunt-contrib-connect", nous pouvons suivre l'article suivant pour effectuer cette configuration : http://www.hierax.org/2014/01/grunt-proxy-setup-for-yeoman.html- Installer le plugin "grunt-connect-proxy" :
npm install grunt-connect-proxy --save-dev
Gruntfile.js> :
- Ajouter la déclaration du plugin au début du fichier :
grunt.loadNpmTasks('grunt-connect-proxy');
connect: { options: { ... }, proxies: [ { context: '/', host: 'localhost', port: 8080 } ], livereload: { options: { open: true, middleware: function (connect, options) { return [ ... // Setup the proxy require('grunt-connect-proxy/lib/utils').proxyRequest ]; } } }, ... }
Dans le cas du plugin "browser-sync"
Dans le cas où Grunt lance son serveur de fichiers statiques via "browser-sync", nous avons à définir le proxy de la manière suivante :browserSync: { dev: { ... }, options: { watchTask: true, proxy: "localhost:8080" } },
Conclusion
Nous venons de voir comment packagée une application Spring Boot ou classique avec Maven.L'utilisation d'un proxy sur le serveur démarré par Grunt permet de ne pas avoir à modifier directement dans le code les URL vers les services REST situés sur le serveur Java.