Maven deploy avec 2 profiles

On a souvent besoin de plusieurs profils lors du développement d’une application. Prenons par exemple une application web qui a besoin de 2 profils :
– un profil auth, où l’authentification est activée. C’est la version de production
– un profil noauth, où l’authentification est désactivée. C’est la version par défaut, utile pour les développeurs.

L’objectif de cet article est d’illustrer comment gérer cette situation avec Maven.

On souhaite donc utiliser Maven pour réussir à :

  • configurer ces 2 profils
  • déployer dans un repository distant les 2 versions
  • générer ces 2 versions lors de la release
  • récuperer ces 2 versions à l’aide de maven

Cela à l’air simple comme cela, mais dans la réalité, c’est loin d’être facile. Après beaucoup d’effort, voici une solution qui fonctionne.

La solution

Il faut

  • utiliser 2 profils
  • utiliser un classifier pour le profil noauth
  • déployer la version noauth sous un autre artifactId, en utilisant le goal deploy-file du plugin deploy

Voici les 2 bouts de configuration pour faire cela :

<plugin>
 <artifactid>maven-war-plugin</artifactid>
 <configuration>
  <classifier>noauth</classifier>
 </configuration>
</plugin>
<plugin>
 <artifactid>maven-deploy-plugin</artifactid>
 <version>2.4</version>
 <configuration>
  <skip>true</skip>
 </configuration>
 <executions>
  <execution>
   <id>deploy-mock</id>
   <goals>
    <goal>deploy-file</goal>
   </goals>
   <phase>deploy</phase>
   <configuration>
    <repositoryid>${project.distributionManagementArtifactRepository.id}</repositoryid>
    <file>${build.directory}/${build.finalName}-noauth.${packaging}</file>
    <url>${project.distributionManagementArtifactRepository.url}</url>
    <artifactid>${artifactId}-noauth</artifactid>
    <groupid>${groupId}</groupid>
    <version>${version}</version>
    <packaging>${packaging}</packaging>
   </configuration>
  </execution>
 </executions>
</plugin>

Release

Pour déployer les 2 versions lors de la release, le plus simple est d’utiliser les commandes suivantes :

mvn release:prepare -P auth
mvn release:perform -P auth
cd target/checkout
mvn clean deploy

Ainsi, la release est effectuée et les 2 versions seront déployées correctement.
Note : comme la version de prod est la vesion auth, la release est faite avec ce profil.
Note : on peut utiliser l’option --batch-mode pour éviter la saisie des paramètres lors de la commande mvn release:prepare, et automatiser la release dans le serveur d’intégration continue.

Récupération des deux versions

Pour que les autres équipes (qualification, pre prod, prod) puissent récupérer les versions, on utilise le pom suivant :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelversion>4.0.0</modelversion>
 <groupid>com.octo.tools</groupid>
 <artifactid>maven-artifact-getter</artifactid>
 <packaging>pom</packaging>
 <version>0.0.1-SNAPSHOT</version>
 <build>
  <plugins>
   <plugin>
    <artifactid>maven-dependency-plugin</artifactid>
    <configuration>
     <artifactitems>
      <artifactitem>
       <groupid>${artifact.groupId}</groupid>
       <artifactid>${artifact.artifactId}</artifactid>
       <version>${artifact.version}</version>
       <type>${artifact.packaging}</type>
       <destfilename>${artifact.fileName}</destfilename>
      </artifactitem>
     </artifactitems>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>

Après l’exécution de cette commande, le war demandé se trouve dans target/dependency/monprojet.war. On peut donc le déployer facilement dans un serveur d’application, soit avec maven, soit avec des commandes shell. Il suffit de changer l’artifactId en monprojet-noauth pour récupérer la version noauth. Cela fonctionne pour une version SNAPSHOT ou une version release (Cela s’adapte donc parfaitement dans un job Hudson paramétré).

Pourquoi cela ne marche pas simplement

En vrac, quelques-uns des problèmes rencontrés

  • La version standard du plugin deploy plante sur des artefact avec classifier
  • Pas de timestamp sur l’upload d’une version SNASPHOT sur un artefact avec classifier le plugin deploy 2.4
  • Les metadata.xml du repository ne contiennent des informations que sur le dernier artefact uploadé, et non une info par classifier. Sur une version SNAPSHOT, on ne peut donc récupérer que le dernier artefact uploadé, quelque soit son classifier.
  • Plusieurs issues ici et ici

14 commentaires sur “Maven deploy avec 2 profiles”

  • Sujet intéressant car tous les retours d'expérience sont bons à prendre. Cependant, les exemples sont illisibles à l'heure ou j'écris ces lignes. Les balises ne s'affichent pas.
  • Voila qui devrait être mieux pour les exemples.
  • Intéressant mais je ne trouve pas que ce soit forcément la meilleure solution. L'idée de maven étant qu'un module produit un artefact. C'est pour cela que produire de multiple artefacts en utilisant des profiles. Plutôt que d'aller à l'encontre des conventions maven je préconiserais de créer un module par artefact. Dans le cas de application web (war) par exemple vous auriez 2 modules. Le premier définit l'application a "canonical" avec auth pour vous. Et la deuxieme depend du premier war et tire parti du "war overlay" que propose le "maven-war-plugin". Cela permet de facilement changer des fichiers de configuration, ajouter ou elever des libraries, etc. S'il s'agissait de jar, le maven-shade-plugin pourrait aider de la même façon. Qu'en pensez vous?
  • Certes cette solution tord le principe Maven : 1 projet == un artefact. Mais : - la notion de profil et de classifier de Maven est quelque part un contournement à ce principe - cette solution est un contournement à des problèmes liés soit la gestion des classifier Maven, soit au niveau de Maven, soit au niveau des repository Maven (voir les bugs reports) - mon projet n'est qu'un seul projet Maven, je ne souhaite pas avoir plusieurs projets Maven juste pour cela - à ma connaisance, les "war overlay" ne sont pas gérés par Eclipse, ce qui ne facilite pas le développement
  • Je suis tout à fait d'accord. Tous les points enoncés sont valide. Je pense qu'il est intéressant de montrer les différentes options possibles avec leurs avantages et inconvenients. A propos du dernier point, je suis d'accord c'est un inconvénient majeur. Les intégrations entre maven et les différents IDE ne sont pas parfaites et ne le seront probablement jamais, la configuration d'un projet avec maven étant beaucoup plus souple que ce que permettent les IDE…
  • J'utilise ce trick pour déployer dans un repo maven un zip (jar + deps + template fichiers de conf) généré par le plugin assembly. En effet, à cause de contraintes de prod, le nom de ce zip est différent de celui de mon artifact jar. J'aurai effectivement pu créer un projet maven qui ne fait que le déploiement mais j'ai déjà plein de modules et cela n'aurait fait qu'ajouter de la complexité. Sinon en maven 2.0.8, il fait replacer les , , etc. par , , etc et ${build.directory} par ${project.build.directory} En tout cas, merci Ben pour l'info.
  • argh... le système ne convertit pas les balises dans les commentaires... Je disais donc: Sinon en maven 2.0.8, il fait replacer les artifactid, groupid, etc. par artifactId, groupId, etc
  • J'ai du mal à comprendre l'utilité de releaser avec un profil autre que celui de la prod. De même, déployer deux versions différentes d'un même artifact est un peu tordu et donc confus pour les développeurs. Dans votre cas, j'aurai plutôt suivit les standards Maven en disant que le profil actif par défaut est la version de prod, donc avec authentification, et que les développeurs s'ils le veulent, utilisent le profil "noauth". Ce profil n'a selon jamais vocation à se retrouver ailleurs que lors de lancement d'un lancement de l'application en développement. Je n'ai encore jamais été confronté à un cas devant tordre cette logique. Ni dans le cas d'une double version d'une même application (interne/externe) ni dans le cas d'intégration ou non à des ws ni dans le cas de la désactivation de l'authentification. Pourriez-vous me donner un cas concret où il est utile de "deploy" ou "releasé" une version "profilée" d'un artifact.
  • Dans notre cas, les 2 versions avec et sans authent sont utilisées par l'équipe de qualification. Toutes les livraisons à cette équipe passent par un repo maven, nous utilisons donc les 2 profils lors des deploy et release. Par ailleurs, la version sans auth est déployée pour les formations : elle ne part pas en production, mais est quand même utilisée "en production" (aka sur un serveur auquel on ne touche pas, qui n'est pas géré par nous).
  • N'est-ce pas un cavalier de potentiellement utiliser en qualification une version différente de la prod ?
  • La version sans auth est utilisée pour qualifier des trucs très précis, à la marge. La majeure partie de la qualification se fait sur la version qui part effectivement en production :-)
  • J'ai un pb comparable: à partir des mêmes sources (flex en l'occurrence), je voudrais construire 2 binaires avec 2 options de compilo différentes. En fait, je veux mettre à dispo, sur mon serveur, à la fois une version de prod et une version debug. Je vais décortiquer cette soluce pour voir si elle ne peut pas nous apporter des billes. Mais globalement, le pb est loin d'être déconnant, la preuve. Merci pour tes infos.
  • Salut j'utilise hudson + m2 release plugin. Un solution que je peux envisager mais non testée, c'est d'utiliser le point d'entrée du plugin maven release perform (le deploiement de la release se fait à ce moment la, le pom.xml resultant de release:prepare est écrasé par l'étape de checkout du perform) Tous les fichiers de releases sont supprimés à la fin du perform. => Dans un profil spécifique pour éviter que cela boucle infiniment, je le nomme "release" par exemple. Lier le plugin maven-antRun-plugin à la phase deploy. Il exécutera un script maven qui prendra en paramètre les profiles à construire et à deployer sur Nexus (une boucle de mvn clean deploy -P !release,profileX). Il est important de bien désactiver le profil release afin de ne pas boucler infiniment. Une fois ces actions terminés le fork maven déclenché par le plugin release se termine et les fichiers de release sont effacés. C'est un peu l'usine à gaz mais cela permet pour une release snapshot Maven de profiter de toute l'automatisation des phases prepare et perform en construisant et deployant pour chaque profil le projet.
  • Autre solution avec le plugin m2 hudson Après le prepare sauvegarder le fichier release-properties Avec ce fichier en paramètre tu peux faire un script (executé avec le plugin batch task par exemple) qui prend également en paramètre l'ensemble des profils et cela boucle autant de fois sur le goal perform.
    1. Laisser un commentaire

      Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *


      Ce formulaire est protégé par Google Recaptcha