連載
» 2008年07月16日 00時00分 公開

Javaバッチフレームワークで多重実行、非同期実行Javaバッチ処理は本当に業務で“使える”の?(4)(3/3 ページ)

[倉元貴一,株式会社NTTデータ]
前のページへ 1|2|3       

TERAバッチでジョブの非同期実行をしてみよう!

 TERAバッチでジョブの非同期実行をする場合、同期実行をする際に加えて必要になるものは、「ジョブ管理テーブル」です。今回は、先ほど作成した多重起動のジョブを非同期実行してみましょう。先ほどまで利用していたHSQLDBにすでにジョブ管理テーブルを作成しているので、DBManagerにて確認してください。ジョブ管理テーブルの仕様は以下のとおりとなっています。

表3 ジョブ管理テーブルの仕様
項番 属性名 カラム名 必須 概要
1 ジョブ依頼番号 REQUEST_NO ジョブ依頼連番(ジョブ管理テーブルの主キー)
2 ジョブID JOB_ID 実行対象のジョブID(bean名)。『STOP』を登録すると起動中のジョブ完了後、非同期バッチデーモンが終了される
3 ジョブBean定義ファイル名 JOB_FILE 実行対象のジョブBeanが登録されているジョブBean定義ファイルのクラスパスからの相対パス。デーモン終了用のジョブID登録時は任意で設定すること
4 パラメータ PARAMETER   ジョブコンテキストに格納する起動引数の値
5 起動状況 STATE 0:起動前、1:起動中、2:再起動中、3:正常終了、4:異常終了、7:中断/強制終了
バッチ登録時は0を初期値として登録する必要がある
6 ジョブ終了コード END_CODE   ジョブ処理終了後返却される終了コード
7 更新時刻 UPDATE_TIME   更新時刻
8 登録時刻 REGISTER_TIME   登録時刻

 必須となっているカラム以外については、自由に設定可能です。

非同期バッチデーモン起動前の準備

 同期実行と非同期実行ではジョブの作成方法はほぼ変わりませんが、一点だけ気を付けなければならないことがあります。それは、「SqlMapConfigファイルは非同期バッチデーモン用に1つしかないため、SqlMapファイルを1カ所にすべて記述しなくてはいけない」という点です。

 非同期バッチデーモン用のSqlMapConfigファイルは「batchapps\common\sqlMapConfig.xml」です。先ほどまでで作成した分割ジョブで利用している「sample\UC0003\UC0003_sqlMap.xml」を上記のファイルに、以下のように追記する必要があります。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
  PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
  "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
  <sqlMapConfig>
    <settings useStatementNamespaces="true" />
    <sqlMap resource="common/jobControl-sqlMap.xml"/>
    <sqlMap resource="common/jobRestart-sqlMap.xml"/>
    <sqlMap resource="common/jobResult-sqlMap.xml"/>
    <!-- ジョブ個別のsqlMapファイルを設定する -->
    <sqlMap resource="sample/UC0003/UC0003_sqlMap.xml"/>
  </sqlMapConfig>

 これで非同期実行の準備は完了です。

非同期バッチデーモンの起動

 非同期バッチデーモンは、TERAバッチにて提供されているため、開発者が作成する必要がありません。同期実行のときと同じ要領で、Eclipseの[実行]ダイアログを開き、[メイン]タブの[プロジェクト]に「terasoluna-batch-sample-foratmarkit04」を指定、[メイン・クラス]にTERAバッチが提供する「jp.terasoluna.fw.batch.springsupport.init.AsyncBatchDaemon」を指定します。

 実行し、以下のようなログがコンソールに出力されることを確認します。

コンソール出力のイメージ
2008/06/23 17:27:35] [AsyncBatchDaemon ] [INFO ] START batch daemon
[2008/06/23 17:27:36] [JobRequestInfo ] [DEBUG] Parameter values: [jobId=BATCH_DAEMON] [jobDiscriptPath=common/AsyncBatchDaemonBean.xml] [parameters=[]] [jobRequestNo=]
[2008/06/23 17:27:36] [JobExecutor ] [INFO ] Job processing START : [jobId=BATCH_DAEMON] [jobRequestNo=] [StartType=SYNC]
[2008/06/23 17:27:37] [DefaultValidatorFactory] [INFO ] Loading validation configurations from [class path resource [common/validator-rules.xml],class path resource [common/validator-rules-ex.xml],class path resource [common/validationCommon.xml]]
[2008/06/23 17:27:37] [DefaultValidatorFactory] [INFO ] Loading validation configurations from [class path resource [common/validator-rules.xml],class path resource [common/validator-rules-ex.xml],class path resource [common/validationCommon.xml]]
[2008/06/23 17:27:37] [EndFileChecker ] [DEBUG] BATCH_DAEMON jobstatus was added to the map.
[2008/06/23 17:27:37] [JobManager ] [INFO ] Job processing START: [jobId=BATCH_DAEMON] [jobRequestNo=] [partitionNo=-1] [partitionKey=NO_Partition] [JobManagerName=AsyncBatchDaemonManager] [JobState=STARTED]

ジョブ管理テーブルへのジョブ依頼情報の登録とジョブの実行

 では、ジョブ管理テーブルにジョブ依頼情報を登録してみましょう。DBManagerから以下のINSERT文を発行します。

INSERT INTO JOB_CONTROL (REQUEST_NO, JOB_ID, JOB_FILE, STATE) VALUES ('001', 'JB0001', 'sample/UC0003/JB0001.xml', 0)

 実行画面は以下のようになります。

図6 ジョブ管理テーブルにジョブ依頼情報を登録 図6 ジョブ管理テーブルにジョブ依頼情報を登録

 上記のSQL文を発行すると、非同期バッチデーモンがジョブ管理テーブルを監視しているため、登録されたジョブ情報を取得し、自動的にジョブを実行します。コンソールに以下のようなログが出力されることを確認してください。

コンソール出力のイメージ
[2008/06/23 19:34:36] [AsyncJobPreLogic ] [DEBUG] Job starting by batch daemon : [jobRequestID : JB0001]
[2008/06/23 19:34:36] [JobExecutor ] [INFO ] Job processing START : [jobId=JB0001] [jobRequestNo=001] [StartType=ASYNC]
[2008/06/23 19:34:36] [JobExecutor ] [DEBUG] Get the newly created JobBeanFactory
[2008/06/23 19:34:37] [EndFileChecker ] [DEBUG] JB0001_001 jobstatus was added to the map.
[2008/06/23 19:34:37] [JobManager ] [INFO ] Job processing START: [jobId=JB0001] [jobRequestNo=001] [partitionNo=-1] [partitionKey=NO_Partition] [JobManagerName=partitionChunkTransactionJobManager] [JobState=STARTED]
[2008/06/23 19:34:37] [StandardCollectorResultHandler] [INFO ] Collector processing result code is NORMAL_END : [jobId=JB0001] [jobRequestNo=001] [partitionNo=-1] [CollectorResult Info:ReturnCode: NORMAL_END ]
[2008/06/23 19:34:37] [JobManager ] [INFO ] Job processing START: [jobId=JB0001] [jobRequestNo=001] [partitionNo=0] [partitionKey=東京] [JobManagerName=childJobManager] [JobState=STARTED]
[2008/06/23 19:34:37] [JobManager ] [INFO ] Job processing START: [jobId=JB0001] [jobRequestNo=001] [partitionNo=1] [partitionKey=大阪] [JobManagerName=childJobManager] [JobState=STARTED]
[2008/06/23 19:34:37] [JobManager ] [INFO ] Job processing START: [jobId=JB0001] [jobRequestNo=001] [partitionNo=2] [partitionKey=福岡] [JobManagerName=childJobManager] [JobState=STARTED]
[2008/06/23 19:34:37] [StandardCollectorResultHandler] [INFO ] Collector processing result code is NORMAL_END : [jobId=JB0001] [jobRequestNo=001] [partitionNo=0] [CollectorResult Info:ReturnCode: NORMAL_END ]
[2008/06/23 19:34:37] [StandardCollectorResultHandler] [INFO ] Collector processing result code is NORMAL_END : [jobId=JB0001] [jobRequestNo=001] [partitionNo=1] [CollectorResult Info:ReturnCode: NORMAL_END ]
[2008/06/23 19:34:37] [StandardCollectorResultHandler] [INFO ] Collector processing result code is NORMAL_END : [jobId=JB0001] [jobRequestNo=001] [partitionNo=2] [CollectorResult Info:ReturnCode: NORMAL_END ]
[2008/06/23 19:34:37] [JB0001JobPostLogic ] [INFO ] 福岡支店で処理をした更新件数は8です。
[2008/06/23 19:34:37] [JB0001JobPostLogic ] [INFO ] 福岡支店で処理をした新規追加件数は8です。
[2008/06/23 19:34:37] [JB0001JobPostLogic ] [INFO ] 大阪支店で処理をした更新件数は11です。
[2008/06/23 19:34:37] [JB0001JobPostLogic ] [INFO ] 大阪支店で処理をした新規追加件数は6です。
[2008/06/23 19:34:37] [JB0001JobPostLogic ] [INFO ] 東京支店で処理をした更新件数は11です。
[2008/06/23 19:34:37] [JB0001JobPostLogic ] [INFO ] 東京支店で処理をした新規追加件数は6です。
[2008/06/23 19:34:37] [JobManager ] [INFO ] Job processing END: [jobId=JB0001] [jobRequestNo=001] [partitionNo=2] [partitionKey=福岡] [JobManagerName=childJobManager] [JobState=ENDING_NORMALLY]
[2008/06/23 19:34:37] [JobManager ] [INFO ] Job processing END: [jobId=JB0001] [jobRequestNo=001] [partitionNo=1] [partitionKey=大阪] [JobManagerName=childJobManager] [JobState=ENDING_NORMALLY]
[2008/06/23 19:34:37] [JobManager ] [INFO ] Job processing END: [jobId=JB0001] [jobRequestNo=001] [partitionNo=0] [partitionKey=東京] [JobManagerName=childJobManager] [JobState=ENDING_NORMALLY]
[2008/06/23 19:34:37] [JobManager ] [INFO ] Job processing END: [jobId=JB0001] [jobRequestNo=001] [partitionNo=-1] [partitionKey=NO_Partition] [JobManagerName=partitionChunkTransactionJobManager] [JobState=ENDING_NORMALLY]
[2008/06/23 19:34:37] [EndFileChecker ] [DEBUG] JB0001_001 jobstatus removed from the map.
[2008/06/23 19:34:37] [JobExecutor ] [INFO ] Job processing END : [jobId=JB0001] [jobRequestNo=001] [StartType=ASYNC] [jobExitCode=0]
[2008/06/23 19:34:37] [AsyncJobPostLogic ] [DEBUG] Succeeded in job result registration processing to DB by batch daemon : [jobId=JB0001]

 また、先ほどの多重実行ジョブの実行時と同様にテーブルの内容を確認してください。

非同期バッチデーモンの終了

 非同期バッチデーモンは、ジョブ管理テーブルから取得したジョブ依頼情報が、デーモン終了用のジョブ依頼であれば終了します。非同期バッチデーモン終了用のジョブ依頼情報は以下のとおりです。

  • ジョブID:「STOP」の文字例
  • ジョブBean定義ファイル名:「StopDaemonBean.xml」

 では、実際に非同期バッチデーモンを終了してみましょう。DBManagerから以下のINSERT文を発行します。

INSERT INTO JOB_CONTROL (REQUEST_NO, JOB_ID, JOB_FILE, STATE) VALUES ('002', 'STOP', 'common/StopDaemonBean.xml', 0)

7 非同期バッチデーモンがデーモン終了用のジョブ依頼を取得 図7 非同期バッチデーモンがデーモン終了用のジョブ依頼を取得

 上記のSQL文を発行すると、今度は非同期バッチデーモンがデーモン終了用のジョブ依頼を取得し、終了します。コンソールに以下のようなログが出力されることを確認してください。

コンソール出力のイメージ
[2008/06/23 19:46:55] [JobRequestInfoCollector] [INFO ] A stop record of an asynchronous batch daemon was recognized.
[2008/06/23 19:46:55] [AsyncJobPreLogic ] [DEBUG] Job starting by batch daemon : [jobRequestID : STOP]
[2008/06/23 19:46:55] [StandardCollectorResultHandler] [INFO ] Collector processing result code is NORMAL_END : [jobId=BATCH_DAEMON] [jobRequestNo=] [partitionNo=-1] [CollectorResult Info:ReturnCode: NORMAL_END ]
[2008/06/23 19:46:55] [JobExecutor ] [INFO ] Job processing START : [jobId=STOP] [jobRequestNo=002] [StartType=ASYNC]
[2008/06/23 19:46:55] [JobExecutor ] [DEBUG] Get the newly created JobBeanFactory
[2008/06/23 19:46:55] [EndFileChecker ] [DEBUG] STOP_002 jobstatus was added to the map.
[2008/06/23 19:46:55] [EndFileChecker ] [DEBUG] STOP_002 jobstatus removed from the map.
[2008/06/23 19:46:55] [JobExecutor ] [INFO ] Job processing END : [jobId=STOP] [jobRequestNo=002] [StartType=ASYNC] [jobExitCode=0]
[2008/06/23 19:46:55] [AsyncJobPostLogic ] [DEBUG] Succeeded in job result registration processing to DB by batch daemon : [jobId=STOP]
[2008/06/23 19:46:55] [JobManager ] [INFO ] Job processing END: [jobId=BATCH_DAEMON] [jobRequestNo=] [partitionNo=-1] [partitionKey=NO_Partition] [JobManagerName=AsyncBatchDaemonManager] [JobState=ENDING_NORMALLY]
[2008/06/23 19:46:55] [EndFileChecker ] [DEBUG] BATCH_DAEMON jobstatus removed from the map.
[2008/06/23 19:46:55] [JobExecutor ] [INFO ] Job processing END : [jobId=BATCH_DAEMON] [jobRequestNo=] [StartType=SYNC] [jobExitCode=0]
[2008/06/23 19:46:55] [AsyncBatchDaemon ] [INFO ] END batch daemon

 以上が、TERAバッチを利用した非同期実行です。

結局、Javaバッチ処理は本当に業務で“使える”の?

 本連載では、全4回にわたってJavaによるバッチ処理の現状から、OSSフレームワークを利用した際のバッチアプリケーションの構築方法について見ていきました。連載を通して読んでいただいた皆さま、ありがとうございました。

 バッチ処理をJavaで実装するということはまだまだ事例としては少ないと思いますが、オープンソースのフレームワークが出てきはじめていることからも伺えるように、徐々に一般的になってきています。その背景には、Javaの性能向上や、Java技術者の拡大、Web/バッチを統一的に扱うことによるコスト削減の要求、運用・保守性を向上したいという要求があります。これらを踏まえると、今後ますますJavaを利用したバッチ処理は一般的なものになっていくと考えられます。

 つまり、Javaによるバッチ処理は業務で“使える”ようになってきた、といっても過言ではないでしょう。本連載を通して1人でも多くの人がバッチ処理の現状とJavaという新しいアプローチに興味を持っていただければ、幸いです。なお、今回作成したアプリケーションのファイルは、SourceForgeからダウンロードできます。

前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。