サポート > Wagby Developer Network(R7) > バッチ処理 > 自作クラスをジョブスケジューラに登録する

バッチ処理を行うシンプルなJavaクラスの作成方法を説明します。これをWagbyが提供するジョブスケジューラに登録します。

顧客モデルを対象とした「顧客登録ジョブ」を用意してみます。次の手順となります。

  1. customize/webapp/WEB-INF/export/init/jfcjob フォルダを用意する。
  2. 同フォルダに XXXJob.xml を保存する。

例として、CreateCustomerJob.xml を作成します。次の内容とします。

<?xml version="1.0" encoding="UTF-8"?>
<jfcjob createApplicationContext="false">
  <name>CreateCustomer</name>
  <memo>CreateCustomer</memo>
  <classname>jp.jasminesoft.wagby.job.CreateCustomerJob</classname>
  <description>顧客データを作成する</description>
</jfcjob>
  • 設定した情報は、ビルドしたアプリケーションの「管理処理 > ジョブ管理... > ジョブマスタ」に含まれるようになります。
  • ジョブマスタモデル (jfcjob) は Wagby のシステムモデルとして含まれています。図1に設計情報を示します。
図1 jfcjobモデル
上の例で、CreateCustomerJob.xml の name 項目と memo 項目は同じとしましたが、memo 項目には日本語を入力することもできます。description 項目は後述する図6で画面に描画されるため、わかりやすい説明文を設定してください。

ジョブクラス

ジョブクラスは、Wagbyのジョブスケジューラから呼び出されます。 ここでは上記で示した CreateCustomerJob.java クラスを用意します。

package jp.jasminesoft.wagby.job;

import org.apache.log4j.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import jp.jasminesoft.jfc.DbActionParameter;
import jp.jasminesoft.jfc.job.JFCBaseJobBean;

public class CreateCustomerJob extends JFCBaseJobBean {
    private final static Logger logger = 
        Logger.getLogger(CreateCustomerJob.class.getName());

    private CreateCustomerTask createCustomerTask;

    public void setCreateCustomerTask(CreateCustomerTask createCustomerTask) {
        this.createCustomerTask = createCustomerTask;
    }

    @Override
    protected String executeInternal0(JobExecutionContext jobContext,
	DbActionParameter p) throws JobExecutionException {
	return createCustomerTask.process(p);
    }
}

このコードに示したように、バッチ処理の本体は CreateCustomerTask というクラスに記述します。ジョブクラスは入れ物であり、ジョブパラメータを受け取ることができるようになっています。このパラメータをタスククラスへの引数とし、実際の処理をタスククラスに委譲します。

タスククラス

バッチ処理の本体です。CreateCustomerTask.java とします。

package jp.jasminesoft.wagby.job;

import jp.jasminesoft.jfc.DbActionParameter;
import jp.jasminesoft.jfc.app.EntityHelper;
import jp.jasminesoft.jfc.service.JFCEntityService;
import jp.jasminesoft.wagby.model.customer.*;
import jp.jasminesoft.wagby.app.customer.*;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class CreateCustomerTask {
    private final static Logger logger = 
        Logger.getLogger(CreateCustomerTask.class.getName());

    @Autowired
    @Qualifier("CustomerHelper")
    protected EntityHelper<Customer, Integer> customerHelper;
    
    @Autowired
    @Qualifier("CustomerEntityService")
    protected JFCEntityService<Customer, Integer> customerEntityService;

    protected String process(DbActionParameter p) {
	logger.info("顧客データ作成ジョブを開始しました。");
	for (int i = 0; i < 100; i++) {
	    Customer customer = new Customer();
	    customerHelper.initialize(customer, p);
	    customerEntityService.insert(customer);
	    logger.info( i + "件の顧客データを登録しました。");
	}
	return "顧客データ作成ジョブを正常終了しました。";
    }
}

タスククラスは@Autowiredアノテーションを利用して(自動生成された)ヘルパやサービスクラスを再利用しています。これによってSQLを書かずに業務処理を実現しています。

タスククラスはPOJOとなっているため、再利用性があります。

以下のファイルを customize/webapp/WEB-INF/applicationContext/customer-ex.xml として保存します。(ファイル名は自動生成されたファイルと重複しないのであれば自由です。)

ここではCreateCustomerTaskをbean定義として用意します。また、CreateCustomerジョブを定義し、CreateCustomerTaskとひも付けます。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd">

  <bean id="CreateCustomer" scope="prototype"
        class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass">
      <value>jp.jasminesoft.wagby.job.CreateCustomerJob</value>
    </property>
    <property name="jobDataAsMap">
      <map>
        <entry key="createCustomerTask" value-ref="CreateCustomerTask"/>
      </map>
    </property>
  </bean>

  <bean id="CreateCustomerTask" scope="prototype"
        class="jp.jasminesoft.wagby.job.CreateCustomerTask"/>
</beans>

追加したファイルは次のとおりです。

customize/java/jp/jasminesoft/wagby/job/CreateCustomerJob.java
customize/java/jp/jasminesoft/wagby/job/CreateCustomerTask.java
customize/webapp/WEB-INF/applicationContext/customer-ex.xml
customize/webapp/WEB-INF/export/init/jfcjob/CreateCustomerJob.xml

このファイルをダウンロードできます。customize フォルダ直下に展開してください。

別途、"customer" モデルを用意してからお試しください。customer モデルの定義内容は問いません。

システム管理者でログオンします。「管理者ガイド(R7) > 準備:ジョブ実行アカウントを利用可能にする」の説明に従って、ジョブ実行アカウントを利用可能にします。

図2 ジョブ実行アカウントを利用可能にする

管理処理タブの「ジョブ管理...」を選択します。

図3 ジョブ管理

「ジョブスケジュール検索」画面を開きます。

図4 ジョブスケジュール検索画面へ

ジョブスケジュールの新規登録画面を開きます。

図5 ジョブスケジュール新規登録画面へ

作成したジョブを選択します。

図6 ジョブを選択する

ジョブ実行アカウントを指定します。この段階では、ジョブは有効にしません。

図7 ジョブ実行アカウントを指定する

「今すぐ実行」ボタンを押下し、このジョブを実行させてみます。

図8 「今すぐ実行」を行う

ジョブが実行されます。wagbyapp/logs/system.logに、ジョブに関するメッセージが記録されます。

図9 ジョブが実行される
ここで紹介したジョブプログラムは、顧客を新規に100件登録するものです。実際に100件登録されたかどうかを確認することができます。

「ジョブパラメータ」を追加し、これをジョブクラスが受け取ることができます。

図10 ジョブパラメータを指定した

受け取る側のソースコードは次のように記述できます。

package jp.jasminesoft.wagby.job;

import org.apache.log4j.Logger;
import org.quartz.JobDataMap;// 追加
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import jp.jasminesoft.jfc.DbActionParameter;
import jp.jasminesoft.jfc.job.JFCBaseJobBean;

public class CreateCustomerJob extends JFCBaseJobBean {
    private final static Logger logger = 
        Logger.getLogger(CreateCustomerJob.class.getName());

    private CreateCustomerTask createCustomerTask;

    public void setCreateCustomerTask(CreateCustomerTask createCustomerTask) {
        this.createCustomerTask = createCustomerTask;
    }

    @Override
    protected String executeInternal0(JobExecutionContext jobContext,
	DbActionParameter p) throws JobExecutionException {

        JobDataMap dataMap = jobContext.getJobDetail().getJobDataMap();
        String args = (String)dataMap.get("process");

	return createCustomerTask.process(p);
    }
}

4行目のimport文を追加しています。ジョブパラメータは org.quartz.JobDataMap クラスが管理します。
24行目,25行目でパラメータを取得しています。図9の例では、キー"process"という名前で(画面から)登録されたパラメータを受け取っています。変数 args には文字列 "AAA" が格納されます。

「サポート > 管理者ガイド(R7) > ジョブスケジュールの指定方法」をお読みください。

  • R7.0.0〜R7.3.2までの版では「更新処理」を行うことはできません。
  • R7.4.0〜R7.5.0までの版で「更新処理」を行う場合、対象モデルのロック方式を「楽観ロック」としてください。R7.5.1以降の版で、ロック方式は楽観ロック・悲観ロックいずれでも動作します。

R7.10より前のWagby(R7.0.0〜R7.9.2)では、org.springframework.scheduling.quartz.JobDetailFactoryBean クラスの代わりに org.springframework.scheduling.quartz.JobDetailBean クラスを指定するようにしてください。これは R7.10 で、Spring Framework のバージョンが 3 から 4 へアップデートされたためです。

具体的にはジョブ定義の xml ファイルが次のようになります。

...
  <bean id="CreateCustomer" scope="prototype"
        class="org.springframework.scheduling.quartz.JobDetailBean">
...

R7.5より前のWagby(R7.0.0〜R7.4.3)では、CreateCustomerJob.xml に用意した jfcjob 要素の createApplicationContext="false" 属性が無視されます。そのため、自動生成された WEB-INF/applicationContext/__jobcontrol.xml に CreateCustomer ジョブ定義が出力されます。これを手動で削除する必要があります。

具体的には $(DEVHOME)/wagbydesigner/webapps/wagbydesigner/WEB-INF/env/work/srcgen/webpage/WEB-INF/applicationContext/__jobcontrol.xml の末尾に含まれる次の行を削除します。

  <!-- extension -->
  <bean id="CreateCustomer" scope="prototype"
        class="org.springframework.scheduling.quartz.JobDetailBean">
    <property name="jobClass">
      <value>jp.jasminesoft.wagby.job.CreateCustomerJob</value>
    </property>
  </bean>

削除したファイルを $(DEVHOME)/customize/webapp/WEB-INF/applicationContext に保存します。つまり、このファイルは今後、カスタマイズフォルダに保存したファイルに上書きされます。このファイルの保守は開発者が行ってください。