Oracle® Fusion Middleware Oracle Mobile Application Frameworkでのモバイル・アプリケーションの開発 2.0 E56274-01 |
|
前 |
次 |
この章では、サード・パーティのWebサービスをMAF AMXアプリケーション機能の実装に統合する方法について説明します。
この章には次の項が含まれます:
Webサービスでは、アプリケーションおよびその機能は、定義済のアプリケーション・プログラミング・インタフェースを使用してデータと情報を交換できます。Webサービスを使用すると、元のアプリケーションのプラットフォームや言語に関係なくビジネス機能を公開できます。これは、ビジネス機能を、他のアプリケーションでも認識され、使用可能な標準XMLコンストラクトで構成されるメッセージに抽象化して公開するからです。
MAFアプリケーションでWebサービスを使用する最も一般的な理由の一部は次のとおりです。
Webサービスとしてはすぐに利用できるが、アプリケーション内で開発するには時間がかかる機能を追加するため
異なるアーキテクチャで実行されるアプリケーションへのアクセスを提供するため
MAFでは、SOAPとRESTの両方のWebサービスをサポートしており、サード・パーティのWebサービスをMAF AMXアプリケーション機能に統合できます。
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の両方のバージョンで次のエンコーディング・スタイルをサポートしています。
|
Webサービス・データ・コントロールの作成後は、図8-2に示すように、Webサービスの操作およびその操作の戻り値が「データ・コントロール」ウィンドウに表示されます。
他のデータ・コントロールと同じく、Webサービス操作から返されたオブジェクトをドラッグ・アンド・ドロップして、MAF AMXページでユーザー・インタフェース・コンポーネントを作成できます。詳細は、第5.3.2.4項「データ・コントロールのビューへの追加」を参照してください。Webサービスの操作から戻されたデータが表示されると、次のオブジェクト・タイプが処理されます。
コレクション
Webサービスの操作により戻された複合オブジェクト
Webサービスの操作により戻された、ネストされた複合オブジェクト
Webサービスの操作を使用して、標準データ型と複合データ型の両方を更新および削除できます。
図8-2に示すように、各データ・コントロール・オブジェクトはアイコンで表されます。表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項「リスト・ビューおよびリスト・アイテム・コンポーネントの使用方法」を参照してください。 |
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サービスのデータ・コントロールを作成できます。
注意: ファイアウォールで保護されている環境で、ファイアウォール外にある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-3参照)。
「Webサービス・データ・コントロールの作成」ウィザードの説明に従って、次の点に注意しながらデータ・コントロールの作成を完了します。
MAFでは、Webサービスに対して基本認証のみをサポートしています(第8.5項「セキュアなWebサービスへのアクセス」を参照)。新しい接続の作成時に、「URL接続の作成」ダイアログの「認証タイプ」フィールドで、「基本」を選択します。
MAFでは、GET
、POST
、PUT
およびDELETE
のすべてのHTTPメソッド・タイプをサポートしています。「リソース」ページの「メソッド表示名」フィールドへの入力時に、これらのメソッド・タイプのいずれかを選択できます(図8-4を参照)。
注意: 同じ接続および同じREST Webサービス・データ・コントロールを使用して4つのメソッドをすべて追加できます。 |
MAFでは、スプレッド・シート・データ内の区切り文字で区切られた値およびXMLデータ・フォーマットのXSLはサポートされません。
REST Webサービス・データ・コントロール定義にローカルXSDファイルを指定することによって、「メソッドの詳細」ページでスキーマの識別を可能にするフィールドのファイルURI参照を作成します(図8-5を参照)。
注意: 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サービスの接続情報は、アプリケーション内の他の接続とともに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側にのみ影響を与えます。 |