CLOVER🍀

That was when it all began.

Apache MavenでリポジトリのMirrorを設定する

前に、ちょっとしたことからApache MavenでリポジトリのMirrorを設定できることを知ったので、メモ。

Mirror?

詳細は、こちらを。

Maven – Guide to Mirror Settings

$HOME/.m2/settings.xmlに書くもので、リポジトリのMirrorを定義できるようです。

どういう時に使うかというと、以下のようなケースがあるようです。

高速化目的もそうですが、置き換えにも使えるんですね、なるほど。

試してみる

というわけで、早速試してみましょう。

今回の環境は、こちらです。

$ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-0ubuntu0.18.04.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)


$ mvn -version
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 1.8.0_191, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-8-openjdk-amd64/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-43-generic", arch: "amd64", family: "unix"

Mirrorとなるリポジトリとして、今回はSonatype Nexusの3.15.0-01を使用しました。とりあえず、デフォルトの状態で起動している
ものとします。

とりあえず、MirrorとなるためのProxyリポジトリ+Groupリポジトリを作ってみます。
create-maven-repo.json

{
    "name": "create-maven-repo",
    "type": "groovy",
    "content": "repository.createMavenProxy('my-maven-proxy-repo', 'https://repo.maven.apache.org/maven2'); repository.createMavenGroup('my-maven-group-repo', ['my-maven-proxy-repo'])"
}

Proxyリポジトリは、Maven Centralに対するプロキシとなります。

スクリプト登録+リポジトリ作成。なお、このNexusが動作しているサーバーのIPアドレスは、「172.17.0.2」とします。

## スクリプト登録
$ curl -u admin:admin123 -i -H "Content-Type: application/json" 'http://172.17.0.2:8081/service/rest/v1/script/' -d @create-maven-repo.json
HTTP/1.1 204 No Content
Date: Mon, 14 Jan 2019 12:41:47 GMT
Server: Nexus/3.15.0-01 (OSS)
X-Content-Type-Options: nosniff


## リポジトリ作成
$ curl -u admin:admin123 -i -XPOST -H "Content-Type: text/plain" 'http://172.17.0.2:8081/service/rest/v1/script/create-maven-repo/run'
HTTP/1.1 200 OK
Date: Mon, 14 Jan 2019 12:43:29 GMT
Server: Nexus/3.15.0-01 (OSS)
X-Content-Type-Options: nosniff
Content-Type: application/json
Content-Length: 147

{
  "name" : "create-maven-repo",
  "result" : "RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=group, format=maven2, name='my-maven-group-repo'}"
}

これで、準備ができました。

サンプルプロジェクトを作る

続いて、このMirrorリポジトリを使うための、サンプルのMavenプロジェクトを作成してみましょう。

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.example</groupId>
    <artifactId>maven-repository-mirror-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/example/maven/App.java

package com.example.maven;

import org.apache.commons.lang3.StringUtils;

public class App {
    public static void main(String... args) {
        System.out.printf(
                "message = %s%n",
                StringUtils.replace("Hello ???!!", "???", "World")
        );
    }
}

とりあえず、Commons Lang 3に依存させてみました、的な簡単なプロジェクトです。サンプルプロジェクトの設定などには、
Mirrorに関する情報は一切現れません。

リポジトリのMirrorを設定する

では、以下を参考にしつつ、Mirrorを設定してみます。

Maven – Guide to Mirror Settings

$HOME/.m2/settings.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
                              https://maven.apache.org/xsd/settings-1.0.0.xsd">
  <mirrors>
    <mirror>
      <id>my-mirror</id>
      <name>My Central Mirror</name>
      <url>http://172.17.0.2:8081/repository/my-maven-group-repo</url>
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
</settings>

ポイントは「mirrorOf」で、ここにどのリポジトリのMirrorかを指定します。今回はMaven Centralを対象とするので、「central」と
記載しました。

それでは、サンプルプロジェクトでビルドを行ってみましょう。

$ mvn compile

すると、設定したMirrorからアーティファクトのダウンロードが行われます。

Downloading from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/commons/commons-lang3/3.8.1/commons-lang3-3.8.1.pom
Downloaded from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/commons/commons-lang3/3.8.1/commons-lang3-3.8.1.pom (28 kB at 90 kB/s)
Downloading from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/commons/commons-parent/47/commons-parent-47.pom
Downloaded from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/commons/commons-parent/47/commons-parent-47.pom (78 kB at 176 kB/s)
Downloading from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/apache/19/apache-19.pom
Downloaded from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/apache/19/apache-19.pom (15 kB at 53 kB/s)
Downloading from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/commons/commons-lang3/3.8.1/commons-lang3-3.8.1.jar
Downloaded from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/commons/commons-lang3/3.8.1/commons-lang3-3.8.1.jar (502 kB at 726 kB/s)

Maven Centralから取得するもの、たとえばプラグインなども同様にMIrrorからダウンロードが行われます。

Downloading from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom
Downloaded from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom (8.1 kB at 6.6 kB/s)
Downloading from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom
Downloaded from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom (9.2 kB at 28 kB/s)
Downloading from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/maven/maven-parent/22/maven-parent-22.pom
Downloaded from my-mirror: http://172.17.0.2:8081/repository/my-maven-group-repo/org/apache/maven/maven-parent/22/maven-parent-22.pom (30 kB at 69 kB/s)

ちゃんとMirrorが使われているようですね。

mirrorOfの書き方

mirrorOfの書き方には、いくつか種類があります。

例えば、以下は全リポジトリのMirrorを定義したことになります。この場合、指定したMirrorリポジトリが、利用するすべての
リポジトリを使った依存関係などを解決できる必要があります。

    <mirror>
      <id>my-mirror</id>
      <name>My Mirror</name>
      <url>http://172.17.0.2:8081/repository/my-maven-group-repo</url>
      <mirrorOf>*</mirrorOf>
    </mirror>

すべての外部リポジトリのMirrorとする場合。

    <mirror>
      <id>my-mirror</id>
      <name>My Mirror</name>
      <url>http://172.17.0.2:8081/repository/my-maven-group-repo</url>
      <mirrorOf>external:*</mirrorOf>
    </mirror>

「myrepo1」と「myrepo2」の2つのリポジトリのMirrorとする場合。

    <mirror>
      <id>my-mirror</id>
      <name>My Mirror</name>
      <url>http://172.17.0.2:8081/repository/my-maven-group-repo</url>
      <mirrorOf>myrepo1,myrepo2</mirrorOf>
    </mirror>

全リポジトリのMirrorとするものの、「myrepo」はMirrorから除外する場合。

    <mirror>
      <id>my-mirror</id>
      <name>My Mirror</name>
      <url>http://172.17.0.2:8081/repository/my-maven-group-repo</url>
      <mirrorOf>*,!myrepo</mirrorOf>
    </mirror>

ちなみに、mirrorOfで指定するのは、pom.xmlとかで指定するrepositoryとかのidですからね。

  <repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>http://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Central Repository</name>
      <url>http://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
  </pluginRepositories>

Maven – POM Reference

とまあ、こんな感じで使えそうですね。

オマケ:デフォルトのリポジトリのIDって、どこで決まってる?

そういえば「central」って、どこで決まってるんでしょうね。

どうやら、このあたりのようです。

maven/RepositorySystem.java at maven-3.6.0 · apache/maven · GitHub

https://github.com/apache/maven/blob/maven-3.6.0/maven-core/src/main/java/org/apache/maven/repository/RepositorySystem.java#L45

https://github.com/apache/maven/blob/maven-3.6.0/maven-model-builder/src/main/resources/org/apache/maven/model/pom-4.0.0.xml