jeudi 15 septembre 2011

Changer les fichiers de configuration avec Maven

L'idée d'aujourd'hui est de pouvoir générer avec Maven des livrables contenant des fichiers de configuration correspondant à différents environnements.
Pour cela j'utilise les profils Maven et une petite tache Ant.

On commence par créer nos fichiers de configuration en les suffixant selon les profils. On a alors les fichiers conf.xml.dev et conf.xml.prd par exemple pour les environnements de développement (dev) et de production (prd).

Lorsque l'on demande à Maven de packager nos livrables, ils contiennent alors les deux fichiers.
La première étape est alors de faire en sorte de ne copier que la resource qui nous intéresse.
Pour cela nous déclarons les profils dans le fichier pom.xml du projet :
<profiles>
  <profile>
    <id>dev</id>
    <activation>
      <activebydefault>true</activebydefault>
    </activation>
    <properties>
      <maven.deployment.suffix>dev</maven.deployment.suffix>
    </properties>
  </profile>
  <profile>
    <id>prd</id>
    <properties>
      <maven.deployment.suffix>prd</maven.deployment.suffix>
    </properties>
  </profile>
</profiles>

Nous avons donc deux profils : "dev" et "prd". "dev" est le profil actif par défaut et les deux profils déclarent une propriété "maven.deployment.suffix".
Pour faire en sorte que Maven sélectionne le bon fichier, il faut configurer le plugin resource dans la section build du xml.
<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <includes>
        <include>**/*.xml</include>
        <include>**/*.xml.${maven.deployment.suffix}</include>
      </includes>
    </resource>
  </resources>
</build>
Il ne faut pas oublier d'inclure les autres types de fichiers à copier comme xml dans l'exemple mais aussi les fichiers properties et autres.

On constate alors que Maven a bien inclu dans le livrable le bon fichier mais notre fichier s'appelle conf.xml.dev au lieu de conf.xml. Pour avoir le fichier de l'environnement de production, il faut utiliser la commande mvn clean package -Pprd

C'est alors qu'intervient Ant, nous allons utiliser une tache Ant pour faire le renommage des fichiers. Pour cela nous allons ajouter le plugin Ant pour permettre l'exécution de la task move lors de la phase process-classes de Maven.
Dans la section build du pom.xml, on a alors :
<build>
  <plugins>
    <plugin>
      <artifactid>maven-antrun-plugin</artifactid>
      <executions>
        <execution>
          <phase>process-classes</phase>
          <configuration>
            <tasks>
              <echo message="Renommage des fichiers..." />
              <property name="maven.deployment.files" value="*.${maven.deployment.suffix}"/>
              <move overwrite="yes" todir="${project.build.directory}/classes" verbose="yes">
                <fileset dir="${project.build.directory}/classes">
                  <include name="**/${maven.deployment.files}"/>
                </fileset>
                <mapper from="${maven.deployment.files}" to="*" type="glob"/>
              </move>
              <echo message="Fin de renommage !"/>
            </tasks>
          </configuration>
          <goals>
            <goal>run</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
  
  <resources>
    .......
  </resources>
</build>

On a alors une copie des fichiers suffixés par le profil dans le même répertoire en utilisant un mapper qui renomme le fichier en supprimant le suffixe.

2 commentaires:

  1. Voici une solution qui me semble plus élégante, parce qu'elle ne fait pas intervenir Ant, aussi parce qu'elle préserve l'extension des fichiers.

    build
    .resources
    ..resource
    ...directory: src/main/resources/common

    profiles
    .profile
    ..id: dev
    ..build
    ...resources
    ....resource
    .....directory: src/main/resources/dev

    Néanmoins, même si j'ai déjà utilisé cette astuce, je trouve aujourd'hui que c'est une mauvaise pratique. Un livrable qui a été validé en test devrait pouvoir être déployé tel quel en production, les variables étant externalisés. Cela évitera des erreurs comme déployer en production un livrable de test !

    RépondreSupprimer
  2. Bonsoir,

    je suis d'accord sur le fait qu'un livrable validé en test devrait être déployé tel quel en production.
    J'ai d'ailleurs changer la configuration du projet par la suite pour le faire.
    J'ai commencé à écrire un article sur comment faire pour pointer des ressources différentes selon l'environnement.

    RépondreSupprimer