2009-08-05 28 views
47

Tôi có một số dự án được xây dựng bởi maven và tôi muốn chia sẻ một số thuộc tính chung giữa chúng - phiên bản mùa xuân, phiên bản trình điều khiển mysql, url cơ sở svn, v.v. - vì vậy tôi có thể cập nhật chúng một lần và nó sẽ được phản ánh trên tất cả các dự án.Làm thế nào để chia sẻ các thuộc tính chung giữa một số dự án maven?

Tôi nghĩ có một siêu đơn với tất cả các thuộc tính, nhưng nếu tôi thay đổi một trong những vấn đề tôi cần phải tăng phiên bản của nó (và cập nhật tất cả các poms kế thừa từ nó) hoặc xóa nó từ tất cả các các máy phát triển mà tôi không muốn làm.

Có thể chỉ định các tham số này ra bên ngoài cho pom không? Tôi vẫn muốn có định nghĩa vị trí bên ngoài trong một pom cha mẹ.

+1

Đi tuyến đường siêu việt và khi bạn cập nhật số phiên bản siêu pom, hãy thực thi: 'mvn -N versions: update-child-modules' http://stackoverflow.com/questions/30571/# 1172805 – Tim

+0

@Tim vấn đề là tôi có một hệ thống phân cấp của một số siêu poms (định nghĩa chung -> dự án mùa xuân -> webapps/services -> mô-đun thực tế. AFAIK phiên bản plugin không làm cập nhật này cascade –

Trả lời

13

Lưu ý rằng ý tưởng ban đầu tôi có ở đây là điều tôi đang làm, nhưng tôi có thể đã tìm thấy ý tưởng tốt hơn mà tôi cũng đã liệt kê bên dưới. Tôi muốn giữ cả hai ý tưởng ở đây để hoàn thành trong trường hợp ý tưởng mới hơn thực hiện công việc không.


Tôi nghĩ rằng bạn có thể giải quyết vấn đề này bằng cách sử dụng pom mẹ, nhưng bạn cần phải có một kho maven và một công cụ CI xây dựng.

Tôi có một vài dự án mà tất cả đều thừa kế các thuộc tính cơ sở từ POM mẹ. Chúng tôi sử dụng Java 1.5, để xây dựng tài sản được thiết lập ở đó. Mọi thứ đều là UTF-8. Tất cả các báo cáo mà tôi muốn chạy, thiết lập Sonar, vv, nằm bên trong POM cha.

Giả sử dự án của bạn đang ở trong điều khiển phiên bản và bạn đã có một công cụ CI, khi bạn đăng ký, công cụ CI của bạn có thể xây dựng cho dự án POM và triển khai SNAPSHOT cho repo maven. Nếu dự án của bạn trỏ tới phiên bản SNAPSHOT của POM cha mẹ, họ sẽ kiểm tra kho lưu trữ để xác thực rằng họ có phiên bản mới nhất ... nếu không họ tải xuống phiên bản mới nhất. Vì vậy, nếu bạn cập nhật phụ huynh, tất cả các dự án khác sẽ cập nhật.

Bí quyết, tôi cho là phát hành bằng SNAPSHOT. Tôi muốn nói các bản phát hành của bạn sẽ ít thường xuyên hơn những thay đổi của bạn. Vì vậy, bạn thực hiện một bản phát hành POM của bạn, sau đó cập nhật POM của bạn kế thừa từ chúng và kiểm tra chúng thành kiểm soát phiên bản. Hãy để các nhà phát triển biết rằng họ cần cập nhật và đi từ đó.

Bạn chỉ có thể kích hoạt các bản dựng ở đó buộc POM mới vào kho và sau đó có tất cả các nhà phát triển nhận các thay đổi tự động khi xây dựng.


Tôi đã xóa ý tưởng từ khóa MỚI nhất/RELEASE vì chúng không hoạt động đối với POM mẹ. Chúng chỉ hoạt động cho các phụ thuộc hoặc bổ sung. Vùng sự cố nằm trong DefaultMavenProjectBuilder. Về cơ bản nó gặp khó khăn trong việc xác định kho lưu trữ nào cần tìm cha mẹ để xác định phiên bản mới nhất hoặc phiên bản phát hành nào. Bạn không chắc chắn lý do tại sao điều này là khác nhau đối với phụ thuộc hoặc plugin mặc dù.


Có vẻ như điều này sẽ ít đau đớn hơn là phải cập nhật POM trên mọi thay đổi đối với POM mẹ.

22

Điều bạn có thể làm là sử dụng Properties Maven plugin. Điều này sẽ cho phép bạn xác định các thuộc tính của bạn trong một tệp bên ngoài và plugin sẽ đọc tệp này.

Với cấu hình này:

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

và nếu bạn có, trong tài sản của bạn nộp những dòng sau:

spring-version=1.0 
mysql-version=4.0.0 

thì đó là điều tương tự như nếu bạn đã viết, trong pom.xml của bạn , các dòng sau:

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

Sử dụng plugin này, bạn sẽ có một số lợi ích:

  • Set dễ dàng một danh sách dài các tính
  • Sửa đổi các giá trị của các tài sản mà không sửa đổi pom.xml mẹ.
+0

Làm thế nào trưởng thành là plugin này xem xét nó là một phiên bản alpha-1? –

+1

Theo lỗi này, nó vẫn không thể sử dụng được cho tôi, vì tôi muốn giảm tốc trong pom cha mẹ: http://jira.codehaus.org/browse/MOJO-1303 –

+0

Bạn có thể cung cấp một 'pom.com' hoàn chỉnh, nơi bạn tham khảo' spring-version'? Theo các cuộc thảo luận trong http://stackoverflow.com/qu estions/849389/làm thế nào để đọc-một-bên ngoài-thuộc tính-file-in-maven nó không thể xác định phiên bản của phụ thuộc. Đúng? –

7

Tôi nghĩ rằng thuộc tính-maven-plugin là cách tiếp cận phù hợp lâu dài, nhưng khi bạn trả lời câu trả lời đó, nó không cho phép các thuộc tính được kế thừa. Có một số cơ sở trong maven-shared-io cho phép bạn khám phá các tài nguyên trên classpath của dự án. Tôi đã bao gồm một số mã bên dưới để mở rộng plugin thuộc tính để tìm các tệp thuộc tính trong các phụ thuộc của plugin.

Cấu hình khai báo đường dẫn đến tệp thuộc tính, vì dự án mô tả được khai báo trên cấu hình plugin, có thể truy cập vào ClasspathResourceLocatorStrategy. Cấu hình có thể được định nghĩa trong một dự án cha, và sẽ được thừa hưởng bởi tất cả các dự án con (nếu bạn làm điều này tránh khai báo bất kỳ tệp nào vì chúng sẽ không được phát hiện, chỉ đặt thuộc tính tệpPaths).

Cấu hình bên dưới giả định rằng có một dự án jar khác gọi là name.seller.rich:test-properties-descriptor:0.0.1 có tệp được gọi là external.properties được đóng gói trong jar (nghĩa là nó được định nghĩa trong src/chính/tài nguyên).

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

Các pom cho dự án Plugin trông như thế này:

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

Các mojo là một bản sao của các tài sản của plug-in ReadPropertiesMojo, với thêm một "filepaths" tài sản để cho phép bạn xác định đường dẫn tương đối vào tệp thuộc tính bên ngoài trong classpath, nó làm cho thuộc tính tệp tùy chọn và thêm phương thức readPropertyFiles() và getLocation() để định vị tệp và hợp nhất bất kỳ tệp tệpPaths nào vào mảng tệp trước khi tiếp tục. Tôi đã nhận xét các thay đổi của mình để làm cho chúng rõ ràng hơn.

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]l.com">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

Bạn đã bao giờ gửi bản này vào Plugin Maven thuộc tính như một bản vá chưa? Bởi vì tôi có cùng một nhu cầu mà tôi có một tập tin thuộc tính trong một cái lọ mà sau đó tôi muốn sử dụng maven-resources-plugin để lọc với một tập tin xml. –

+0

Đây là một câu trả lời tuyệt vời, nhưng tôi gặp một số rắc rối, tôi có một pom cha mẹ, nơi tôi đọc trong các phiên bản từ một tập tin ngay bên cạnh nó và gọi các phương pháp thiết lập cần thiết, tài sản được thiết lập nhưng khi đến thời gian để giải quyết phụ thuộc họ không được sử dụng ... Tôi có cần nó để buộc phải tái nội suy, thử nó với 'project.getModel(). setProperties (propectProperties)' nhưng không may mắn tôi thực sự muốn điều này để làm việc: '( – sloven

Các vấn đề liên quan