【MuleSoft】MCD資格の勉強メモ（記載中）

・現時点、MCDに限りですが、資格のトレーニングや試験問題が日本語化され、無料で受講・受験できます。※資格受験は、期間限定で無料の様です。無料バウチャー発行には一定条件があります。（随時変わるよう。）
・以下Webトレーニング受講と、Workshopの参加（＝毎月やっている？）が、受験において、大変効果的でした。
###Anypoint Platform Development: Fundamentals (開発: 基礎) (Mule 4)
https://training.mulesoft.com/course/development-fundamentals-mule4-japanese

その他、便利なリンク
https://quip.com/JBhRAIbXU9VO
https://qiita.com/nkitaarashi/items/08cb3499aa2091e5da72



以下、勉強用メモ。記載中。（※試験に特化してるわけでない。）

##1 - アプリケーションネットワークとAPI主導の接続性
・いままでPoint to pointで作ってましたが、拡張性がよろしくないので、Muleを使って疎結合でやりましょう。以下3階層で定義。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/c03ba70d-e5ec-3f38-89bf-4c87addcfbb4.png)
・C4Eを設立しましょう
　→センター・フォー・イネーブルメント
　※イネーブルメント：実施可能？使用可能？
　→C4Eは、アセットのコンシューム（どれだけIT資産・資源）が再利用されたかが評価となる。
　→役割：事業部門の開発者がコンシューム（呼び出し）できる、発見・再利用可能なアセットを生成し、管理する。
・アプリケーションネットワーク
　→セルフサービスによりボトムアップで出現
　→他の組織からもコンシューム（活用）できるように設計された再利用可能なIT資産・アセットを生成する。
・モダンAPI
　→再利用可能、扱いやすい・管理しやすい設計
　→API仕様を使ってAPIを設計し、迅速にフィードバックを得る、という特徴

・SOAP Webサービス
　→従来のWebサービス
　→XML形式でWSDLファイルで定義
・REST Webサービス
　→モダン、より扱いやすい、軽量
　→JSON形式
　→通信プロトコルはHTTP
　　→HTTPプロトコルは以下5つの操作ができる。
　　　POST→登録
　　　GET→取得
　　　DELETE→削除
　　　PUT→更新
　　　PATCH→部分的に更新
・ProgrammableWebには、19,000以上のAPIがある。

・RESTful API
→保護されていない unsecure API
→保護されている secure API
　　→ログイン情報やトークンが必要な可能性あり。
　　→OAuth, SAML, JWTなどでAPIを保護できる。

・API開発サイクル
①まず、APIの設計をしましょう（部品作成）
　　⇒Design CenterのFlow Designerを利用
②その後API仕様をフローに組み込みましょう、テストしましょう。（実装・テスト）
　　⇒AnypointoStudio（開発）、Restクライアント（テスト）
③運用しましょう。（監視したり、トラブル対応したり。
　　⇒API Manager
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/55699775-68a7-3e15-9e52-252daeebf693.png)



##2 - Anypoint Platformの概要
・APIのライフサイクルに必要な機能は全部Anypoint上にあります。
【DesignCenter】APIを作る（迅速な開発）
https://docs.mulesoft.com/jp/design-center/
【Exchange】APIをセルフサービスで検索・公開（コラボレーション）
　　　⇒REST APIがExchangeに追加されると、自動的に【API Portal】が生成されます。（APIportal⇒自動生成されたドキュメント、モッキングサービスなど）
　　　⇒API portalは、内部（社内のみ）と外部（全体公開）の共有設定が可能。
【ManagementCenter】セキュリティ、拡張性、パフォーマンス管理（表示・制御）
【Mule】軽量で力強いランタイム・実行環境、アプリの実行するサーバー（Muleランタイムをホスト）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/25dfb30e-a241-3eea-ff96-5586d7afe241.png)

・設計/シミュレーション/フィードバック/検証を終えると、
　API仕様書（RAML仕様書）が出来上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/9d457dfe-b9f6-c9d7-f1d8-ec5db8e354c9.png)

・API仕様書をインポートし、AnypointStudioで開発を行います。
・MUnitで、テストもできます。
　⇒これでWebサービス/APIが構築されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/d08e0609-aeee-997c-f4b7-075b014962dc.png)

・API管理のフェーズでは、APIManagerを使います。
・RuntimeManagerでデプロイや監視（パフォーマンスのモニタリング）を行います。
・API　Analyticsではどのように使われているか分析。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/dcb06d8a-a1b0-b25f-b673-0134e0da27f1.png)

・コネクタ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/f416fa48-f30b-66ae-f7d0-6757d573659e.png)

・1度のAPIの設計で、様々な環境にデプロイできる。
（１）お客さんがHostする環境⇒オンプレ、PrivateCloud（AWSなど）
（２）CloudHub⇒Muleが完全に管理するIPaaS

・Muleアプリ
　⇒XMLの集合体
　⇒Muleのイベントプロセッサが、Flowで結合されている。
　⇒Flowの構成は、イベントの開始条件、処理、エラーハンドリング

・Muleイベントデータの構成
　⇒Muleアプリがトリガされた時に以下イベント発生
　　※Attribute（属性）は、parameterやヘッダーを保持
　　※Payload（本文）は、実際に処理されるデータ
　　※Variables（変数）は、プロセッサーを使って定義
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/8ef36dc8-45ba-0151-5aac-fc7175705274.png)

以下、Attribute
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/9d4b45b9-efcd-6e9d-b814-ca62a23da2f1.png)

★「WT2-3 デモ - 任意(12:31)」が分かりやすいです。
⇒HTTP Listenerで受信→Flight情報を取得→Transformコンポーネントでマッピング定義やDataWeaveでの変換を行う流れの中で、AttributeやPayLoadの値がどうなるか説明
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/5884629b-f207-b080-ff07-0b0b0f8dfc93.png)

・DataWeave⇒Excelの関数みたいなもの。式言語。
・DataWeaveは #[]で記述し、設定は${}で記述する。
・Transformコンポーネント
　⇒データのInputとOutputのマッピングを管理
・Mule4：「4」は、バージョンを指しているそうです。

##3 - APIの設計
・APIを作るには以下手法があります。
　→手動でガリガリコーディング
　→RAML　等。
・RAMLとは？
　→RESTful APIをシンプルに記述するための言語
　→オープンソース
　→RAMLを使うと、モックされたエンドポイントやドキュメントなど自動生成可能。
　→YAMLやJSONをベース
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/c3a4ed01-7be2-f8a8-d596-83d9a5afd7f3.png)

・サンプルデータは以下２つのファセットを利用
exampleは単数、examplesは複数の時に利用

⇒記載中:sunny::sunny::sunny:

##4 - APIの作成
・AnypointStudioを利用し、開発を行う。
・以下フローの構造だが、イベントプロセッサは1つ以上必須。それ以外はなくても成立。
・イベントソース（リスナー）には、受信の定義を記載。ここを消すと、どこから呼び出す記述を記載しないとそのフローは呼ばれない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/b35262ad-832e-d4b7-679d-0401b09a7bd2.png)

・データ接続
→Databaseコネクタを利用
　これでほぼすべてのJDBCリレーショナルデータベースに接続可能。
→返り値は、Javaの配列。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/4a7b501f-690e-6fa1-7909-b9fa0692ec1c.png)

・TransformMessageコンポーネント
　DataWeaveを使い、データを変換するコンポーネント
※表記ゆれで混乱しますが、「WT2-3 デモ - 任意(12:31)」で出てきたTransformコンポーネントと同じです。

・SetPayload
　→PayLoadに値をセット。

・HTTPリスナーから手動で作るのではなく、
　ExchangeからAPIkitを取得し、RESTfulインターフェースを作ることも可能。
　→api:routerとコンソールが自動生成される。

・FlowReferenceからフローを呼ぶことができる。
→親フローから子フローにイベントが渡される。
→フロー名を記載することにより、フローを呼べる（例：getFlightsなど）

・AnypointStudioからExchangeへAPIの仕様に対して更新をかけられる。
（逆にExchangeからAPIを落とすことも可能。）⇒API Sync
・Gitのようなインターフェースの利用が可能で、PushやPull、Mergeなど可能。競合したときにはコンフリクトエラーが出る。


##5 - APIのデプロイと管理
・APIをデプロイするにあたり、以下3環境がある。
　→ここの説明がよくわらない。:sunny::sunny::sunny:
　→「2 - Anypoint Platformの概要」でもCloudHubの話が出てるが、関連性に関しては言及無しなので何がどれに対応するか不明。前に出てきた環境説明のどことMappingするか不明。
（１）CloudHub→Muleが管理する環境、IPaaS。オートスケーリングなども提供。デプロイ先のデータセンターを選べる。
（２）Muleランタイム→顧客ホストするサーバ上での稼働。サーバは顧客のものだが、管理はMule上で可能。1サーバに複数アプリ可能。
（３）AnypointラインタイムFabric→？

⇒記載中


##6 - （未作成）Muleイベントに対するアクセスと変更

##7 - （未作成）Muleアプリケーションの構造化

##8 - （未作成）Webサービスのこんしゅーむ

##9 - （未作成）イベントフローの制御

##10 - エラー処理
↓こちらにもフローの例など掲載
https://qiita.com/nori83/items/4dc6c9546bdb09502c4e

・アプリ、フロー、プロセスの3段階のレベルでのエラーが起きる
　　※アプリのエラー⇒フロー外のGlobalError_Handler、フローにもプロセッサーにもエラーハンドラが設定されていない時のみ実行される。
・エラーメッセージは、Muleのデフォルトのものと、カスタムで定義したものがある。
https://docs.mulesoft.com/jp/mule-runtime/4.3/on-error-scope-concept
・Errorがスローされると、Errorオブジェクトが出来る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/46bf4348-613d-be79-571d-a39c7bce8188.png)

・重要なのは以下。
 error.description → 文字列
 error.errortype
　　 → オブジェクト（例: VALIDATION:INVALID_BOOLEAN, HTTP:UNAUTHORIZEDなど）
　　 → 親をもっており、階層構造となっている。最上位はANY

・HTTPリスナから返される情報
★デフォルトの成功レスポンス
　- payload 　※エラーオブジェクトが出来ない。
　- ステータスコード：200

★デフォルトのエラーレスポンス
　- error.description　※エラーオブジェクトが出来る。
　- ステータスコード：500

※値は上書き可能。

・Errorスコープは2種類ある。複数設定できる。また、Errorスコープに該当条件を指定することも可能。（Typeで対象エラーを選択するか、WhereにBooleanのDataWeave式で該当条件を記載。error.errortype.namespace == 'HTTP' ）
どこにも該当しないとMuleのデフォルトのエラーハンドラに渡される。
（１）On Error Propagate
（２）On Error Continue
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/3e678e6c-d427-9f41-3a8b-d7bcc0f012bf.png)

以下、いずれも、エラースコープ処理内の全てのプロセッサが実行される。
（１）On Error Propagate
　→Errorオブジェクトが生成される。
　→エラーが起きると、エラーをスローした後、残りのフローは実行されない。
　→HTTPリスナは、エラーを返す。
（２）On Error Continue（成功したかのように見せかける）
　→エラーが起きると、エラーをスローしない。
　→HTTPリスナは、成功を返す。

※デフォルトでは、「On Error Propagate」で処理が行われるため、エラーが返ってきて、後続処理が止まる。


親フローからChildFlowを呼んだ時にEでエラーが発生した場合。
ChildFlowではOnErrorPropagateなのでエラーを親フローに返すが、親フロー側がOnErrorContinue(=エラー発生時に処理を止めてエラーを出さないもの)なので、成功としてレスポンスが返される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/0a0a9805-f8a9-bc77-807d-a0a6f94d9ab9.png)

・サブフローにはイベントの取得元やエラースコープ定義がない。
（前のフローの説明でchildFlowにErrorスコープを定義している図があったが、ChildFlowはサブフローではなく、個別フローということか・・？:sunny:謎）
https://docs.mulesoft.com/jp/mule-runtime/4.3/about-flows



＜模擬試験に関する参考サイト＞
https://help.mulesoft.com/s/question/0D52T00004mXUBOSA4/explanation-to-question-of-selfassesment-quiz-module-10-question-2

⇒記載中



##11 - DataWrave変換の記述
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/81d91fa7-bade-c25c-fe73-660b0cf61527.png)


・生成されたデータは、以下3つの異なる型で構成可能。
　①Object　→　キーと値のペアが、集合している状態
　②Array　→　カンマ区切り値のシーケンス
　③Simple Literals（リテラル）→？？？:sunny::sunny::sunny:
https://wa3.i-3-i.info/word15346.html

・DataWeave変換式
JSONで入ってきたのを、XMLに変換の場合
★入力(JSON)
{ "firstname":"Suzuki",
  "lastname":"Hanako" }

★変換(JSON→XML)
%dw 2.0
output application/xml　　←どう出力するか表現。ここではXML形式で吐きたい。
---                      ←この線で（↑）Headerと（↓）Bodyを区切る。
{ 
 user:{
   fname:payload.firstname,　　　←これをDataWeave式っていう。
   lname:payload.lastname
  }
}

★出力(XML)
<?xml version="1.0" ​encoding="UTF-8"?>
 < user>
   < fname>Suzuki< /fname>
   < lname>Hanako< /lname>
 < /user>

・出力形式（MIME）は色々指定可能。
application/json, application/xml, application/java, text/plain,
application/dw, application/csv

・DataWeaveのエラー
application/dwを使って変換し、エラーを検知する。
以下2タイプある。
　（１）スクリプトエラー　　⇒構文ミス
　（２）フォーマットエラー　　⇒データ変換時の問題。例えば、XML形式に変換したいのに、元のデータがそれを満たしてない。
application/dwでエラーが出たら（１）、でなければ（２）となる。
・コメントの書き方
　//  コメント

 /**
    　複数行コメント  
  */
 
11.基本的なデータ構造の変換
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/01c88ebe-527a-2f44-5439-960498229892.png)

・オブジェクト
user:{
 fname:payload.firestname,
 lname:payload.lastname,
 num:1
}

・配列
{
  {fname: payload.firstname, num:1},
  {lname: payload.lastname, num:2}
} 

・属性（attribute）を設定するには、 @(attName: attValue)を使用
★入力(JSON)
{ "firstname":"Suzuki",
  "lastname":"Hanako" }

★変換(JSON→XML)
%dw 2.0
output application/xml　
user:{
　user @(fname:payload.firstname,  ←カンマで区切って属性（Attribute）を2つ指定
     lname:payload.lastname):{
     lname:payload.lastname
   }
}

★出力
<?xml version="1.0" ​encoding="UTF-8"?>
 < user fname="Suzuki" lname="Hanako">
   < lname>Hanako</ lname>
 < /user>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/394b1ecc-b64d-5318-4be3-2a59a9afe3b9.png)
ポイント：XMLからJSONへの変換の際には、要素（ < lastname>Mule< /lastname>）だけ変換され、属性(Attribute,ここだと<userの中の属性)は変換されない。
ポイント：属性をとってきたい場合、@を付ける。

・変換関数（map関数 → 配列を返す ）
★$$→配列の何番目なのか示す。$(index)でも同じ結果
★map→この形式に変換したい！というとき。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/9ab23386-9351-1feb-dc65-6901520e6f1e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/09b7fa78-d1cf-0283-232b-ac1d3302774a.png)

＜メモ＞
・payload[0].price → 199
・payload.price ​→ [199,450]
・[payload.price,payload.test] → [[199, 450],[0, 24]]
・変数 aaaに値を設定したが、その値を呼び出したいとき。
　　→ #[var.aaa]


・XMLは配列をサポートしていない。
　なので、map操作を{(・・・)}で囲むことにより、key-valueペアに変換できる。
　　※｛｝はオブジェクト定義、() は配列の各要素をkey-valueペアとして変換
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/34710565-a744-d0a4-f0f6-cf858499a70c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/8cc935e3-4e18-1266-59d9-f415ee9fcb0d.png)

・ヘッダーに、「var」を使い、変数の定義・使用が可能。
以下は、varディレクティブに対して、定数、もしくはラムダ式を割り当てしている場合。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/336378e3-7750-af72-c875-cfb3b5336406.png)

関数としても書ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/e1e670a3-2360-273e-c5bd-2623078ae6a5.png)

・do → ローカル変数の初期化
:sunny::sunny::sunny:ここよくわからなかった。（※11-4の動画）

・as → 型変換  （例: as Number、as Boolean　とか）
・format →　そのまま。日付などの書式・フォーマット変換
　　someDate as DataTime { format: "yyyyMMddHHmm"}

・カスタムのデータ型を作ることも可能
typeを使う。
★変換
%dw 2.0
output application/json　←JSON形式で吐く
type Hensuumei = DataTime {format: "yyyyMMddHHmm"}　←Hensuumeiの定義
---　←上がヘッダー、下がボディ
someDate : payload.departureDate as Hennsuumei　←someDateに、入力値のdeparturedDateの値を、Hensuumeiの形式で変換


・複数関数を組み合わせる場合、左から実行されます。
  flights orderBy $.price filter ($.availableSeats > 30)
　　⇒ソートし、そのあとフィルタする

・コアな関数は上記の通り、何もせずとも普通に使えます。（containとか、isEmptyとか、mapとか）
　それ以外は、関数もしくはモジュールを、Importして使う必要があります。
%dw 2.0
output application/xml
inport dw::core::Strings　←こんな感じでInport
---

・DataWeaveからフローをコール
　→lookupを使います。
　{a: lookup("フロー名"), {b:"Hello"}) }　　← Helloは、フローに渡すPayload
   ※制約：サブフローはCallできない。

・DataWeaveのコードは、DWLファイルか、関数のモジュールにインライン記述可能。
・typeOf関数は、型を返却する。
　例） typeOf({a:1})　→　Object
　例） typeOf([1,2])　→　Array

＜模擬試験に関する参考サイト＞
・groupByをしてしまうと、配列になってしまうため、orderByできず、
なので、GroupByは最後になります。
https://help.mulesoft.com/s/question/0D52T000054n8hJSAQ/module-11-quiz-question-1-please-explain-how-to-arrive-at-the-dataweave-expression

##12 - フローのトリガー
・ファイルやフォルダ操作のコネクタは以下4種
　File（ローカルのファイル）、FTP、FTPS、SFTP
・以下をサポート
　ファイルの一致、ロック、上書き、内容追加、新規ファイル生成など
・＜前準備＞Fileモジュールの追加⇒グローバル要素として作業ディレクトリを追加する。
(1) CloudHub　⇒コネクタはtmpフォルダでしか利用不可。
(2) Customer-Hosted（顧客がホスト）　⇒Muleを実行するアカウントが、指定ディレクトリへの読み書き権限を持っている必要あり。

・Schedulerコンポーネント
　→特定の日時や頻度でフローを実行するためのコンポーネント

・On New or Updated Fileリスナ
　ディレクトリに定期的にポーリングをし、新規・更新されたファイルを探索。見つかったファイルに対して1つメッセージ生成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/0a0aa629-85cb-74b1-7968-1e22f368e35d.png)
　ファイルが新規か否かの判定は、ファイル名の変更や作成日時を持つなど。

・ウォーターマーク
　⇒データがどのような状態にあったか記録（同期時に再取得する際に比較されるタイムスタンプ）
　⇒データストア間でデータを同期させるときに使用
　①自動ウォーターマーク　⇒　作成日など（CREATED_TIMESTAMP, MODIFIED_TIMESTAMP）
　②手動ウォーターマーク　⇒　複雑な場合に個別定義

・DBコネクタのOn Table Rowオペレーションを使えば、DBにレコード追加のタイミングでフローをTrigger可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/244d12e9-43e6-fe62-5f24-09d3d5d31c47.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/f6122a00-5ffd-ebde-4c26-b8699031aa42.png)
　→ SELECT * FROM tabke WHERE TIMESTAMP >: watermark

・重複レコードの防止
　→IDカラムを指定して、重複してないか確認

・＜自動ウォーターマーク＞
ObjectStoreコンポーネントを利用し、シンプルなキー/値のペアを保存する。
　→ウォーターマークなどの同期情報、アクセストークンなどの一時的な情報、ユーザ情報など
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/9924d4ea-1681-efd4-0192-a5ea9043ff3f.png)

・JMS(java Messaging Service)
　→メッセージ交換の通信において広く利用されているAPI
　・2つのメッセージングモデルをサポート
　　　①キュー（1対1）
　　　　　⇒キューにメッセージが送信されると、1つ1人の受信者がキューからメッセージを出す。
　　　　　⇒受信者がキューをリスンしてる必要なし
　　　②トピック（パブサブ、1対N）
　　　　　⇒送信者はTopicへPush、トピックから購読者へメッセージが飛ぶ
　　　　　⇒受信者がTopicをリスンしてないとダメ。

・システム間でのメッセージはJMSコンポーネント
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/34d33b2b-bcf2-277e-ea4f-da4e98c56c31.png)

＜模擬試験に関する参考サイト＞
payloadを変更したくない時に、「targetValue」を利用します。
今回、ChiledFlowの「targetValue」属性にpayloadを指定してます。
なので、今回、Muleの元のPayloadの値は、変わってないわけです。（つまりJSONのまま。）
https://help.mulesoft.com/s/question/0D52T00004mXSCjSAO/mulesoftu-development-fundamentals-mule4-assessment-quiz-module-12-question-1-answer
https://docs.mulesoft.com/mule-runtime/4.1/target-variables
ちなみにここの問題、動画の中で解説されてなくない・・・？と議論になってます、が、デモの中で触れていたようです。↓
https://help.mulesoft.com/s/question/0D52T00004uuoyiSAA/is-it-just-me-or-are-the-endofmodule-quiz-questions-sometimes-unrelated-to-not-covered-in-the-corresponding-module




##13 - レコードの処理
・For each
　→配列のみ入力可能。それ以外が入ってきたら、エラーはでないが０となる。
　→順次処理（シングルスレッド）
　→イベントのコレクション（配列）を分割し、個々のデータを処理する。
　　　★ポイント：”コレクション”がインプットであること。
　→なんか起きたらFor eachは処理を停止し、エラーへ進む。　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/f8a692ba-39ad-3e10-dab7-dc19985e0fcb.png)
・Parallel for eachの利用も可能。
　→複数のスレッドで並列処理をする。
　→分割したイベントの1つでエラーが発生しても、そのほかの正常なイベントは影響なくすすむ。

・Batch Job（※ EnterpriseEditionのみ利用可能。 ）
　→配列のみ入力可能。それ以外が入ってきたら、エラーはでないが０となる。　→一括処理（マルチスレッド）
　→大きなメッセージをレコードのブロックに分割し、非同期で処理。
　→処理した結果を他システムやキューに渡すことも可能。
　→大量データ、ほぼリアルタイム、ETLとしての機能
　　例）クラウド間の連絡先情報の連携、CSVをHadoopにアップロード、
　　　　API実行からレガシーシステムに送信される大量データの処理など
　・バッチサイズ1　→ [1] [2] [3]
　・バッチサイズ2　→ [1,2] [3]
　・バッチサイズ3　→ [1,2,3]

バッチジョブは、順々に処理されるバッチステップを含む。（必ず1以上）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/e822a6d0-80d8-772e-8f3e-c4a205e437d6.png)

バッチジョブの3つのフェーズ
①Load and Dispatch
　・Payloadの読み込み
　・コレクションを個別のレコードに分割し、キューに入れる。
　　　→パフォーマンス考慮し、デフォルト100レコードずつの処理になっている。（変更可能）
　　　→スレッドプールのサイズは、Muleランタイムで自動決定。（変更可能？不明:sunny:）
②Process
　・バッチステップの中で、非同期で処理を実行する。
　　→キューの各レコードが、バッチステップに送られる。
　　レコードは、処理されるとキューに戻され、次のStepの処理を待つ。
　　レコードは、どのStepまで処理されたか値を持っている。
　　非同期なので、前のレコードの順番待たずに処理を進むことがある。
　　　→すべてのレコードが全バッチStepを処理するまで続く。
③On Complete
　・処理結果のレポートを作る。
　　→バッチ処理が行われる前の変数を含んだ元々のイベントを返す。

Batch Jobの前に定義した変数は、後続のすべてのバッチStepで利用可能。
Stepの中でも変数変えたり、変数追加することも可能。
（★ただし、Batch Job外では利用できない。何を入れてもnullで吐かれる。）
　→バッチスコープの各レコードで”のみ”利用可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/0722b207-dc41-276f-5e36-dc588a1edde5.png)

・バッチ処理のエラー時の対応は以下3つの設定が可能。
　以下該当すると、バッチ処理を止め、OnCompleteに進む。
　（１）１つでもエラー発生(N>0)　★デフォルト設定
　　　→１つでもエラーが発生したら全部処理止めてOnCompleteへ。
　（２）N件以上（N>1）
　　　→特定件数以上発生したら処理を止める。
　（３）止めない
　　　→何件エラーが発生しても処理を止めない。
　　　　OnComplete側で失敗したレコードの処理をどうするか定義必要。

以下、CSVファイルを読み込み、Java形式へ変換。
まずはCSVのサイズをセットする、SetVariableをBatch Job外に定義。
そのあと1つ目のBatch Stepの中にpayload.NameのSetValiableを定義。
各Loggerの値を確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/9d4d309f-17ad-7da6-b214-b44d8fbbc2d4.png)

・Transform Messageコンポーネントの変換前
まだCSVの状況（カンマ区切り）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/72b57e1c-3527-35e4-7368-9f743c87fa39.png)
・Payloadにコレクションごとのサイズが明記
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/de18f81f-a007-e3ad-75a0-17f3e345a5a6.png)
・バッチ処理を行うCSVの行数が３つ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/9d30db57-2676-6d37-e42f-77cd1e0c6046.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/e49b89ea-a775-8c86-b0a6-8e726de4194d.png)
・1個目のLoggar、Cnameに顧客の名前が入ってる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/f25d0376-6974-92be-6ffa-3f26e5ce273d.png)

・バッチStepごとにログが吐かれる。（DogParkは2個目のレコード）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/62ba2ece-30e8-1bd8-44f7-e63252039900.png)

・OnCompleteでは、SuceessとErrorのサマリ結果がでる。

＝＝②Processの深堀↓＝＝

・バッチStepには、処理するレコードを絞り込むための以下2方式がある。クエリに以下属性がある。
（１）Accept Expression
　　　→関数でエラー定義できる。
（２）Accept Policy
　　　→先行のレコードにエラーが起きたらSkipするなど
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/5355775f-52cc-40ad-5a85-0dbe9ef36b41.png)

・Batch Aggregatorを使い、一括処理が可能。
　→1回1回APIコールするのではなく、100件ごとに、一括でアップロード処理をするなど。

＜Batch Jobを使い、DatabaseのレコードとSFDCとの連携を実施＞
（１）まず、SFDCにレコードが存在しているか確認
（２）存在するならフラグを立てる。
（３）Batch Aggregatorでフラグが立っていないレコードを集約し、SFDCへInsert

存在するレコードはexist=trueで表現
（Batch Job開始前に定義し、処理が進む中で随時値が変わる。クエリのAccept Expression属性に、このexistフラグがFalseかの指定も可能。（）重複レコードを弾く意図。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/679497e1-52ff-8758-7f88-7a4c20c651df.png)

・デバッグは、セーブポイントついているコンポーネントの、処理の「前」でまずは止まる。

＜模擬試験に関する参考URL＞
・Q1
ForEachはコレクション（配列）を分割し、順次処理します。
問題文には、コレクションでないと書いており、Inputの形式があってない。ので0。もしコレクションだったら、2ファイルがOutput（3件データいるが、バッチサイズ2のため。）
https://help.mulesoft.com/s/question/0D52T000052JPBSSA4/is-answer-of-question-1-of-module-13-quiz-correct

・Q2
一見、[11,12,13]が回答な気もしますが、BatchJobは1個1個分割して処理されるので、その結果11→12→13の順にログが吐かれ、最後のログは13となります。
https://help.mulesoft.com/s/question/0D52T00004mXSK3SAO/module-13-quiz-question-2-please-kindly-explain-why-this-is-incorrect

・Q3とQ4:
ポイントは、変数がバッチStepの中で定義されているという点です。
バッチStep内で定義された変数は、バッチStep内の固有になります。
なので、CompleteフェーズやBatchJob外で、元の変数に戻ります。
バッチStep内で作成された変数も固有なので、バッチStep外で利用できません。
　・counter→BatchStep外で1を定義してたため、1で出力（counter to 1）フローのどこからでも呼び出して使えます。
　・stepVar→BatchStep内での変数定義なのでBatchStep外で使えない、つまりnull
https://help.mulesoft.com/s/question/0D52T00004sPn0u/quiz-13-que-3-please-explain-the-logic-for-d-as-answer

・Q6:
AcceptExpressionで、3で割った時に余りが0でないものが通過するので、1と3が該当。そしてAggregateで、バッチサイズが2であることから、2件ずつ処理するので出力は[.333,1]
https://help.mulesoft.com/s/question/0D52T00004mXSK4SAO/module-13-quiz-question-6-please-kindly-explain-why-option-quotaquot-is-the-correct-answer