intra-mart Accel Platform 非同期プログラミングガイド 第4版 2021-08-01

パラメータ

ここでは、タスクの実装およびタスクメッセージ登録処理で簡単に説明したパラメータの受け渡しにおける制限ついて説明します。

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.util.Mapの実装クラス

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

value に指定できる値はのクラスはこの表で示されているもののいずれかです。

数値の制限

パラメータに数値を指定する場合、登録時と取得時ではその設定方法が異なります。

詳細については非同期処理機能の仕様書を参照してください。

登録時はパラメータとして使用できるインスタンス(Java)に示す型で登録しますが、取得時はjava.lang.Numberの該当するメソッドで取得する必要があります。

パラメータとして使用できるインスタンス(Java)
該当するプリミティブ型 登録時に使用する型 取得時の方法
byte java.lang.Byte java.lang.Number#byteValue
short java.lang.Short java.lang.Number#shortValue
int java.lang.Integer java.lang.Number#intValue
long java.lang.Long java.lang.Number#longValue
float java.lang.Float java.lang.Number#floatValue
double java.lang.Double java.lang.Number#doubleValue

パラメータに対して数値を登録する場合の例をパラメータに数値を登録する場合に、パラメータに設定されている数値を取得する場合の例をパラメータに登録されている数値を取得する場合に示します。

パラメータに数値を登録する場合
package sample.task;

import java.util.HashMap;
import java.util.Map;

import jp.co.intra_mart.foundation.asynchronous.TaskControlException;
import jp.co.intra_mart.foundation.asynchronous.TaskManager;

public class NumberParameterRegister {
   ...

   public void register() throws TaskControlException {
      Map<String, Object> parameter = new HashMap<String, Object>();
      parameter.put("BYTE", Byte.valueOf((byte) 123));
      parameter.put("SHORT", Short.valueOf((short) 12345));
      parameter.put("INTEGER", Integer.valueOf(123456789));
      parameter.put("LONG", Long.valueOf(1234567890L));
      parameter.put("FLOAT", Float.valueOf(123.45F));
      parameter.put("DOUBLE", Double.valueOf(123.456789));

      TaskManager.addParallelizedTask("sample.task.TestTask", parameter);
   }
   ...

}
パラメータに登録されている数値を取得する場合
package sample.task;

import java.util.Map;

import jp.co.intra_mart.foundation.asynchronous.AbstractTask;

public class NumberParameterTask extends AbstractTask {
   ...

   @override
   public void run() {
      Map<String, ?> parameter = getParameter();

      // 直接 java.lang.Byte や java.lang.Integer 等にキャストしないこと
      byte byteVal = ((Number) parameter.get("BYTE")).byteValue();
      short shortVal = ((Number) parameter.get("SHORT")).shortValue();
      int intVal = ((Number) parameter.get("INTEGER")).intValue();
      long longVal = ((Number) parameter.get("LONG")).longValue();
      float floatVal = ((Number) parameter.get("FLOAT")).floatValue();
      double doubleVal = ((Number) parameter.get("DOUBLE")).doubleValue();
   }
   ...

}

注意

パラメータから数値型を取得する場合、java.lang.Integerjava.lang.Doubleなどの具象クラスにキャストしないようにしてください。 数値型をjava.lang.Number以外の型にキャストすると例外が発生する場合があります。

パラメータに登録されている数値を取得する場合の代わりに以下のような実装をすると例外が発生する場合があります。

Map<String, ?> parameter = getParameter();

// 直接 java.lang.Byte や java.lang.Integer 等にキャストすると例外が発生する可能性がある
byte byteVal = (Byte) parameter.get("BYTE");
short shortVal = (Short) parameter.get("SHORT");
int intVal = (Integer) parameter.get("INTEGER");
long longVal = (Long) parameter.get("LONG");
float floatVal = (Float) parameter.get("FLOAT");
double doubleVal = (Double) parameter.get("DOUBLE");

注意

パラメータに数値を登録する場合およびパラメータに登録されている数値を取得する場合では、ソースコードの説明を簡略化するためにnullが設定された場合が考慮されていません。 実際の開発時には、必要に応じてnullが設定された場合にも対応するような実装をしてください。

java.util.Listの制限

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

詳細については非同期処理機能の仕様書を参照してください。

登録時はjava.util.Listを実装した型(例:java.util.ArrayListjava.util.LinkedList等)で登録しますが、取得時はjava.util.Listにキャストする必要があります。

パラメータに対してjava.util.Listを登録する場合の例をパラメータにListを登録する場合に、パラメータに設定されているjava.util.Listを取得する場合の例をパラメータに登録されているListを取得する場合に示します。

パラメータにListを登録する場合
package sample.task;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.co.intra_mart.foundation.asynchronous.TaskControlException;
import jp.co.intra_mart.foundation.asynchronous.TaskManager;

public class ListParameterRegister {
   ...

   public void register() throws TaskControlException {
      // java.util.List の実装として java.util.ArrayList を使用
      List<Object> list = new ArrayList<Object>();
      list.add(...);
      list.add(...);
      ...
      Map<String, Object> parameter = new HashMap<String, Object>();
      parameter.put("LIST", list);

      TaskManager.addParallelizedTask("sample.mytest.MyTask", parameter);
   }
   ...

}
パラメータに登録されているListを取得する場合
package sample.task;

import java.util.List;
import java.util.Map;

import jp.co.intra_mart.foundation.asynchronous.AbstractTask;

public class ListParameterTask extends AbstractTask {
   ...

   @override
   public void run() {
      Map<String, ?> parameter = getParameter();

      // java.util.List にキャストすること
      List<?> list = (List<?>) parameter.get("LIST");
      ...
   }
   ...

}

注意

パラメータからjava.util.List型のデータを取得する場合、java.util.ArrayListjava.util.LinkedListなどの具象クラスにキャストしないようにしてください。 たとえ登録時と同じクラスを指定しても、java.util.List以外の型にキャストすると例外が発生する場合があります。

パラメータに登録されているListを取得する場合の代わりに以下のような実装をすると例外が発生する場合があります。

Map<String, ?> parameter = getParameter();

// java.util.List の実装クラスにキャストすると例外が発生する可能性がある
java.util.ArrayList<Object> list =
   (java.util.ArrayList<Object>) parameter.get("LIST");

注意

パラメータにListを登録する場合およびパラメータに登録されているListを取得する場合では、ソースコードの説明を簡略化するため、パラメータにnullが設定された場合が考慮されていません。 実際の開発時には、必要に応じてnullが設定された場合にも対応するような実装をしてください。

java.util.Mapの制限

タスクメッセージ を登録した時の key-value のマッピング情報のみが保存されます。 それ以外の情報(例:登録時に使用したjava.util.Mapの実装クラス、登録内容の順序、等)は保証されません。

詳細については非同期処理機能の仕様書を参照してください。

登録時はjava.util.Mapを実装した型(例:java.util.HashMapjava.util.TreeMap等)で登録しますが、取得時はjava.util.Mapにキャストする必要があります。

パラメータに対してjava.util.Mapを登録する場合の例をパラメータにMapを登録する場合に、パラメータに設定されているjava.util.Mapを取得する場合の例をパラメータに登録されているMapを取得する場合に示します。

パラメータにMapを登録する場合
package sample.task;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import jp.co.intra_mart.foundation.asynchronous.TaskControlException;
import jp.co.intra_mart.foundation.asynchronous.TaskManager;

public class MapParameterRegister {
   ...

   public void register() throws TaskControlException {
      // java.util.Map の実装として java.util.TreeMap を使用
      Map<String, Object> map = new TreeMap<String, Object>();
      map.put("key1", "value1");
      map.put("key2", "value2");
      // ...
      // TreeMap なので key は String#compareTo メソッドに依存した順序となる
      // ex.
      // for (String key : map.keySet()) <- key は "key1", "key2", ... の順に取得される

      Map<String, Object> parameter = new HashMap<String, Object>();
      parameter.put("MAP", map);

      TaskManager.addParallelizedTask("sample.mytest.MyTask", parameter);
   }
   ...

}
パラメータに登録されているMapを取得する場合
package sample.task;

import java.util.Map;

import jp.co.intra_mart.foundation.asynchronous.AbstractTask;

public class MapParameterTask extends AbstractTask {
   ...

   @override
   public void run() {
      Map<String, ?> parameter = getParameter();

      // 必ず java.util.Map にキャストすること
      Map<String, ?> map = (Map<String, ?>) parameter.get("MAP");
      String value1 = (String) map.get("key1");
      String value2 = (String) map.get("key2");
      ...

      // 登録時の Map の実装とは異なる場合があるので、 key の順序も異なる場合がある
      // ex.
      // for (String key : map.keySet()) <- key の取得順は不定
      ...
   }
   ...

}

注意

パラメータからjava.util.Mapの型を取得する場合、java.util.HashMapjava.util.TreeMapのようなjava.util.Mapのサブクラスにキャストしないようにしてください。 たとえ登録時と同じクラスを指定しても、java.util.Map以外の型にキャストすると例外が発生する場合があります。

パラメータに登録されているMapを取得する場合の代わりに以下のような実装をすると例外が発生する場合があります。

Map<String, ?> parameter = getParameter();

// java.util.Map のサブクラスにキャストすると例外が発生する可能性がある
java.util.TreeMap<String, Object> map =
   (java.util.TreeMap<String, Object>) parameter.get("MAP");

注意

パラメータにListを登録する場合およびパラメータに登録されているListを取得する場合では、ソースコードの説明を簡略化するため、パラメータにnullが設定された場合が考慮されていません。 実際の開発時には、必要に応じてnullが設定された場合にも対応するような実装をしてください。

ループ構造の禁止

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

例えば、ループ構造を含むパラメータのコード例に示すようなパラメータはループ構造を含んでいるため、タスクメッセージ登録時に例外が発生します。

ループ構造を含むパラメータのコード例
package sample.mytest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.co.intra_mart.foundation.asynchronous.TaskControlException;
import jp.co.intra_mart.foundation.asynchronous.TaskManager;

public class ParameterExamples {

   private void exampleLoop() {
      Map<String, Object> parameter = new HashMap<String, Object>();
      parameter.put("KeyNormal", "abcdefg");
      List<Object> valueLoop = new ArrayList<Object>();
      valueLoop.add("Value01");
      valueLoop.add(Integer.valueOf(100));
      valueLoop.add(parameter);

      // parameter["KeyLoop"][2] が parameter そのものになる(ループ構造)
      parameter.put("KeyLoop", valueLoop);

      try {
         // parameterにループ構造が含まれるため例外が発生する
         TaskManager.addParallelizedTask("sample.mytest.MyTask", parameter);
      } catch (TaskControlException e) {
         // ...
      }
   }
}

ループ構造を含むパラメータのコード例に示す構造では、parameterループを含むパラメータ構造のような構造です。

Parallelized Task Queue

ループを含むパラメータ構造

同値性の保証と同一性

複数の箇所から同一のインスタンスを参照しているようなパラメータの場合、値が同じ別のインスタンスが登録された場合と同様な振る舞いをします。

詳細については非同期処理機能の仕様書を参照してください。

同一のインスタンスへの参照を含むパラメータのコード例(登録時)に同一のインスタンスへの参照を含むパラメータを登録する例を示します。

同一のインスタンスへの参照を含むパラメータのコード例(登録時)
package sample.task;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import jp.co.intra_mart.foundation.asynchronous.TaskControlException;
import jp.co.intra_mart.foundation.asynchronous.TaskManager;

public class IdenticalReferenceParameterRegister {
   ...

   public void register() throws TaskControlException {
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("key1", "value1");
      map.put("key2", "value2");
      List<Object> list = new ArrayList<Object>();
      list.add("item1");
      list.add(map);
      list.add("item3");
      Map<String, Object> parameter = new HashMap<String, Object>();
      parameter.put("param1", list);
      parameter.put("param2", list);

      TaskManager.addParallelizedTask("sample.mytest.MyTask", parameter);
   }
   ...

}

同一のインスタンスへの参照を含むパラメータのコード例(登録時)に示したコードでは、同一インスタンスを参照しているパラメータ(イメージ図)に示すような構造のパラメータを設定しようとしています。

Parameter including multiple references to the same instance

同一インスタンスを参照しているパラメータ(イメージ図)

一方、このパラメータを同一のインスタンスへの参照を含むパラメータのコード例(取得時)のように取得することを考えます。

同一のインスタンスへの参照を含むパラメータのコード例(取得時)
package sample.task;

import java.util.Map;

import jp.co.intra_mart.foundation.asynchronous.AbstractTask;

public class IdenticalReferenceParameterTask extends AbstractTask {
   ...

   @override
   public void run() {
      Map<String, ?> parameter = getParameter();

      ...
   }
   ...

}

同一のインスタンスへの参照を含むパラメータのコード例(取得時)に示したタスクのビジネスロジック実行時にパラメータを取得すると、同一の値を持つインスタンスを参照しているパラメータ(イメージ図)のような構造のインスタンスです。

Parameter including multiple references to the same instance

同一の値を持つインスタンスを参照しているパラメータ(イメージ図)

同一インスタンスを参照しているパラメータ(イメージ図)同一の値を持つインスタンスを参照しているパラメータ(イメージ図)の両者を比べると、以下のことがわかります。

サーバサイドJavaScript

制限

サーバサイドJavaScriptでパラメータを受け渡す場合、以下のような制限があります。 パラメータの制限については非同期処理機能の仕様書を参照してください。

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

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

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

配列の制限

タスクメッセージを登録した時の値およびその順序のみが保存されます。

詳細については非同期処理機能の仕様書を参照してください。

パラメータに対して配列を登録する場合の例をパラメータに配列を登録する場合に、パラメータに設定されている配列を取得する場合の例をパラメータに登録されている配列を取得する場合に示します。

パラメータに配列を登録する場合
function register() {
   ...

   let list = [];
   list.push(...);
   list.push(...);

   let parameter = {};
   parameter.LIST = list;

   let workManager = new WorkManager();
   workManager.addParallelizedTask("system/async/test/test_task", parameter);
   ...
}
パラメータに登録されている配列を取得する場合
let parameter;

function setParameter(request) {
   parameter = request;
}

function run() {
   let list = parameter.LIST;
   ...
}
...

連想配列の制限

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

詳細については非同期処理機能の仕様書を参照してください。

パラメータに対して連想配列を登録する場合の例をパラメータに連想配列を登録する場合に、パラメータに設定されている連想配列を取得する場合の例をパラメータに登録されている連想配列を取得する場合に示します。

パラメータに連想配列を登録する場合
function register() {
   ...

   let map = {};
   map.key1 = "value1";
   map.key2 = "value2";
   ...

   let parameter = {};
   parameter.MAP = map;

   let workManager = new WorkManager();
   workManager.addParallelizedTask("system/async/test/test_task", parameter);
   ...
}
パラメータに登録されている連想配列を取得する場合
let parameter;

function setParameter(request) {
   parameter = request;
}

function run() {
   let map = parameter.MAP;
   let value1 = map.key1;
   let value2 = map.key2;
   ...

   // 登録時の連想配列と key の順序が異なる場合がある
   // ex.
   // for (let key in map) <- key の取得順は不定
   ...
}
...

ループ構造の禁止

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

例えば、ループ構造を含むパラメータのコード例に示すようなパラメータはループ構造を含んでいるため、タスクメッセージ登録時に例外が発生します。

ループ構造を含むパラメータのコード例
function register() {
   let parameter = {};
   parameter.KeyNormal = "abcdefg";

   let valueLoop = [];
   valueLoop.push("Value01");
   valueLoop.push(100);
   valueLoop.push(parameter);

   // parameter.KeyLoop[2] が parameter そのものになる(ループ構造)
   parameter.KeyLoop = valueLoop;

   let workManager = new WorkManager();
   let result =
      workManager.addParallelizedTask("system/async/test/test_task", parameter);
      // result.error が true となる
}

ループ構造を含むパラメータのコード例に示す構造では、parameterループを含むパラメータ構造のような構造です。

Parallelized Task Queue

ループを含むパラメータ構造

同値性の保証と同一性

複数の箇所から同一のオブジェクトを参照しているようなパラメータの場合、値が同じ別のオブジェクトが登録された場合と同様な振る舞いをします。

詳細については非同期処理機能の仕様書を参照してください。

同一のオブジェクトへの参照を含むパラメータのコード例(登録時)に同一のオブジェクトへの参照を含むパラメータを登録する例を示します。

同一のオブジェクトへの参照を含むパラメータのコード例(登録時)
function register() {
   let map = {};
   map.key1 = "value1";
   map.key2 = "value2";

   let list = [];
   list.push("item1");
   list.push(map);
   list.push("item3");

   let parameter = {};
   parameter.param1 = list;
   parameter.param2 = list;

   // parameter.param1 と parameter.param2 は、同一のオブジェクトを参照していることを確認
   parameter.param1[0] = "new_item";
   if (parameter.param1[0] == parameter.param2[0]) {
      // 両者が同一のオブジェクトを参照しているので、上記の条件式は true となる
   } else {
   }

   let workManager = new WorkManager();
   workManager.addParallelizedTask("system/async/test/test_task", parameter);
}

同一のオブジェクトへの参照を含むパラメータのコード例(登録時)に示したコードでは、同一インスタンスを参照しているパラメータ(イメージ図)に示すような構造のパラメータを設定しようとしています。

Parameter including multiple references to the same instance

同一インスタンスを参照しているパラメータ(イメージ図)

一方、このパラメータを同一のオブジェクトへの参照を含むパラメータのコード例(取得時)のように取得することを考えます。

同一のオブジェクトへの参照を含むパラメータのコード例(取得時)
let parameter;

function setParameter(request) {
   parameter = request;
}

function run() {
   // 同値性の検証
   if (parameter.param1[0] == parameter.param2[0]) {
      // 両者は別オブジェクトであるが、値と構造が同じなので、上記の条件式は true となる
   } else {
   }

   // parameter.param1 と parameter.param2 は、異なるオブジェクトを参照していることを確認
   parameter.param1[0] = "modified_item";
   if (parameter.param1[0] == parameter.param2[0]) {
   } else {
      // 両者が異なるオブジェクトを参照しているので、上記の条件式は false となる
   }
   ...
}
...

同一のオブジェクトへの参照を含むパラメータのコード例(取得時)に示したタスクのビジネスロジック実行時にパラメータを取得すると、同一の値を持つインスタンスを参照しているパラメータ(イメージ図)のような構造のインスタンスです。

Parameter including multiple references to the same instance

同一の値を持つインスタンスを参照しているパラメータ(イメージ図)

同一インスタンスを参照しているパラメータ(イメージ図)同一の値を持つインスタンスを参照しているパラメータ(イメージ図)の両者を比べると、以下のことがわかります。