Talend入門 (12)　 ～子ジョブ～

##全体の目的
Talendの超簡単なサンプルジョブを作成して，ETLジョブ開発に必要なスキルを習得することが目的です。

##対象者
ETL / EAI技術者

##環境
|使用環境|バージョン|
|:----:|:------------------|
|OS|Windows10|
|Talend|7.3.1|	

##サンプル一覧
以下の順番で習得していきます

|#|内容|
|:----:|:------------------|
|1|[はじめてのTalend](https://qiita.com/airkoda/items/a837d3c5d851d98d2612)|
|2|[ファイルI/O](https://qiita.com/airkoda/items/1cd12c05c6136add7178)|
|3|[データベースI/O](https://qiita.com/airkoda/items/bc807c920c3adebad837)|
|4|[tMap](https://qiita.com/airkoda/items/fa4a9c022b5d688698e0)|
|5|[イテレータ](https://qiita.com/airkoda/items/404d2d65eff535b2126c)|
|6|[メタデータ](https://qiita.com/airkoda/items/4b42cf2a86f34abb6c87)|
|7|[Context変数](https://qiita.com/airkoda/items/42d294fca40b81aa20fb)|
|8|[Global Map](https://qiita.com/airkoda/items/1aba0d36905c755deeae)|
|9|[tHashInput/tHashOutput](https://qiita.com/airkoda/items/d9347865190f0f3ab180)|
|10|[エラーハンドリング](https://qiita.com/airkoda/items/85e7c49a9bf6a21db6d5)|
|11|[ロギング](https://qiita.com/y-fujioka-yoshiharu/items/e0280f34cff2e3d00bda)|
|**12**|**[子ジョブ（ジョブのネスト）（今回）](https://qiita.com/y-fujioka-yoshiharu/items/04ea4bd74ded382cf03c)**|
|13-1|[設定ファイル読み込みオリジナル版](https://qiita.com/airaotaku/items/92f114795108f25e6d0f)|
|13-2|[設定ファイル読み込みコンポ版](https://qiita.com/airyama/items/83c2bf9b2d51a79c3714)|
|14|[tJava](https://qiita.com/airkoda/items/4d81d76c36b6fcbd4d89)|

[サンプルコード（Talendプロジェクトデータ）](https://github.com/kd2air/qiita)

##今回の目的
別々に作成したジョブにコンテキストの値や実行結果を渡す方法を理解する。

##子ジョブと親ジョブについて
Talendでは[tRunJob]コンポーネントを用いてジョブを実行することができます。このとき[tRunJob]コンポーネントを用いてジョブを呼び出した側を親ジョブ、呼び出された側を子ジョブといいます。
また、プログラミング用語としてif（ 条件A ）{ ... if（ 条件B ）{ ... } ... } といったように、条件分岐やループの内部に、別の条件分岐やループなどが含まれている状態をネストまたは入れ子と呼びます。今回作成するジョブからジョブを呼び出す形もネストといえるでしょう。
参照：[IT用語辞典 e-words](https://e-words.jp/w/%E3%83%8D%E3%82%B9%E3%83%88.html)

##サンプルプログラム概要
1. 子ジョブと親ジョブの二つのジョブを作成
2. 親ジョブから子ジョブに値を渡す
3. 親ジョブか渡された値を用いて子ジョブを実行する
4. 子ジョブの実行結果を親ジョブに渡す
5. 子ジョブから渡された値を用いて親ジョブの処理を実行する

###子ジョブの作成
リポジトリの[ジョブ]を右クリックし[ジョブの作成]を選択します。
[名前]に**child**と入力し[Finish]ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/ddc9e1b0-5448-df4b-1c09-58014a4cabe4.png)
[Contexts(context)]タブを開き[+]ボタンを１回クリックします。
そして、以下ようにContext変数を定義します。

| Name      | Type      | value |
|:----------|:----------|:------|
| num_chiled|int integer|0      |
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/4e99b650-a07a-dc28-8e79-25d63fa353ca.png)
[tJava]を配置します。
[tJava]のコードを以下のように記載します。

```java:
System.out.println("子ジョブでの初期値 : "+context.num_child);
context.num_child+=10;
System.out.println("子ジョブでの値を加算後 : "+context.num_child);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/9b8ae431-034e-73a3-2ab5-b9351689b28f.png)
実行してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/e889acf6-f9ea-4243-b210-9e3f3a0858f2.png)
初期値に１０が加算されていることが分かります。

###親ジョブの作成
リポジトリの[ジョブ]を右クリックし[ジョブの作成]を選択します。
[名前]に**parent**と入力し[Finish]ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/d3ef0017-693f-cb32-09b8-c56a3af4ab4c.png)
リポジトリの[chiled]をドラッグ＆ドロップします。
![d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/470d50be-7172-80b7-e88e-86c9f69a7797.png)
[chiled]の[コンポーネント]タグを開いて[コンテキストパラメーター]の[+]ボタンを１回クリックします。
値は以下のように設定します。

|パラメータ| 値 |
|:-        |:- |
|num_chiled| 2 |
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/e1b4854f-da1c-3917-658b-c890967ccb0c.png)
実行してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/af13ce2e-dbc9-7001-24d8-bf072d73304c.png)
子ジョブのnum_chiledに**２**が渡されて子ジョブが実行されていることが分かります。
このままだと子ジョブの実行結果を親ジョブで使用できません。以降で子ジョブから親ジョブに値を渡す方法を説明します。

###子ジョブの実行結果を親ジョブに渡す
####子ジョブ
ジョブ[child]を開いて[tFixedFlowInput]、[tBufferOutput]を配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/ca5b871b-c4a0-6c83-a6bb-fa818b89cf61.png)
[tJava_1]と[tFixedFlowInput_1]をOnSubjobOk、[tFixedFlowInput_1]と[tBufferOutput_1]をロウでつなぎます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/2f77e736-034f-4597-d4d5-3d6a26d7ae46.png)
[tFixedFlowInput_1]のスキーマ編集画面で+を１回クリックし１カラム定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/844198c6-040f-759d-304e-fdae758eb87c.png)
[値]にoutChildが追加されるのでoutChildの値をcontext.num_childにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/b5ba2abb-c1fa-95aa-e876-7e69830afe50.png)
[tBufferOutput_1]の同期カラムをクリックします。

####親ジョブ
ジョブ[parent]を開いて[tJavaRow]を配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/3b7aacb3-1267-aa50-fb4a-b3e990a61cc6.png)
コンポーネント[child]と[tJavaRow_1]をロウでつなぎます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/4428704b-99bf-302d-8ee4-4151fb3e7e9d.png)
コンポーネント[child]の[子ジョブのスキーマのコピー]をクリックします。
![d2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/a16cd453-6692-e371-563a-d009b8d7481d.png)
スキーマの編集画面を開くとoutChildが追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/bfcbc2f1-6b4b-3ec2-827f-9762f8318088.png)
[tJavaRow_1]の[同期カラム]をクリックして、以下の文を[コード]に記述します。

```java:
System.out.println("子ジョブから親ジョブに値を渡したときの結果:"+row1.outChild);
row1.outChild += 100;
System.out.println("子ジョブから親ジョブに値を渡したあと100を加算した結果:"+row1.outChild);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/6f0070b5-8d5c-5369-e3b9-1d49a66168bb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/503007e8-cb19-690f-e68d-4bdf14db5ad3.png)
実行してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252625/97015d15-1eed-127d-335a-7fea9b1fe7f3.png)
以下の４点が動作していることが確認できると思います。

1. 親ジョブから子ジョブに値を渡す
2. 親ジョブから渡された値を用いて子ジョブを実行する
3. 子ジョブの実行結果を親ジョブに渡す
4. 子ジョブから渡された値を用いて親ジョブの処理を実行する


##まとめ
今回は子ジョブについて学んできました。
子ジョブを使うことで別々に作成したジョブに値を渡したり、受け取ることができました。
あらたに利用したコンポーネントと用途をおさらいしておきます。

- tRunJob
    - コンポーネント[child]のことである。別のジョブを使いたいときに使用する。このとき、[tRunJob]を用いてジョブを呼び出すほうを親ジョブ、呼び出されるジョブを子ジョブという。
- tBufferOutput
    - 子ジョブから親ジョブに値を返却するときに使用できる。

毎度のことですが、ほんのさわりの部分だけを解説していますのでぜひここから深掘りしてみてください。

##次回以降
次回は設定ファイル読み込みについてやっていきます。