MavenのactiveByDefaultにはクセがある

Created: 2018-06-09

Mavenで複数のプロファイルを切替える場合に、そのデフォルトとして、プロファイルをマークするのがactiveByDefaultという設定なわけですが、これの挙動が少し想像とズレていたのでそのメモ。

サンプルは以下。
https://github.com/yo1000/example.Maven-ActiveByDefaults

要件

  • Java 1.8.0_121
  • Maven 3.5.3
$ ./mvnw -v
Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-25T04:49:05+09:00)
Maven home: ~/.m2/wrapper/dists/apache-maven-3.5.3-bin/2c22a6s60afpuloj4v181qvild/apache-maven-3.5.3
Java version: 1.8.0_121, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.3", arch: "x86_64", family: "mac"

検証

検証に際し、以下のようなpom.xmlを用意しました。

<?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.yo1000</groupId>
    <artifactId>example.maven.activeByDefault</artifactId>
    <version>1.0.0</version>

    <name>example.maven.activeByDefault</name>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
    <profiles>
        <profile>
            <id>A</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib</artifactId>
                    <version>1.1.0</version>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>B</id>
            <dependencies>
                <dependency>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib</artifactId>
                    <version>1.2.0</version>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>C</id>
        </profile>
    </profiles>
</project>

検証内容

依存関係の設定が異なる、プロファイルなしと、3つのプロファイルを用意しました。まとめると以下の4つです。

  • プロファイルなし: kotlin-stdlib-1.0.0に依存
  • プロファイルA: kotlin-stdlib-1.1.0に依存(activeByDefault)
  • プロファイルB: kotlin-stdlib-1.2.0に依存
  • プロファイルC: 個別の依存設定はないため、プロファイルなしと同義

これらに対し、以下のコマンドを発行したときに、依存関係にどのような変化があるかを検証します。

./mvnw clean dependency:tree -P ${ProfileId}

検証結果

以下5パターンの検証をしました。それぞれ結果です。

プロファイルなし

kotlin-stdlib:jar:1.1.0に依存。activeByDefaultの設定が効いているため、プロファイルAが適用される結果となった。

./mvnw clean dependency:tree

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.1.0:compile[INFO]    \- org.jetbrains:annotations:jar:13.0:compile

プロファイルA

kotlin-stdlib:jar:1.1.0に依存。プロファイルAを指定したため、プロファイルAが適用される結果となった。

./mvnw clean dependency:tree -P A

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.1.0:compile[INFO]    \- org.jetbrains:annotations:jar:13.0:compile

プロファイルB

kotlin-stdlib:jar:1.1.0に依存。プロファイルBを指定したため、プロファイルBが適用される結果となった。

./mvnw clean dependency:tree -P B

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.2.0:compile[INFO]    \- org.jetbrains:annotations:jar:13.0:compile

プロファイルC

kotlin-stdlib:jar:1.0.0に依存。プロファイルCを指定したため、プロファイル側での依存はない状態が適用される結果となった。

./mvnw clean dependency:tree -P C

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.0.0:compile[INFO]    \- org.jetbrains.kotlin:kotlin-runtime:jar:1.0.0:compile

プロファイルX

kotlin-stdlib:jar:1.1.0に依存。activeByDefaultの設定が効いているため、プロファイルAが適用される結果となった。

./mvnw clean dependency:tree -P X

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.1.0:compile[INFO]    \- org.jetbrains:annotations:jar:13.0:compile

実はこのパターンこそが、今回のポストを書く発端となったものでした。pom.xmlに定義されていないプロファイルが指定された場合、どうなるのか。

当初想像していたのは、プロファイルが存在しないため、プロファイル側での依存はない状態(kotlin-stdlib:jar:1.0.0に依存)が適用されるものかと思い込んでいました。

ところが、実際の結果では想像と異なり、存在しないプロファイルが指定された場合、プロファイルが指定されなかった場合と同じように扱われてしまい、activeByDefaultの設定されたプロファイル(kotlin-stdlib:jar:1.1.0に依存)が適用されました。

つまり、activeByDefaultというのはpom.xmlに定義されていないプロファイルが指定された場合にも、効いてしまうようなのです。

以上のような結果が得られたため、activeByDefaultを使用する場合には、適用されるプロファイルに注意したい。

avatar

Written by yo1000 | YO!CHI KIKUCHI
Loves 🌱 Spring, 🦢 Pelikan fountain pen and 🦁 FINAL FANTASY VIII