Comment partager des propriétés communes entre plusieurs projets maven?

j'ai plusieurs projets construits par maven, et je veux partager quelques propriétés communes parmi elles - la version de printemps, la version de pilote mysql, l'url de base svn, etc. - donc je peux les mettre à jour une fois et il sera réfléchi sur tous les projets.

j'ai pensé avoir un seul super pom avec toutes les propriétés, mais si je change l'un des problèmes, je dois soit augmenter sa version (et de mettre à jour tous les pom hériter de lui) ou de le supprimer de toutes les machines des développeurs ce que je n'ai pas envie de faire.

peut spécifier ces paramètres à l'extérieur du pom? Je veux toujours avoir la définition d'emplacement externe dans une pom parent.

49
demandé sur Hamedz 2009-08-05 10:47:17

3 réponses

Note que l'idée originale que j'ai ici est quelque chose que je fais, mais que j'ai peut-être trouvé une bien meilleure idée que j'ai également listé ci-dessous. Je voulais garder les deux idées ici pour l'exhaustivité dans le cas où l'idée plus récente ne pas travail.


je pense que vous pouvez résoudre ce problème en utilisant la pom mère, mais vous avez besoin d'un dépôt maven et d'un outil de construction CI.

j'ai plusieurs projets qui héritent tous des propriétés de base d'un parent POM. Nous utilisons Java 1.5, de sorte que la propriété build s'y installe. Tout est UTF-8. Tous les rapports que je souhaite exécuter, sonar setup, etc, sont à l'intérieur du POM parent.

en supposant que votre projet est sous contrôle de version et que vous avez un outil de CI, lorsque vous vous enregistrez, votre outil de CI peut construire sur POM project et déployer le SNAPSHOT sur les repos maven. Si vos projets pointent vers le SNAPSHOT version de la POM mère, ils vont vérifier le dépôt pour valider qu'ils ont la dernière version...sinon, ils téléchargent la dernière version. Donc si vous mettez à jour le parent, tous les autres projets seront mis à jour.

le truc, je suppose qu'il sort avec un instantané. Je dirais que vos sorties seront beaucoup moins fréquentes que vos changements. Donc vous effectuez une sortie de votre POM, puis mettez à jour vos POM qui héritent d'eux et les vérifiez dans le contrôle de version. Laisser les devs savent qu'ils ont besoin de faire une mise à jour et à partir de là.

vous pourriez juste déclencher des constructions là en forçant les nouvelles Pom dans le dépôt et ensuite faire que tous les devs récupèrent les modifications automatiquement après la construction.


j'ai supprimé les mots clés les plus récents parce qu'ils ne fonctionnent pas pour les mères. Ils ne fonctionnent que pour les dépendances ou les plugins. Le problème se situe dans DefaultMavenProjectBuilder. Essentiellement il a du mal à déterminer quel dépôt rechercher pour le parent de déterminer ce que la dernière version ou la version de publication est. Je ne sais pas pourquoi c'est différent pour les dépendances ou des plugins.


il semble que ceux-ci seraient moins douloureux que d'avoir à mettre à jour les pom sur chaque changement de POM parent.

13
répondu Mike Cornell 2009-08-12 16:42:04

ce que vous pouvez faire est d'utiliser le propriétés maven plugin . Cela vous permettra de définir vos propriétés dans un fichier externe, et le plugin va lire ce fichier.

avec cette configuration:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>properties-maven-plugin</artifactId>
            <version>1.0-alpha-1</version>
            <executions>
                <execution>
                    <phase>initialize</phase>
                    <goals>
                        <goal>read-project-properties</goal>
                    </goals>
                    <configuration>
                        <files>
                            <file>my-file.properties</file>
                        </files>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

et si vous avez, dans votre fichier de propriétés, les lignes suivantes:

spring-version=1.0
mysql-version=4.0.0

alors c'est la même chose que si vous écriviez, dans votre pom.xml, les lignes suivantes:

<properties>
    <spring-version>1.0</spring-version>
    <mysql-version>4.0.0</mysql-version>
</properties>

avec ce plugin, vous aurez plusieurs avantages:

  • établir facilement une longue liste de propriétés
  • Modifier les valeurs de ces propriétés sans modifier le pom parent.XML.
25
répondu romaintaz 2017-09-19 17:07:58

je pense que les propriétés-maven-plugin est la bonne approche à long terme, mais comme vous avez répondu à cette réponse, il ne permet pas les propriétés à hériter. Il y a des installations à maven-shared-io qui vous permettent de découvrir des ressources sur le Project classpath. J'ai inclus ci-dessous du code qui étend le plugin propriétés pour trouver des fichiers de propriétés dans les dépendances du plugin.

la configuration déclare un chemin vers un fichier de propriétés, parce que le le projet descripteur est déclaré sur la configuration du plugin, il est accessible à la ClasspathResourceLocatorStrategy. La configuration peut être définie dans un projet parent, et sera héritée par tous les projets enfants (si vous le faites, évitez de déclarer des fichiers car ils ne seront pas découverts, définissez seulement la propriété filePaths).

la configuration ci-dessous suppose qu'il existe un autre projet jar appelé name.vendeur.riche:test-propriétés-descripteur:0.0.1 qui a un fichier appelé externe.propriétés empaquetées dans le jar (c'est-à-dire qu'il a été défini dans src/main/resources).

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>properties-ext-maven-plugin</artifactId>
  <version>0.0.1</version>
  <executions>
    <execution>
      <id>read-properties</id>
      <phase>initialize</phase>
      <goals>
        <goal>read-project-properties</goal>
      </goals>
    </execution>
  </executions>                              
  <configuration>
    <filePaths>
      <filePath>external.properties</filePath>
    </filePaths>
  </configuration> 
  <dependencies>
    <!-- declare any jars that host the required properties files here -->
    <dependency>
      <groupId>name.seller.rich</groupId>
      <artifactId>test-properties-descriptor</artifactId>
      <version>0.0.1</version>
    </dependency>
  </dependencies>
</plugin>

Le pom pour le plugin projet ressemble à ceci:

<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>org.codehaus.mojo</groupId>
  <artifactId>properties-ext-maven-plugin</artifactId>
  <packaging>maven-plugin</packaging>
  <version>0.0.1</version>
  <dependencies>
    <dependency>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>properties-maven-plugin</artifactId>
      <version>1.0-alpha-1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.shared</groupId>
      <artifactId>maven-shared-io</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>
</project>

le mojo est une copie des propriétés ReadPropertiesMojo du plugin, avec une propriété supplémentaire "filePaths" pour vous permettre de définir le chemin relatif vers le fichier de propriétés externes dans classpath, il rend la propriété fichiers optionnelle, et ajoute le readPropertyFiles() et les méthodes getLocation () pour localiser les fichiers et fusionner les chemins de fichiers dans le tableau des fichiers avant de continuer. J'ai commenté mes changements pour les rendre plus clairs.

package org.codehaus.mojo.xml;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file 
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 * KIND, either express or implied.  See the License for the 
 * specific language governing permissions and limitations 
 * under the License.
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.io.location.ClasspathResourceLocatorStrategy;
import org.apache.maven.shared.io.location.FileLocatorStrategy;
import org.apache.maven.shared.io.location.Location;
import org.apache.maven.shared.io.location.Locator;
import org.apache.maven.shared.io.location.LocatorStrategy;
import org.apache.maven.shared.io.location.URLLocatorStrategy;
import org.codehaus.plexus.util.cli.CommandLineUtils;

/**
 * The read-project-properties goal reads property files and stores the
 * properties as project properties. It serves as an alternate to specifying
 * properties in pom.xml.
 * 
 * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a>
 * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a>
 * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $
 * @goal read-project-properties
 */
public class ReadPropertiesMojo extends AbstractMojo {
    /**
     * @parameter default-value="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

    /**
     * The properties files that will be used when reading properties.
     * RS: made optional to avoid issue for inherited plugins
     * @parameter
     */
    private File[] files;

    //Begin: RS addition
    /**
     * Optional paths to properties files to be used.
     * 
     * @parameter
     */
    private String[] filePaths;
    //End: RS addition

    /**
     * If the plugin should be quiet if any of the files was not found
     * 
     * @parameter default-value="false"
     */
    private boolean quiet;

    public void execute() throws MojoExecutionException {
        //Begin: RS addition
        readPropertyFiles();
        //End: RS addition

        Properties projectProperties = new Properties();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];

            if (file.exists()) {
                try {
                    getLog().debug("Loading property file: " + file);

                    FileInputStream stream = new FileInputStream(file);
                    projectProperties = project.getProperties();

                    try {
                        projectProperties.load(stream);
                    } finally {
                        if (stream != null) {
                            stream.close();
                        }
                    }
                } catch (IOException e) {
                    throw new MojoExecutionException(
                            "Error reading properties file "
                                    + file.getAbsolutePath(), e);
                }
            } else {
                if (quiet) {
                    getLog().warn(
                            "Ignoring missing properties file: "
                                    + file.getAbsolutePath());
                } else {
                    throw new MojoExecutionException(
                            "Properties file not found: "
                                    + file.getAbsolutePath());
                }
            }
        }

        boolean useEnvVariables = false;
        for (Enumeration n = projectProperties.propertyNames(); n
                .hasMoreElements();) {
            String k = (String) n.nextElement();
            String p = (String) projectProperties.get(k);
            if (p.indexOf("${env.") != -1) {
                useEnvVariables = true;
                break;
            }
        }
        Properties environment = null;
        if (useEnvVariables) {
            try {
                environment = CommandLineUtils.getSystemEnvVars();
            } catch (IOException e) {
                throw new MojoExecutionException(
                        "Error getting system envorinment variables: ", e);
            }
        }
        for (Enumeration n = projectProperties.propertyNames(); n
                .hasMoreElements();) {
            String k = (String) n.nextElement();
            projectProperties.setProperty(k, getPropertyValue(k,
                    projectProperties, environment));
        }
    }

    //Begin: RS addition
    /**
     * Obtain the file from the local project or the classpath
     * 
     * @throws MojoExecutionException
     */
    private void readPropertyFiles() throws MojoExecutionException {
        if (filePaths != null && filePaths.length > 0) {
            File[] allFiles;

            int offset = 0;
            if (files != null && files.length != 0) {
                allFiles = new File[files.length + filePaths.length];
                System.arraycopy(files, 0, allFiles, 0, files.length);
                offset = files.length;
            } else {
                allFiles = new File[filePaths.length];
            }

            for (int i = 0; i < filePaths.length; i++) {
                Location location = getLocation(filePaths[i], project);

                try {
                    allFiles[offset + i] = location.getFile();
                } catch (IOException e) {
                    throw new MojoExecutionException(
                            "unable to open properties file", e);
                }
            }

            // replace the original array with the merged results
            files = allFiles;
        } else if (files == null || files.length == 0) {
            throw new MojoExecutionException(
                    "no files or filePaths defined, one or both must be specified");
        }
    }
    //End: RS addition

    /**
     * Retrieves a property value, replacing values like ${token} using the
     * Properties to look them up. Shamelessly adapted from:
     * http://maven.apache.
     * org/plugins/maven-war-plugin/xref/org/apache/maven/plugin
     * /war/PropertyUtils.html
     * 
     * It will leave unresolved properties alone, trying for System properties,
     * and environment variables and implements reparsing (in the case that the
     * value of a property contains a key), and will not loop endlessly on a
     * pair like test = ${test}
     * 
     * @param k
     *            property key
     * @param p
     *            project properties
     * @param environment
     *            environment variables
     * @return resolved property value
     */
    private String getPropertyValue(String k, Properties p,
            Properties environment) {
        String v = p.getProperty(k);
        String ret = "";
        int idx, idx2;

        while ((idx = v.indexOf("${")) >= 0) {
            // append prefix to result
            ret += v.substring(0, idx);

            // strip prefix from original
            v = v.substring(idx + 2);

            idx2 = v.indexOf("}");

            // if no matching } then bail
            if (idx2 < 0) {
                break;
            }

            // strip out the key and resolve it
            // resolve the key/value for the ${statement}
            String nk = v.substring(0, idx2);
            v = v.substring(idx2 + 1);
            String nv = p.getProperty(nk);

            // try global environment
            if (nv == null) {
                nv = System.getProperty(nk);
            }

            // try environment variable
            if (nv == null && nk.startsWith("env.") && environment != null) {
                nv = environment.getProperty(nk.substring(4));
            }

            // if the key cannot be resolved,
            // leave it alone ( and don't parse again )
            // else prefix the original string with the
            // resolved property ( so it can be parsed further )
            // taking recursion into account.
            if (nv == null || nv.equals(nk)) {
                ret += "${" + nk + "}";
            } else {
                v = nv + v;
            }
        }
        return ret + v;
    }

    //Begin: RS addition
    /**
     * Use various strategies to discover the file.
     */
    public Location getLocation(String path, MavenProject project) {
        LocatorStrategy classpathStrategy = new ClasspathResourceLocatorStrategy();

        List strategies = new ArrayList();
        strategies.add(classpathStrategy);
        strategies.add(new FileLocatorStrategy());
        strategies.add(new URLLocatorStrategy());

        List refStrategies = new ArrayList();
        refStrategies.add(classpathStrategy);

        Locator locator = new Locator();

        locator.setStrategies(strategies);

        Location location = locator.resolve(path);
        return location;
    }
    //End: RS addition
}
7
répondu Rich Seller 2009-08-12 10:40:28