Talend入門 (8)　～Global Map～

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

##対象者
ETL / EAI技術者

##環境
|使用環境|バージョン|
|:----:|:------------------|
|OS|Windows10|
|Talend|7.1.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)

##今回の目的
Global Mapについて理解する。

##Global Mapとは
ジョブ内で扱うことのできるハッシュマップです。一時的なグローバル変数としても便利に利用できます。

##サンプルプログラム概要
バッチの処理開始時間と終了時間をファイル名で出力するバッチジョブを作成してみます。

## Global Mapを利用したジョブ

それではサンプルジョブを作成していきましょう。
リポジトリの[ジョブ]を右クリックし[ジョブの作成]を選択します。
[名前]に**globalmap**と入力し[Finish]ボタンをクリックします。
![GS000210.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/2895e721-c8b2-1e6a-3c7d-5490d080a47b.png)

### バッチのメイン処理を作成
[tRowGenerator]と[tFileOutputDelimited]を配置します。
![GS000211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/f7e50555-a19a-e91f-ef34-ef78ae1b8842.png)

#### [tRowGenerator]の設定
[tRowGenerator]のスキーマの編集で1カラムだけ準備します。
![GS000212.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/0a440513-02b2-c649-24b1-bae64d286bc5.png)

RowGeneratorエディターで関数を設定します。

| カラム              | 関数 |
|:-----------------|:------------------|
| newColumn    | TalendDataGenerator.getFirstName()  |

![GS000213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/e3f018b5-490d-ffbf-cfb2-50bf7c1003a8.png)

#### [tFileOutputDelimited]の設定

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名    | "C:/work/globalmap/tmp.csv"  |  |
| 追加    | チェックを入れておく  | スクショ取り忘れました。。 |
![GS000214.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/bcec45ba-28c3-7632-15bc-e3c134b36690.png)

#### テスト実行
二つのコンポーネントをロウでつなぎ実行確認しておきましょう。
![GS000216.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/ede3f7da-5030-a68b-dc9c-a3c8fad2b83c.png)

tmp.csvが作成されればＯＫです。
![GS000217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/0463af17-4b1f-82af-1419-74559352e26b.png)

### 開始終了時刻の取得
[tJava]を２つと[tSleep]を一つ配置します。
![GS000218.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/b3cee1d1-0a97-86af-1562-124ec2514294.png)

#### [tJava_1]の設定
開始時刻を取得しています

コード

```java
String start_datetime = TalendDate.getDate("CCYYMMDDhhmmss");

// プリントデバッグ
System.out.println(start_datetime);

// startというキーのグローバルマップに値を格納
globalMap.put("start", start_datetime);
```

ポイント
**globalMap.put(key, val)**でGlobal Mapにオブジェクトを格納することができます。

![GS000219.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/0872e0c2-00be-bcaa-5661-38fa5f6f780d.png)

#### [tSleep]の設定

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| 一時停止(秒)    | 3  | メイン処理が3秒かかったという状態にしている |
![GS000220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/8fa9eecd-9552-b36c-0ff2-e5e7c9fd7ce5.png)

#### [tJava_2]の設定
終了時刻の取得とファイル名を作成しています

コード

```java
String end_datetime = TalendDate.getDate("CCYYMMDDhhmmss");

// プリントデバッグ
System.out.println(end_datetime);

// startというキーのグローバルマップを取得
String start = (String)globalMap.get("start");

// outfileというキーのグローバルマップに値を格納
// CCYYMMDDhhmmss-CCYYMMDDhhmmss.csv というファイル名を準備する
globalMap.put("outfile", start + "-" + end_datetime + ".csv");
```

ポイント
**globalMap.get(key)**でGlobal Mapからキーで設定したオブジェクトを取得できます。
![GS000221.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/fc5446ed-dcc8-7a68-e688-31ad0e2df85a.png)

#### 処理フローの設定

| つなぐコンポーネント       | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| [tJava_1] と [tSleep_1]   | OnComponentOk  |  |
| [tSleep_1] と [tRowGenerator_1]   | OnComponentOk  |  |
| [tRowGenerator_1] と [tJava_2]   | OnSubjobOk  | ファイル出力まで終わってから処理する |
![GS000222.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/b126e187-93aa-7993-8c19-1fecbf7ba2b7.png)

#### テスト実行
エラーがなく開始および終了時刻が標準出力されることを確認しておきましょう。
![GS000224.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/dcd7de6f-71a4-f898-61df-c8f32330734b.png)

### 仕上げ（ファイルリネーム）
tmp.csvを[tJava_2]で準備したファイル名にリネームします。
[tFileCopy]を配置しパラメータを設定します。

#### [tFileCopy_1]の設定

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名    | "C:/work/globalmap/tmp.csv"  | [tFileOutputDelimited]で指定したもの |
| コピー先ディレクトリ    | "C:/work/globalmap"  |  |
| 名前の変更    | チェックを入れる  |  |
| 宛先ファイル名    | **(String)globalMap.get("outfile")**  | [tJava_2]でGlobal Mapに格納しておいた値を取得 |
| コピー元ファイルの削除    | チェックを入れる  |  |

| つなぐコンポーネント       | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| [tJava_2] と [tFileCopy_1]   | OnComponentOk  | ひとつしかコンポーネントがないのでOnSubjobOkでもよい |

![GS000225.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/5b74c17f-e113-d35c-4f0d-f79399946a64.png)

#### 実行
それでは実行してましょう。
ファイル名に開始と終了時刻を持ったファイルが作成できました。
![GS000228.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/aed0b998-d92e-4e6c-e834-2e36b460a7c0.png)

### tips（格納済みのGlobal Map）
実はあらかじめ利用できるGlobal Mapがあります。
Outlineに表示されている値はGlobal Mapに格納されているのです。
確認してみましょう。

#### [tJava_3]の設定
まずは本日3つ目の[tJava]を配置します。
コードの設定を開いたらOutlineにある[tFileCopy_1]の[デスティネーションファイルパス]をマウスでドラッグ＆ドロップします。
すると**((String)globalMap.get("tFileCopy_1_DESTINATION_FILEPATH"))**というようにGlobal Mapの取得コードをキャストまで含めて用意してくれます。
 
![GS000225b2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/78932951-b841-3092-083f-dc24ea20ad90.png)

#### ファイルパスを標準出力
コード設定とコンポーネントを接続し設定を完了させます。

```java
System.out.println( ((String)globalMap.get("tFileCopy_1_DESTINATION_FILEPATH")) );
```

| つなぐコンポーネント       | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| [tFileCopy_1] と [tJava_3]   | OnComponentOk  | ひとつしかコンポーネントがないのでOnSubjobOkでもよい |

![GS000225c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/42c0bdbd-04ac-556d-a528-cd1a048c3114.png)

#### 実行
ファイルパスが出力できました。
![GS000226.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/6a57dc75-ebc3-ce13-a60b-3428299f3057.png)

### Context変数との使い分け
**Context変数**と**Global Map**はどちらもグローバル変数として利用できますが、次ような使い分けが良いと思います。

- Context変数
    - コンフィグ値のように実行時に決まっている値
    - 実行時引数
- Global Map
    - 一時的な変数
    - 動的なリストオブジェクトなど使いまわす値

##まとめ
今回はGlobal Mapの使い方を確認しました。
Key - Value型のハッシュマップであることが分かってもらえたと思います。
あらたに利用したコンポーネントと用途をおさらいしておきます。

- tJava
    - Javaのコードをそのまま記載できる。(詳しくは第14回tJavaで。。)
- tSleep
    - ジョブをスリープさせる
- tFileCopy
    - 今回はリネーム(コピー&削除)で利用

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

##次回以降
次回は tHashInput/Output をやっていきます。