Question

J'ai plusieurs projets construits par maven, et je souhaite partager certaines propriétés communes - version Spring, version du pilote mysql, URL de base svn, etc. - afin que je puisse les mettre à jour une fois, et cela sera répercuté sur tous les projets. .

Je pensais avoir un seul super-pom avec toutes les propriétés, mais si je modifie l'un des problèmes, j'ai besoin d'incrémenter sa version (et de mettre à jour tous les poms hérités de celui-ci) ou de le supprimer de tous les développeurs. «machines que je ne veux pas faire.

Peut-on spécifier ces paramètres de manière externe au pom? Je souhaite toujours avoir la définition d'emplacement externe dans un pom parent.

Était-ce utile?

La solution

Notez que l'idée originale que j'ai ici est quelque chose que je suis en train de faire, mais que j'ai peut-être trouvé une bien meilleure idée que j'ai également énumérée ci-dessous. Je souhaitais conserver ces deux idées ici pour qu'elles soient complètes au cas où l'idée la plus récente ne fonctionnerait pas .

Je pense que vous pouvez résoudre ce problème en utilisant le pom parent, mais vous devez disposer d'un référentiel maven et d'un outil de construction de CI.

J'ai plusieurs projets qui héritent tous des propriétés de base d'un POM parent. Nous utilisons Java 1.5, de sorte que la propriété de construction est configurée ici. Tout est UTF-8. Tous les rapports que je souhaite exécuter, la configuration de Sonar, etc., se trouvent dans le POM parent.

En supposant que votre projet soit sous contrôle de version et que vous disposiez d'un outil de configuration, lors de votre enregistrement, votre outil de configuration peut créer un projet POM et déployer le composant SNAPSHOT sur le dépôt de référence. Si vos projets pointent sur la version SNAPSHOT du POM parent, ils vérifieront dans le référentiel qu'ils possèdent 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, est de relâcher avec un instantané. Je dirais que vos communiqués vont arriver beaucoup moins souvent que vos changements. Vous exécutez donc une version de votre POM, puis mettez à jour vos POM qui en héritent et les archivez dans le contrôle de version. Dites aux développeurs qu'ils doivent faire une mise à jour et partir de là.

Vous pouvez simplement déclencher des générations là-bas en forçant les nouveaux POM dans le référentiel, puis laisser tous les développeurs enregistrer les modifications automatiquement lors de la construction.

J'ai supprimé l'idée des mots clés LATEST / RELEASE car ils ne fonctionnent pas pour les POM parents. Ils ne fonctionnent que pour les dépendances ou les plugins. La zone problématique est dans DefaultMavenProjectBuilder. Essentiellement, il a du mal à déterminer le référentiel dans lequel rechercher le parent afin de déterminer quelle est la version la plus récente ou la version la plus récente. Vous ne savez pas pourquoi cela est différent pour les dépendances ou les plugins.

Cela semble être moins pénible que de devoir mettre à jour les POM à chaque changement de POM parent.

Autres conseils

Ce que vous pouvez faire est d'utiliser le Propriétés du plugin Maven . Cela vous permettra de définir vos propriétés dans un fichier externe et le plug-in lira 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>

En utilisant ce plugin, vous aurez plusieurs avantages:

  • Définissez facilement une longue liste de propriétés
  • Modifiez les valeurs de ces propriétés sans modifier le pom.xml parent.

Je pense que le plug-in properties-maven est la bonne approche à long terme, mais si vous avez répondu à cette réponse, il ne permet pas l'héritage des propriétés. Il existe certaines installations dans maven-shared-io qui vous permettent de découvrir des ressources sur le classpath du projet. J'ai inclus ci-dessous du code qui étend le plug-in de propriétés à la recherche de fichiers de propriétés dans les dépendances du plug-in.

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

La configuration ci-dessous suppose qu’il existe un autre projet jar appelé name.seller.rich:test-properties-descriptor:0.0.1 qui contient un fichier appelé external.properties dans le jar (c’est-à-dire qu’il a été défini dans src / main / ressources).

<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 du projet de plugin se présente comme suit:

<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 du ReadPropertiesMojo du plug-in de propriétés, avec un "filePaths" supplémentaire. Cette propriété vous permet de définir le chemin relatif du fichier de propriétés externe dans le chemin de classe. Elle rend la propriété de fichiers facultative et ajoute les méthodes readPropertyFiles () et getLocation () pour localiser les fichiers et fusionner tous les chemins de fichiers dans le tableau de fichiers avant de continuer. . J'ai commenté mes modifications pour les rendre plus claires.

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
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top