みなさん、こんにちは!
今回は、Talendのジョブ内でグローバル変数を使用する方法を取り上げます。
Talendのグローバル変数管理方法
大きく分けて2つあります。
- context(コンテキスト)を使用する
- globalMapを使用する
それぞれについて、詳しく見ていきましょう。
contextとglobalMap
contextとは?
グローバル変数のようなものです。
環境ごとにデフォルト値を使い分けることができます。
コンテキストは大きく分けて2種類存在します。
contextの環境
Talendでは、実行環境ごとにコンテキストを定義しておくことができます。
環境は、Contextsタブの一番右にある+ボタンなどで管理ができます。
デフォルトでは、Defaultという環境しか存在しませんが、例えば、開発環境での値、本番環境での値をそれぞれ別に定義したい(DB接続のためのパラメータ等)場合に、環境を別に分けると便利でしょう。
contextの種類と定義方法
contextには、ローカルコンテキストと共通コンテキストの2種類存在します。
ローカルコンテキスト
開発画面下部にある、Contexts(コンテキスト)タブでそのジョブごとに定義する変数がローカルコンテキストです。
左下の+ボタン、×ボタンなどで追加、削除を行います。
Nameには変数名を、Typeには型を、そのさらに右側の列は、環境ごとに使用するデフォルト値を定義します。
環境ごとに使用するデフォルト値は、Talendから実行する際に値を設定させるプロンプトを表示することもできます。
上記画像の”Value”と”Prompt”の間にチェックボックスが有りますが、これにチェックを付けるとジョブ実行時にプロンプトが表示されます。
共通コンテキスト
複数のジョブで共通した値を使用したいケースなどでは、コンテキストを外出しして定義します。(例えば、出力するファイルパス(のルート)など)
こちらを共通コンテキストと呼びます。
定義は、左側のRepository(リポジトリ)のContextsから行います。
新規Contextを定義する場合、Contextsを右クリックしてCreate context groupをクリックします。(英語表記ですみません)
すると、下記の様にコンテキスト名を決めるウインドウが立ち上がります。
ここに共通コンテキストの名称を入力、Description(説明)欄も入力してNextを押下します。
下記の画面に遷移します。
ここで、コンテキストの名称、型、各環境でのデフォルト値を定義することができます。
編集が完了したらFinishを押下して終了です。
定義した共通コンテキストは、Contextsタブの左下にあるアイコン群の中の一番右のアイコンを押下することで読み込むことができます。
画像右上のウインドウで、使用したい定義済みのコンテキストを選択し、OKを押下します。
contextの使い方
定義したコンテキストは、各コンポーネントに与えるパラメータや、tJava, tJavaRowなどのJavaコードを記述する箇所で呼び出すことができます。
下記の様に、context. を定義したコンテキスト名に付与することでアクセスすることができます。
[java] context.genLength[/java]
又は、
[java] context.getProperty("genLength")[/java]
のように、getPropertyメソッドを使用してのアクセスも可能です。
コンテキストに値をセットする場合は、上記の丁度逆のアクションを行えば良く、
[java] context.genLength = 10[/java]
又は、
[java] context.setProperty("genLength", 10)[/java]
とすればokです。
Talendが正常に動いていれば、context. と入力した時に、Ctrl + Spaceを押下することで、補完というかプロパティの候補を表示してくれるので便利です。(大体どんなエディタでもこの機能はありますよね)
ちなみに、私は殆ど使用しませんが、tContextLoadというコンポーネントを使用して、コンテキストに値をセットすることもできます。
context使用時の注意点
前述の通り、contextの値取得/設定には2種類の方法があります。
が、コーディングする上では何れかの方法に統一した方が無難です。
下記のコードをご覧ください。
1つのprop1というコンテキストに対して、2種類の方法で(代入とメソッド使用)アクセスしています。
(prop1には、デフォルト値として”default value”が与えられています)
この状態でジョブ実行します。すると、コンソールには下記の様に出力されます。
(変更前)と表示されている箇所では、A, B共に”default value”を出力していますが、
setPropertyでprop1の値を変更した直後では、A, Bの値が異なっていることが分かります。
setPropertyしたコンテキストは、getPropertyしないと正常に変更後の値が取り出せません。
その後、今度は代入方式でprop1の値を変更し、最後の出力は、
getProperty側では”override prop1″と出力、
直接値参照側では”override prop1 by assignment”と出力されています。
以上の様に、contextの値にアクセスする方法は2種類あるのですが、何れかに統一しておかないと、値を変更したのに参照したら値が変わっていない!!ということになりかねませんので注意が必要です。
globalMapとは?
Talendがジョブ実行する時に生成されている、ジョブ内のどこでも参照できるグローバルなハッシュマップです。
キーを与えると、値を取り出せるkey-valueのマップです。
確か、javajetのテンプレートに仕込まれていた…記憶が…あります。ここは曖昧です。違ってたらごめんなさい。
globalMapの使い方
値を格納する
[java]globalMap.put("mykey", "myvalue")[/java]のようにして、globalMapに値を登録できます。
第一引数はキーで、String型の値を渡します。
第二引数は値で、メソッドがObject型の引数を取るようになっているので、基本なんでも格納することができます。
値を取得する
[java]String str = (String)globalMap.get("meykey")[/java]のようにして、globalMapに登録しておいた値を取得できます。
第一引数はキーです。String型の値を渡します。
ここで、globalMap.getはObject型を返却してくるので、取得値をキャストしておく必要があります。
tSetGlobalVarコンポーネントを使用する
tSetGlobalVarというコンポーネントを使用することでも、globalMapに値をセットすることができます。
Variablesに、KeyとValueを定義することで1行ごとにglobalMapへ値を格納することができます。
1Rowにつき、複数のKey-Valueペアの値格納ができますので、多少便利です。
また、tSetGlobalVarを使用することで、「あ、ここでglobalMapに値を入れているんだな」ということを明示でき、他人が見ても多少ジョブが分かり易くなるメリットがあります。
globalMapをジョブで試してみる
実際にglobalMapをジョブで使ってみましょう。今回は下記のようなジョブを作ってみました。
tSetGlobalVarは無しバージョンです。
このジョブの概要としては、
とある入力ファイル(IDとITEM_CDを持つトランザクション)から、とあるITEM_CDを持つトランザクションのID一覧を表示するというものです。
「globalMapに値をセット」で、一覧表示したいIDをglobalMapに保存しておき、
「globalMapに格納」で、1行ごとのトランザクションID-ITEM_CDをglobalMapに保存、
「globalMapの値をゲット」で、最初に保存しておいた一覧表示したいIDを取り出し、また別に保存しておいたトランザクションから一致するIDのものを取得して表示する、みたいな動きをします。
「globalMapに値をセット」
折角なので、コードを見てみましょう。折角なんで。
一番初めのコンポーネントは、単一値のglobalMapセットです。
putメソッドにキー, 値を渡して使用します。
値の方は、メソッドがObject型を受け付けるので、なんでも渡してokです。
「csv入力(ITEM_CD)」
globalMapの話には関係ありませんが、こういう項目定義しています、というのを確認する為に載せました。
TRAN_NOとITEM_CDという項目を持つcsvを入力としています。
参考までに、使用した入力データはこんな感じです。
「globalMapに値を格納」
こちらは、tJavaRowで1行ごとに値をglobalMapに格納するパターンです。
単一値とは異なり、putする時のキー値のコントロールが必要です。
今回は、最後にITEM_CDを取得キーとしてトランザクションIDを引くので、格納キーはinput_row.ITEM_CDとし、格納値は、トランザクションIDのリストとしています。
(リストじゃないと一覧表示できないんで)
上記のように、プリミティブ型以外も格納できます。結構実践でも使います。
「globalMapの値をゲット」
最後に、結果確認用にglobalMapから値をgetしています。
このジョブでは、csvの中から、とあるITEM_CDを持つTRAN_NOを一覧表示します。
まずは最初に格納した出力したいITEM_CDをglobalMapからgetしています。
globalMapの返却値はObject型なので、Stringキャストします。
次に、tJavaRowで格納したITEM_CD-TRAN_NOのリストをglobalMapからgetしています。
キーはつい今しがた取得したcheck_targetで、取得値はArryaList<String>型なので、キャストします。
最後に、取得したリスト件数分、コンソール出力しています。
contextとglobalMapはどう使い分ければ良いの?
共通コンテキストの使い分けは問題無いかと思います。
複数のジョブで同一の値を使い分けたい場合に力を発揮します。
ローカルコンテキストとglobalMapは多少キャラが被っていますので、使い分けに迷うかと思います。
ローカルコンテキストの使いどころ
下記においては、ローカルコンテキストを使うのが良いと思います。
- 親ジョブ-子ジョブで値の受け渡しをしたい場合
- ジョブへの入力パラメータを公開したい場合
- 環境によって値を使い分けたい場合
- こんなグローバル変数があるよと明示したい場合
globalMapの使いどころ
下記においては、globalMapを使うのが良いと思います。
- Row接続などで複数の値をグローバル変数として保持したい場合
- tHashInput/Outputとかぶりますけど
- Hashとして使いたい場合
- とある値を渡すと、とある値に変換して渡して欲しい場合など
ex:品目コードを渡すと品目の単位を返してほしい
- とある値を渡すと、とある値に変換して渡して欲しい場合など
- 作業用にグローバル変数が必要で、contextを汚したくない場合
おわりに
今回は、Talendにおけるグローバル変数管理方式であるcontextとglobalMapについてまとめてみました。
途中からcontextに関する説明を追記していったので、ちょっと記事の構成が見にくかったかもしれません。すみません。
contextもglobalMapも、とても重要で便利な機能ですので、是非活用していきましょう。
(特にcontextにおいては、ジョブへのパラメータ渡しや、親/子ジョブへのパラメータ渡しにも使用しますので、大変重要です)
今回は以上です。