はじめに
この記事はJavaバッチフレームワークのAsakusa Frameworkで簡単なバッチアプリケーションを作成する方法を共有します。
公式にはAsakusa Framework チュートリアルが存在しますが、本記事では手軽にAsakusaの開発や運用について概要を理解して雰囲気をつかんでもらえることを目的としています。
動作環境
以下の環境で動作確認をしています。
- Windows 10 (64bit)
- JDK 1.8.0_161
- Gradle 4.5
(以下の手順を試す前に、JDKとGradleのインストールを済ませておいてください。)
やりたいこと
紹介するサンプルアプリケーションは、入力ファイル(内容はHello
だけ)を読み込んで、内容をHello, World!
に更新してファイルを出力する簡単なものです。
DFDの形式にすると以下のようなものになります。
開発環境の準備
以下のフォルダを作成して、サンプルアプリケーションのプロジェクト用フォルダとします。
C:¥asakusa-develop¥helloworld
作成したプロジェクト用フォルダの配下にGradleのビルドスクリプトファイル(build.gradle
)を作成します。
今回のサンプルアプリケーションはWindowsのJVM上で実行させるため、Asakusa Vanillaを構成しています。
ここの設定を変えることでHadoopやM3BP用のアプリケーションを生成することも可能です。
作成したGradleスクリプトの詳細については、Asakusa Gradle Plugin リファレンスを参照してください。
group 'com.example'
buildscript {
repositories {
maven { url 'http://asakusafw.s3.amazonaws.com/maven/releases' }
maven { url 'http://asakusafw.s3.amazonaws.com/maven/snapshots' }
}
dependencies {
classpath group: 'com.asakusafw.gradle', name: 'asakusa-distribution', version: '0.10.0'
}
}
apply plugin: 'asakusafw-sdk'
apply plugin: 'asakusafw-organizer'
apply plugin: 'asakusafw-vanilla'
apply plugin: 'eclipse'
asakusafwOrganizer {
vanilla.enabled true
profiles.prod {
hadoop.embed true
}
}
以下のGradleコマンドを実行するとEclipseのプロジェクトとしてインポート可能な構成ファイルが生成されます。(プロジェクトフォルダの下で実行してください)
C:¥asakusa-develop¥helloworld>gradle eclipse
IntelliJ IDEAを利用したい場合は、公式のIntelliJ IDEAの利用を参照してください。
なお、Eclipseを使うのであれば、Shafu(Asakusa開発用のEclipseプラグイン)の利用を検討してください。
データモデルクラスの生成
データモデルを定義するDMDL(Data Model Definition Language)スクリプトファイルを作成します。
以下のスクリプトでは、入力モデルと出力モデルはそれぞれinput
とoutput
という名前で、Direct I/O CSVで入出力を行う設定になっています。
以下のフォルダを作成してその配下にスクリプトファイル(models.dmdl
)を作成します。
C:¥asakusa-develop¥helloworld¥src¥main¥dmdl
@directio.csv
input = {
value : TEXT;
};
@directio.csv
output = {
value : TEXT;
};
以下のGradleコマンドを実行すると、作成したスクリプトファイルを元にAsakusa Frameworkで利用可能なデータモデルクラスが生成されます。(プロジェクトフォルダの下で実行してください)
C:¥asakusa-develop¥helloworld>gradle compileDMDL
演算子クラスの作成
以下のフォルダを作成してその配下にcom.example.operator.HelloWorldOperator
クラスを作成します。
実装する演算子の処理は入力ファイルのvalueに値(, World!
)を追加する処理なので、@Update
演算子を実装します。
演算子に関する詳細については、Asakusa DSL演算子リファレンスを参照してください。
com.example.modelgen.dmdl.model.Input
クラスは先ほどのDMDLから自動生成されたクラスです。
C:¥asakusa-develop¥helloworld¥src¥main¥java
package com.example.operator;
import com.asakusafw.vocabulary.operator.Update;
import com.example.modelgen.dmdl.model.Input;
public abstract class HelloWorldOperator {
@Update
public void appendMessage(Input input) {
input.setValueAsString(input.getValueAsString() + ", World!");
}
}
入出力定義クラスの作成
入力定義クラスと出力定義クラスを作成します。それぞれ、AbstractInputCsvInputDescription
とAbstractOutputCsvOutputDescription
を継承して実装しています。これらのクラスもDMDLから自動生成されています。
ファイル入出力クラスの詳細については、Direct I/O ユーザーガイド - ファイルの入出力を参照するとよいでしょう。
入力定義クラスの作成
package com.example.jobflow;
import com.example.modelgen.dmdl.csv.AbstractInputCsvInputDescription;
public class InputFile extends AbstractInputCsvInputDescription {
@Override
public String getBasePath() {
return "input";
}
@Override
public String getResourcePattern() {
return "hello.csv";
}
}
出力定義クラスの作成
package com.example.jobflow;
import com.example.modelgen.dmdl.csv.AbstractOutputCsvOutputDescription;
public class OutputFile extends AbstractOutputCsvOutputDescription {
@Override
public String getBasePath() {
return "output";
}
@Override
public String getResourcePattern() {
return "helloworld.csv";
}
}
ジョブフロークラスの作成
以下のジョブフロークラスでは、コンストラクタでデータフローのImport
に入力定義クラス(InputFile
)を設定し、Export
に出力定義クラス(OutputFile
)を設定しています。
describeメソッドにデータフローを記述します。サンプルでは、入力モデル(input
)から更新演算子(appendMessage
)へ結線してその結果を出力モデル(output
)へ出力しています。
詳細については、Asakusa DSLユーザーガイド - Flow DSL を参照してください。
package com.example.jobflow;
import com.asakusafw.vocabulary.flow.Export;
import com.asakusafw.vocabulary.flow.FlowDescription;
import com.asakusafw.vocabulary.flow.Import;
import com.asakusafw.vocabulary.flow.In;
import com.asakusafw.vocabulary.flow.JobFlow;
import com.asakusafw.vocabulary.flow.Out;
import com.asakusafw.vocabulary.flow.util.CoreOperatorFactory;
import com.example.modelgen.dmdl.model.Input;
import com.example.modelgen.dmdl.model.Output;
import com.example.operator.HelloWorldOperatorFactory;
import com.example.operator.HelloWorldOperatorFactory.AppendMessage;
@JobFlow(name = "helloWorldJob")
public class HelloWorldJob extends FlowDescription {
final In<Input> input;
final Out<Output> output;
public HelloWorldJob(
@Import(name = "input", description = InputFile.class)
In<Input> input,
@Export(name = "output", description = OutputFile.class)
Out<Output> output) {
this.input = input;
this.output = output;
}
@Override
protected void describe() {
CoreOperatorFactory core = new CoreOperatorFactory();
HelloWorldOperatorFactory operator = new HelloWorldOperatorFactory();
AppendMessage appendedMessage = operator.appendMessage(input);
output.add(core.restructure(appendedMessage.out, Output.class));
}
}
バッチクラスの作成
以下のバッチクラスは、ジョブフロークラス(HelloWorldJob
)を実行するだけです。
バッチクラスについては、Asakusa DSLユーザーガイド - Batch DSLを参照してください。
package com.example.batch;
import com.asakusafw.vocabulary.batch.Batch;
import com.asakusafw.vocabulary.batch.BatchDescription;
import com.example.jobflow.HelloWorldJob;
@Batch(name = "example.helloWorld")
public class HelloWorldBatch extends BatchDescription {
@Override
protected void describe() {
run(HelloWorldJob.class).soon();
}
}
ここまでで、ソースフォルダの配下は次のような構成になっていると思います。
アプリケーションのビルド
次のGradleコマンドでサンプルアプリケーションのデプロイメントアーカイブファイルを生成します。(プロジェクトフォルダの下で実行してください)
C:¥asakusa-develop¥helloworld>gradle assemble
実行に成功するとbuild
フォルダの配下にデプロイメントアーカイブファイルが作成されています。
C:¥asakusa-develop¥helloworld¥build¥asakusafw-helloworld.tar.gz
アプリケーションのデプロイ
今回はWindows上にデプロイするので(商用などの場合はHadoopやM3BP環境へデプロイするのですが。。)Windows環境変数にASAKUSA_HOME
を追加します。
変数 | 値 |
---|---|
ASAKUSA_HOME | C:¥asakusa-develop¥asakusa |
生成したデプロイメントアーカイブファイル(asakusafw-helloworld.tar.gz
)をASAKUSA_HOMEの配下に展開します。
ASAKUSA_HOMEの下で以下のコマンドを実行します。
C:¥asakusa-develop¥asakusa>java -jar tools¥bin¥setup.jar
setup: C:¥asakusa-develop¥asakusa
framework version: 0.10.0
installation path is not a POSIX file system: C:¥asakusa-develop¥asakusa
アプリケーションの実行
入力ファイルの配備
バッチの入力ファイルを以下のフォルダへ配備します。デフォルトではユーザーホームディレクトリ以下のtarget¥testing¥directio
フォルダの配下に配備します。
入力定義クラスで設定したbasePath
(getBasePath
メソッドの返り値)とresourcePattern
(getResourcePattern
メソッドの返り値)に一致するようにします。
C:¥...<ユーザーホームディレクトリ>...¥target¥testing¥directio¥input¥
Hello
Asakusa CLIで実行する
このサンプルでは、Asakusa CLIを利用するため(商用では、YAESSで実行することになります)、WindowsのPATH環境変数に以下の値を追加します。
%ASAKUSA_HOME%¥bin
以下のコマンドでバッチアプリケーションを実行します。
asakusa run vanilla.example.helloWorld
実行結果として以下のファイルが出力されていることを確認します。
C:¥...<ユーザーホームディレクトリ>...¥target¥testing¥directio¥output¥
"Hello, World!"
最後に
Asakusa Frameworkのversionも0.10.0になって開発や運用の敷居が下がってきているので、このタイミングでまとめてみようと思い立ちこの記事を書いてみましたが如何だったでしょうか?まだ書き足りないことも多いのですが、また次回の記事で紹介していければと思います。