Archive for 2月, 2014

jBatch(JSR-352) on Java SE 環境

先日のデブサミの発表後、jBatch (JSR-352) についてご質問を頂き、また別件でも同じ質問を頂きましたので、その内容を共有致します。

jBatch を cron 等で実行したいのだが、jBatch は Java EE 環境でしか実行できないのか?とのご質問を頂きました。
答えは、jBatch の仕様上、Java SE 環境上でも動作するように実装されております。

ただし、Java EE 環境上で実装する方がとても簡単に実装・運用ができますので個人的にはJava EE 環境上での動作をお薦めします。仮に Java SE 環境上で jBatch (jBatch の RI)を実行したい場合は下記をご参照ください。

1. 準備

Java SE 環境上で jBatch を稼働させるためには、JavaDB(Derby) が必要です。
また、jBatch の RI を使って Java SE 環境上で動作させるためには、
jBatch RI の実行に必要なライブラリ一式を下記より入手します。

https://java.net/projects/jbatch/downloads/download/jsr352-SE-RI-1.0.zip

zip を展開すると下記のファイルが含まれています。下記全ファイルを lib 配下にコピーしてください。

  • derby.jar
  • javax.inject.jar
  • jsr352-SE-RI-javadoc.jar
  • javax.batch.api.jar
  • jsr352-RI-spi.jar
  • jsr352-SE-RI-runtime.jar

2. Batch コンテナを実行するための設定

次に Batch コンテナを稼働させるためのプロパティの設定を行います。
META-INF ディレクトリ配下に services ディレクトリを作成して
それぞれ下記のファイルを作成してください。

src/META-INF/services/batch-config.properties

JDBC_DRIVER=org.apache.derby.jdbc.EmbeddedDriver
# JDBC_URL=jdbc:derby://localhost:1527/batchdb;create=true
JDBC_URL=jdbc:derby://localhost:1527/batchdb

src/META-INF/services/batch-services.properties

J2SE_MODE=true

以上で基本的には Java SE 環境上で動作させるために必要な設定は完了です。

3. 動作確認

それでは、バッチであるファイルの内容を別のファイルに書き出すサンプルを作成します。(※ 以降は Java EE 環境での実装と同じです。)
下記に、本 jBatch プロジェクトのディレクトリ構成を下記に示します。

まず、メイン・メソッドから Batch の JOB: “my-batch-job” を起動します。

package com.yoshio3.main;

import java.util.Properties;
import javax.batch.operations.JobOperator;
import javax.batch.runtime.BatchRuntime;

/**
 *
 * @author Yoshio Terada
 */
public class StandAloneBatchMain {

    public static void main(String... args) {
        JobOperator job = BatchRuntime.getJobOperator();
        long id = job.start("my-batch-job", new Properties());
    }    
}

この、”my-batch-job” の処理内容は、META-INF/batch-jobs ディレクトリ配下に、”my-batch-job.xml” として定義します。

“my-batch-job” の内容を下記に示します。プロパティを2つ input_file,output_file 定義し、それぞれ /tmp/input.txt, /tmp/output.txt を示します。また、JOB の step としてチャンク形式の step を1つ定義し、データの読み込み用(reader)、処理用(processor)、書き込み(writer)用の処理を、それぞれ、MyItemReader, MyItemProcessor, MyItemWriter に実装します。

<job id="my-batch-job"
     xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
    <properties>
        <property name="input_file" value="/tmp/input.txt"/>
        <property name="output_file" value="/tmp/output.txt"/>
    </properties>

    <step id="first-step">
        <chunk item-count="5">
            <reader    ref="com.yoshio3.chunks.MyItemReader"/>
            <processor ref="com.yoshio3.chunks.MyItemProcessor"/>
            <writer    ref="com.yoshio3.chunks.MyItemWriter"/>
        </chunk>
    </step>
</job>

読み込み用の処理は、ItemReader を実装したクラスを作成します。ここでは、input_file で指定されたプロパティのファイル(/tmp/input.txt)ファイルを読み込み、1行読み込んでその値を返します。

package com.yoshio3.chunks;

import java.io.BufferedReader;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.batch.api.chunk.ItemReader;
import javax.batch.runtime.context.JobContext;
import javax.inject.Inject;

public class MyItemReader implements ItemReader {

    @Inject
    JobContext jobCtx;

    BufferedReader bufReader;

    @Override
    public void open(Serializable checkpoint) throws Exception {        
        String fileName = jobCtx.getProperties()
                .getProperty("input_file");
        bufReader = Files.newBufferedReader(Paths.get(fileName),Charset.forName("UTF-8"));
    }

    @Override
    public void close() throws Exception {
        bufReader.close();
    }

    @Override
    public Object readItem() throws Exception {
        String data = bufReader.readLine();
        System.out.println("Reader readItem : " + data);
        return data;
    }

    @Override
    public Serializable checkpointInfo() throws Exception {
        return null;
    }
}

次に、読み込んだデータの加工処理部分は、ItemProsessor を実装したクラスに記述します。ここでは、読み込んだデータ(文字列)に対して、文字列を付加して返しています。

package com.yoshio3.chunks;

import javax.batch.api.chunk.ItemProcessor;

/**
 *
 * @author Yoshio Terada
 */
public class MyItemProcessor implements ItemProcessor {

    @Override
    public Object processItem(Object item) throws Exception {
        String line = (String)item ;
        StringBuilder sBuilder = new StringBuilder();
        sBuilder.append("Processor processItem : ");
        sBuilder.append(line);
        String returnValue = sBuilder.toString();
        System.out.println(returnValue);
        return returnValue;
    }    
}

最後に書き出し部分を ItemWriter を実装したクラスに記述します。ここでは、oputput_file のプロパティを取得して書き出すファイル名を取得しています。次にファイルに対して取得したデータを書き出しています。

package com.yoshio3.chunks;

import java.io.BufferedWriter;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import javax.batch.api.chunk.ItemWriter;
import javax.batch.runtime.context.JobContext;
import javax.inject.Inject;

/**
 *
 * @author Yoshio Terada
 */
public class MyItemWriter implements ItemWriter {

    @Inject
    JobContext jobCtx;

    String fileName;

    BufferedWriter bufWriter;

    @Override
    public void open(Serializable checkpoint) throws Exception {
        fileName = jobCtx.getProperties()
                .getProperty("output_file");
        bufWriter = Files.newBufferedWriter(Paths.get(fileName), Charset.forName("UTF-8"));
    }

    @Override
    public void close() throws Exception {
        bufWriter.close();
    }

    @Override
    public void writeItems(List<Object> items) throws Exception {
        for (Object obj : items) {
            String data = (String) obj;
            System.out.println("Writer writeItems : " + data);

            bufWriter.write(data);
            bufWriter.newLine();
        }
    }

    @Override
    public Serializable checkpointInfo() throws Exception {
        return null;
    }
}

上記を実装した後、コンパイルをしてください。


# java -classpath
  lib/jsr352-ri-1.0/javax.inject.jar:
  lib/jsr352-ri-1.0/derby.jar:
  lib/jsr352-ri-1.0/jsr352-RI-spi.jar:
  lib/jsr352-ri-1.0/javax.batch.api.jar:
  lib/jsr352-ri-1.0/jsr352-SE-RI-javadoc.jar:
  lib/jsr352-ri-1.0/jsr352-SE-RI-runtime.jar:
  build/classes com.yoshio3.main.StandAloneBatchMain

実行すると下記のようなログを確認できます。chunk 形式ではデフォルトで 10 件まとめて読み込み&処理を実施し、
まとめて 10 件書き込むという動作を下記からも確認できるかと思います。

2 18, 2014 12:10:50 午後 com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl createSchema
情報: JBATCH schema does not exists. Trying to create it.
2 18, 2014 12:10:50 午後 com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl createIfNotExists
情報: CHECKPOINTDATA table does not exists. Trying to create it.
2 18, 2014 12:10:50 午後 com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl createIfNotExists
情報: JOBINSTANCEDATA table does not exists. Trying to create it.
2 18, 2014 12:10:50 午後 com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl createIfNotExists
情報: EXECUTIONINSTANCEDATA table does not exists. Trying to create it.
2 18, 2014 12:10:50 午後 com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl createIfNotExists
情報: STEPEXECUTIONINSTANCEDATA table does not exists. Trying to create it.
2 18, 2014 12:10:50 午後 com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl createIfNotExists
情報: JOBSTATUS table does not exists. Trying to create it.
2 18, 2014 12:10:50 午後 com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl createIfNotExists
情報: STEPSTATUS table does not exists. Trying to create it.
Reader readItem : hogehoge1
Processor processItem : hogehoge1
Reader readItem : hogehoge2
Processor processItem : hogehoge2
Reader readItem : hogehoge3
Processor processItem : hogehoge3
Reader readItem : hogehoge4
Processor processItem : hogehoge4
Reader readItem : hogehoge5
Processor processItem : hogehoge5
Reader readItem : hogehoge6
Processor processItem : hogehoge6
Reader readItem : hogehoge7
Processor processItem : hogehoge7
Reader readItem : hogehoge8
Processor processItem : hogehoge8
Reader readItem : hogehoge9
Processor processItem : hogehoge9
Reader readItem : hogehoge10
Processor processItem : hogehoge10
Writer writeItems : Processor processItem : hogehoge1
Writer writeItems : Processor processItem : hogehoge2
Writer writeItems : Processor processItem : hogehoge3
Writer writeItems : Processor processItem : hogehoge4
Writer writeItems : Processor processItem : hogehoge5
Writer writeItems : Processor processItem : hogehoge6
Writer writeItems : Processor processItem : hogehoge7
Writer writeItems : Processor processItem : hogehoge8
Writer writeItems : Processor processItem : hogehoge9
Writer writeItems : Processor processItem : hogehoge10
Reader readItem : hogehoge11
Processor processItem : hogehoge11
Reader readItem : hogehoge12
Processor processItem : hogehoge12
Reader readItem : hogehoge13
Processor processItem : hogehoge13
Reader readItem : hogehoge14
Processor processItem : hogehoge14
Reader readItem : hogehoge15
Processor processItem : hogehoge15
Reader readItem : hogehoge16
Processor processItem : hogehoge16
Reader readItem : hogehoge17
Processor processItem : hogehoge17
Reader readItem : hogehoge18
Processor processItem : hogehoge18
Reader readItem : hogehoge19
Processor processItem : hogehoge19
Reader readItem : hogehoge20
Processor processItem : hogehoge20
Writer writeItems : Processor processItem : hogehoge11
Writer writeItems : Processor processItem : hogehoge12
Writer writeItems : Processor processItem : hogehoge13
Writer writeItems : Processor processItem : hogehoge14
Writer writeItems : Processor processItem : hogehoge15
Writer writeItems : Processor processItem : hogehoge16
Writer writeItems : Processor processItem : hogehoge17
Writer writeItems : Processor processItem : hogehoge18
Writer writeItems : Processor processItem : hogehoge19
Writer writeItems : Processor processItem : hogehoge20
Reader readItem : null

書き込む間隔を変更したい場合は、Job XML の設定を変更し<chunk item-count=”5″>を設定します。

<job id="my-batch-job"
     xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
    <properties>
        <property name="input_file" value="/tmp/input.txt"/>
        <property name="output_file" value="/tmp/output.txt"/>
    </properties>

    <step id="first-step">
        <chunk item-count="5">
            <reader    ref="com.yoshio3.chunks.MyItemReader"/>
            <processor ref="com.yoshio3.chunks.MyItemProcessor"/>
            <writer    ref="com.yoshio3.chunks.MyItemWriter"/>
        </chunk>
    </step>
</job>

<chunk item-count=”5″>を設定した後、実行すると下記のような結果が得られます。

run:
Reader readItem : hogehoge1
Processor processItem : hogehoge1
Reader readItem : hogehoge2
Processor processItem : hogehoge2
Reader readItem : hogehoge3
Processor processItem : hogehoge3
Reader readItem : hogehoge4
Processor processItem : hogehoge4
Reader readItem : hogehoge5
Processor processItem : hogehoge5
Writer writeItems : Processor processItem : hogehoge1
Writer writeItems : Processor processItem : hogehoge2
Writer writeItems : Processor processItem : hogehoge3
Writer writeItems : Processor processItem : hogehoge4
Writer writeItems : Processor processItem : hogehoge5
Reader readItem : hogehoge6
Processor processItem : hogehoge6
Reader readItem : hogehoge7
Processor processItem : hogehoge7
Reader readItem : hogehoge8
Processor processItem : hogehoge8
Reader readItem : hogehoge9
Processor processItem : hogehoge9
Reader readItem : hogehoge10
Processor processItem : hogehoge10
Writer writeItems : Processor processItem : hogehoge6
Writer writeItems : Processor processItem : hogehoge7
Writer writeItems : Processor processItem : hogehoge8
Writer writeItems : Processor processItem : hogehoge9
Writer writeItems : Processor processItem : hogehoge10
Reader readItem : hogehoge11
Processor processItem : hogehoge11
Reader readItem : hogehoge12
Processor processItem : hogehoge12
Reader readItem : hogehoge13
Processor processItem : hogehoge13
Reader readItem : hogehoge14
Processor processItem : hogehoge14
Reader readItem : hogehoge15
Processor processItem : hogehoge15
Writer writeItems : Processor processItem : hogehoge11
Writer writeItems : Processor processItem : hogehoge12
Writer writeItems : Processor processItem : hogehoge13
Writer writeItems : Processor processItem : hogehoge14
Writer writeItems : Processor processItem : hogehoge15
Reader readItem : hogehoge16
Processor processItem : hogehoge16
Reader readItem : hogehoge17
Processor processItem : hogehoge17
Reader readItem : hogehoge18
Processor processItem : hogehoge18
Reader readItem : hogehoge19
Processor processItem : hogehoge19
Reader readItem : hogehoge20
Processor processItem : hogehoge20
Writer writeItems : Processor processItem : hogehoge16
Writer writeItems : Processor processItem : hogehoge17
Writer writeItems : Processor processItem : hogehoge18
Writer writeItems : Processor processItem : hogehoge19
Writer writeItems : Processor processItem : hogehoge20
Reader readItem : null

以上のように、Java SE の環境でも jBatch (JSR-352) を実行する事ができます。今回は参考のため jBatch の RI を使用しましたが、各 Java EE 7 準拠のアプリケーション・サーバで必要なライブラリはそれぞれ異なるかと想定します。必要なライブラリは各アプリケーション・サーバでお調べください。

2014年2月18日 at 12:51 PM 2件のコメント

Java EE 7 の新機能紹介と Java のイベントのご紹介

2014年2月13日(木)・14日(金)に目黒雅叙園でDevelopers Summit 2014 が開催されました。

今日は関東はあいにくの天気(大雪)で、とても足元が悪い中多くの方にイベントやセッションに参加して頂きまして誠にありがとうございました。また、Developers Summit 2014の事務局の皆様に置かれましても、同様に(Javaの)大規模イベントの企画を行っている者として、数多くの難作業があった事が用意に想像ができるため、イベントの主催者の皆様全員にあつく御礼を申し上げます。

私自身は、本日 14日(金)に【14-D-6】45 new features of Java EE 7 in 45 minutes というセッションを持たせて頂き発表を行いました。私のセッションにも非常に多くの開発者の皆様にご参加いただき良いフィードバックや、難しすぎたといったフィードバックなども頂きそうしたご意見を次回につなげていきたいと思います。本日発表に使用した資料を下記に公開します。実際にプレゼン時にはアニメーション等も使用しているため、下記の静的なコンテンツと内容は若干変わりますがご参考頂ければ誠に幸いです。

今回の個人的な所管として、45 分で 45 個 (総ページ数 P 90) の Java EE 7 の新機能をご紹介する事は初めてのチャレンジだったため、時間内に終わるか発表前から心配しておりましたが、結果、なんとかそして大幅な時間超過なく終える事ができました (最後はかなり足早になってしまい申し訳ありません)。本日、ご紹介した内容を本来であれば1件づつブログなどの記事にまとめられれば良いのですが、私自身次のステップに足を向けなればならないため、直近でブログに書く事は困難かもしれません。(もちろん時間ができれば書きますが。)どうぞご理解頂ければ幸いです。

さて、その次のステップでございますが、今日のセッションの最後に申し上げましたが、5 月に今年最大の Java のお祭りイベントを企画しております。そしてこれからその準備に多くの時間を割くようになります。現時点で詳細を申し上げる事はできませんが、5月18日〜5月24日まで、Java の開発者の皆様は極力日程を空けておいていただけないでしょうか。正式な情報が決まり次第、JJUG / 日本オラクルから正式アナウンスがあるかと想定します。

2/17 追記:JJUG のイベントとオラクルのイベントは、別イベントとして、別日程で開催されます。また、JJUG のイベント JJUG CCC につきましては、Call for Papers の募集も既に開始しておりますので日程等の詳細は JJUG のサイトをご覧ください。

日本オラクルからの正式なアナウンスまでは是非お待ちいただきたいのですが、今から 5 月の出張申請、もしくは上長への申請を上げておいていただければ誠に幸いです。

今年のイベントは、Java SE 8 の正式リリース後という事もあり、昨年以上の盛り上がりをご期待頂けるかと思いますので、どうぞお楽しみにしてください。

「5月末 Java のお祭りをするどぉーーーー!!!」

2014年2月14日 at 11:36 PM


Java Champion & Evangelist

ご注意

このエントリは個人の見解であり、所属する会社の公式見解ではありません

カレンダー

2014年2月
« 1月   3月 »
 12
3456789
10111213141516
17181920212223
2425262728  

カテゴリー

Twitter

clustermap

ブログ統計情報

  • 979,791 hits

Feeds