| Oracle® Fusion Middleware Oracle Mobile Application Frameworkでのモバイル・アプリケーションの開発 2.0.1 E57592-01 |
|
![]() 前 |
![]() 次 |
この章では、サード・パーティのWebサービスをMAF AMXアプリケーション機能の実装に統合する方法について説明します。
この章の内容は次のとおりです。
Webサービスでは、アプリケーションおよびその機能は、定義済のアプリケーション・プログラミング・インタフェースを使用してデータと情報を交換できます。Webサービスを使用すると、元のアプリケーションのプラットフォームや言語に関係なくビジネス機能を公開できます。これは、ビジネス機能を、他のアプリケーションでも認識され、使用可能な標準XMLコンストラクトで構成されるメッセージに抽象化して公開するからです。
MAFアプリケーションでWebサービスを使用する最も一般的な理由の一部は次のとおりです。
Webサービスとしてはすぐに利用できるが、アプリケーション内で開発するには時間がかかる機能を追加するため
異なるアーキテクチャで実行されるアプリケーションへのアクセスを提供するため
MAFでは、SOAP WebサービスとREST Webサービスの両方の消費をサポートしています。
MAFアプリケーションでWebサービスを使用すると、次の手順を実行できます。
モバイル・アプリケーションのエンド・ユーザーが関心を寄せる大規模な(エンタープライズ)データ・ストアから、すべてのデータまたはデータのサブセットを提供します。
モバイル・デバイスのリソースにとっては処理に時間がかかりすぎる機能を提供します。この原因として考えられるのは、デバイスが行う必要がある実際の作業量か、または機能が基づくデータ・セットがデバイス上でローカルに使用可能なものよりもはるかに大きいことです。
次のWebサービス使用のシナリオでは、データ・アクセス(シナリオ1)の他に、計算およびデータ駆動型の機能(シナリオ2および3)を示します。
エンタープライズ・データ・ストアから一連の商談データをフェッチして、エンド・ユーザーがデバイスでそのデータを操作し、Webサービスを介してエンタープライズ・データ・ストアに変更をポストできるようにします。
一部のエンタープライズ・データに対して生成されるレポートを要求し、そのレポートをフェッチします。
顧客サイトへのルートのマップ・イメージを取得します。
MAFを使用して開発されたアプリケーション機能でWebサービスを使用する場合、外部Webサービスのデータ・コントロールを作成するのが最も一般的な方法です。詳細は、第7.1項「バインディングおよびデータ・コントロールの概要」を参照してください。
JDeveloperでは、そのサービスのWeb Services Description Language (WSDL)ファイルのみを使用して、既存のSOAP Webサービスのデータ・コントロールを作成します。ローカル・ファイル・システムでWSDLファイルを参照するか、Universal Description, Discovery and Integration (UDDI)レジストリでWSDLファイルを検索するか、WSDL URLを直接入力することができます。
|
注意: ファイアウォールで保護されている環境で、ファイアウォール外にあるWebサービスを使用する場合は、JDeveloperで「Webブラウザとプロキシ」の設定を構成する必要があります。詳細は、第8.7項「ブラウザ・プロキシ情報の構成」を参照してください。 |
SOAP Webサービス・データ・コントロールを作成するには:
「アプリケーション」ウィンドウで、アプリケーション名を右クリックし、JDeveloperのメイン・メニューから「ファイル」→「新規」→「ギャラリから」を選択します。
「新規ギャラリ」ダイアログで、左側の「ビジネス層」ノードを開いて「Webサービス」を選択します。右側の「アイテム」リストから「Webサービス・データ・コントロール(SOAP/REST)」を選択して(図8-1を参照)、「OK」をクリックします。
「Webサービス・データ・コントロールの作成」ウィザードの「データ・ソース」ページで、「SOAP」を選択します。
ウィザードの指示に従って、データ・コントロールの作成を完了します。
|
注意: MAFでは、SOAP 1.1および1.2の両方のバージョンで次のエンコーディング・スタイルをサポートしています。
|
MAFでは、DataControls.dcxファイルにカスタムのプロバイダ・クラスを指定できます(例8-3を参照)。このカスタム・クラスでは、oracle.adfinternal.model.adapter.webservice.provider.soap.SOAPProviderを拡張します。これは、SoapHeader[] getAdditionalSoapHeaders()メソッドの実装の指定に使用できます。
例8-1は、SOAPProviderを拡張し、例8-2に示したカスタム・ヘッダーの作成方法を示しています。
例8-1 カスタムSOAPヘッダーの定義
package provider.ebs.soap;
import oracle.adfinternal.model.adapter.webservice.provider.soap.SOAPProvider;
import oracle.adfinternal.model.adapter.webservice.provider.soap.SoapHeader;
public class EBSSOAPProvider extends SOAPProvider {
public SoapHeader[] getAdditionalSoapHeaders() {
SoapHeader header[] = new SoapHeader[2];
SoapHeader token = null;
SoapHeader user = null;
SoapHeader pass = null;
header[0] = new SoapHeader("http://xmlns.oracle.com/apps/fnd/soaprovider/plsql/fnd_user_pkg/",
"SOAHeader");
header[0].addChild(new SoapHeader(
"http://xmlns.oracle.com/apps/fnd/soaprovider/plsql/fnd_user_pkg/",
"Responsibility",
"SYSTEM_ADMINISTRATOR"));
header[0].addChild(new SoapHeader(
"http://xmlns.oracle.com/apps/fnd/soaprovider/plsql/fnd_user_pkg/",
"RespApplication",
"SYSADMIN"));
header[0].addChild(new SoapHeader(
"http://xmlns.oracle.com/apps/fnd/soaprovider/plsql/fnd_user_pkg/",
"SecurityGroup",
"STANDARD"));
header[0].addChild(new SoapHeader(
"http://xmlns.oracle.com/apps/fnd/soaprovider/plsql/fnd_user_pkg/",
"NLSLanguage",
"AMERICAN"));
header[0].addChild(new SoapHeader(
"http://xmlns.oracle.com/apps/fnd/soaprovider/plsql/fnd_user_pkg/",
"Org_Id",
"0"));
header[1] = new SoapHeader(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security");
token = new SoapHeader(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"UsernameToken");
user = new SoapHeader(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Username",
"sysadmin");
pass = new SoapHeader(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Password",
"sysadmin");
header[1].addChild(token);
token.addChild(user);
token.addChild(pass);
return header;
}
}
例8-2は、新しいカスタム・ヘッダーを示しています。
例8-2 SOAPヘッダー
<soap:Header xmlns:ns1="http://xmlns.oracle.com/apps/fnd/soaprovider/plsql/fnd_user_pkg/">
<ns1:SOAHeader>
<ns1:Responsibility>SYSTEM_ADMINISTRATOR</ns1:Responsibility>
<ns1:RespApplication>SYSADMIN</ns1:RespApplication>
<ns1:SecurityGroup>STANDARD</ns1:SecurityGroup>
<ns1:NLSLanguage>AMERICAN</ns1:NLSLanguage>
<ns1:Org_Id>0</ns1:Org_Id>
</ns1:SOAHeader>
<wsse:Security xmlns:wsse=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
soap:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsse=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Username>sysadmin</wsse:Username>
<wsse:Password Type=
http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-username-token-profile-1.0#PasswordText">sysadmin</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
@return
例8-3は、SOAPProvider登録に関するDataControls.dcxファイルのサンプル・エントリを示しています。
例8-3 DataControls.dcxファイルでのSOAPProviderの登録
<definition xmlns="http://xmlns.oracle.com/adfm/adapter/webservice"
name="SoapService" version="1.0"
provider="oracle.adf.model.adapter.webservice.SOAPMessageHandler"
wsdl="http://@SRG_WS_HOST@:@SRG_WS_PORT@/SoapService/SoapServicePort?wsdl" >
<service name="SoapService" namespace="http://model/"
connection="SoapService">
<port name="SoapServicePort">
<operation name="echoSoapHeader"/>
</port>
</service>
</definition>
|
注意: MAFを使用して動的SOAPヘッダーを指定することはできません。 |
JDeveloperでは、既存のREST Webサービスのデータ・コントロールを作成できます。このREST Webサービスは、XMLレスポンスを戻します。
|
注意: ファイアウォールで保護されている環境で、ファイアウォール外にあるWebサービスを使用する場合は、JDeveloperで「Webブラウザとプロキシ」の設定を構成する必要があります。詳細は、第8.7項「ブラウザ・プロキシ情報の構成」を参照してください。 |
同じ接続を使用して、REST Webサービス・データ・コントロールに1つ以上のHTTPメソッドを関連付けることができます。RESTサービスにより公開されたカスタム操作にアクセスできます。これらのカスタム操作は、HTTPメソッドの1つにマップされ、データ・コントロールを作成することでクライアントに公開できます。
モバイル・デバイスでセキュリティおよび通知機能を使用する場合は、RESTデータ・コントロールによって公開された特定の操作で使用する標準のHTTPヘッダーにカスタム・ヘッダーおよびカスタム値を追加できます。
始める前に
データ・コントロールがアクセスするREST Webサービスへのアクセス権があることを確認します。
REST Webサービス・データ・コントロールを作成するには:
「アプリケーション」ウィンドウで、アプリケーション名を右クリックし、JDeveloperのメイン・メニューから「ファイル」→「新規」→「ギャラリから」を選択します。
「新規ギャラリ」ダイアログで、左側の「ビジネス層」ノードを開いて「Webサービス」を選択します。右側の「アイテム」リストから「Webサービス・データ・コントロール(SOAP/REST)」を選択して(図8-1を参照)、「OK」をクリックします。
「Webサービス・データ・コントロールの作成」ウィザードの「データ・ソース」ページで、「REST」を選択します(図8-2参照)。
「Webサービス・データ・コントロールの作成」ウィザードの説明に従って、次の点に注意しながらデータ・コントロールの作成を完了します。
MAFでは、Webサービスに対して基本認証のみをサポートしています(第8.5項「セキュアなWebサービスへのアクセス」を参照)。新しい接続の作成時に、「URL接続の作成」ダイアログの「認証タイプ」フィールドで、「基本」を選択します。
MAFでは、GET、POST、PUTおよびDELETEのすべてのHTTPメソッド・タイプをサポートしています。「リソース」ページの「メソッド表示名」フィールドへの入力時に、これらのメソッド・タイプのいずれかを選択できます(図8-3を参照)。
|
注意: 同じ接続および同じREST Webサービス・データ・コントロールを使用して4つのメソッドをすべて追加できます。 |
MAFでは、スプレッド・シート・データ内の区切り文字で区切られた値およびXMLデータ・フォーマットのXSLはサポートされません。
REST Webサービス・データ・コントロール定義にローカルXSDファイルを指定することによって、「メソッドの詳細」ページでスキーマの識別を可能にするフィールドのファイルURI参照を作成します(図8-4を参照)。
|
注意: MAFではコンパイル時にXSD構造の内部定義を作成するため、アプリケーションのコンパイル後はXSDを変更しないようにします。したがって、XSDファイルをローカルで参照することをお薦めします。リモートXSDの使用がパフォーマンスに悪影響を与えるのは、MAFではアプリケーションを実行するたびにXSDを取得するためです。 |
前述の手順に従ってREST Webサービス・データ・コントロールを作成すると、そのコントロールは、JDeveloper経由で使用可能な他の技術によって提供される、対応するコントロールとまったく同じように動作します。
RESTDemoという名前のMAFサンプル・アプリケーション(開発コンピュータのjdev_install/jdeveloper/jdev/extensions/oracle.maf/SamplesディレクトリにあるPublicSamples.zipファイルにあります)は、MAFアプリケーションでのREST Webサービスの使用方法を示しています。
データ・コントロールを使用しないJavaによるREST Webサービスの使用方法の詳細は、第8.6.2項「REST Webサービス・アダプタの使用方法」を参照してください。
Webサービス・データ・コントロールの作成後は、図8-5に示すように、Webサービスの操作およびその操作の戻り値が「データ・コントロール」ウィンドウに表示されます。
他のデータ・コントロールと同じく、Webサービス操作から返されたオブジェクトをドラッグ・アンド・ドロップして、MAF AMXページでユーザー・インタフェース・コンポーネントを作成できます。詳細は、第5.3.2.4項「データ・コントロールのビューへの追加」を参照してください。Webサービスの操作から戻されたデータが表示されると、次のオブジェクト・タイプが処理されます。
コレクション
Webサービスの操作により戻された複合オブジェクト
Webサービスの操作により戻された、ネストされた複合オブジェクト
Webサービスの操作を使用して、標準データ型と複合データ型の両方を更新および削除できます。
図8-5に示すように、各データ・コントロール・オブジェクトはアイコンで表されます。表8-1は、各アイコンが表すもの、「データ・コントロール」パネルの階層内で表示される場所、そのアイコンを使用して作成できるコンポーネントを示しています。詳細は、第7.6項「「データ・コントロール」パネルでのデータバインドされたUIコンポーネントの作成」を参照してください。
表8-1 Webサービスの「データ・コントロール」パネルのアイコンおよびオブジェクト階層
| アイコン | 名前 | 説明 | 作成できるコンポーネント |
|---|---|---|---|
|
|
データ・コントロール |
データ・コントロールを表します。データ・コントロール自体を使用してUIコンポーネントを作成することはできませんが、その下に表示される子オブジェクトは、いずれも使用できます。通常、各Webサービスに対するデータ・コントロールは1つです。 |
他のオブジェクトのコンテナとして機能し、コンポーネント作成には使用されません。 |
|
コレクション |
サービスの操作から返されるデータ・コントロールを表現します。コレクションは、メソッド戻りオブジェクト、他のコレクション、または構造化属性の下の子としても表示されます。コレクションの下の子は、属性、他のコレクション、カスタム・メソッド、コレクションに対して実行できる組込み操作などです。 |
フォーム、表、グラフ、ツリー、レンジ・ナビゲーションの各コンポーネント、およびマスター/ディテール・コンポーネント。第6.5項「データ視覚化の指定」も参照してください。 |
|
|
|
属性 |
オブジェクト内の個別のデータ要素(行の属性など)を表します。属性は、自分の属するコレクションまたはメソッド戻りの下に、子として表示されます。 |
ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。第6.2項「ページ・レイアウトの設計」も参照してください。 |
|
構造化された属性 |
複合型でありコレクションではない、返されたオブジェクトを表します。たとえば、構造化属性は、現在のサービス・リクエストに割り当てられた単一のユーザーを表現します。 |
ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。第6.2項「ページ・レイアウトの設計」も参照してください。 |
|
|
メソッド |
データ・コントロールの操作またはその公開された構造のいずれかを表し、パラメータの受入れや、ビジネス・ロジックの実行を行ったり、オプションで単一の値、構造、またはそれらのコレクションを戻すことができます。 |
コマンド・コンポーネント。 パラメータを受け入れるメソッドの場合: コマンド・コンポーネントおよびパラメータ付きフォーム。また、第6.3項「UIコンポーネントの作成と使用方法」も参照してください。 |
|
|
メソッド戻り値 |
Webサービス・メソッドによって戻されたオブジェクトを表します。戻されたオブジェクトは、単一の値またはコレクションです。 メソッド戻りは、これを戻すメソッドの下に、子として表示されます。メソッドの戻りオブジェクトの下の子として表示されるオブジェクトは、該当コレクションの属性、親コレクションに関連するアクションを実行する他のメソッド、および親コレクション上で実行可能な操作です。 単一値のメソッド戻り値がドロップされると、メソッドはフレームワークにより自動的に起動されなくなります。メソッドを起動するために、対応するメソッドをボタンとしてドロップする必要があります。また、タスク・フローを使用している場合は、メソッド・アクティビティを作成できます。 |
コレクションと属性、および問合せフォームの場合と同じコンポーネント。 |
|
|
操作 |
親オブジェクトに対してアクションを実行する、組込みデータ・コントロール操作を表します。データ・コントロール操作は、コレクションの下の「操作」ノードにあります。1つ以上のパラメータが操作に必要な場合、それらのパラメータは操作の下の「パラメータ」ノードにリストされます。 現在行のナビゲーションと設定のために、 |
ボタン、リンク、メニューなどのユーザー・インタフェース・コマンド・コンポーネント。詳細は、第6.3項「UIコンポーネントの作成と使用方法」を参照してください。 |
|
|
パラメータ |
メソッドまたはその下に表示される操作によって宣言されたパラメータ値を表します。パラメータは、メソッドまたは操作の下の「パラメータ」ノード内に表示されます。 配列および構造化パラメータは、データ・コントロールの下の更新可能な構造化属性およびコレクションとして公開され、UI上にADFフォームまたは更新可能な表としてドロップできます。UIを使用して配列または複合オブジェクト(標準のJava型ではない)のパラメータを作成できます。 |
ラベル、テキストおよび選択リストの各コンポーネント。詳細は、第6.3.15項「リスト・ビューおよびリスト・アイテム・コンポーネントの使用方法」を参照してください。 |
Webサービスの接続情報は、アプリケーション内の他の接続とともにconnections.xmlファイルに保存されます。このファイルは、Webサービス・データ・コントロールの作成時に「新しいWebサービス・データ・コントロール」ウィザードによって.adf/META-INFディレクトリに生成されるため、明示的に作成する必要はありません(第8.2項「Webサービス・データ・コントロールの作成」を参照)。
接続設定を変更するには、connections.xmlファイルを編集します。
Webサービス・データ・コントロールを作成すると、URIのエンド・ポイントを変更できます。これは、テスト環境から本番環境にアプリケーション機能を移行するような場合に便利です。
エンド・ポイントを変更するには、connections.xmlファイルを編集します。
MAFは、保護されたWebサービスと保護されていないWebサービスの両方をサポートしています。詳細は、第21章「モバイル・アプリケーションの保護」を参照してください。
MAFアプリケーションから保護されたWebサービスにアクセスするには、アプリケーションに追加されたWebサービス・データ・コントロールの構成が必要な場合もあります。
SOAPベースのWebサービスでは次の事前定義済のセキュリティ・ポリシーがサポートされます。
oracle/wss_http_token_client_policy
oracle/wss_http_token_over_ssl_client_policy
oracle/http_basic_auth_over_ssl_client_policy
oracle/wss_username_token_client_policy
oracle/wss_username_token_over_ssl_client_policy
これらのポリシーとその使用方法の詳細は、『Oracle Fusion Middleware Oracle Web Services ManagerによるWebサービスの保護とポリシーの管理』の「使用する事前定義済ポリシーの決定」および「事前定義済ポリシー」の章を参照してください。
SOAP Webサービスが保護されている場合は、oracle/wss_http_token_over_ssl_client_policyまたはoracle/wss_http_token_client_policyのいずれかでWebサービス・データ・コントロールを構成することでアクセスが可能になります。これを行うには、図8-6に示す「データ・コントロール・ポリシーの編集」ダイアログを使用します。このダイアログは次の方法で開くことができます。
「アプリケーション」ウィンドウで、アプリケーションのビュー・コントローラ・プロジェクトにある.dcxファイルを選択します。
「構造」ウィンドウで、構成が必要なWebサービス・データ・コントロールを右クリックし、ポップアップ・メニューから「Webサービス・セキュリティの定義」を選択します。
|
注意: JDeveloperは、Webサービス・ポリシー定義を |
Cookieベースの認可のためにモバイル・アプリケーションがREST Webサービスを要求するたびに、MAFのセキュリティ・フレームワークは、REST Webサービスのトランスポート・レイヤーが、REST WebサービスのURLエンド・ポイントに関連付けられているログイン接続に対してCookieの挿入が可能かどうかをチェックできるようにします。つまり、connections.xmlファイルに<injectCookiesToRESTHttpHeader value="true"/>が含まれている必要があります。REST Webサービス・コールでログイン・サーバーのCookieを有効にするようにMAFアプリケーション・ログインを構成する方法の詳細は、第21.4.3項「Oracle Mobile and Social Identity Managementを使用して認証を構成する方法」を参照してください。
これは、Oracle Access Management Mobile and Social (OAMMS)認証コンテキストにも当てはまり、WebリソースはOracle Access Managerサーバー10g WebGateによって保護されており、アクセス・トークンはObSSOCookieという暗号化されたCookieとして挿入されます。詳細は、第21.4.11項「REST Webサービス・コールへのCookieの挿入を可能にする場合の処理」を参照してください。
REST WebサービスがOAuthアクセス・トークンを予期している場合、REST Webサービスをサポートする事前定義済のセキュリティ・ポリシーoracle/oauth2_config_client_policyにREST接続を関連付ける必要があります。現在、JDeveloperのデザインタイムではポリシーの関連付けがサポートされていません。REST接続を編集してポリシー・セットをWebサービスに手動で添付する必要があり、例8-4に示すように、URIはoracle/oauth2_config_client_policyに設定され、someapiは接続名です。
例8-4 REST接続へのポリシー・セットの関連付け
<sca11:policySet xmlns:sca11="http://docs.oasis-open.org/ns/opencsa/sca/200912"
name="policySet"
attachTo="MODULE('someapi')"
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
DigestAlgorithm="http://www.w3.org/ns/ws-policy/Sha1Exc"
URI="oracle/oauth2_config_client_policy"
orawsp:status="enabled" orawsp:id="1"/>
</sca11:policySet>
たとえば、ソーシャル認証サーバーに対して認証するようにOAMMSサーバーが構成され、MAFアプリケーションがソーシャル・サービス・プロバイダのREST APIを起動する必要がある場合に、このポリシーを構成します。
保護されたWebサービスにおけるユーザーの資格証明は、Webサービス・リクエストの起動時にそのリクエストに動的に挿入されます。このプロセスは、SOAP WebサービスとREST Webサービスで似ています。
MAFは、Oracle Web Services Manager (OWSM)モバイル・エージェントを使用して、Webサービス・リクエスト経由でユーザー・アイデンティティを伝播します。
Webサービスを起動する前に、ユーザーは、保護されたMAFアプリケーション機能の呼出しまたはアクセス制御サービス(ACS)で制御されたアプリケーションの起動を試みるユーザーによってトリガーされた認証プロンプトに応答する必要があります。後者では、アプリケーションでACS URLを使用してデフォルトのログイン・サーバーを定義し、user.roles設定に依存する制約を持つ機能を少なくとも1つは備えておく必要があります。ユーザーの資格証明は、資格証明ストアに格納されます。この資格証明ストアは、認証プロバイダのサーバーURLおよびユーザーと関連付けられた資格証明の格納に使用される、デバイス・ネイティブかつローカルなリポジトリです。実行時に、MAFでは、すべての資格証明がその使用前にIDM Mobile資格証明ストアに格納されているものとみなします。
connections.xmlファイルには、Webサービスの接続参照のadfCredentialStoreKey属性に、ログイン・サーバー接続のadfCredentialStoreKeyの値を指定して、ログイン・サーバーをWebサービスのセキュリティに関連付ける必要があります(例8-5および例8-6を参照)。
|
注意: JDeveloperでは |
例8-5は、adfCredentialStoreKey="MyAuth"として参照されるWebサービス接続の定義を示しています。ここで、MyAuthとは、ログイン接続の参照名です。
例8-5 Webサービス接続の定義
<Reference name="URLConnection1"
className="oracle.adf.model.connection.url.HttpURLConnection"
adfCredentialStoreKey="MyAuth"
xmlns="">
<Factory className="oracle.adf.model.connection.url.URLConnectionFactory"/>
<RefAddresses>
<XmlRefAddr addrType="URLConnection1">
<Contents>
<urlconnection name="URLConnection1"
url="http://myhost.us.example.com:7777/
SecureRESTWebService1/Echo">
<authentication style="challange">
<type>basic</type>
<realm>myrealm</realm>
</authentication>
</urlconnection>
</Contents>
</XmlRefAddr>
<SecureRefAddr addrType="username"/>
<SecureRefAddr addrType="password"/>
</RefAddresses>
</Reference>
例8-6は、ログイン接続の定義を示しています。ここでのMyAuthは、ログイン・サーバー接続における資格証明ストア・キーの値として使用されます。
例8-6 ログイン接続の定義
<Reference name="MyAuthName"
className="oracle.adf.model.connection.adfmf.LoginConnection"
adfCredentialStoreKey="MyAuth"
partial="false"
manageInOracleEnterpriseManager="true"
deployable="true"
xmlns="">
<Factory className="oracle.adf.model.connection.adfmf.LoginConnectionFactory"/>
<RefAddresses>
<XmlRefAddr addrType="adfmfLogin">
<Contents>
<login url="http://172.31.255.255:7777/
SecuredWeb1-ViewController-context-root/faces/view1.jsf"/>
<logout url="http://172.31.255.255:7777/
/SecuredWeb1-ViewController-context-root/faces/view1.jsf"/>
<accessControl url="http://myhost.us.example.com:7777/
UserObjects/jersey/getUserObjects" />
<idleTimeout value="10"/>
<sessionTimeout value="36000"/>
<userObjectFilter>
<role name="testuser1_role1"/>
<role name="testuser2_role1"/>
<privilege name="testuser1_priv1"/>
<privilege name="testuser2_priv1"/>
<privilege name="testuser2_priv2"/>
</userObjectFilter>
</Contents>
</XmlRefAddr>
</RefAddresses>
</Reference>
認証の失敗によってWebサービス・リクエストが拒否された場合は、MAFにより適切な例外が戻され、適切なアクションが起動されます(第22.4項「ロギングの使用方法と構成」を参照)。既存の例外で状況を適切に示せない場合は、新しい例外が追加されます。
connections.xmlファイルは構成サービスの下でデプロイされ、管理されています。詳細は、第9章「MAFアプリケーションで使用されるエンド・ポイントの構成」を参照してください。
FAR内のconnections.xmlファイルは、MAFアプリケーションのデプロイ時に集約されます。資格証明はデプロイメント固有のデータを表しており、FAR内に格納することは想定されていません。
MAFアプリケーションでは、JavaコードからWebサービス層(RESTおよびSOAPの両方)を起動して、その結果をJavaメソッドで使用できます。
MAFでは、使用可能なGenericTypeBeanSerializationHelperユーティリティ・クラスが提供され、POJO (JavaBeansオブジェクト)とMAFのGenericTypeオブジェクトとの間で次の変換ルールのセットに基づいて変換が実行されます。
POJOからGenericTypeオブジェクトに変換する場合:
プロパティの決定に標準JavaBeansの反映ルールが使用されます。
変換プロセスでは一時プロパティが無視されます。
読取り可能プロパティはGenericType属性に変換されます。
配列プロパティはGenericType内で繰返し属性として表されます。
マッピング・プロパティはGenericType内で個別の属性として表されます。
非プリミティブ・プロパティはネストされたGenericTypeオブジェクトとして表されます。
GenericTypeオブジェクトからPOJOに変換される場合:
プロパティの決定に標準JavaBeansの反映ルールが使用されます。
変換プロセスでは一時プロパティが無視されます。
書込み可能プロパティはGenericType属性に変換されます。
GenericType内の繰返し属性は配列オブジェクトに変換されます。
POJOにMapインタフェースが実装されている場合は、標準アクセッサを介して設定できないすべてのプロパティがMapのsetメソッドを介してPOJOに設定されます。
非プリミティブ属性はネストされたPOJOオブジェクトとして表されます。
このヘルパーAPIを使用する利点は、Webサービスから受け取ったレスポンスを取得して、1回のコールでJavaBeanに変換できることです。
たとえば、Webサービスは、ビジネス・ロジック全体で再利用する必要があるEmployeeオブジェクトを渡したり戻したりします。このオブジェクトには次のプロパティ・セットがあります。
String型のname
address (street、city、stateおよびzipcodeの各属性を持つ複合オブジェクト)
long型のid
float型のsalary
String型のphone(複数のphoneになる可能性もある)
String型のpassword(このpasswordはバックエンドのWebサービスに送信しないでください)
例8-7は、考えられるEmployeeオブジェクトのコードを示しています。
例8-7 Employeeオブジェクト
public class Employee {
protected String name;
protected Address address;
protected long id;
protected float salary;
protected String[] phone;
protected transient String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setPassword(String password) {
this.password = password;
}
public String[] getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
例8-8は、EmployeeクラスのAddressオブジェクトのコードとして考えられるものを示しています。
例8-8 Addressオブジェクト
public class Address {
protected String street;
protected String city;
protected String state;
protected String zipcode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
変換ルールについては次に注意します。
passwordは一時的に定義されるため、変換アルゴリズムに対しては無視されます。
name、address、idおよびsalaryにはすべてgetメソッドおよびsetメソッドがあるため、それらはすべてGenericTypeとの間で変換が行われます。
プロパティ・タイプに基づき、oracle.adfmf.misc.ConverterクラスのcoerceToType(Object, Class)メソッドの定義に従って、プロパティをタイプ間で強制変換できます。
addressなどの複合オブジェクトは、変換アルゴリズムによって再帰的に処理することで、変換の方向により、子であるGenericTypeを構築するか、POJO複合オブジェクトを作成してデータを移入します。
phoneはStringオブジェクトの配列で、それぞれが一意の電話番号を表しており、またこの要素のカーディナリティは2以上のため、変換アルゴリズムによってGenericTypeオブジェクト内のphone属性におけるすべての組合せが検索され、それらが配列として表される他、Bean上ではsetPhoneメソッドが起動されます。GenericTypeBeanSerializationHandlerのtoGenericTypeメソッドでは各配置要素が取得され、個別のphone属性としてtoGenericTypeに追加されます。
次のように定義されている場合:
final String EMPLOYEE_VIRTUAL_BEAN_NAME = "EmployeeDC.Types.Employee"; Employee emp = getEmployee(); GenericType gt = null;
Employeeオブジェクトは、次のようにGenericTypeに変換されます。
gt = GenericTypeBeanSerializationHelper.toGenericType
(EMPLOYEE_VIRTUAL_BEAN_NAME, emp);
GenericTypeは次のようにEmployeeオブジェクトに変換されます。
emp = GenericTypeBeanSerializationHelper.fromGenericType
(Employee.class, gt, null);
正常に変換するには次の点を考慮します。
POJOでは通常、それらに関連付けられたGenericType構造に厳密に従います。
GenericType構造から外れた場合は、次のいずれかの方法に従います。
追加のBeanプロパティを一時的に宣言します。
操作パラメータとして使用されたときに欠落データをバッキング・サービスが処理できる場合は、POJOからオプション・プロパティを除外できます。
GenericTypeは、SOAPデータ・コントロールにのみ公開されます。仮想タイプには、toGenericTypeメソッドに渡される、関連付けられた仮想Bean名があります。JDeveloperの「データ・コントロール」ウィンドウで仮想タイプ上にカーソルを置くことによって仮想Bean名にアクセスできます。通常の名前フォーマットは、<DCName>.Types.<methodName>.<argName>です。
詳細は、Oracle Fusion Middleware Oracle Mobile Application Framework Java APIリファレンスを参照してください。
MAFを使用すると、プログラムからWebサービス・オブジェクトのイテレータにアクセスして、そのオブジェクトの行を挿入および削除できます。これを行うには、oracle.adfmf.bindings.iterator.BasicIteratorクラスのcreateRowおよびdeleteRowメソッドを使用します。
例8-9は、行をWebサービス・オブジェクトに追加する方法を示しています。
例8-9 行の挿入
String keyFieldNames[] = {"EMPLID","ACAD_CAREER","INSTITUTION"};
String keyFieldValues[] = {"SR12030","UGRD","PSUNV"};
AmxAccessorIteratorBinding acIter =
(AmxAccessorIteratorBinding)((AdfmfJavaUtilities.getValueExpression
("#{bindings.KEYIterator}", Object.class))
.getValue(AdfmfJavaUtilities.getAdfELContext()));
BasicIterator iter = acIter.getIterator();
GenericType key = (GenericType)iter.getDataProvider();
key.setAttribute("FIELDNAME", keyFieldNames[0]);
key.setAttribute("FIELDVALUE", keyFieldValues[0]);
int totalRowCount = 0;
int currIndex = 0;
for (int i = 1; i < keyFieldNames.length; i++) {
totalRowCount = iter.getTotalRowCount();
currIndex = iter.getCurrentIndex();
System.out.println("Starting to add rows.. \n\t Total Row Count: " +
totalRowCount + "\n\t Current Row Index: " + currIndex);
// Create rows for key iterator
iter.createRow();
totalRowCount = iter.getTotalRowCount();
System.out.println("\t Total Row Count after creating row: " + totalRowCount);
if (iter.hasNext()) {
iter.next();
}
currIndex = iter.getCurrentIndex();
System.out.println("\t Current Row Index after setting current
index to newly added row: " + currIndex);
GenericType key1 = (GenericType)iter.getDataProvider();
key1.setAttribute("FIELDNAME", keyFieldNames[i]);
key1.setAttribute("FIELDVALUE", keyFieldValues[i]);
}
// Execute method
// Add call to execute the action binding to execute the action.
// If this is a web service call, the modified GenericType object
// will be sent to the server and the server will respond appropriately
|
注意: ブール入力パラメータの有無にかかわらず、 |
oracle.adfmf.dc.ws.rest.RestServiceAdapterインタフェースを使用して、RESTコールで送信されるデータにアクセスできます(このデータは、JavaScript Object Notationと表される場合があります)。RestServiceAdapterインタフェースによって、Webサービス・データ・コントロールを作成したり、それと直接やりとりする必要なしに、Webサービス操作の実行をトリガーできます。
MAFアプリケーションでRestServiceAdapterインタフェースを使用するには、connections.xmlファイルに接続が存在することを確認し(第8.3項「新しいWebサービス接続の作成」を参照)、次の例で示すようにコードをBeanクラスに追加します。
例8-10は、GETリクエストに対するRestServiceAdapterの使用方法を示しています。
例8-10 GETリクエストに対するRestServiceAdapterの使用方法
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
// Clear any previously set request properties, if any
restServiceAdapter.clearRequestProperties();
// Set the connection name
restServiceAdapter.setConnectionName("RestServerEndpoint");
// Specify the type of request
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);
// Specify the number of retries
restServiceAdapter.setRetryLimit(0);
// Set the URI which is defined after the endpoint in the connections.xml.
// The request is the endpoint + the URI being set
restServiceAdapter.setRequestURI("/WebService/Departments/100");
String response = "";
// Execute SEND and RECEIVE operation
try {
// For GET request, there is no payload
response = restServiceAdapter.send("");
}
catch (Exception e) {
e.printStackTrace();
}
例8-11は、POSTリクエストに対するRestServiceAdapterの使用方法を示しています。
例8-11 POSTリクエストに対するRestServiceAdapterの使用方法
String id = "111";
String name = "TestName111";
String location = "TestLocation111";
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("RestServerEndpoint");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_POST);
restServiceAdapter.setRetryLimit(0);
restServiceAdapter.setRequestURI("/WebService/Departments");
String response = "";
// Execute SEND and RECEIVE operation
try {
String postData = makeDepartmentPost("DEPT", id, name, location);
response = restServiceAdapter.send(postData);
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("The response is: " + response);
private String makeDepartmentPost(String rootName, String id,
String name, String location) {
String ret = "<" + rootName + ">";
ret += "<DEPTID>" + id + "</DEPTID>";
ret += "<NAME>" + name + "</NAME>";
ret += "<LOCATION>" + location + "</LOCATION>";
ret += "</" + rootName + ">";
return ret;
}
例8-12は、PUTリクエストに対するRestServiceAdapterの使用方法を示しています。
例8-12 PUTリクエストに対するRestServiceAdapterの使用方法
String id = "111";
String name = "TestName111";
String location = "TestLocation111";
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("RestServerEndpoint");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_PUT);
restServiceAdapter.setRetryLimit(0);
restServiceAdapter.setRequestURI("/WebService/Departments");
String response = "";
// Execute SEND and RECEIVE operation
try {
String putData = makeDepartmentPut("DEPT", id, name, location);
response = restServiceAdapter.send(putData);
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("The response is: " + response);
private String makeDepartmentPut(String rootName, String id,
String name, String location) {
String ret = "<" + rootName + ">";
ret += "<DEPTID>" + id + "</DEPTID>";
ret += "<NAME>" + name + "</NAME>";
ret += "<LOCATION>" + location + "</LOCATION>";
ret += "</" + rootName + ">";
return ret;
}
例8-13は、DELETEリクエストに対するRestServiceAdapterの使用方法を示しています。
例8-13 DELETEリクエストに対するRestServiceAdapterの使用方法
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("RestServerEndpoint");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_DELETE);
restServiceAdapter.setRetryLimit(0);
restServiceAdapter.setRequestURI("/WebService/Departments/44");
String response = "";
// Execute SEND and RECEIVE operation
try {
// For DELETE request, there is no payload
response = restServiceAdapter.send("");
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("The response is: " + response);
RestServiceAdapterを使用する場合は、AcceptヘッダーとContent-Typeヘッダーを設定して、MIMEタイプの不一致が原因でリクエストおよびレスポンスのペイロードが無効と判断されないようにします。
|
注意: REST Webサービス・アダプタでは、モバイル・アプリケーション上の文字セットとしてUTF-8のみをサポートします。UTF-8は、アダプタのプログラムに埋め込まれています。 |
次のRestServiceAdapterメソッドを使用すると、javax.microedition.io.HttpConnectionを取得およびカスタマイズでき、さらに接続の入力と出力ストリームへのアクセスおよびやり取りが可能になり、これによってHttpConnectionからデータを読み取り、今後のサーバーへのアップロードのためにそれに書き込むことができます。
HttpConnectionを取得します。
HttpConnection getHttpConnection(String requestMethod,
String request,
Object httpHeadersValue)
HttpConnectionのOutputStreamを取得します。
OutputStream getOutputStream(HttpConnection connection)
HttpConnectionのInputStreamを取得します。
InputStream getInputStream(HttpConnection connection)
HttpConnectionを閉じます。
void close (HttpConnection connection)
connections.xmlファイルで接続名を検索し、接続のエンド・ポイントを返します。
String getConnectionEndPoint(String connecionName)
これらのメソッドは、RestServiceAdaperのsendメソッドおよびsendReceiveメソッドと同じ機能を実現しつつ、接続をカスタマイズする機会と、リクエストを送信し、レスポンスを受信するというプロセスを提供します。
例8-14では、指定されたリクエスト・メソッド、リクエストおよびHTTPヘッダー値を使用して、HttpConnectionを初期化して返しています。また、資格証明ストアから基本認証をリクエスト・ヘッダーに挿入し、入力ストリームを取得し、接続を閉じます。
例8-14 HttpConnectionの取得およびそのメソッドの使用
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
// Specify the type of request
String requestMethod = RestServiceAdapter.REQUEST_TYPE_GET;
// Get the connection end point from connections.xml
String requestEndPoint = restServiceAdapter.getConnectionEndPoint("GeoIP");
// Get the URI which is defined after the end point
String requestURI = "/xml/" + someIpAddress;
// The request is the end point + the URI being set
String request = requestEndPoint + requestURI;
// Specify some custom request headers
HashMap httpHeadersValue = new HashMap();
httpHeadersValue.put("Accept-Language", "en-US");
httpHeadersValue.put("My-Custom-Header-Item", "CustomItem1");
// Get the connection
HttpConnection connection =
restServiceAdapter.getHttpConnection(requestMethod,
request,
httpHeadersValue);
// Get the input stream
InputStream inputStream = restServiceAdapter.getInputStream(connection);
// Define data
ByteArrayOutputStream byStream = new ByteArrayOutputStream();
int res = 0;
int bufsize = 0, bufread = 0;
byte[] data = (bufsize > 0) ? new byte[bufsize] : new byte[1024];
// Use the input stream to read data
while ((res = inputStream.read(data)) > 0) {
byStream.write(data, 0, res);
bufread = bufread + res;
}
data = byStream.toByteArray();
// Use data
...
restServiceAdapter.close(connection);
...
Webサービス・コールから受け取ったバイナリ(非テキスト)レスポンスを処理するには、RestServiceAdapterを使用できます。これらのレスポンスには、PDFファイルやビデオ・ファイルなど、どの種類のバイナリ・データでも含めることができます。使用するRestServiceAdapterメソッドはsendReceiveです。
例8-15は、ファイルのリクエストをRESTサーバーに送信し、そのファイルをディスクに保存する方法を示しています(例8-16を参照)。
例8-15 ファイルのリクエストの送信
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("JagRestServerEndpoint");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);
restServiceAdapter.setRetryLimit(0);
restServiceAdapter.setRequestURI("/ftaServer/v1/kpis/123/related/1");
// Set credentials needed to access the REST server
String theUsername = "hr_spec_all";
String thePassword = "Welcome1";
String userPassword = theUsername + ":" + thePassword;
String encoding = new sun.misc.BASE64Encoder().encode(userPassword.getBytes());
restServiceAdapter.addRequestProperty("Authorization", "Basic " + encoding);
// Execute the SEND / RECEIVE operation.
// Since it is a GET request, there is no payload.
try {
this.responseRaw = restServiceAdapter.sendReceive("");
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("The response is: " + this.responseRaw);
// Write the response to a file
writeByteArrayToFile(this.responseRaw);
例8-16は、例8-15のコードによって呼び出されるメソッドを示しています。このメソッドでは、ファイルに対するbyte[]レスポンスをディスクに保存します。
例8-16 ファイルのディスクへの保存
public void writeByteArrayToFile(byte[] fileContent) {
BufferedOutputStream bos = null;
try {
FileOutputStream fos = new FileOutputStream(new File(fileToSavePath));
bos = new BufferedOutputStream(fos);
// Write the byte [] to a file
System.out.println("Writing byte array to file");
bos.write(fileContent);
System.out.println("File written");
}
catch(FileNotFoundException fnfe) {
System.out.println("Specified file not found" + fnfe);
}
catch (IOException ioe) {
System.out.println("Error while writing file" + ioe);
}
finally {
if(bos != null) {
try {
// Flush the BufferedOutputStream
bos.flush();
// Close the BufferedOutputStream
bos.close();
}
catch (Exception e) {
}
}
}
maf-config.xmlファイルを使用すると、RESTレスポンスに予期しないまたはXSDで定義されていない子または属性が含まれていた場合のMAFの動作を指定できます。
厳密な検証が有効になっている場合、MAFでは例外をスローします。
厳密な検証が無効になっている場合は、条件がログに記録され、例外をスローすることなく実行が継続されます。
例8-17は、validatedパラメータの設定方法を示しています。このパラメータの値をtrueに定義した場合、厳密な検証が行われます。値がfalse (デフォルト)の場合、厳密な検証は行われません。
コール対象のWebサービスが自社ファイアウォールの外部にある場合は、HTTPプロキシ・サーバーを使用できるような適切な構成にJavaシステム・プロパティが設定されていることを確認する必要があります。
デフォルトでは、MAFはiOSおよびAndroidプラットフォームのシステム設定を使用してプロキシ情報を判別します。たとえば、iOSデバイスの設定ユーティリティを使用してプロキシ情報が設定されている場合、CVMがそれを自動的に取り込みます。
|
注意: MAFアプリケーションごとに異なるプロキシを定義できます。 |
デバイス設定からプロキシ情報を取得しない場合は、まず-Dcom.oracle.net.httpProxySourceシステム・プロパティを追加する必要があります。このプロパティのデフォルト値は「native」であり、プロキシ情報はデバイス設定から取得されます。userなど別の値(たとえば、-Dcom.oracle.net.httpProxySource=user)を指定して、それを無効にする必要があります。
CVMは、次の2種類のメカニズムを使用してネットワーク接続を有効にします。
汎用接続フレームワーク(GCF)。このメカニズムが使用された場合、プロキシはシステム・プロパティ-Dcom.sun.cdc.io.http.proxy=<host>:<port>によって定義されます。
java.net API。このメカニズムが使用された場合、プロキシは標準のhttp.proxyHostおよびhttp.proxyPortによって定義されます。
いずれの場合でも、cvm.propertiesファイルに3つすべてのプロパティを定義することをお薦めしますが、そうすると次のようになります。
java.commandline.argument=-Dcom.oracle.net.httpProxySource=user java.commandline.argument=-Dcom.sun.cdc.io.http.proxy=www-proxy.us.mycompany.com:80 java.commandline.argument=-Dhttp.proxyHost=www-proxy.us.mycompany.com java.commandline.argument=-Dhttp.proxyPort=80
|
注意: これらのプロパティは、ネットワーク・コールのCVM側にのみ影響を与えます。 |