
ラボ 2: Product APIのMySQLデータベース接続
ステップ 1: プロジェクトにデータベース・コネクタを追加
プロジェクトにデータベースコネクタを追加する必要があります。 そのためには、以下の手順に従ってください。
-
Mule パレットに移動します。
-
Add Modules をクリックします。
-
Database を選択します。
-
水色のパネルにアイコンをドラッグ&ドロップします。
パレットに戻ると、データベース・コネクタが表示されます。
ステップ 2: プロパティファイルの作成
Muleのベストプラクティスは、接続情報をパラメーター化することです。 データベースコネクタを設定するために、このベストプラクティスを活用します。
-
src/main/resources に
config
という名前のフォルダを作成します。 -
src/main/resources/configに
configuration.yaml
というファイルを作成します。 -
configuration.yamlファイルに以下のテキストを挿入します。
mysql: host: "services.mythicalcorp.com" port: "3306" user: "product" password: "Mule1379" database: "products_test"
パスワードは、Mule Credential Vaultを使用して暗号化できます。
-
configuration.yamlファイルを保存します。
-
api.xml ファイルに戻ります。 Global Elements タブを押します
-
Create(作成) ボタンを押して、Configuration Properties(構成プロパティ) を検索します。
-
OKを押します。
-
ファイルのテキストボックスに
config/configuration.yaml
と入力します。ファイル参照も可能です。
ステップ 3: Get Products フローの実装
このステップでは、get:\productフローを実装します。データベースからproductを取得するには、次の実装が必要です:
-
データベースからレコードを取得します。
-
レコードをjson形式に変換します。
以下の手順を参考にしてください:
-
productを取得するフローを探します。
もう一度確認: get:\product:api-config flow で作業していることを確認してください。
-
このフローにDatabase Connectorを追加します。
-
Database Connector をクリックし、 Transformation の前にSelect アイコンをドラッグ&ドロップします。
Database Connector を Source セクションではなく、Process セクションにドロップします。
-
データベース アイコンをダブルクリックすると、構成パネルが表示されます。
-
名前を Get Products に変更します。
-
これでプロパティが定義できたので、新しいコネクタ構成を追加してみましょう。
ドロップしたDatabase Connectorに戻り、クリックしてプロパティを開き、コネクタ構成の
ボタンをクリックします。
-
名前 に
Products_Database_Configuration
と入力します。 -
Connection でMySQL Connectionを選択します。
database connection(データベース接続)を選択すると、JDBCドライバの追加を求められます。
-
Configure… ボタンを押します。新しいウィンドウが開きます。
-
Add Maven depenency を選択します。
-
以下のデータを入力します:
-
Group id:
mysql
-
Artifact id:
mysql-connector-java
-
Version:
8.0.20
-
-
Finish をクリックします。
Anypoint Studioは、依存関係を自動的にダウンロードします。
-
データベースの設定では、プロパティに以下の値を指定します:
-
Host: ${mysql.host}
-
Port: ${mysql.port}
-
User: ${mysql.user}
-
Password: ${mysql.password}
-
Database: ${mysql.database}
Muleは、余分な設定を必要とせずに、デフォルトでconfiguration.yamlファイルに入れた設定プロパティの${key}だけで設定できます。
-
-
Test Connection をクリックして接続性を確認します。
-
OK をクリックします。
-
再び OK をクリックしてMySQLの設定を閉じます。
データベースの設定が完了したので、クエリを追加します。
SELECT p.id, p.name, p.description, p.product_number, p.manufactured, p.colors, p.categories, p.stock, p.safety_stock_level, p.standard_cost, p.list_price, p.size, p.size_unit_measure_code, p.weight, p.weight_unit_measure_code, p.days_to_manufacture, p.images, p.modified_date, p.created_date FROM product p LIMIT 10
"LIMIT 10" パラメータを使用して、最大10項目までしか取得できないようにクエリを制限しています。 多くのお客様は、お気に入りのクエリツール(SQL Query Analyzer, TOAD, DBVisualizer, ….)を使用して、必要なクエリを作成し、スタジオのテキストボックスに貼り付けています。
次に、データベースのレコードをJSON形式に変換する必要があります。
-
Transform Message アイコンをダブルクリックします。左側にはクエリからのフィールドが、右側にはAPIが返すフィールドが表示されます。フィールド間をドラッグ&ドロップすることで、フィールドをグラフィカルにマッピングすることができます。
このTransform Messageコンポーネントは、MuleSoftのユニバーサルDataWeave変換言語を使用して、データをどの形式へ変換するかを指定します。 XMLの場合にxpath/XSLTを使用したり、JSONやCSVの場合にコードを書いて変換といったことを行う必要はありません。すべての変換にDataWeaveを使用してください。DataWeaveは、Muleの内部でデータをクエリして変換するためのシンプルで強力なツールです。
-
既存の内容を削除して、以下のDataWeaveによる変換をテキストビューにコピーします。
%dw 2.0 output application/json --- payload map (product, index) -> { id: product.id, categories: (product.categories default "") splitBy ",", colors: (product.colors default "") splitBy ",", createdDate: product.created_date as String {format: "yyyy-MM-dd"}, modifiedDate: product.modified_date as String {format: "yyyy-MM-dd"}, safetyStockLevel: product.safety_stock_level as Number, stock: product.stock as Number, daysToManufacture: product.days_to_manufacture, name: product.name, description: product.description, images: (product.images default "") splitBy ",", listPrice: product.list_price, manufactured: product.manufactured, productNumber: product.product_number, size: product.size, sizeUnitMeasureCode: product.size_unit_measure_code, standardCost: product.standard_cost, weightUnitMeasureCode: product.weight_unit_measure_code, weight: product.weight }
colours、categories、imagesは配列であり、データベース内ではカンマで区切られた文字列として保存されているので、その文字列を", "で区切られた各要素に分割するSplit By関数を使用しています。より複雑なマッピング要件をサポートするために、DataWeave内で利用可能な関数が複数用意されています。詳細については、DataWeave documentation を参照してください。
-
以上でこの手順は終了です。Transform Messageのウィンドウに表示されている保存をクリックします。
-
ここまでで、API の実装をテストする準備が整いました。
ラボ 1 と同じ手順に従って以下を行ってください。
-
アプリケーションを起動します。
-
ログをチェックして、正常にデプロイされていることを確認します。
-
コンソールまたはPostmanを使用して、Get Productsへアクセスしてテストします。場合によっては、Content-TypeおよびAcceptヘッダーの設定を application/jsonにする必要があるかもしれません。エラーレスポンスを受信した場合は、インストラクターに問い合わせてください。
-
-
ここまでの一連の操作でAPIからのレスポンスを受信し、MySQLデータベースからproductを取得することができました。ラボ1でのレスポンス内容と異なることが確認できます。
(結果の例です。結果については異なる場合があります。)
このフローが動作していることを確認できたので、次の実装に移ります。何か問題があれば、インストラクターに問い合わせてください。
ステップ 4: 特定のproductを取得するフローを実装
このステップでは、get:\product/{id}フローを実装します。
データベースからproductを取得するには、次のようにします:
-
データベースからレコードを取得します。
-
レコードが見つかったかどうかを確認します。
-
見つかった場合は、そのレコードをjson形式に変換します。
-
見つからなかった場合は、"Not found" というレスポンスを作成します。
以下の手順を参考にしてください:
-
get:\product/{id}フローからすべてのTransform Messageを削除します。これを行うには、アイコンを右クリックしてDeleteを選択するだけです。または、アイコンを選択してDeleteキーを押します。
-
SelectコンポーネントをDatabase Connectorからドラッグ&ドロップします。
-
アイコンをダブルクリックして設定タブを開きます。
-
以下のパラメータを入力して完了です:
-
Display Name:
Get Product By ID
-
Connector configuration:
Products_Database_Configuration
を選択します。 -
SQL Query Text:
SELECT p.id, p.name, p.description, p.product_number, p.manufactured, p.colors, p.categories, p.stock, p.safety_stock_level, p.standard_cost, p.list_price, p.size, p.size_unit_measure_code, p.weight, p.weight_unit_measure_code, p.days_to_manufacture, p.images, p.modified_date, p.created_date FROM product p WHERE p.id = :id
-
-
入力パラメータを追加してみましょう。 fx ボタンをクリックしてから、Transformationアイコンをクリックします。
新しいウィンドウが表示されます。
-
検索ボックスでidを検索します。Attributes → uriParams → id と辿るとみつけることができます。
-
InputエリアからOutputエリアへidフィールドをドラッグ&ドロップします。
-
ボタンを押します。
ここではパラメータを使用したクエリを記述しています。クエリ内で変数を使用するように記述し、もう1つのテキストボックスでパラメータを定義します。
productが見つかったかどうかを検証します。商品が存在しない場合は例外処理を発生させるように実装します。 そのためには Validations Module を追加する必要があります。
-
Mule Paletteに移動し、Validation Moduleを追加します。
-
Validationコネクタを選択し、is not empty collection をドラッグ&ドロップします。
フローは以下のようになるはずです:
このバリデータコンポーネントは VALIDATION:EMPTY_COLLECTION型 の例外処理を起こします。 上位のフローはこの例外をキャッチし、404(Not Found)レスポンスを返答します。
-
これを実現するには、 api-main フローで定義されているエラー処理に進みます。
-
On Error Propagate type: APIKIT:NOT_FOUND のコンポーネントを見つけてください。
-
アイコンをクリックします。
設定プロパティが表示されます。
-
Type テキストボックスをクリックします。
チェックボックスのリストが開き、キャッチできる可能性のあるすべてのエラーが表示されます。
-
VALIDATION:EMPTY_COLLECTION を選択します。
エラーが表示されていない場合は、
APIKIT:NOT_FOUND
テキストの後にカンマで区切って、エラー名を手動で入力してください。最終的な文字列はAPIKIT:NOT_FOUND,VALIDATION:EMPTY_COLLECTION
である必要があります。 -
パネルの右上にある保存アイコンを押します。
次に先ほどのGetメソッドに戻り、フローの最後にTransform Messageコンポーネントを追加します。
このスクリプトをDataWeaveトランスフォームのテキストビューにコピーします:
%dw 2.0 output application/json var product = payload[0] --- { id: product.id, name: product.name, description: product.description, manufactured: product.manufactured, productNumber: product.product_number, colors: (product.colors default "") splitBy "," , categories:(product.categories default "") splitBy "," , safetyStockLevel: product.safety_stock_level, standardCost: (product.standard_cost default "0.0") as String {format: "##.##"} as Number, listPrice: (product.list_price default "0.0") as String {format: "##.##"} as Number, stock: product.stock, safetyStockLevel: product.safety_stock_level, daysToManufacture: product.days_to_manufacture, size: product.size, sizeUnitMeasureCode: product.size_unit_measure_code, weight: product.weight, weightUnitMeasureCode: product.weight_unit_measure_code, daysToManufacture: product.days_to_manufacture, images: (product.images default "") splitBy ",", modifiedDate: (product.modified_date default "") as Date {format: "yyyy-MM-dd"}, createdDate: (product.created_date default "") as Date {format: "yyyy-MM-dd"} }
-
Transform Message は、DBのレコードをレスポンス用に定義されたJSON形式に変換します。データベースのSelectは行のリストを返すので、1レコード分の内容を扱うようにするために、最初のレコードを選択します。
-
先ほどと同様にAPIを実行しDBにはいっているIDと、そうでないIDを使って "product/{id}"をGETで呼び出してみてください。
-
テスト終了後、コンソールビューMuleランタイムを停止します。
最終的にはこのようなフローになるはずです。
このフローが動作していることが確認できたので、次の実装に移りましょう。何か問題があれば、インストラクターに問い合わせてください。
ステップ 5: Create Product フローを実装
このステップでは、post:\productフローを実装します。データベースにproductを作成するには、以下を行う必要があります:
-
DBにproductを挿入する。
-
productとIDを応答として返します。
以下の手順で説明していきます:
-
post:\product:application\json:api-config flowからTransform Messageコンポーネントを削除します。これを行うには、その上で右クリックして「Delete」を選択するか、選択して「Delete」キーを押します。
-
パレットを使って、必要なコンポーネントをドラッグ&ドロップして、次ようなフローを作成します:
-
Insertコンポーネントを設定することから始めます。以下のようにパラメータを設定して、商品をデータベースに保存します:
-
Display Name:
Insert Product
-
Connector configuration:
Products_Database_Configuration
-
SQL Query Text:
INSERT INTO product(name, description, product_number, manufactured, colors, categories, stock, safety_stock_level, standard_cost, list_price, size, size_unit_measure_code, weight, weight_unit_measure_code, days_to_manufacture, images, modified_date, created_date) VALUES(:name, :description, :productNumber, :manufactured, :colors, :categories, :stock, :safetyStockLevel, :standardCost, :listPrice, :size, :sizeUnitMeasureCode, :weight, :weightUnitMeasureCode, :daysToManufacture, :images,CURDATE(), CURDATE() );
-
-
ボタンをクリックして、DataWeaveパネルを開きます。
-
以下の内容を記述してTransform Messageを完成させます:
%dw 2.0 output application/json fun getManufacturedCode(value) = if (value == true) 1 else 0 --- { categories: (payload.categories default []) joinBy ",", colors: (payload.colors default []) joinBy ",", daysToManufacture: payload.daysToManufacture, description: payload.description, images: (payload.images default []) joinBy ",", listPrice: payload.listPrice, manufactured: getManufacturedCode(payload.manufactured), name: payload.name, productNumber: payload.productNumber, safetyStockLevel: payload.safetyStockLevel, size: payload.size, sizeUnitMeasureCode: payload.sizeUnitMeasureCode, standardCost: payload.standardCost, stock: payload.stock, weight: payload.weight, weightUnitMeasureCode: payload.weightUnitMeasureCode }
DataWeaveでは関数を宣言して if else 構文が使えることを確認してください。 ここでは、生成された値をbooleanからintegerに変換しています。
この操作は新しいproductを作成するので、新しく生成されたIDを取得する必要があります。これをどのように実装するかは、データベースエンジンのドライバーによって異なります。
-
MySQLの場合は、"Insert Product" ブロックの "Advanced "に進みます。
-
Auto Generated Keys セクションを見つけます。
-
Auto Generated Keys を
True
に設定します。 -
Auto Generated Keys column namesで「Edit inline」を選択します。
-
下の表に値
id
を追加します。このような構成になります:
元のペイロードを失いたくないので、生成されたキーを変数に保存します。
-
-
Advancedの中で、Output値が表示されるまで下にスクロールします。
-
以下の値を入力してください:
-
Target Variable:
generated_key
-
Target Value:
#[payload.generatedKeys.GENERATED_KEY]
-
-
次に、レスポンスのTransform Messageを設定します。 このステップでは、元のリクエストペイロードとデータベースから返されたIDをマージする必要があります。以下に示したスクリプトを使うことで実現することができます。 元のリクエストのペイロードを取得し、「id」というフィールドを追加しています。
-
次の変換を追加します:
%dw 2.0 output application/json --- payload ++ id: vars.generated_key
-
最後に、カスタムビジネスイベントを構成しましょう。Custom Business Eventを追加およびパラメータの設定を行い、作成したproductの情報を今後のビジネス分析のために記録します:


-
Display Name:
New Product Created Event
-
Event Name:
New Product Created Event
-
Key Performance Indicators テーブルで、これら2つの属性を追加します。:
Name Expression / Value Product ID
#[payload.id]
Product Name
#[payload.name]
-
先ほどの手順でAPIを実行し、"products"をPOSTで呼び出して動作していることを確認してみてください。
product ID は一意でなければならないので、ランダムな値に変更する必要があります。この変更を行うにあたって問題がある場合は、直接データベースに問い合わせて値を提供するようにインストラクターに依頼してください テスト終了後、コンソールビューからMuleランタイムを停止します。
このフローが動作していることが確認できたので、次の実装に移りましょう。何か問題があれば、先に進む前にインストラクターへご連絡ください。
-
ステップ 6: Update Product フローを実装
このステップでは、put:\product{id}フローを実装します。データベース内のproductを更新するには、データベースへUPDATEをコールするだけです。
以下の手順で進めていきます:
-
put:\product{id}フローからコンポーネントを削除します。これを行うには、それぞれを右クリックしてDeleteを選択するか、コンポーネントを選択してDeleteキーを押します。
-
パレットから必要なコンポーネントをドラッグ&ドロップして、以下のようなフローを作成します:
-
以下のパラメータでデータベースを構成します:
-
Display Name:
Update Product
-
Connector configuration:
Products_Database_Configuration
-
SQL Query Text:
update product set name = :name, description = :description, product_number = :productNumber, manufactured = :manufactured, colors = :colors, categories= :categories, stock = :stock, safety_stock_level = :safetyStockLevel, standard_cost = :standardCost, list_price = :listPrice, size = :size, size_unit_measure_code = :sizeUnitMeasureCode, weight = :weight, weight_unit_measure_code = :weightUnitMeasureCode, days_to_manufacture = :daysToManufacture, images = :images, modified_date = CURDATE() where id = :id
-
-
ボタンをクリックし、さらに
ボタンをクリックして DataWeave パネルを開きます。
-
以下のスクリプトを記述し、完成させます。
%dw 2.0 output application/java fun getManufacturedCode(value) = if (value == true) 1 else 0 --- { id: attributes.uriParams.id, categories: (payload.categories default []) joinBy ",", colors: (payload.colors default []) joinBy ",", daysToManufacture: payload.daysToManufacture, description: payload.description, images: (payload.images default []) joinBy ",", listPrice: payload.listPrice, manufactured: getManufacturedCode(payload.manufactured), name: payload.name, productNumber: payload.productNumber, safetyStockLevel: payload.safetyStockLevel, size: payload.size, sizeUnitMeasureCode: payload.sizeUnitMeasureCode, standardCost: payload.standardCost, stock: payload.stock, weight: payload.weight, weightUnitMeasureCode: payload.weightUnitMeasureCode }
前のステップで行ったように、更新されたレコードの数を記録します。
-
loggerコンポーネントを開いて下さい。
-
を押して、DataWeave式を追加していきます。
-
次の DataWeave 式を追加します:
"Number of affected rows: " ++ ((payload.affectedRows default -1 )as String)
前のステップと同様にテストを実行し、終了後、コンソールビューを使用してMuleランタイムを停止します。
このフローが動作していることが確認できたので、次の実装に移りましょう。何か問題があれば、インストラクターに問い合わせてください。
ステップ 7: Delete Productフローを実装
このステップでは、delete:\product{id}フローを実装します。データベース内のproductを削除するには、データベースに対してDELETEをコールするだけです。
以下の手順に従って進行します:
-
delete:\product{id}フローからすべてのコンポーネントを削除します。これを行うには、各コンポーネントを右クリックしてDeleteを選択するか、コンポーネントを選択してDeleteキーを押します。
-
パレットを使って、必要なコンポーネントをドラッグ&ドロップして、このようなフローを作成します:
-
データベースコンポーネントを次のように構成します:
-
Display Name:
Delete Product
-
Connector configuration:
Products_Database_Configuration
-
SQL Query Text:
delete from product where id=:id
-
Input Parameters:
{ id:attributes.uriParams.id }
削除されたレコードの数を確認するためにloggerを追加します。
-
-
loggerコンポーネントに注目
-
を押して、DataWeave式を追加します。
-
次のDataWeave式を追加します:
"Number of records deleted: " ++ (payload as String)
204を返しているので、メッセージのペイロードはありません。
これで、前のステップと同じようにAPIを実行して、存在しているid(前のステップで作成したものなど)で "products/{id}"に対してDELETEを呼び出して、動作しているかどうかを確認することができます。
時間に余裕があれば、GET /products/{id}フローのように実装を拡張して、レコードが存在しない場合にNOT FOUND応答を返すようにすることもできます。
テストが終わったら、コンソールビューを使用してMuleランタイムを停止します。
何か問題があれば、先に進む前にインストラクターへご連絡ください。
これで実装が動作するようになったので、次のラボではエンドツーエンドでのテストを行い、ユニットテストを追加していきます。
まとめ
以下の手順を完了しました:
このモジュールでは、MySQLデータベースに対してシステムAPIを実装しました。 また、AnypointStudioに組み込まれているローカルのMuleランタイムでAPIを実行してテストしました。
演習の中でDataWeaveの使用法を紹介しました。DataWeaveは、データベースのレコードをjson形式に変換する強力なツールです。また、Database Connectorを使用して、データベースへのアクセスがどれだけ簡単にできるかを確認しました。
ここで注意しなければならないのは、APIの実装が実際のMuleアプリケーションであるということです。統合アプリケーションを構築したり、APIを公開したりするのに、追加の知識は必要ないので、Mule開発者は統合とAPIの両方に簡単に取り組むことができます。
詳細については、 Dataweave のドキュメントを参照してください。
詳細については、 Database Connecter のドキュメントを参照してください。
詳細については、 Configuration Properties のドキュメントを参照してください。
詳細については、 Secure Configuration Properties のドキュメントを参照してください。
ラボ 3 に進んでください。