最初のプラグインを作る
前回はMavenプラグインの役割を確認し、プラグイン開発の環境をDockerコンテナに作成するところまで出来ました。
そんなわけで、今回はいよいよMaven本家のチュートリアルに従って実際にプラグインを作ってみます。
まずは前回作ったDockerコンテナにVSCodeのRemote Development拡張で接続しましょう。
コンテナにアクセスできたら「Ctrl + @」でTerminalを開き、下記のコマンドを実行して作業用ディレクトリを作成します。
mkdir /usr/src/work
「work」ディレクトリが作成できたら、VSCodeのメニューから「File → Open folder」で作成したworkディレクトリを開きます。
プラグイン開発プロジェクトのひな型はこのコマンドで作ります
mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-plugin
groupId
artifactId
の入力を求められるので、チュートリアルのサンプルに従って下記の通り入力します。
groupId | sample.plugin | |
artifactId | hello-maven-plugin | |
version | 1.0-SNAPSHOT | ※デフォルトのままでいいので 何も入力せずにEnter |
package | sample.plugin | ※デフォルトのままでいいので 何も入力せずにEnter |
プロジェクトひな型が作成成功するとこんなフォルダ構成ができると思います。
前回、「プラグインにはgoalが定義されていて、ビルドフェーズと紐づけることでビルド ライフサイクルに組み込むことができる」という流れを確認しました。
このフォルダ構成の中にあるMyMojo.java
というファイルがまさにgoal
を定義したものになります。
Your First Mojo
テンプレートに最初から用意されているMyMojo.java
はいったん置いておいて、ごく簡単なgoal
を実装してみましょう。
「hello-maven-plugin/src/main/java/sample/plugin」の下、MyMojo.javaの隣にGreetingMojo.java
を新規作成してください。
package sample.plugin;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
/**
* Says "Hi" to the user.
*
*/
@Mojo(name = "sayhi")
public class GreetingMojo extends AbstractMojo
{
public void execute() throws MojoExecutionException
{
getLog().info("Hello, world.");
}
}
goal
を実装したクラスはMojo
と呼ばれるそうです。
MojoクラスはAbstractMojo
の派生クラスとし、execute()
メソッドに実際の処理を実装します。
GreetingMojoでは「Hello, world.」とログ出力するだけの実装になっています。
ちなみにGreetingMojoは「sayhi」という名前のgoalとして定義されています。@Mojo
というアノテーションでname
プロパティにgoal名を指定すればいいようです。
GreetingMojo.javaが実装できたら次はpom.xml
を確認してみます。
mvn archetype:generate
コマンドでひな型を作成した場合、pom.xmlは下記3つが生成されています。
- hello-maven-plugin/pom.xml
- hello-maven-plugin/it/simple-it/pom.xml
- hello-maven-plugin/test/resources/project-to-test/pom.xml
今回必要なのは 1. だけです。2. および 3. はテスト用みたいなので、ひとまず置いておきます。
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>sample.plugin</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<name>hello-maven-plugin Maven Plugin</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
・
・
・
ポイントの1つ目は「packaging」にはmaven-plugin
を指定することです。
こうすることで、hello-maven-pluginプロジェクトをMavenプラグインとしてビルドすることになります。
ポイントの2つ目は依存関係です。
・
・
・
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${maven.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
・
・
・
依存関係で特に重要なのはmaven-core
とmaven-plugin-annotations
です。
これらはAbstractMojo
クラスや@Mojo
アノテーションが定義されているライブラリで、依存関係に含まれていないとコンパイルに失敗してしまいます。
プラグインを実行してみる
まずは作成したhello-maven-plugin
をビルドしましょう。
cd /usr/src/work/hello-maven-plugin
mvn install
このコマンドを実行して、BUILD SUCCESSと出力されたら、hello-maven-plugin
はMavenのローカルリポジトリにインストールされます。
BUILD FAILUREと出力されているうちはビルドに失敗しているので、コードの何かが間違えている可能性があります。
エラーの内容をよく確認して修正してください。
次に作成したプラグインを利用するための適当なプロジェクトを作ります。
cd /usr/src/work
mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4
groupId | sample.plugin | |
artifactId | hello-world | |
version | 1.0-SNAPSHOT | ※デフォルトのままでいいので 何も入力せずにEnter |
package | sample.plugin | ※デフォルトのままでいいので 何も入力せずにEnter |
コマンドが成功すると work ディレクトリの配下、hello-maven-pluginの隣にhello-worldディレクトリが作成されていて、配下にプロジェクトができていると思います。
今回はhello-maven-pluginを試してみるだけなので、hello-worldのソースコードは一切触らず置いておきます。
hello-worldディレクトリ下の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>sample.plugin</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>hello-world</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>hello-maven-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>sayhi</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
まず、72~76行目で今回作成したhello-maven-plugin
をビルド時のプラグインとして追加します。
次に79~96行目で「sayhi」というゴールと「compile」というビルドフェーズを紐づけています。
これで、hello-maven-pluginが実行できるはずです。
早速、hello-worldディレクトリでmvn installコマンドを実行してみましょう。
cd /usr/src/work/hello-world
mvn install
下記のように実行結果が出力されていて、ちょうど真ん中あたりでhello-maven-plugin
の「sayhi」ゴールが実行されていることがわかると思います。
改造してみる
プラグインはpom.xml上でプロパティを定義して、実行時に参照することができます。
GreetingMojo.javaを改造して試してみましょう。
package sample.plugin;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
/**
* Says "Hi" to the user.
*
*/
@Mojo(name = "sayhi", defaultPhase = LifecyclePhase.COMPILE)
public class GreetingMojo extends AbstractMojo
{
/**
* The greeting to display.
*/
@Parameter(property = "sayhi.greeting", defaultValue = "Hello World!" )
private String greeting;
public void execute() throws MojoExecutionException
{
getLog().info("Hello, world. - " + greeting);
}
}
この改造を加えた後hello-maven-pluginプロジェクトでmvn install
しておきましょう。
ちゃんとBUILD SUCCESSと出力されていることが確認しておいてください。
改造ポイント1
改造ポイントの1つ目は@Mojo
アノテーションにdefaultPhase = LivecyclePhase.COMPILE
を追加していることです。
前回少しだけ触れた「ゴールとビルド フェーズのデフォルトの紐づけを実装時に定義する方法」というのがこれです。
こうすることで、hello-maven-pluginを利用する時のpom.xmlで<phase>
の定義を省略してもcompileフェーズとsayhiゴールがデフォルトで紐づけられることになります。
<plugins>
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>hello-maven-plugin</artifactId>
<executions>
<execution>
<!-- <phase>compile</phase> -->
<goals>
<goal>sayhi</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
このように<phase>
の定義をコメントアウトしてhello-worldプロジェクトをmvn package
してみます。
この通り、ちゃんとcompileフェーズでsayhiゴールが実行されていることが確認できました。
改造ポイント2
改造ポイントの2つ目はgreeting
プロパティを定義していることです。
greeting
はprivateフィールドとして定義していますが、@Parameter
アノテーションを使うことで後から値を設定できるようになっています。
また@Parameter
アノテーションはproperty
とdefaultValue
という2つのプロパティでプロパティ名と省略時の値を指定できます。
再びhello-maven-pluginを利用する時のpom.xmlに下記のように<configuration>
を追加します。(13~15行目)
<plugins>
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>hello-maven-plugin</artifactId>
<executions>
<execution>
<!-- <phase>compile</phase> -->
<goals>
<goal>sayhi</goal>
</goals>
</execution>
</executions>
<configuration>
<greeting>compile</greeting>
</configuration>
</plugin>
</plugins>
pom.xmlで指定した「compile」という文字が「Hello, world. – compile」という形で出力されていることが確認できました。
もう少し続きます
そんなわけで今回はMavenプラグインの初めての実装とその実装したプラグイン ゴールをビルドフェーズと紐づける方法について試してみました。
作成したGreetingMojoはそれ自体はなんてことのないプラグインです。
ですが、次回は今回作ったGreetingMojoを使って色々試してみようと思います。
気になったことを試してみて、Mavenプラグインの理解を深めていければと思います。
ちなみに前回の記事はこちら。
コメント