2009-08-05 6 views
47

У меня есть несколько проектов, построенных maven, и я хочу поделиться с ними некоторыми общими свойствами - весной версией, версией драйвера mysql, svn base url и т. Д. - поэтому я могу их обновить один раз, и это отразится на всех проектах.Как поделиться общими свойствами среди нескольких проектов maven?

Я думал о наличии единственного супер-помпе со всеми свойствами, но если я изменю одну из проблем, мне нужно либо увеличить его версию (и обновить все наследуемые им поры), либо удалить ее из всех которые я не хочу делать.

Можете указать эти параметры снаружи для pom? Я все еще хочу иметь определение внешнего местоположения в родительском помпе.

+1

Перейти супер маршрут POM, и когда-либо обновить супер POM номер версии, выполните: 'МВН -N версии: обновление-ребенок-modules' http://stackoverflow.com/questions/30571/# 1172805 – Tim

+0

@ Проблема в том, что у меня есть иерархия нескольких суперпомов (общие определения -> весенние проекты -> webapps/services -> действительный модуль. AFAIK плагин версии не выполняет это каскадное обновление. –

ответ

13

Обратите внимание, что оригинальная идея, которую я имею здесь, - это то, что я делаю, но я, возможно, нашел гораздо лучшую идею, которую я также перечислял ниже. Я хотел сохранить обе идеи здесь для полноты, если новая идея не работа.


Я думаю, вы можете решить эту проблему, используя родительский POM, но вы должны иметь хранилище Maven и инструмент CI сборки.

У меня есть несколько проектов, которые наследуют базовые свойства от родительского POM. Мы используем Java 1.5, так что там устанавливается свойство build. Все это UTF-8. Все отчеты, которые я хочу запустить, настройка Sonar и т. Д., Находятся внутри родительского POM.

Предполагая, что ваш проект находится в управлении версиями, и у вас есть инструмент CI, когда вы регистрируетесь, ваш инструмент CI может построить проект POM и развернуть SNAPSHOT в репозитории maven. Если ваши проекты указывают на версию родительского ПОМ SNAPSHOT, они проверят репозиторий, чтобы проверить, что у них последняя версия ... если они не загружают последнюю версию. Поэтому, если вы обновите родителя, все остальные проекты будут обновлены.

Трюк, я полагаю, выпускает с помощью SNAPSHOT. Я бы сказал, что ваши релизы будут проходить гораздо реже, чем ваши изменения. Таким образом, вы выполняете выпуск своей POM, а затем обновляете свои POM, которые наследуют их, и проверяете их на контроль версий. Пусть разработчики знают, что им нужно сделать обновление и перейти оттуда.

Вы можете просто запустить сборки там, заставляя новые POM в репозитории, а затем все разработчики автоматически приступают к изменениям при сборке.


Я удалил идею ключевых слов LATEST/RELEASE, потому что они не работают для родительских POM. Они работают только для зависимостей или плагинов. Проблемная область находится в DefaultMavenProjectBuilder. По существу у него есть проблемы с определением того, какой репозиторий ищет родителя, чтобы определить, что такое последняя версия или версия выпуска. Не уверен, почему это зависит от зависимостей или плагинов.


Похоже, что это было бы менее болезненно, чем необходимость обновлять ПОМ при каждом изменении родительского ПОМ.

22

Что вы можете сделать, это использовать Properties Maven plugin. Это позволит вам определить ваши свойства во внешнем файле, и плагин прочитает этот файл.

При такой конфигурации:

<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> 

и если у вас есть, в свойствах файла следующие строки:

spring-version=1.0 
mysql-version=4.0.0 

, то это то же самое, как если бы вы написали в вашем pom.xml , следующие строки:

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

Используя этот плагин, вы получите несколько преимуществ:

  • Набор легко длинный список свойств
  • Измените значения этих свойств без изменения родительского pom.xml.
+0

Насколько зрелым является этот плагин, учитывая его является альфа-1 версией? –

+1

Согласно этой ошибке, она по-прежнему не пригодна для меня, так как я хочу иметь замедление в родительском помпе: http://jira.codehaus.org/browse/MOJO-1303 –

+0

Не могли бы вы предоставить полный 'pom.com', где вы ссылаетесь на« весеннюю версию »? Согласно обсуждениям в http://stackoverflow.com/qu estions/849389/how-to-read-an-external-properties-file-in-maven невозможно определить версию зависимостей. Правильно? –

7

Я думаю, что свойство-maven-plugin - это правильный подход в долгосрочной перспективе, но поскольку вы ответили на этот ответ, он не позволяет наследовать свойства. В maven-shared-io есть несколько возможностей, которые позволяют вам находить ресурсы в пути к классам проекта. Я включил некоторый код ниже, который расширяет плагин свойств, чтобы найти файлы свойств в зависимостях плагина.

Конфигурация объявляет путь к файлу свойств, поскольку проект дескриптора объявлен в конфигурации плагина, он доступен для ClasspathResourceLocatorStrategy. Конфигурация может быть определена в родительском проекте и будет наследоваться всеми дочерними проектами (если вы это сделаете, избегайте объявления каких-либо файлов, поскольку они не будут обнаружены, установите свойство filePaths).

В приведенной ниже конфигурации предполагается, что существует еще один проект jar с именем name.seller.rich:test-properties-descriptor:0.0.1, в котором есть файл с именем external.properties, упакованный в банку (то есть он был определен в src/Основные/ресурсы).

<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> 

П для проекта плагина выглядит следующим образом:

<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> 

колдовской является копия свойств плагина ReadPropertiesMojo, с дополнительными «Путем к файлам» собственности, чтобы определить относительный путь к внешнему файлу свойств в пути к классам, он делает необязательным свойство файлов и добавляет методы readPropertyFiles() и getLocation() для поиска файлов и слияния любых файловых полей в массив файлов перед продолжением. Я прокомментировал свои изменения, чтобы сделать их более ясными.

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:[email protected]">Zarar Siddiqi</a> 
* @author <a href="mailto:[email protected]">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 
} 
+5

Вы когда-нибудь отправляли это в плагин Properties Maven как патч? Поскольку у меня есть такая же потребность, когда у меня есть файл свойств в банке, я тогда хочу использовать maven-resources-plugin для фильтрации с помощью xml-файла. –

+0

Это отличный ответ, но у меня проблемы, у меня есть родительский pom, где я читаю в версиях из файла рядом с ним и вызываю необходимые методы набора, свойства устанавливаются, но когда наступает время для решения зависимостей, они не нужно использовать ... Мне нужно, чтобы заставить повторить интерполяцию, попробовал его с помощью 'project.getModel(). setProperties (propectProperties)', но мне не повезло, что я действительно хочу, чтобы это работало: '( – sloven

 Смежные вопросы

  • Нет связанных вопросов^_^