intra-mart Accel Platform 非同期仕様書 第5版 2018-08-01

タスク

タスクはビジネスロジックを実行する部分です。 非同期処理機能を利用する場合、開発者はタスクを提供する必要があります。

タスクを実装するにあたり、開発言語として以下のものを利用することができます。

  • Java
  • サーバサイドJavaScript

タスクの実装

Java

Javaでタスクを作成する場合、ビジネスロジックを実行するクラスは以下の条件をすべて満たす必要があります。

  • jp.co.intra_mart.foundation.asynchronous.Taskインタフェースを実装したクラスであること

  • 以下のいずれのクラスでもないこと。

    • 内部クラス(inner class)
    • ローカルクラス(local class)
    • 無名クラス(anonymous class)
  • クラスの修飾子が以下の条件をすべて満たしていること

    • publicであること
    • abstractではないこと
  • publicで引数なしのコンストラクタを持っていること

  • いずれのメソッドもsynchronizedとして宣言されていないこと

    (メソッド内部でsynchronizedブロックを使用することは可能)

また、Javaでタスクを作成する場合、以下の点について注意してください。

  • jp.co.intra_mart.foundation.asynchronous.Taskインタフェースで定義されている各メソッドは異なるスレッドから呼び出される場合があります。
    同一のスレッドであることを前提とする実装をしないでください。

    コラム

    スレッドに関連付けられているリソース等が存在する場合、リソースの取得と解放を異なるメソッド上で行おうとすると
    不具合が発生する場合があります。

    非同期処理機能では、少なくとも以下の異なるスレッドが存在します。

    • タスクのコンストラクタおよびTask#setParameterメソッドを呼び出すスレッド
    • タスクのTask#runメソッドを呼び出すスレッド
    • タスクのTask#releaseメソッドを呼び出すスレッド

    その他のイベント通知に関連するメソッド(Task#taskAcceptedTask#taskStartedTask#taskCompletedTask#taskRejected)を起動するスレッドは不定です。 runメソッドと同じスレッドから呼び出される場合もあれば、上記のいずれからも異なるスレッドから呼び出される場合もあります。 そのため、特定のスレッドに依存するような実装はしないようにしてください。

    なお、Task#runメソッドおよびTask#releaseメソッドの組み合わせ以外は、同一のタスクにおいて各メソッドが異なるスレッド上から起動された場合であっても、複数のメソッドが同時に実行されないように制御されています。 異なるスレッド上からメソッドが呼び出される時のイメージ図も参照してください。

  • Task#run以外のメソッドではJava EEのリソースやintra-mart Accel Platformから提供されるリソースの取得は行わないでください。

Method calls on different threads

異なるスレッド上からメソッドが呼び出される時のイメージ図

Taskインタフェース

Taskインタフェース

package jp.co.intra_mart.foundation.asynchronous;

import java.util.Map;

public interface Task extends Runnable {

    void release();

    void setParameter(Map<String, ?> parameter);

    void taskAccepted(TaskEvent taskEvent);

    void taskStarted(TaskEvent taskEvent);

    void taskCompleted(TaskEvent taskEvent);

    void taskRejected(TaskEvent taskEvent);
}
コンストラクタ

非同期処理機能を利用するタスクを作成する場合、publicで引数なしのコンストラクタを持っている必要があります。

注意

非同期処理機能からコンストラクタによってインスタンスが生成された場合、このコンストラクタの内部ではTask#runで説明したリソースを取得できない場合があります。 これらのリソースに依存しないように実装してください。

Task#run

コラム

run()メソッドは、実際にはTaskインタフェースのスーパーインタフェースjava.lang.Runnableで宣言されています。

public void run();

非同期として実行したいビジネスロジックを記述します。

開発者は以下の点に注意してこのメソッドを実装する必要があります。

  • 無限ループにならないこと
  • Task#releaseが呼ばれた時、速やかに終了すること

非同期処理機能からrunメソッドが呼ばれた場合、このメソッドの内部では以下のリソースを使用することができます。

  • コンテキストに保持された値
    タスクメッセージ登録時には、その時点におけるコンテキストの情報も同時に保存されます。
    非同期処理機能からrun()メソッドが実行されている場合、内部でこのコンテキストの情報を取得することができます。
    コンテキストの詳細についてはjp.co.intra_mart.foundation.contextパッケージのAPIリスト等を参照してください。
  • JNDIによる参照
    intra-mart Accel Platformが搭載されたWebモジュールから参照可能なJNDI名前空間において、"java:comp"から始まる参照名を利用することが可能です。
  • データベースに保持された値
    非同期処理機能からrun()メソッドが実行されている場合、内部でintra-mart Accel Platformで扱うデータベースにアクセスすることが可能です。
    intra-mart Accel Platformで扱うデータベースの詳細についてはjp.co.intra_mart.foundation.databaseパッケージのAPIリスト等を参照してください。
  • ストレージサービスに保持された値
    非同期処理機能からrun()メソッドが実行されている場合、内部でストレージサービスにアクセスすることが可能です。
    ストレージサービスの詳細についてはjp.co.intra_mart.foundation.service.client.fileパッケージのAPIリスト等を参照してください。
Task#release
public void release();

このメソッドはTask#runで実行中のビジネスロジックを中断する場合、非同期処理機能から呼び出されます。

このメソッドが呼ばれた場合、速やかにビジネスロジックを終了するようにこのメソッドおよびTask#runを実装してください。

このメソッドはTask#runを実行しているスレッドとは別のスレッドから呼び出される場合があります。

注意

非同期処理機能からreleaseメソッドが呼ばれた場合、このメソッドの内部ではTask#runで説明したリソースを取得できない場合があります。 これらのリソースに依存しないように実装してください。

Task#setParameter
public void setParameter(
   java.util.Map<java.lang.String, ?> parameter
);

非同期ではTaskManager#addParallelizedTaskを通じてタスクメッセージを登録する際に、独自のパラメータを設定することが可能です。 タスク実行エンジンはビジネスロジックを開始する前にこのメソッドを呼び出し、登録時に設定されたパラメータを渡します。

ここで渡されたパラメータをインスタンス変数等に登録しておけば、Taskインタフェースで定義されているsetParameter以外のすべてのメソッドでその値を参照することができます。

パラメータとして登録できる値の制限についてはJavaを利用するときのパラメータの制限を参照してください。

注意

非同期処理機能からsetParameterメソッドが呼ばれた場合、このメソッドの内部ではTask#runで説明したリソースを取得できない場合があります。 これらのリソースに依存しないように実装してください。

Task#taskAccepted
public void taskAccepted(
   jp.co.intra_mart.foundation.asynchronous.TaskEvent taskEvent
);

タスクキューの中で選択待機状態だったタスクメッセージがタスクに変換され、処理実行可能状態となった時に呼び出されます。

このメソッドで例外が発生しても非同期処理機能は後続の処理を続行します。 このメソッド内で例外が発生しないような実装を推奨します。

このメソッドが呼び出されるタイミングの詳細についてはタスク受付を参照してください。

注意

非同期処理機能からtaskAcceptedメソッドが呼ばれた場合、このメソッドの内部ではTask#runで説明したリソースを取得できない場合があります。 これらのリソースに依存しないように実装してください。

Task#taskStarted
public void taskStarted(
   jp.co.intra_mart.foundation.asynchronous.TaskEvent taskEvent
);

処理実行可能状態となっていたタスクのビジネスロジックが開始される直前に呼び出されます。

このメソッドで例外が発生しても非同期処理機能は後続の処理を続行します。 このメソッド内で例外が発生しないような実装を推奨します。

このメソッドが呼び出されるタイミングの詳細についてはタスク処理開始を参照してください。

注意

非同期処理機能からtaskStartedメソッドが呼ばれた場合、このメソッドの内部ではTask#runで説明したリソースを取得できない場合があります。 これらのリソースに依存しないように実装してください。

Task#taskCompleted
public void taskCompleted(
   jp.co.intra_mart.foundation.asynchronous.TaskEvent taskEvent
);

実行中のタスクのビジネスロジックが完了された直後に呼び出されます。

このメソッドで例外が発生しても非同期処理機能は後続の処理を続行します。 このメソッド内で例外が発生しないような実装を推奨します。

このメソッドが呼び出されるタイミングの詳細についてはタスク処理完了を参照してください。

注意

非同期処理機能からtaskCompletedメソッドが呼ばれた場合、このメソッドの内部ではTask#runで説明したリソースを取得できない場合があります。 これらのリソースに依存しないように実装してください。

Task#taskRejected
public void taskRejected(
   jp.co.intra_mart.foundation.asynchronous.TaskEvent taskEvent
);

何らかの理由でタスクメッセージの受け付けが拒否され、受付待機状態にできなかった時に呼び出されます。

このメソッドで例外が発生しても非同期処理機能は後続の処理を続行します。 このメソッド内で例外が発生しないような実装を推奨します。

このメソッドが呼び出されるタイミングの詳細についてはタスク受付拒否を参照してください。

注意

非同期処理機能からtaskRejectedメソッドが呼ばれた場合、このメソッドの内部ではTask#runで説明したリソースを取得できない場合があります。 これらのリソースに依存しないように実装してください。

TaskEventインタフェース

TaskEventインタフェース

package jp.co.intra_mart.foundation.asynchronous;

public interface TaskEvent {

   TaskException getException();

   TaskEventType getType();

   Task getTask();
}

タスクの各種イベント発生時に呼び出されるメソッドの引数として渡されます。

TaskEvent#getException
public jp.co.intra_mart.foundation.asynchronous.TaskException getException();

イベント発生時の例外情報を取得します。

例外が発生していなかった場合はnullが返されます。

TaskEvent#getType
public jp.co.intra_mart.foundation.asynchronous.TaskEventType getType();

発生したイベントの種類を取得します。

種類 内容
TaskEventType.TASK_ACCEPTED Task#taskAcceptedが呼び出されたことを表します。
TaskEventType.TASK_STARTED Task#taskStartedが呼び出されたことを表します。
TaskEventType.TASK_COMPLETED Task#taskCompletedが呼び出されたことを表します。
TaskEventType.TASK_REJECTED Task#taskRejectedが呼び出されたことを表します。
TaskEvent#getTask
public jp.co.intra_mart.foundation.asynchronous.Task getTask();

イベント発生元のタスクのインスタンスが返されます。

AbstractTask抽象クラス

タスクの実装方法としてjp.co.intra_mart.foundation.asynchronous.AbstractTaskクラスのサブクラスを作成する方法もあります。 このクラスはjp.co.intra_mart.foundation.asynchronous.Taskインタフェースのほとんどのメソッドにおいて何もしないように実装しているので、開発者は必要なメソッドをオーバライドするだけでタスクを実装できます。

また、jp.co.intra_mart.foundation.asynchronous.AbstractTaskには以下のメソッドが追加されています。

AbstractTask抽象クラスに追加されているメソッド
public java.util.Map<java.lang.String, ?> getParameter()

上記のメソッドを呼び出すことでTask#setParameterメソッドで設定されたパラメータを取得することができます。

サーバサイドJavaScript

サーバサイドJavaScriptでタスクを作成する場合、 以下の関数が定義されたJSファイルを用意する必要があります。

コラム

それぞれの関数はTaskインタフェースで定義している内容とほぼ一致しますが、Task#releaseに該当するものはサーバサイドJavaScriptでは用意されていません。

JSファイルはWorkManager#addParallelizedTaskの引数で指定されたものです。

JSファイル

run()

この関数の定義は必須です。

非同期として実行したいビジネスロジックを記述します。

非同期処理機能からこのメソッドが呼ばれた場合、このメソッドの内部では以下の情報を取得することができます。

  • コンテキストに保持された値
    タスクメッセージ登録時には、その時点におけるコンテキストの情報も同時に保存されます。
    非同期処理機能からrun()関数が実行されている場合、内部でこのコンテキストの情報を取得することができます。
    コンテキストの詳細についてはサーバサイドJavaScriptのAPIリスト等を参照してください。
  • データベースに保持された値
    非同期処理機能からrun()関数が実行されている場合、内部でintra-mart Accel Platformで扱うデータベースにアクセスすることが可能です。
    intra-mart Accel Platformで扱うデータベースの詳細についてはサーバサイドJavaScriptのAPIリスト等を参照してください。
  • ストレージサービスに保持された値
    非同期処理機能からrun()関数が実行されている場合、内部でストレージサービスにアクセスすることが可能です。
    ストレージサービスの詳細についてはサーバサイドJavaScriptのAPIリスト等を参照してください。

開発者は以下の点に注意してこのメソッドを実装する必要があります。

  • 例外を出力しないこと
  • 無限ループにならないこと
setParameter(parameter)

この関数の定義は任意です。

非同期ではTaskManager#addParallelizedTaskを通じてタスクメッセージを登録する際に、独自のパラメータを設定することが可能です。 タスク実行エンジンはビジネスロジックを開始する前にこのメソッドを呼び出し、登録時に設定されたパラメータを渡します。

ここで渡されたパラメータをインスタンス変数等に登録しておけば、Taskインタフェースで定義されているsetParameter以外のすべてのメソッドでその値を参照することができます。

パラメータとして登録できる値の制限についてはサーバサイドJavaScriptを利用するときのパラメータの制限を参照してください。

taskAccepted(event)

この関数の定義は任意です。

タスクキューの中で待機中だったタスクメッセージがタスクに変換され、実行可能状態となった時に呼び出されます。

この関数で例外が発生しても非同期処理機能は後続の処理を続行します。 この関数内で例外が発生しないような実装を推奨します。

この関数が呼び出されるタイミングの詳細についてはタスク受付を参照してください。

taskStarted(event)

この関数の定義は任意です。

実行可能状態となっていたタスクのビジネスロジックが開始される時に呼び出されます。

この関数で例外が発生しても非同期処理機能は後続の処理を続行します。 この関数内で例外が発生しないような実装を推奨します。

この関数が呼び出されるタイミングの詳細についてはタスク処理開始を参照してください。

taskCompleted(event)

この関数の定義は任意です。

実行中のタスクのビジネスロジックが完了された時に呼び出されます。

この関数で例外が発生しても非同期処理機能は後続の処理を続行します。 この関数内で例外が発生しないような実装を推奨します。

この関数が呼び出されるタイミングの詳細についてはタスク処理完了を参照してください。

taskRejected(event)

この関数の定義は任意です。

何らかの理由でタスクメッセージの受け付けが拒否され、実行可能状態にできなかった時に呼び出されます。

この関数で例外が発生しても非同期処理機能は後続の処理を続行します。 この関数内で例外が発生しないような実装を推奨します。

この関数が呼び出されるタイミングの詳細についてはタスク受付拒否を参照してください。

イベント

各種イベント発生時に呼び出される関数にはイベント情報が引数として渡されます。

イベント情報は以下の属性を持つオブジェクトです。

属性 内容
type 発生したイベントの種類
error エラー発生の判定フラグ
type

発生したイベントの種類を取得します。

種類 内容
TASK_ACCEPTED taskAccepted(event)が呼び出されたことを表します。
TASK_STARTED taskStarted(event)が呼び出されたことを表します。
TASK_COMPLETED taskCompleted(event)が呼び出されたことを表します。
TASK_REJECTED taskRejected(event)が呼び出されたことを表します。
error

イベント発生時に例外が発生していたかどうかを取得します。

  • 例外が発生していた場合はtrueが返されます。
  • 例外が発生していなかった場合はfalseが返されます。

パラメータの制限

タスクメッセージをタスクキューに登録する時、ビジネスロジックの実行に必要となる独自のパラメータを渡し、タスクの実行時にそのパラメータを取得して利用することが可能です。 パラメータとして使用できる値には制限があります。

Javaを利用するときのパラメータの制限

登録時

Javaを利用してタスクメッセージをタスクキューに登録する場合、受け渡すパラメータには以下のような制限があります。

  • パラメータはnullか、java.util.Mapを実装したクラスのインスタンスのみ指定できます。
  • パラメータとして指定するマップのkey部はjava.lang.Stringのみです。
  • パラメータとして指定するマップのkey部には必ず値が設定される必要があります。nullを指定することはできません。
  • パラメータとして指定するマップのvalue部にはnullか、パラメータとして使用できるインスタンス(Java)に示す値のいずれかのみ指定できます。
パラメータとして使用できるインスタンス(Java)
クラス 備考
java.lang.Boolean  
java.lang.Byte  
java.lang.Short  
java.lang.Integer  
java.lang.Long  
java.lang.Float  
java.lang.Double  
java.lang.String  
java.util.Listの実装クラス

リストの要素として指定できる値はパラメータとして使用できるインスタンス(Java)で示されているもののいずれかです。

TaskManager#addParallelizedTaskまたはTaskManager#addSerializedTaskを通じてタスクメッセージを登録した時の値およびその順序のみが保存されます。 それ以外の情報(例:登録時に使用したjava.util.Listの実装クラス、等)は保証されません。

java.util.Mapの実装クラス

key に指定できる値はjava.lang.Stringのインスタンスのみです。nullは指定できません。

value に指定できる値はnullまたはパラメータとして使用できるインスタンス(Java)で示されているもののいずれかです。 TaskManager#addParallelizedTaskまたはTaskManager#addSerializedTaskを通じてタスクメッセージを登録した時の key-value のマッピング情報のみが保存されます。 それ以外の情報(例:登録時に使用したjava.util.Mapの実装クラス、登録内容の順序、等)は保証されません。

注意

パラメータとして使用できるインスタンス(Java)に示す値を使用している場合であっても、ループ構造を含んではいけません。

取得時

登録時に設定したパラメータはTask#setParameterの引数で取得できますが、以下のような制限があります。

数値型のパラメータ

数値型のパラメータに示す値はすべてjava.lang.Numberとして扱います。 設定した時の値を取得する場合、一度java.lang.Numberにダウンキャストし、該当するメソッド(xxxValue())を使用してください。

数値型のパラメータ
登録時のクラス 実際の値取得時に使用するメソッド
java.lang.Byte java.lang.Number#byteValue()
java.lang.Short java.lang.Number#shortValue()
java.lang.Integer java.lang.Number#intValue()
java.lang.Long java.lang.Number#longValue()
java.lang.Float java.lang.Number#floatValue()
java.lang.Double java.lang.Number#doubleValue()
java.util.List型のパラメータ

登録時にjava.util.List型を利用している場合、取得時にはjava.util.Listの実装クラスの情報は保持されません。

ダウンキャストする時は必ずjava.util.Listインタフェースとしてください。

java.util.Map型のパラメータ

登録時にjava.util.Map型を利用している場合、取得時にはjava.util.Mapの実装クラスの情報は保持されません。

ダウンキャストする時は必ずjava.util.Mapインタフェースとしてください。

なお、キーは登録時の制限と同様にjava.lang.Stringです。

パラメータの構造

登録時のパラメータの中に、あるインスタンスを複数の箇所から参照しているような構造があっても、取得時には異なるインスタンスを参照しているような構造になっている場合があります。

パラメータの参照先の値は保持されますが、参照先のインスタンスの同一性は保たれません。

サーバサイドJavaScriptを利用するときのパラメータの制限

登録時

サーバサイドJavaScriptを利用してタスクメッセージをタスクキューに登録する場合、受け渡すパラメータには以下のような制限があります。

  • パラメータは連想配列のみ指定できます。
  • パラメータとして指定する連想配列のkey部は文字列および整数のみ指定できます。 整数を指定した場合、文字列として扱われます。
  • パラメータとして指定する連想配列のkey部には必ず値が設定される必要があります。nullを指定することはできません。
  • パラメータとして指定する連想配列のvalue部にはnullか、パラメータとして使用できるインスタンス(サーバサイドJavaScript)に示す値のいずれかのみ指定できます。
パラメータとして使用できるインスタンス(サーバサイドJavaScript)
クラス 備考
Boolean  
数値型  
文字列  
配列

配列の要素として指定できる値はパラメータとして使用できるインスタンス(サーバサイドJavaScript)で示されているもののいずれかです。

WorkManager#addParallelizedTaskまたはWorkManager#addSerializedTaskを通じてタスクメッセージを登録した時の値およびその順序のみが保存されます。

連想配列

key に指定できる値は文字列および整数のみです。nullは指定できません。

value に指定できる値はnullまたはパラメータとして使用できるインスタンス(サーバサイドJavaScript)で示されているもののいずれかです。

WorkManager#addParallelizedTaskまたはWorkManager#addSerializedTaskを通じてタスクメッセージを登録した時の key-value のマッピング情報のみが保存されます。 それ以外の情報(例:登録内容の順序、等)は保証されません。

注意

パラメータとして使用できるインスタンス(サーバサイドJavaScript)に示す値を使用している場合であっても、ループ構造を含んではいけません。

取得時

登録時に設定したパラメータはsetParameter(parameter)の引数で取得できますが、以下のような制限があります。

パラメータの構造

登録時のパラメータの中に、あるインスタンスを複数の箇所から参照しているような構造があっても、取得時には異なるインスタンスを参照しているような構造になっている場合があります。

パラメータの参照先の値は保持されますが、参照先のインスタンスの同一性は保たれません。