2009-08-05 8 views
47

Mam kilka projektów zbudowanych przez maven i chcę podzielić się z nimi niektórymi typowymi właściwościami - wersją wiosenną, wersją sterownika mysql, adresem bazowym svn itd. - aby móc je aktualizować raz i będzie to widoczne we wszystkich projektach.Jak udostępniać wspólne właściwości między kilkoma ważnymi projektami?

Pomyślałem o posiadaniu jednego super-pom ze wszystkimi właściwościami, ale jeśli zmienię jeden z problemów, potrzebuję albo zwiększyć jego wersję (i zaktualizować wszystkie poms po nim odziedziczę) albo usunąć ją ze wszystkich Maszyny programistów, których nie chcę robić.

Czy można określić te parametry z zewnątrz pom? Nadal chcę mieć definicję zewnętrznej lokalizacji w rodzicu pom.

+1

Idź super trasę POM, a gdy kiedykolwiek zaktualizować super pom numer wersji, wykonaj: '-n mvn wersje: update-dziecko-modules' http://stackoverflow.com/questions/30571/# 1172805 – Tim

+0

@Tym problemem jest posiadanie hierarchii kilku super-pomsów (ogólne definicje -> projekty wiosenne -> webapps/services -> aktualny moduł) AFAIK plugin wersji nie robi tej aktualizacji kaskadowej –

Odpowiedz

13

Zauważ, że oryginalny pomysł, który tu mam, jest czymś co robię, ale może znalazłem o wiele lepszy pomysł, który również wymienię poniżej. Chciałem zachować tutaj oba pomysły na kompletność w przypadku, gdy nowszy pomysł działa , a nie.


myślę, że można rozwiązać ten problem za pomocą pom nadrzędnego, ale trzeba mieć repozytorium maven oraz narzędzie CI build.

Mam kilka projektów, które wszystkie dziedziczą właściwości podstawowe od macierzystego POM. Używamy Java 1.5, więc tam ustawiamy właściwość kompilacji. Wszystko jest w UTF-8. Wszystkie raporty, które chcę uruchomić, ustawienia sonaru itp. Znajdują się w macierzystym POM.

Zakładając, że twój projekt jest w kontroli wersji i masz narzędzie CI, podczas odprawy twoje narzędzie CI może zbudować na projekcie POM i wdrożyć SNAPSHOT do repozytoriów maven. Jeśli twoje projekty wskazują na wersję SNAPSHOT nadrzędnego POM, sprawdzą repozytorium, aby sprawdzić, czy mają najnowszą wersję ... jeśli nie, to pobierz najnowszą wersję. Jeśli zaktualizujesz obiekt nadrzędny, wszystkie pozostałe projekty zostaną zaktualizowane.

Podstęp, jak sądzę, uwalnia się z SNAPSHOTEM. Powiedziałbym, że twoje wydania pojawią się znacznie rzadziej niż twoje zmiany. Wykonasz więc zwolnienie POM, a następnie zaktualizujesz POM, które odziedziczyły po nich i sprawdzisz w kontroli wersji. Niech twórcy wiedzą, że muszą zrobić aktualizację i przejść od tego miejsca.

Można po prostu wywołać kompilacje, zmuszając nowe POMy do repozytorium, a następnie umożliwić wszystkim programistom automatyczne pobieranie zmian po kompilacji.


Usunąłem pomysł słów kluczowych NAJNOWSZE/ZWOLNIENIE, ponieważ nie działają one dla macierzystych POM. Działają tylko w przypadku zależności lub wtyczek. Obszar problemowy znajduje się w DefaultMavenProjectBuilder. Zasadniczo ma problem z określeniem, które repozytorium ma wyszukać rodzica, aby ustalić, co jest najnowszą lub wersją wydania. Nie wiem, dlaczego jest inaczej w przypadku zależności lub wtyczek.


Brzmi tak, jakby były mniej bolesne niż konieczność aktualizacji POM przy każdej zmianie w macierzystym POM.

22

Co można zrobić, to użyć numeru Properties Maven plugin. Umożliwi to zdefiniowanie twoich właściwości w zewnętrznym pliku, a wtyczka odczyta ten plik.

Przy tej konfiguracji:

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

i jeśli trzeba, we właściwościach pliku następujące wiersze:

spring-version=1.0 
mysql-version=4.0.0 

to jest to samo, co jeśli pisze w swojej pom.xml , następujące linie:

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

Za pomocą tej wtyczki będziesz miał kilka zalet:

  • Set łatwo długa lista właściwości
  • zmodyfikować wartości tych właściwości bez modyfikowania pom.xml nadrzędnego.
+0

Jak dojrzała jest ta wtyczka z jej uwzględnieniem to jest wersja alfa-1? –

+1

Według tego błędu nadal nie jest to dla mnie użyteczne, ponieważ chcę spowolnić działanie w pom nadrzędnej: http://jira.codehaus.org/browse/MOJO-1303 –

+0

Czy możesz podać kompletny 'pom.com', gdzie odsyłasz' wiosenną wersję'? Według dyskusji na http://stackoverflow.com/qu estions/849389/how-to-read-an-external-properties-file-in-maven nie jest możliwe określenie wersji zależności. Dobrze? –

7

Myślę, że właściwości-maven-plugin jest właściwym podejściem długoterminowym, ale odpowiedź na nie nie pozwala na odziedziczenie właściwości. Istnieje kilka udogodnień w maven-shared-io, które pozwalają odkryć zasoby w ścieżce klas projektu. Poniżej zamieściłem kod, który rozszerza wtyczkę właściwości, aby znaleźć pliki właściwości w zależnościach wtyczki.

Konfiguracja deklaruje ścieżkę do pliku właściwości, ponieważ projekt deskryptora jest deklarowany w konfiguracji wtyczki, jest dostępny dla ClasspathResourceLocatorStrategy. Konfiguracja może być zdefiniowana w projekcie nadrzędnym i będzie dziedziczona przez wszystkie projekty podrzędne (jeśli to zrobisz, unikaj deklarowania plików, ponieważ nie zostaną wykryte, ustaw tylko właściwość filePaths).

Poniższa konfiguracja zakłada, że ​​istnieje inny projekt jar o nazwie nazwa.seller.rich: test-właściwości-descriptor:0.0.1, który ma plik o nazwie external.properties pakowany do słoika (tj. Został zdefiniowany w src/główne/zasoby).

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

POM dla projektu wtyczki wygląda następująco:

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

Mojo jest kopią właściwości pluginu ReadPropertiesMojo z dodatkową „filepaths” własności, co pozwala określić względną ścieżkę do pliku właściwości zewnętrznych w ścieżce klasy, czyni właściwość plików opcjonalną i dodaje metody readPropertyFiles() i getLocation() w celu zlokalizowania plików i scalenia dowolnych plików filePath z tablicą plików przed kontynuowaniem. Skomentowałem moje zmiany, aby były jaśniejsze.

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

Czy kiedykolwiek przesłałeś to do wtyczki Properties Maven jako patch? Ponieważ mam taką samą potrzebę, gdy mam plik właściwości w słoiku, a następnie chcę użyć wtyczki maven-resources do filtrowania za pomocą pliku xml. –

+0

To jest świetna odpowiedź, ale mam pewne problemy, mam pom nadrzędny, gdzie czytam w wersjach z pliku tuż obok i wywołać niezbędne metody zestawu, właściwości ustawić, ale gdy przychodzi czas na rozwiązanie zależności, nie przyzwyczajaj się ... Czy potrzebuję tego, aby wymusić ponowną interpolację, wypróbowałem ją za pomocą 'project.getModel(). setProperties (propectProperties)' ale bez powodzenia naprawdę chcę, aby to działało: '( – sloven

Powiązane problemy