読者です 読者をやめる 読者になる 読者になる

しおしお

IntelliJのあれやこれや

JSR352-Batch Applicationを試してみた(Batchlet編)

JSR352(Batch Application)を動かして見たので、その記録を残しておくと。

まず、動かしてみたいレベルだったのでサクッと動かすことができそうなBatchletを使っています。
実際にバッチアプリケーションを作成する際は、BatchletにはSQL一発ですむ処理を実装したりするのだと思います。

早速コードなどなどを見ていきます。

ジョブ定義

ジョブ定義は、META-INF/batch-jobs配下にxmlファイルで作成する必要があります。
こんな感じですね。
f:id:sioiri:20150606004658p:plain

ファイルの内容は下のようになっています。
そんな難しい構造ではないのでさくっと作れます。jobのid属性には、xmlのファイル名の拡張子をなくしたものを設定します。
今回は、Batchletを動かすので、ステップ定義(step id="step"の部分)にbatchletを定義します。
ref属性には、cdiで管理されているBatchletの名前を設定します。ref属性には、FQCNでBatchletを指定できますが、CDIの管理対象にならないので@Injectが効かなかったりします。(JobContextやStepContextは特別扱いされているっぽくインジェクションされるようです。)

<job id="batchletSample" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
  <step id="step">
    <batchlet ref="helloWorldBatchlet" />
  </step>
</job>

Batchletの実装

Batchletの処理はprocessメソッドで行うので、とりあえず実行したジョブ名称をログ(標準出力)に出してみます。

Namedアノテーションをはっているので、ジョブxmlにはこのオブジェクトの名前を設定するだけで良くなります。(前述のジョブxmlのbatchlet部のように)

import javax.batch.api.AbstractBatchlet;
import javax.batch.runtime.context.JobContext;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@Dependent
public class HelloWorldBatchlet extends AbstractBatchlet {

    // ジョブ名称を取得するためにJobContextをインジェクション
    @Inject
    JobContext jobContext;

    @Override
    public String process() throws Exception {
        System.out.format("**************************************************%n"
                        + "  job name: %s%n  **************************************************",
                jobContext.getJobName());
        return "SUCCESS";
    }
}

バッチ実行用のAPI

jax-rs使って、指定されたバッチジョブを実行する感じにしています。kotlinで書いていますが、Javaで書いてもあまり変わらないと思います。
戻り値は、ジョブの実行を一意に識別できるExecutionIdとしています。このIDは、ジョブのリスタート時に指定したりするので割りと重要な値となっています。

ジョブの実行は、BatchRuntimeからJobOperatorを取得してstartを呼び出すだけです。
このstartメソッドには、ジョブ名称(ジョブxml拡張子を除いたもの)を指定します。2番めのパラメータにはバッチ引数を指定するのですが今回は不要なのでnullを渡しています。

@Path(value = "/")
open class BatchResource {

  @GET
  @Path(value = "/run/{jobName}")
  open fun start(PathParam("jobName") jobName: String): String {
    val jobOperator = BatchRuntime.getJobOperator()
    val executionId = jobOperator.start(jobName, null)
    return executionId.toString()
  }
}

実行してみよう

端折りますが、バッチ処理と実行用APIglassfishにデプロイして実行します。glassfishには、JSR352のRIのjBatchがのっています。SE環境でも実行することは可能ですが、面倒臭そうだったのでglassfish上で動かす方を試してみました。

実行は、IntelliJさんのRest Clientからやってみます。
f:id:sioiri:20150606010538p:plain

実行してみると、レスポンスとしてExecutionIdが戻ってきます
f:id:sioiri:20150606011031p:plain

Batchletで行っているジョブ出力の結果も確認できます。
f:id:sioiri:20150606011347p:plain

一応glassfishの管理コンソールからも実行結果を確認できます。
f:id:sioiri:20150606011235p:plain

思っていたよりサクッと動いた感があります。

ソースコード全量はこちら→siosio/jbatch-sample · GitHub


おわり。