Oracle® Mobile Application Framework Oracle Mobile Application Frameworkでのモバイル・アプリケーションの開発 2.1.0 E60836-01 |
|
![]() 前 |
![]() 次 |
この章では、サード・パーティのWebサービスをMAF AMXアプリケーション機能の実装に統合する方法について説明します。
この章の内容は次のとおりです。
Webサービスでは、アプリケーションおよびその機能は、定義済のアプリケーション・プログラミング・インタフェースを使用してデータと情報を交換できます。Webサービスを使用すると、元のアプリケーションのプラットフォームや言語に関係なくビジネス機能を公開できます。これは、ビジネス機能を、他のアプリケーションでも認識され、使用可能な標準XMLコンストラクトで構成されるメッセージに抽象化して公開するからです。
MAFアプリケーションでは、Webサービスを使用してリモート・データ・ソースと対話します。具体的には、次のとおりです。
リモート・データ・ソース内のデータの問合せ。
リモート・データ・ソースとの双方向のデータ書込み。
MAFアプリケーションでWebサービスを使用する最も一般的なユース・ケースの一部を次に示します。
Webサービスとしてはすぐに利用できるが、アプリケーション内で開発するには時間がかかる機能を追加するため
異なるアーキテクチャで実行されるアプリケーションへのアクセスを提供するため
MAFアプリケーションでWebサービスを使用すると、次の手順を実行できます。
Webサービス上で公開されている機能のサブセットからの選択。Webサービスによって提供されているエンタープライズ・データ以外はリクエストできないので、Webサービス・データ・コントロールで公開しているアプリケーション機能の数を減らすことにより、エンタープライズ・データに対するアクセス可能またはアクセス不可の制限設定に対応できます。
モバイル・デバイスのリソースにとっては処理に時間がかかりすぎる機能を提供します。この原因として考えられるのは、デバイスが行う必要がある実際の作業量か、または機能が基づくデータ・セットがデバイス上でローカルに使用可能なものよりもはるかに大きいことです。
注意: CPU負荷の高い機能はサービス(サーバー側)にアウトソースするよう検討することをお薦めします。 |
MAFでは、SOAP WebサービスとREST Webサービスの両方の消費をサポートしています。使用するタイプを決定する前に、次の点を考慮してください。
大規模なペイロードや冗長なXML Schemaを使用しているSOAPは、MAFアプリケーションのパフォーマンスに影響する可能性があります。REST Webサービス(利用可能な場合)を使用するか、Oracle Service Bus (http://www.oracle.com/technetwork/middleware/service-bus/overview/index.html
を参照)のようなミドルウェア・ソリューションを挿入して、ペイロードをSOAPからREST JSONに変換することをお薦めします。
MAFはETL (抽出、変換、ロード)ツールではないので、複雑なWebサービスのペイロードに対応するにはコードを記述する必要があり、その結果、コードが複雑になるだけでなく、パフォーマンスも低下する可能性があります。Oracle Service Busのようなミドルウェア・ソリューションを使用することで、モバイル環境に適したデータ・ペイロードの形成が可能になります。
次のWebサービス使用のシナリオでは、データ・アクセス(シナリオ1)の他に、計算およびデータ駆動型の機能(シナリオ2および3)を示します。
エンタープライズ・データ・ストアから一連の商談データをフェッチして、エンド・ユーザーがデバイスでそのデータを操作し、Webサービスを介してエンタープライズ・データ・ストアに変更をポストできるようにします。
一部のエンタープライズ・データに対して生成されるレポートを要求し、そのレポートをフェッチします。
顧客サイトへのルートのマップ・イメージを取得します。
MAFを使用して開発されたアプリケーション機能でWebサービスを使用する場合、外部Webサービスのデータ・コントロールを作成するのが最も一般的な方法です。詳細については、次の情報を参照してください。
JDeveloperでは、既存のREST Webサービスのデータ・コントロールを作成できます。このREST Webサービスは、XMLレスポンスを戻します。
注意: ファイアウォールで保護されている環境で、ファイアウォール外にあるWebサービスを使用する場合は、JDeveloperで「Webブラウザとプロキシ」の設定を構成する必要があります。詳細は、第15.10項「ブラウザ・プロキシ情報の構成」を参照してください。 |
同じ接続を使用して、REST Webサービス・データ・コントロールに1つ以上のHTTPメソッドを関連付けることができます。RESTサービスにより公開されたカスタム操作にアクセスできます。これらのカスタム操作は、HTTPメソッドの1つにマップされ、データ・コントロールを作成することでクライアントに公開できます。
モバイル・デバイスでセキュリティおよび通知機能を使用する場合は、RESTデータ・コントロールによって公開された特定の操作で使用する標準のHTTPヘッダーにカスタム・ヘッダーおよびカスタム値を追加できます。
始める前に
データ・コントロールがアクセスするREST Webサービスへのアクセス権があることを確認します。
REST Webサービス・データ・コントロールを作成するには:
「アプリケーション」ウィンドウで、アプリケーション名を右クリックし、JDeveloperのメイン・メニューから「ファイル」→「新規」→「ギャラリから」を選択します。
「新規ギャラリ」ダイアログで、左側の「ビジネス層」ノードを開いて「Webサービス」を選択します。右側の「アイテム」リストから「Webサービス・データ・コントロール(SOAP/REST)」を選択して(図15-4を参照)、「OK」をクリックします。
Webサービス・データ・コントロールの作成ウィザードの「データ・ソース」ページで、「REST」を選択します(図15-1参照)。
「Webサービス・データ・コントロールの作成」ウィザードの説明に従って、次の点に注意しながらデータ・コントロールの作成を完了します。
MAFでは、Webサービスに対して基本認証のみをサポートしています(第15.7項「セキュアなWebサービスへのアクセス」を参照)。新しい接続の作成時に、「URL接続の作成」ダイアログの「認証タイプ」フィールドで、「基本」を選択します。
MAFでは、GET
、POST
、PUT
およびDELETE
のすべてのHTTPメソッド・タイプをサポートしています。「リソース」ページの「メソッド表示名」フィールドへの入力時に、これらのメソッド・タイプのいずれかを選択できます(図15-2を参照)。
注意: 同じ接続および同じREST Webサービス・データ・コントロールを使用して4つのメソッドをすべて追加できます。 |
「メソッドの詳細」ページ(図15-3を参照)のリソース・メソッドごとに、XMLペイロードとレスポンス・コンテンツに使用するXSDのファイル参照を指定する必要があります。XSDは、ViewControllerプロジェクト内のファイルとして使用できる必要があります。
注意: MAFではコンパイル時にXSD構造の内部定義を作成するため、アプリケーションのコンパイル後はXSDを変更しないようにします。そのため、XSDファイルをローカルに参照することをお薦めします(これには、MAFアプリケーションをオフラインで使用できるという利点もあります)。リモートXSDの使用がパフォーマンスに悪影響を与えるのは、MAFではアプリケーションを実行するたびにXSDを取得するためです。 |
前述の手順に従ってREST Webサービス・データ・コントロールを作成すると、そのコントロールは、JDeveloper経由で使用可能な他の技術によって提供される、対応するコントロールとまったく同じように動作します。
RESTDemoという名前のMAFサンプル・アプリケーション(開発コンピュータのjdev_install
/jdeveloper/jdev/extensions/oracle.maf/Samples
ディレクトリにあるPublicSamples.zip
ファイルにあります)は、MAFアプリケーションでのREST Webサービスの使用方法を示しています。
データ・コントロールを使用しないJavaによるREST Webサービスの使用方法の詳細は、第15.8.2項「REST Webサービス・アダプタの使用方法」を参照してください。
JDeveloperでは、そのサービスのWeb Services Description Language (WSDL)ファイルのみを使用して、既存のSOAP Webサービスのデータ・コントロールを作成します。ローカル・ファイル・システムでWSDLファイルを参照するか、Universal Description, Discovery and Integration (UDDI)レジストリでWSDLファイルを検索するか、WSDL URLを直接入力することができます。
注意: ファイアウォールで保護されている環境で、ファイアウォール外にあるWebサービスを使用する場合は、JDeveloperで「Webブラウザとプロキシ」の設定を構成する必要があります。詳細は、第15.10項「ブラウザ・プロキシ情報の構成」を参照してください。 |
SOAP Webサービス・データ・コントロールを作成するには:
「アプリケーション」ウィンドウで、アプリケーション名を右クリックし、JDeveloperのメイン・メニューから「ファイル」→「新規」→「ギャラリから」を選択します。
「新規ギャラリ」ダイアログで、左側の「ビジネス層」ノードを開いて「Webサービス」を選択します。右側の「アイテム」リストから「Webサービス・データ・コントロール(SOAP/REST)」を選択して(図15-4を参照)、「OK」をクリックします。
「Webサービス・データ・コントロールの作成」ウィザードの「データ・ソース」ページで、「SOAP」を選択します。
ウィザードの指示に従って、データ・コントロールの作成を完了します。
注意: MAFでは、SOAP 1.1および1.2の両方のバージョンで次のエンコーディング・スタイルをサポートしています。
|
MAFでは、DataControls.dcx
ファイルにカスタムのプロバイダ・クラスを指定できます(例15-3を参照)。このカスタム・クラスでは、oracle.adfinternal.model.adapter.webservice.provider.soap.SOAPProvider
を拡張します。これは、SoapHeader[] getAdditionalSoapHeaders()
メソッドの実装の指定に使用できます。
例15-1は、SOAPProvider
を拡張して、例15-2に示すカスタム・ヘッダーを作成する方法を示しています。
例15-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; } }
例15-2は、新しいカスタム・ヘッダーを示しています。
例15-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
注意: SOAPProvider を拡張するクラスに変数を渡す事前定義済のメカニズムはありません。Javaの標準的な手法で十分に対応できます。たとえば、メンバー変数とアクセッサをクラスに追加すれば、getAdditionalSoapHeaders() メソッドによって返されたSoapHeader[] のコンテンツの設定時に、それらを参照できます。 |
例15-3は、SOAPProvider
登録に関するDataControls.dcx
ファイルのサンプル・エントリを示しています。
例15-3 DataControls.dcxファイルでのSOAPProviderの登録
<definition xmlns="http://xmlns.oracle.com/adfm/adapter/webservice" name="SoapService" version="1.0" provider="provider.ebs.soap.EBSSOAPProvider" 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では、SOAPサービス参照から作成されたすべてのWebサービス・データ・コントロールについて、DataControls.dcx
ファイルにdcStructureVersion
プロパティを追加します。デフォルトでは、このプロパティは2に設定されています。
ヒント: 以前のバージョンのMAFを使用してアプリケーションを開発し、引き続き同じコードを使用してJavaからのレスポンスにアクセスする場合は、このプロパティを削除するか、その値を1に変更する必要があります。 |
dcStructureVersion
プロパティはカスタマイズ目的で使用され、Webサービス・データ・コントロールによって返された結果の構造に影響します。
SOAPコールから返されたオブジェクトにアクセスするには、次のようなコードを使用してください。
result = (GenericType)AdfmfJavaUtilities.invokeDataControlMethod("WeatherSOAP", null, "GetCityWeatherByZIP", pnames, pvals, ptypes); // access SOAP object to obtain information about the returned object result.get("City");
コレクションを使用する場合は、次のようなコードの使用を検討してください。
result = (GenericType)AdfmfJavaUtilities.invokeDataControlMethod("WeatherSOAP", null, "GetCityWeatherByZIP", pnames, pvals, ptypes); result = result!=null && result.getParent()!=null ? result.getParent() : result;
Webサービス・データ・コントロールの作成後は、図15-5に示すように、Webサービスの操作およびその操作の戻り値が「データ・コントロール」ウィンドウに表示されます。
他のデータ・コントロールと同じく、Webサービス操作から返されたオブジェクトをドラッグ・アンド・ドロップして、MAF AMXページでユーザー・インタフェース・コンポーネントを作成できます。詳細は、第12.3.2.4項「データ・コントロールのビューへの追加」を参照してください。Webサービスの操作から戻されたデータが表示されると、次のオブジェクト・タイプが処理されます。
コレクション
Webサービスの操作により戻された複合オブジェクト
Webサービスの操作により戻された、ネストされた複合オブジェクト
Webサービスの操作を使用して、標準データ型と複合データ型の両方を更新および削除できます。
図15-5に示すように、各データ・コントロール・オブジェクトはアイコンで表されます。表15-1は、各アイコンが表すもの、「データ・コントロール」パネルの階層内で表示される場所、そのアイコンを使用して作成できるコンポーネントを示しています。詳細は、第14.6項「「データ・コントロール」パネルでのデータバインドされたUIコンポーネントの作成」を参照してください。
表15-1 Webサービスの「データ・コントロール」パネルのアイコンおよびオブジェクト階層
アイコン | 名前 | 説明 | 作成できるコンポーネント |
---|---|---|---|
|
データ・コントロール |
データ・コントロールを表します。データ・コントロール自体を使用してUIコンポーネントを作成することはできませんが、その下に表示される子オブジェクトは、いずれも使用できます。通常、各Webサービスに対するデータ・コントロールは1つです。 |
他のオブジェクトのコンテナとして機能し、コンポーネント作成には使用されません。 |
![]() |
コレクション |
サービスの操作から返されるデータ・コントロールを表現します。コレクションは、メソッド戻りオブジェクト、他のコレクション、または構造化属性の下の子としても表示されます。コレクションの下の子は、属性、他のコレクション、カスタム・メソッド、コレクションに対して実行できる組込み操作などです。 |
フォーム、表、グラフ、ツリー、レンジ・ナビゲーションの各コンポーネント、およびマスター/ディテール・コンポーネント。第13.5項「データ視覚化の指定」も参照してください。 |
|
属性 |
オブジェクト内の個別のデータ要素(行の属性など)を表します。属性は、自分の属するコレクションまたはメソッド戻りの下に、子として表示されます。 |
ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。第13.2項「ページ・レイアウトの設計」も参照してください。 |
![]() |
構造化された属性 |
複合型でありコレクションではない、返されたオブジェクトを表します。たとえば、構造化属性は、現在のサービス・リクエストに割り当てられた単一のユーザーを表現します。 |
ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。第13.2項「ページ・レイアウトの設計」も参照してください。 |
![]() |
メソッド |
データ・コントロールの操作またはその公開された構造のいずれかを表し、パラメータの受入れや、ビジネス・ロジックの実行を行ったり、オプションで単一の値、構造、またはそれらのコレクションを戻すことができます。 |
コマンド・コンポーネント。 パラメータを受け入れるメソッドの場合: コマンド・コンポーネントおよびパラメータ付きフォーム。また、第13.3項「UIコンポーネントの作成と使用方法」も参照してください。 |
![]() |
メソッド戻り値 |
Webサービス・メソッドによって戻されたオブジェクトを表します。戻されたオブジェクトは、単一の値またはコレクションです。 メソッド戻りは、これを戻すメソッドの下に、子として表示されます。メソッドの戻りオブジェクトの下の子として表示されるオブジェクトは、該当コレクションの属性、親コレクションに関連するアクションを実行する他のメソッド、および親コレクション上で実行可能な操作です。 単一値のメソッド戻り値がドロップされると、メソッドはフレームワークにより自動的に起動されなくなります。メソッドを起動するために、対応するメソッドをボタンとしてドロップする必要があります。また、タスク・フローを使用している場合は、メソッド・アクティビティを作成できます。 |
コレクションと属性、および問合せフォームの場合と同じコンポーネント。 |
![]() |
操作 |
親オブジェクトに対してアクションを実行する、組込みデータ・コントロール操作を表します。データ・コントロール操作は、コレクションの下の「操作」ノードにあります。1つ以上のパラメータが操作に必要な場合、それらのパラメータは操作の下の「パラメータ」ノードにリストされます。 現在行のナビゲーションと設定のために、 |
ボタン、リンク、メニューなどのユーザー・インタフェース・コマンド・コンポーネント。詳細は、第13.3項「UIコンポーネントの作成と使用方法」を参照してください。 |
![]() |
パラメータ |
メソッドまたはその下に表示される操作によって宣言されたパラメータ値を表します。パラメータは、メソッドまたは操作の下の「パラメータ」ノード内に表示されます。 配列および構造化パラメータは、データ・コントロールの下の更新可能な構造化属性およびコレクションとして公開され、UI上にADFフォームまたは更新可能な表としてドロップできます。UIを使用して配列または複合オブジェクト(標準のJava型ではない)のパラメータを作成できます。 |
ラベル、テキストおよび選択リストの各コンポーネント。詳細は、第13.3.15項「リスト・ビューおよびリスト・アイテム・コンポーネントの使用方法」を参照してください。 |
Webサービスの接続情報は、アプリケーション内の他の接続とともにconnections.xml
ファイルに保存されます。このファイルは、Webサービス・データ・コントロールの作成時に新しいWebサービス・データ・コントロールウィザードによってadf/META-INF
ディレクトリに生成されるため、明示的に作成する必要はありません(第15.2項「RESTを使用したWebサービス・データ・コントロールの作成」および第15.3項「SOAPを使用したWebサービス・データ・コントロールの作成」を参照)。
接続設定を変更するには、connections.xml
ファイルを編集します。
Webサービス・データ・コントロールを作成すると、URIのエンド・ポイントを変更できます。これは、テスト環境から本番環境にアプリケーション機能を移行するような場合に便利です。
エンド・ポイントを変更するには、connections.xml
ファイルを編集します。
MAFは、保護されたWebサービスと保護されていないWebサービスの両方をサポートしています。詳細は、第29章「MAFアプリケーションの保護」を参照してください。
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サービス・データ・コントロールを構成することでアクセスが可能になります。これを行うには、図15-6に示す「データ・コントロール・ポリシーの編集」ダイアログを使用します。このダイアログは次の方法で開くことができます。
「アプリケーション」ウィンドウで、アプリケーションのビュー・コントローラ・プロジェクトにある.dcx
ファイルを選択します。
「構造」ウィンドウで、構成が必要なWebサービス・データ・コントロールを右クリックし、ポップアップ・メニューから「Webサービス・セキュリティの定義」を選択します。
注意: JDeveloperは、Webサービス・ポリシー定義をwsm-assembly.xml ファイル(アプリケーション・ワークスペースのMETA-INF ディレクトリにあります)に格納します。 |
Cookieベースの認可のためにMAFアプリケーションがREST Webサービスを要求するたびに、MAFのセキュリティ・フレームワークは、REST Webサービスのトランスポート・レイヤーが、REST WebサービスのURLエンド・ポイントに関連付けられているログイン接続に対してCookieの挿入が可能かどうかをチェックできるようにします。つまり、connections.xml
ファイルに<injectCookiesToRESTHttpHeader value="true"/>
が含まれている必要があります。REST Webサービス・コールでログイン・サーバーのCookieを有効にするようにMAFアプリケーション・ログインを構成する方法の詳細は、第29.4.3項「Oracle Mobile and Social Identity Managementを使用して認証を構成する方法」を参照してください。
これは、Oracle Access Management Mobile and Social (OAMMS)認証コンテキストにも当てはまり、WebリソースはOracle Access Managerサーバー10g WebGateによって保護されており、アクセス・トークンはObSSOCookieという暗号化されたCookieとして挿入されます。詳細は、第29.4.13項「REST Webサービス・コールへのCookieの挿入を可能にする場合の処理」を参照してください。
REST WebサービスがOAuthアクセス・トークンを予期している場合、REST Webサービスをサポートする事前定義済のセキュリティ・ポリシーoracle/oauth2_config_client_policy
にREST接続を関連付ける必要があります。現在、JDeveloperのデザインタイムではポリシーの関連付けがサポートされていません。REST接続を編集してポリシー・セットをWebサービスに手動で添付する必要があり、例15-4
に示すように、URIはoracle/oauth2_config_client_policy
に設定され、someapiは接続名です。
例15-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サービスのセキュリティに関連付ける必要があります(例15-5および例15-6を参照)。
注意: JDeveloperではconnections.xml ファイルの概要エディタが提供されないため、「プロパティ」ウィンドウを使用して、<Reference> 要素のadfcredentialStoreKey 属性をログイン・サーバー接続のadfCredentialStoreKey 属性用に構成されている名前で更新できます。または、「ソース」エディタを使用して属性を追加または更新できます。 |
例15-5は、adfCredentialStoreKey="MyAuth"
として参照されるWebサービス接続の定義を示しています。ここで、MyAuth
とは、ログイン接続の参照名です。
例15-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>
例15-6は、ログイン接続の定義を示しています。ここでのMyAuth
は、ログイン・サーバー接続における資格証明ストア・キーの値として使用されます。
例15-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により適切な例外が戻され、適切なアクションが起動されます(第30.4項「ロギングの使用方法と構成」を参照)。既存の例外で状況を適切に示せない場合は、新しい例外が追加されます。
connections.xml
ファイルは構成サービスの下でデプロイされ、管理されています。詳細は、第16章「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サービスに送信しないでください)
例15-7は、考えられるEmployee
オブジェクトのコードを示しています。
例15-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; }
例15-8は、Employee
クラスのAddress
オブジェクトのコードとして考えられるものを示しています。
例15-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
メソッドを使用します。
例15-9は、行をWebサービス・オブジェクトに追加する方法を示しています。
例15-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
注意: ブール入力パラメータの有無にかかわらず、createRow メソッドのシグネチャを使用できます。パラメータを指定せずにこのメソッドを使用した場合、ブール・パラメータの値をtrue に設定してcreateRow を使用した場合と同じ結果が生成されます。createRow() とcreateRow(true) では、どちらも新しい行を作成し、それをイテレータに挿入します。 |
oracle.adfmf.dc.ws.rest.RestServiceAdapter
インタフェースを使用して、RESTコールで送信されるデータにアクセスできます(このデータは、JavaScript Object Notationと表される場合があります)。RestServiceAdapter
インタフェースによって、Webサービス・データ・コントロールを作成したり、それと直接やりとりする必要なしに、Webサービス操作の実行をトリガーできます。
MAFアプリケーションでRestServiceAdapter
インタフェースを使用するには、connections.xml
ファイルに接続が存在することを確認し(第15.5項「新しいWebサービス接続の作成」を参照)、次の例で示すようにコードをBeanクラスに追加します。
例15-10は、GET
リクエストに対するRestServiceAdapter
の使用方法を示しています。
例15-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(); }
例15-11は、POST
リクエストに対するRestServiceAdapter
の使用方法を示しています。
例15-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; }
例15-12は、PUT
リクエストに対するRestServiceAdapter
の使用方法を示しています。
例15-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; }
例15-13は、DELETE
リクエストに対するRestServiceAdapter
の使用方法を示しています。
例15-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サービス・アダプタでは、MAFアプリケーション上の文字セットとして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
メソッドと同じ機能を実現しつつ、接続をカスタマイズする機会と、リクエストを送信し、レスポンスを受信するというプロセスを提供します。
例15-14では、指定されたリクエスト・メソッド、リクエストおよびHTTPヘッダー値を使用して、HttpConnection
を初期化して返しています。また、資格証明ストアから基本認証をリクエスト・ヘッダーに挿入し、入力ストリームを取得し、接続を閉じます。
例15-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
です。
例15-15は、ファイルのリクエストをRESTサーバーに送信し、そのファイルをディスクに保存する方法を示しています(例15-16を参照)。
例15-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);
例15-16は、例15-15のコードによって呼び出されるメソッドを示しています。このメソッドでは、ファイルに対するbyte[]
レスポンスをディスクに保存します。
例15-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では例外をスローします。
厳密な検証が無効になっている場合は、条件がログに記録され、例外をスローすることなく実行が継続されます。
例15-17は、validated
パラメータの設定方法を示しています。このパラメータの値をtrue
に定義した場合、厳密な検証が行われます。値がfalse
(デフォルト)の場合、厳密な検証は行われません。
XMLだけでなく、MAFアプリケーションで使用しているREST WebサービスもJavaScript Object Notation (JSON)形式で指定されたメッセージに対応できます。
RESTDemoという名前のMAFサンプル・アプリケーション(開発コンピュータのjdev_install
/jdeveloper/jdev/extensions/oracle.maf/Samples
ディレクトリにあるPublicSamples.zip
ファイルにあります)にはRESTJSONBean.java
ファイルが含まれ、RestServiceAdapter
(詳細は第15.8.2項「REST Webサービス・アダプタの使用方法」を参照)を使用してJSONをREST Webサービスのメッセージ形式として使用できるようにする方法を示しています。
このRESTDemoにはRESTJSONResponse.java
ファイルも含まれており、このファイルはJSONメッセージで表現され、JSONBeanSerializationHelper
クラスのfromJSON
メソッドを使用して適切な形式に変換されます。
RESTJSONBean
のloadData
メソッド(例15-18を参照)では、関連APIの使用方法を示します。
例15-18 JSONをメッセージ形式として使用する方法
public class RESTJSONBean { ... public void setResponse(RESTJSONResponse response) { RESTJSONResponse oldResponse = this.response; this.response = response; propertyChangeSupport.firePropertyChange("response", oldResponse, response); } public void loadData() { RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter(); // Clear previously set request properties, if any restServiceAdapter.clearRequestProperties(); // Set the connection name restServiceAdapter.setConnectionName("GeoIP"); // 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("/json/" + getSearchIp()); setJsonResponse(""); // Execute SEND and RECEIVE operation try { // For GET request, there is no payload setJsonResponse(restServiceAdapter.send("")); // Create a new RESTJSONResponse object and // parse the returned JSON string into this class RESTJSONResponse res = new RESTJSONResponse(); res = (RESTJSONResponse)JSONBeanSerializationHelper. fromJSON(RESTJSONResponse.class, getJsonResponse()); setResponse(res); } catch (Exception e) { e.printStackTrace(); } } ... }
追加情報と例については、Oracle Mobile Application Frameworkを使用したモバイル・アプリケーションでのREST-JSON Webサービスの使用方法というチュートリアルを参照してください。
MAFのREST Webサービス・クライアントはJavaScriptをサポートしていないため、MAFアプリケーションではJavaScriptの実行が必要なREST変換を正常に処理できません。つまり、クライアント側でJavaScriptを実行する必要があるサーバー・レスポンスは完了できません。元のリクエストの完了にJavaScriptのサポートが必要なWebページをリダイレクト経由で間接的に取得するコードは、MAFアプリケーションに含めることはできません。
次に示すのは、ほとんどのWebブラウザがJavaScriptをサポートしている場合に、受け入れ可能なシナリオです。ただし、MAFアプリケーション内で使用された場合は、期待どおりの結果にならない可能性があります。
アプリケーションがREST Webサービスを使用してデータをリクエストし、アプリケーション・サーバーがそのリクエストを認証サーバーにリダイレクトします。認証サーバーによって提供されるページは、さらに別のページにリダイレクトされ、その後で元のRESTエンド・ポイントに戻ります。この一連のリダイレクトでは、認証サーバーによって提供されるWebページのいずれかで、クライアントがJavaScriptを実行し、エンド・ユーザーがアプリケーション・サーバーに対して認証されることになります。
コール対象の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
によって定義されます。
いずれの場合でも、maf.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側にのみ影響を与えます。 |