Mojo and EoT
Mojoは、Maven2のPlugin Frameworkであり、Maven1のJelly(と比較して、開発効率、特に、EoT(Ease of Testing: テスト容易性)が良い。
Maven2
説明省略
Jelly
- Jellyは、Maven1のPlugin 用スクリプトであり、XML形式である。
Maven Project自身も、この選択は失敗だったと感じているようでMaven2ではあっさり捨てられた... - 悪い所
- インタプリタである。
- XML形式であり、記述性が悪い。(# スクリプト自体をXMLにするなんて...)
- 継承が利用できない。
- Unit Testが困難。
Mojo
- Mojoは、Maven2のPlugin Frameworkであり、POJO(Plain Old Jav Object)である。
- Mojoは、アフリカ系米国人社会のスラング( 調べてみよう!)
- 良い所
- POJOだ。
- 使い慣れたJavaだ。
- 既存のMojoからの継承ができる。
- 既存のJava Libraryをバンバン活用できる
- POJOであり、Unit Testが楽。
Mojoの作り方
初めは、archetype:create
$ mvn archetype:create -DgroupId=example -DartifactId=plugin01 -DarchetypeArtifactId=maven-archetype-mojo
...
いきなり、install
$ mvn install
...
そのまま、goal
$ mvn example:plugin01:1.0-SNAPSHOT:touch <- ここに注目
[INFO] Scanning for projects...
[INFO]----------------------------------------------------------------------------
[INFO] Building Maven Mojo Archetype
[INFO] task-segment: [example:plugin01:1.0-SNAPSHOT:touch]
[INFO]----------------------------------------------------------------------------
[INFO] [01:touch] <- ここに注目
[INFO]----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO]----------------------------------------------------------------------------
[INFO] Total time: < 1 second
[INFO] Finished at: Thu Mar 02 11:39:14 JST 2006
[INFO] Final Memory: 1M/3M
[INFO]----------------------------------------------------------------------------
$
何がおこったか
これは、archetype:createで作成されたSample Plugin(MyMojo.java)をcompile、Install(Local Repogitoryに)して、実行したためである。
src/main/java/example/MyMojo.java
package example;
...
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* Goal which touches a timestamp file.
*
* @goal touch <- ここに注目
*
* @phase process-sources
*/
public class MyMojo
extends AbstractMojo <- ここに注目
{
/**
* Location of the file.
* @parameter expression="${project.build.directory}"
* @required
*/
private File outputDirectory;
public void execute() <- ここに注目
throws MojoExecutionException
{
File f = outputDirectory;
if ( !f.exists() )
{
f.mkdirs();
}
File touch = new File( f, "touch.txt" );
FileWriter w = null;
try
{
w = new FileWriter( touch );
w.write( "touch.txt" );
}
catch ( IOException e )
{
throw new MojoExecutionException( "Error creating file " + touch, e );
}
finally
{
if ( w != null )
{
try
{
w.close();
}
catch ( IOException e )
{
// ignore
}
}
}
}
}
このように、Maven2のMojoは、Maven1のJellyと比較して、開発、Install、実行が容易なことが理解できたと思う。
Mojoの開発時にこのような作業を繰り返せば、誰でも、Mojoを開発することができる。
などと、思っていたら、ちゃんちゃら、間違い!
MojoのEoTは、もっとスマートなのである!!
Log出力をさせる
実行経過をLog出力させたいのは、だれでも思うことである。
Mojoでは、以下の方法で、Log出力させる。
src/main/java/example/MyMojo.java(抜粋)
public void execute()
throws MojoExecutionException
{
getLog().info("outputDirectory: " + outputDirectory); <- ここに注目
...}
実行結果は、
$ mvn example:plugin01:1.0-SNAPSHOT:touch
...
[INFO] [01:touch]
[INFO] outputDirectory: foobar <- ここに注目
[INFO] BUILD SUCCESSFUL
...
$
通常は、Info Levelまでしか出力しない。
Debug Levelまで出力させる場合は、実行時に-X(--debug) optionを付ける。
しかし、実際は、他のModuleのDebug 情報まで出力されて、かえって見にくいのでお奨めしない。
Unit Testの方法
Mojo(Maven Java Object)は、POJO(Plain Old Java Object)だから、Unit Testが簡単にできる。
Setter methodを書く
MyMojo.javaには、private変数のoutputDirectoryにアクセスするsetter methodが無いので書く。
Mavenの実行時には、Maven自体が今はやりのDI(Dependency Injection: 依存性注入)のしくみを使って、private 変数にアクセスするが、Test時にはその機能は使えない。
# Testのためだけに、publicなsetter methodを書くのは、設計の原則に反すると思うのは、私だけ?
src/main/java/example/MyMojo.java(抜粋)
public class MyMojo
extends AbstractMojo
{
...
private File outputDirectory;
// ここから
public void setOutputDirectory(File outputDirectory)
{
this.outputDirectory = outputDirectory;
}
// ここまで
...
}
Unit Testを書く
Unit Test用のDirectoryは作られないので、自分で掘る。
$ mkdir -p src/test/java/example
...
src/test/java/example/MyMojoTest/java
package example;
import java.io.File;
import junit.framework.TestCase;
import org.apache.maven.plugin.MojoExecutionException;
public class MyMojoTest
extends TestCase
{
public void testMyMojo()
{
try
{
File outputDirectory = new File("/tmp");
MyMojo mojo = new MyMojo();
mojo.setOutputDirectory(outputDirectory);
mojo.execute();
File f = new File(outputDirectory, "touch.txt");
assertTrue(f.isFile());
}
catch(MojoExecutionException e)
{
e.printStackTrace();
}
}
}
まったく普通のPOJOのUnit Testのように書ける!!
Unit Testする
$ mvn test <- ここに注目
[INFO] Scanning for projects...
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
[info] outputDirectory: /tmp <- ここに注目
[surefire] Running example.MyMojoTest
[surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.02 sec
Results :
[surefire] Tests run: 1, Failures: 0, Errors: 0
[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ----------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Thu Mar 02 17:02:54 JST 2006
[INFO] Final Memory: 4M/8M
[INFO] ----------------------------------------------------------------------------
$
このようにMojoは、簡単にテストできる。
しかも、getLog().info()の結果まで、ちゃんと表示される
Mojo最高!!