有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java按属性激活Maven概要文件不适用于依赖项目吗?

我需要使用同一个父pom文件支持多种类型的客户端构建。我面临的挑战是,不同的客户将使用略有不同的库。例如,一个客户端可能使用SQL server,另一个客户端可能使用MySQL。这是一个简单的例子,但其他库可能包括那些可能需要许可证的库,这些许可证是我们内部没有的,但我们的客户机会有。如果不在内部排除它们,将导致Maven再进行位构建,因为库不会出现在我们的存储库中。我最初的想法是在我们的父pom中为每个客户机创建一个概要文件,然后在这些概要文件中定义仅用于该客户机的任何依赖项。这些配置文件将由缺少属性或具有特定值的属性激活。当涉及多个模块时,尤其是当一个孩子依赖另一个孩子时,我对解决依赖关系的方式有问题。我认为问题的关键在于,在解决过程中的某个时刻,触发配置文件的变量没有被设置,但请允许我举一个简单的例子:

父pom:

<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.test</groupId>
  <artifactId>parent</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>

  <modules>
    <module>../child-a</module>
    <module>../child-b</module>
  </modules>

<profiles>
    <profile>
        <id>client-a</id>
        <activation>
            <property>
                <name>!clientbuild</name>
            </property>
        </activation>
        <dependencies>
            <dependency>
                <groupId>com.microsoft.sqlserver</groupId>
                <artifactId>sqljdbc4</artifactId>
                <version>4.0</version>
            </dependency>
        </dependencies>
    </profile>
    <profile>
        <id>client-b</id>
        <activation>
            <property>
                <name>clientbuild</name>
                <value>clientb</value>
            </property>
        </activation>
        <dependencies>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.34</version>
            </dependency>
        </dependencies>
    </profile>
  </profiles>
</project>

我在我的父母pom中定义了客户a和客户b档案。在没有“clientbuild”属性的情况下,应激活client-a配置文件;在“clientbuild”属性设置为“clientb”时,应激活“client-b”配置文件。如果我在parent上运行dependency:tree,并在maven用户“setting.xml”文件中指定“clientb”,我会得到以下结果:

--- maven-dependency-plugin:2.8:tree (default-cli) @ parent ---
com.test:parent:pom:0.0.1-SNAPSHOT
\- mysql:mysql-connector-java:jar:5.1.34:compile

--- maven-dependency-plugin:2.8:tree (default-cli) @ child-a ---
com.test:child-a:jar:0.0.1-SNAPSHOT
\- mysql:mysql-connector-java:jar:5.1.34:compile

--- maven-dependency-plugin:2.8:tree (default-cli) @ child-b ---
com.test:child-b:jar:0.0.1-SNAPSHOT
+- com.test:child-a:jar:0.0.1-SNAPSHOT:compile
|  \- com.microsoft.sqlserver:sqljdbc4:jar:4.0:compile
\- mysql:mysql-connector-java:jar:5.1.34:compile

“parent”和“child-a”项目具有正确的依赖关系,但“child-b”具有来自这两个概要文件的依赖关系。从树中,我可以看到包含了不正确的依赖项,因为maven认为“child-a”具有sqljdbc的依赖项。我的信念是,在构建时,maven从父pom获取“child-a”并解析其依赖关系,而不使用我在maven“settings.xml”文件中设置的“clientbuild”属性。有没有办法让maven在整个依赖项解析过程中使用“clientbuild”属性

通过各种实验,我已经确定,如果我要删除“!clientbuild”并用针对某个值的检查来替换它(然后在我的settings.xml中指定该值),或者如果我没有激活要求,并用-p手动触发配置文件,我会得到所需的结果。不幸的是,我们不能强制我们的第一个客户机在构建过程中使用-P或指定任何其他参数,因此使用“clientbuild”属性的缺失是目前我可以对“client-a”使用的唯一激活检查。此外,如果我用“activeByDefault”替换这个检查,那么在将“clientb”作为属性添加到我的“settings.xml”文件时,我会得到与上面相同的行为

所以,考虑到所有这些,我的问题是:我正在尝试做的事情是可能的吗?我知道我的要求很不寻常。理想情况下,我希望在构建期间始终指定配置文件,但不幸的是,这对于我们的客户来说是不可能的

简而言之,我需要在默认情况下激活一个包含某些依赖项的概要文件,但是如果由属性激活,这些依赖项将被另一个概要文件中的另一组依赖项所替换。此外,如上图所示,当属于同一父模块的一些模块相互依赖时,这需要起作用。有没有人有这方面的经验,或者我可以尝试其他方法

最后,我将使用Eclipse(特别是Spring工具套件)及其附带的嵌入式Maven 3

编辑(子pom和settings.xml): 根据要求,这里是child-a和child-b的POM。我还包括了我的用户设置。当我试图将“clientbuild”属性应用为“clientb”时,我所用的xml文件

child-a POM:

<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>
  <parent>
    <groupId>com.test</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>child-a</artifactId>
  <packaging>jar</packaging>
</project>

child-b POM:

<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>
  <parent>
    <groupId>com.test</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>child-b</artifactId>
  <packaging>jar</packaging>

  <dependencies>
    <dependency>
        <groupId>com.test</groupId>
        <artifactId>child-a</artifactId>
        <version>${project.version}</version>
    </dependency>
  </dependencies>
</project>

设置。clientb“clientbuild”属性处于活动状态时的xml:

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <pluginGroups>
  </pluginGroups>

  <proxies>
  </proxies>

  <servers>
  </servers>

  <mirrors>
  </mirrors>

  <profiles>
   <profile>
    <id>client-profile</id>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
        <clientbuild>clientb</clientbuild>
    </properties>
   </profile>
  </profiles>
</settings>

我还尝试设置标签,在我的设置中激活“客户端构建”配置文件。xml而不是使用activeByDefault标记,但这产生了相同的结果

编辑2(关于关系和使用JVM参数的澄清):为了澄清,客户机a/客户机b配置文件对child-a/child-b模块之间的关系没有影响。不管配置文件如何,这种关系都是child-b依赖于child-a。client-a/client-b配置文件影响的唯一一件事是是否将sqljdbc或mysql connector java添加为父级的依赖项

至于命令行中使用的clientbuild变量。传递-Dclientbuild=clientb将生成所需的依赖关系树

--- maven-dependency-plugin:2.8:tree (default-cli) @ parent ---
com.test:parent:pom:0.0.1-SNAPSHOT
\- mysql:mysql-connector-java:jar:5.1.34:compile

--- maven-dependency-plugin:2.8:tree (default-cli) @ child-a ---
com.test:child-a:jar:0.0.1-SNAPSHOT
\- mysql:mysql-connector-java:jar:5.1.34:compile

--- maven-dependency-plugin:2.8:tree (default-cli) @ child-b ---
com.test:child-b:jar:0.0.1-SNAPSHOT
+- com.test:child-a:jar:0.0.1-SNAPSHOT:compile
\- mysql:mysql-connector-java:jar:5.1.34:compile

但是,我想/需要使用设置的原因是:。改为xml是因为,在修复手动maven构建时,使用命令行参数并不能修复Eclipse的嵌入式maven仍将解析依赖项的事实,正如我在上面的初始依赖项:树输出中所示(child-b将具有两个配置文件的依赖项,而不仅仅是client-b配置文件)。这本身是可以接受的(即使行为不符合预期),但是由于许可和其他原因,我们在激活的配置文件中没有一些不应该被激活的依赖项(来自客户端-a配置文件)。如果两个概要文件的依赖关系都存在,将导致Eclipse中出现许多缺失的工件错误


共 (1) 个答案

  1. # 1 楼答案

    我发现的是:

    1. child-b正在使用设置中设置的属性从父级激活正确的配置文件。xml

    2. 在child-b的依赖项解析期间,child-a没有继承此属性,因此激活了不正确的配置文件。我不能完全解释为什么该属性没有被继承,但我能想到的唯一解释是,该属性只应用于正在构建的项目,而不是它的依赖项。我不确定我是否觉得这应该是一种行为,但这是我观察到的

    TLDR

    为了解决上述问题,我最终做的是使用:true将两个概要文件中的所有依赖项设置为可选。由于optional的一个副作用/功能禁用了可传递性,因此任何正在构建的给定项目(本例中为child-b)都将激活正确的配置文件,但具有相同父级的任何其他项目依赖项都不会继承错误的依赖项。请注意,child-a的错误配置文件仍将被激活,因此如果配置文件中有其他标记(例如插件或其他东西),这些标记仍将被错误激活。在我的用例中,这碰巧不是问题,因为概要文件只包含依赖项