SOAP(シンプル・オブジェクト・アクセス・プロトコル)は、HTTPおよびXML上に構築されたウェブサービス基準です。SOAP Ext.data.soap.ProxyおよびExt.data.soap.Readerは、SOAPリクエストの作成やSOAPレスポンスをExt.data.Storeにロードする便利な方法を提供します。本ガイドでは、SOAP ProxyおよびReaderを使用して、ブレンダに関する情報を提供する架空のSOAPサービスからデータをロードしたり、保存したりする方法を説明します。本ガイドでは、Ext JSデータパッケージに関する基本的な知識を前提条件としています。このガイドでは、Ext JSのデータパッケージに関して、ある程度経験のある読者を想定しています。
注意:_この機能はSencha Completeをお買い上げいただくことにより、ご利用いただけます。このクラスの使用に関する詳細は、当社のSencha Completeの製品ページをご覧ください。_
SOAPサービスからストアへ
初めに、Ext.data.StoreをSOAPデータで使用するために必要な最もシンプルな設定を見ていきましょう。
最初に、Ext.data.Modelを作成します。
Ext.define('Blender', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'string' },
{ name: 'price', type: 'float' }
]
});
次にストア、プロキシ、リーダーを作成します。
var store = Ext.create('Ext.data.Store', {
model: 'Blender',
proxy: {
type: 'soap',
url: 'BlenderService/',
api: {
create: 'CreateBlender',
read: 'GetBlenders',
update: 'UpdateBlender',
destroy: 'DeleteBlender'
},
soapAction: {
create: 'http://example.com/BlenderService/CreateBlender',
read: 'http://example.com/BlenderService/GetBlenders',
update: 'http://example.com/BlenderService/UpdateBlender',
destroy: 'http://example.com/BlenderService/DeleteBlender'
},
operationParam: 'operation',
targetNamespace: 'http://example.com/',
reader: {
type: 'soap',
record: 'm|Blender',
namespace: 'm'
}
}
});
指定したコンフィグオプションを解説します。“Blender”モデルのインスタンスを含むStoreを作成しました。このStoreはSOAPプロキシで設定しました。プロキシのオプションを詳しく説明します。
- Ext.data.soap.Proxy#url - プロキシは、4つのCRUD (作成、読み込み、更新、破棄)動作のために、SOAPサービスのエンドポイントurlとして使用します。ブラウザの同一出所制限のために、このurlは、Ext JSアプリケーションと同じドメイン、プロトコル、ポート上にあることが必要です。リモートのSOAPサービスと通信することが必要な場合、サーバー上にサーバーサイドのプロキシを作成して、リモートサーバからレスポンスを取得し、返さなければなりません。
- Ext.data.soap.Proxy#api - 正規のExt.data.proxy.Ajaxでは、api設定プロパティは、CRUD動作それぞれに別々のurlを指定します。ただし、SOAP Proxyでは、apiプロパティは、各CRUD動作にSOAP操作を設定するために使用されます。注意:アプリケーションで実際に使用される動作それぞれの操作だけを指定することが必要です。例えば、このプロキシがデータのロードだけで、データの書き込みを目的としない場合、設定する必要があるのは’Read’動作だけです。
- Ext.data.soap.Proxy#soapAction - SOAP仕様は、SOAPリクエストそれぞれがSOAPAction HTTPリクエストヘッダーを含むことを義務付けています。soapActionコンフィグは、各CRUD動作と送信されるSOAPActionヘッダーを指定します。soapActionは、apiコンフィグを使用して設定されたSOAP操作それぞれに指定することが必要です。
Ext.data.soap.Proxy#operationParam - 操作名を含むurlパラメータの名前。例えば、‘operation’のoperationParamは、次のようなReadリクエストurlになります。
http://example.com/BlenderService/?operation=GetBlenders
Ext.data.soap.Proxy#targetNamespace - SOAPサービスのターゲット名前空間。SOAPエンベロープを作成するために必要です。
- Ext.data.soap.Proxy#reader - SOAP Ext.data.soap.Readerは、SOAPレスポンスからレコードを抽出し、Ext.data.Modelインスタンスにパースします。ReaderのExt.data.soap.Reader#recordプロパティは、SOAPレスポンスにレコードを含む反復XML要素のtagNameです。ReaderのExt.data.soap.Reader#namespaceプロパティは、レコードのフィールドデータを含む要素のXML名前空間プレフィックスです。
レコードのロード
これですべてが設定されたため、データをストアにロードするのは、ストアのloadメソッドを呼び出す場合と同じように簡単です。バックグラウンドでは、プロキシのAPI設定プロパティのread
プロパティによって指定された操作に対するSOAPリクエストが作成されます(例では「GetBlenders」)。GetBlenders SOAP操作に“brand”パラメータが必要であると想定します。このパラメータはストアのloadメソッドに直接渡すことができます。またはパラメータの値が設定できるリクエストがすべてに同じ場合、Ext.data.soap.Proxy#extraParamsコンフィグを使用してプロキシに直接設定することができます。今回の例では、ストアのloadメソッドに渡してみましょう。
store.load({
params: {
brand: 'Blendtec'
}
});
上記の呼び出しは、次へのポストをトリガーします。
http://example.com/BlenderService/?operation=GetBlenders
上記のリクエストに対するレスポンスが次のようになったと想定します。
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<m:GetBlendersResponse xmlns:m="http://example.com/">
<m:Blender>
<m:id>1</m:id>
<m:name>Total Blender Classic WildSide</m:name>
<m:price>454.95</m:price>
</m:Blender>
<m:Blender>
<m:id>2</m:id>
<m:name>The Kitchen Mill</m:name>
<m:price>179.95</m:price>
</m:Blender>
</m:GetBlendersResponse>
</soap:Body>
</soap:Envelope>
ストアのレコードがロードされた後どのようになるかを確認できるように、ロードの呼び出しにコールバック関数を渡しましょう。
store.load({
params: {
brand: 'Blendtec'
},
callback: function() {
console.log(store.getCount()); // 2 records were loaded.
console.log(store.getAt(0).get('name')); // get the name field of the first
record. } });
SOAPエンベロープとボディのカスタマイズ
ここで、使用しているブラウザの開発者ツールを使用して、発信するXHRリクエストを確認しましょう。次へのHTTP POSTを確認できます。
http://example.com/BlenderService/?operation=GetBlenders
ここで、このリクエストのポストボディを確認します。SOAPエンベロープはこのようになっているはずです(見やすいようにフォーマットしています)。
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetBlenders xmlns="http://example.com/">
<brand>Blendtec</brand>
</GetBlenders>
</soap:Body>
</soap:Envelope>
このSOAPエンベロープは、Ext.data.soap.Proxy#envelopeTplテンプレートを使用して作成され、SOAPボディは、Ext.data.soap.Proxy#readBodyTplテンプレートを使用して作成されています。SOAPサービスが違うフォーマットを要求する場合、ボディテンプレートを修正する必要があるかもしれません。一般には、エンベロープテンプレートを修正する必要はありませんが、カスタマイズすることが可能です。このような設定可能なテンプレートはそれぞれ、Ext.XTemplateインスタンス、またはXTemplateを形成する文字列の配列のいずれかです。以下の例では、カスタムテンプレートを使用して、“soap”エンベロープの名前空間接頭辞を“s”に変更しています。
proxy: {
...
envelopeTpl: [
'<?xml version="1.0" encoding="utf-8" ?>',
'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">',
'{[values.bodyTpl.apply(values)]}',
'</s:Envelope>'
],
readBodyTpl: [
'<s:Body>',
'<{operation} xmlns="{targetNamespace}">',
'<tpl foreach="params">',
'<{$}>{.}</{$}>',
'</tpl>',
'</{operation}>',
'</s:Body>'
]
}
store.load()をもう一度呼び出すと、新しいテンプレートから生成されているポストボディが確認できます。
<?xml version="1.0" encoding="utf-8" ?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetBlenders xmlns="http://example.com/">
<brand>Blendtec</brand>
</GetBlenders>
</s:Body>
</s:Envelope>
作成、更新、破棄
Create、Update、Destroyのリクエストは、SOAPボディの作成方法以外、Readリクエストとほぼ同様に機能します。Readリクエストはパラメータを使用してSOAPボディを作成しますが、Create、Update、Destroyリクエストはレコードを使用してSOAPボディを作成する点だけが異なります。デフォルトでは、Create、Update、DestroyリクエストでSOAPボディを作成するために使用されるテンプレートは、すべて同じです。
[
'<soap:Body>',
'<{operation} xmlns="{targetNamespace}">',
'<tpl for="records">',
'{% var recordName=values.modelName.split(".").pop(); %}',
'<{[recordName]}>',
'<tpl for="fields">',
'<{name}>{[parent.get(values.name)]}</{name}>',
'</tpl>',
'</{[recordName]}>',
'</tpl>',
'</{operation}>',
'</soap:Body>'
]
テンプレートは、上記のSOAPエンベロープとボディのカスタマイズで説明したように、Ext.data.soap.Proxy#createBodyTpl、Ext.data.soap.Proxy#updateBodyTpl、Ext.data.soap.Proxy#destroyBodyTpl設定オプションを使用してカスタマイズできます。またはExt.data.soap.Proxy#writeBodyTpl設定オプションを使用して、これら3つの動作すべてに同じテンプレートを適用することができます。
Createリクエストを発行するには、まず新しいレコードを作成する必要があります。
var blender = Ext.create('Blender', {
name: 'WildSide Jar',
price: 99
});
次に、レコードをストアに追加し、syncメソッドを呼び出します。
store.add(blender);
store.sync();
これによって、create操作パラメータのあるHTTP POSTがエンドポイントurlに発行されます。
`http://example.com/BlenderService/?operation=CreateBlender`
このリクエストのポストボディを調べると、新しく作成されたレコードがSOAPボディにエンコードされたのが分かります。
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<CreateBlender xmlns="http://example.com/">
<Blender>
<id>0</id>
<name>WildSide Jar</name>
<price>99</price>
</Blender>
</CreateBlender>
</soap:Body>
</soap:Envelope>
Createリクエストに対するレスポンスには、サーバーによって作成されたレコードが含まれるので、レコードのidがクライアントサイドで更新されます。例:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<m:GetBlendersResponse xmlns:m="http://example.com/">
<m:Blender>
<m:id>3</m:id>
<m:name>WildSide Jar</m:name>
<m:price>99</m:price>
</m:Blender>
</m:GetBlendersResponse>
</soap:Body>
</soap:Envelope>
ストアの同期が成功した後、idプロパティを確認すると、レコードのidが正しいことが検証できます。
store.sync({
success: function() {
console.log(blender.getId()); // 3
}
});
レコードを更新するには、フィールドを変更してから、ストアを同期させるだけです。
store.getAt(0).set('price', 200);
store.sync();
レコードを破棄するには、ストアから削除してから、同期させます。
store.removeAt(1);
store.sync();
Create動作と同様に、UpdateまたはDestroy動作に対するサーバーのレスポンスにレコードが含まれている場合、クライアントサイドのレコードはレスポンス内のデータで更新されます。
これで、SOAPおよびExt JSを使用するために必要な知識が学習できました。詳しくは、SOAP Ext.data.soap.ProxyおよびExt.data.soap.ReaderのAPIドキュメントを参照してください。
実例や完全なソースコードについては、SOAPグリッドの例を参照してください。