如何定义组织特定的父POM?

3

环境: Maven 2.2.1 我有两个Java项目在svn下(projectA,projectB)。我的Maven结构如下...

For projectA 
pom.xml (contains ProjectA parent pom definitions)

   module moduleA
   module moduleB


For projectB 
pom.xml (contains ProjectB parent pom definitions)

   module moduleC
   module moduleD

projectA/pom.xml和projectB/pom.xml包含了一些通用定义,如junit、selenium、编译器、eclipse插件等,这些定义对两个项目都是通用的。(例如下面所示)

    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.4</version>
        <type>jar</type>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.7</version>
        <scope>test</scope>
    </dependency

我应该如何创建/组织一个特定于组织的项目pom,其中包括这些常见定义,以便个别项目不必重新创建/维护。是否有人可以提供一些已经完成此操作的片段或项目?
编辑1:
公司/pom.xml
<modelVersion>4.0.0</modelVersion>

<groupId>com.mycompany</groupId>
<artifactId>company</artifactId>
<packaging>pom</packaging>

<name>parent</name>
<version>1.0.0</version>

<build>
    <defaultGoal>install</defaultGoal>
</build>

<dependencies>
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.4</version>
        <type>jar</type>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

projectA/pom.xml

<modelVersion>4.0.0</modelVersion>

<parent>
    <groupId>com.mycompany</groupId>
    <artifactId>company</artifactId>
    <version>1.0.0</version>
</parent>

<groupId>com.mycompany</groupId>
<artifactId>projectA</artifactId>
<packaging>pom</packaging>

<name>projectA</name>
<version>1.0.0</version>

<modules>
    <module>moduleA</module>

<build>
    <defaultGoal>install</defaultGoal>
</build>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

projectA/moduleA/pom.xml

<modelVersion>4.0.0</modelVersion>

<parent>
    <groupId>com.mycompany</groupId>
    <artifactId>projectA</artifactId>
    <version>1.0.0</version>
    <relativePath>../pom.xml</relativePath>
</parent>

<groupId>com.mycompany</groupId>
<artifactId>moduleA</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<name>moduleA</name>

<build>
    <finalName>moduleA</finalName>
    <defaultGoal>install</defaultGoal>
</build>

<dependencies>
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
    </dependency>
</dependencies>

抛出以下错误:
Project ID: com.mycompany:moduleA
POM Location: c:\temp\maven\projectA\moduleA\pom.xml
Validation Messages:

    [0]  'dependencies.dependency.version' is missing for commons-lang:comm
ons-lang:jar
    [1]  'dependencies.dependency.version' is missing for javax.servlet:ser
vlet-api:jar
3个回答

7
我认为将依赖项添加到“超级”POM中需要重新考虑,这会不必要地耦合项目(但可能表明如果项目不是分散的,则它们应该被合并)。我认为@lexicore的最后一条评论也很有意义,扩展面向对象编程的类比,它也感觉像“混合抽象层次”。
Alex Gitelman提供了正确的答案,您需要使用dependencyManagement,如此处所示 Dependency Scope Maven3应该支持POM片段,请参见How to use Maven 3 mixins?,我一直在等待。
我们有一个组织Über POM,但它只包含:
<organization>
    <name>...</name>
    <url>...</url>
</organization>

<developers>
    <developer>
        <id>...<id>
        <name>...</name>
        <email>...</email>
        <roles>
            <role>...</role>
        </roles>
    </developer>

<distributionManagement>
    ...
</distributionManagement>

<repositories>
    <!-- your proxy repo here -->
</repositories>

这些是很少更改的内容(如果我们更改存储库/发布管理,则所有项目都必须更改;如果开发人员离开或加入,我们可以在任何方便的时间更新项目POM)。依赖关系专门属于正在考虑的模块,仅因为两个独立的项目现在共享依赖关系并不意味着它们总是如此。我完全理解每个项目都需要复制“n”个XML的烦恼(编译器插件、报告插件、junit等),但每个项目中不同的活动水平肯定会导致它们在某些时候分歧。关于持续集成中的级联构建,如果A项目要求更改超级依赖项POM,那么您的所有其他项目都将被迫重新构建——如果您只有2个项目,这可能很好,但即使是这样,您是否在提交更改之前检出并构建了两个项目?

4
如果您只需要重用依赖项,请创建另一个打包为pom的项目,并在其中指定依赖项。我们称其为OrgDependencies,然后将其作为依赖项包含在您的projectAprojectB中。它将传递地从OrgDependencies项目中拉取所有依赖项。
在您的示例中,在projectA中,不要使用
<parent>
    <groupId>com.mycompany</groupId>
    <artifactId>company</artifactId>
    <version>1.0.0</version>
</parent>

尝试输入 < /p >
<dependencies>
  <dependency>
    <groupId>com.mycompany</groupId>
    <artifactId>company</artifactId>
    <version>1.0.0</version>
  </dependency>
</dependencies>

从模块中删除对commons-lang等的依赖。


更新。

虽然我之前的解决方案使用传递依赖应该是可行的,但实际上你需要在公司范围的pom.xml文件中定义<dependencyManagement>部分。

这是你定义版本的地方。

注意:任何在dependencyManagement部分中的内容都不是真正的依赖关系,而只是一个描述符,允许指定版本并排除传递依赖(如果必要)以防普通dependencies部分指定了该依赖项。因此,您可以在dependencyManagement中放置任意数量的项目,它不会使所有后代都依赖于它们。

我测试过了,它可以工作:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany</groupId>
    <artifactId>company</artifactId>
    <packaging>pom</packaging>

    <name>parent</name>
    <version>1.0.0</version>

    <build>
        <defaultGoal>install</defaultGoal>
    </build>

    <dependencyManagement>
        <dependencies>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.4</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        </dependencies>
    </dependencyManagement>
</project>

我尝试了你的建议,但是它无法拉取我的子模块中的传递依赖项。 - Joe
你能提供具体信息吗?你是如何设置父项目的?你是如何引用它的?出现了什么错误?这种方法对我绝对有效。 - Alex Gitelman
1
感谢添加代码。模块不应显式指定依赖项。相反,它们或者projectA/projectB应该包含对父级的依赖。如果您想拥有单独的依赖关系并仅指定来自父POM的版本,则这不是正确的方法。在这种情况下,请尝试通过“parent”标记引用父POM。 - Alex Gitelman
@Alex - 有点困惑。我在moduleA/pom.xml中添加了parent标签,以便开发人员可以从该目录构建。此外,我通过parent标签在projectA/pom.xml中引用公司范围的pom。我需要做出哪些更正才能运行它? - Joe
1
我编辑了答案并添加了一些解释。虽然我也希望您的父级解决方案能够起作用。如果我有时间,我将尝试一些实验。 - Alex Gitelman
显示剩余11条评论

3
在OS项目中,我通常使用3个以上级别的POM:
- “公司范围POM”包含开发范围定义,例如分发管理、插件版本等等。非常稳定,通常只有一个版本号。例如:Sonatype OSS Parent。 - “项目POM”包含项目范围定义:Java编译器版本、依赖管理等等。其父级为公司范围POM。例如:JAXB2 Basics Project。版本随每个发布而更新。 - 不同级别的“模块POMs”。列出各自的依赖关系(依赖版本从项目POM继承),添加“特殊”的构建步骤。例如:JAXB Basics
我在其他OS项目(如Apache)中看到了类似的模式。
还有一些注释:
- 根据公司规模和产品组织结构,您还可以有“部门POM”或“产品POM”。 - 把POM继承看作OOP继承。您会将哪些内容放入哪个抽象类中,以使类层次结构稳定但动态?例如,在公司范围POM中定义依赖关系的版本是没有意义的,因为版本经常变化。相反,在每个项目中定义分发管理将违反DRY原则。

我已经按照上面的示例做了,唯一的区别是公司范围的pom包含所有依赖项/版本。因此,子模块无法解析。如果依赖项/版本存在于项目pom中,则子模块可以解析依赖项/版本。 - Joe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接