Oracle® Mobile Application Framework Oracle Mobile Application Frameworkでのモバイル・アプリケーションの開発 2.5.0.0.0 E94553-01 |
|
前 |
次 |
この章の内容は次のとおりです。
MAFは、MAFアプリケーションにおけるJSONオブジェクトを使用したREST Webサービスの消費をサポートしています。MAFでこのタイプのWebサービスが他のWebサービスよりも推奨される理由は、生成するペイロードが通常は少ないため、アプリケーションと、アプリケーションがアクセスするサービスとの間の通信のレスポンス時間が短くなるからです。
MAFアプリケーションでREST-JSON Webサービスを使用する場合は、WebサービスのURLエンド・ポイントへの接続をアプリケーションで構成する必要があります。MAFは、このエンド・ポイントをアプリケーションのconnections.xml
ファイルに格納します。また、connections.xml
に構成した値をとるアダプタ(RESTServiceAdapter
)を記述し、それを使用して、Webサービスに送信するリクエストURIを構築します。Webサービスが返すデータをモデル化するJavaクラスを記述する必要もあります。これらのクラスを使用して、WebサービスがアクセスするデータにアプリケーションのAMXページをバインドするデータ・コントロールを生成します。アプリケーションが保護されたWebサービスにアクセスする場合は、そのWebサービスのURLエンド・ポイントへの接続にセキュリティ・ポリシーを関連付ける必要があります。アプリケーションが、自社ファイアウォールの外部でホストされているサービスにアクセスする必要がある場合は、アプリケーションのmaf.properties
ファイルにエントリを構成する必要もあります。
注意:
RESTServiceAdapter
を記述するかわりに、MAFにより提供される、REST Webサービスにアクセスするクライアント・データ・モデルを生成するためのデザインタイム・サポートを使用します。「MAFアプリケーションでのクライアント・データ・モデルの作成」を参照してください。WorkBetterサンプル・アプリケーションは、RESTServiceAdapter
を使用してRESTサービスをプログラムで消費する例を示します。WorkBetterサンプル・アプリケーションのソース・コードにアクセスする方法の詳細は、「サンプルのMAFアプリケーション」を参照してください。
RestServiceAdapter
を使用して、RESTコールにより送信されたデータにアクセスし、Webサービス操作の実行をトリガーします。oracle.maf.api.dc.ws.rest
パッケージからのRestServiceAdapterFactory.createRestServiceAdapter()
APIは、RestServiceAdapter
を実装するアダプタを作成します。
サービスのURLエンド・ポイントへの接続がconnections.xml
ファイルに存在することを確認し、次の例で示すようにコードをBeanクラスに追加します。
Mobile Cloud Serviceに診断情報を送信するアダプタを作成する必要がある場合は、「Oracle Mobile Cloud Serviceへの診断情報の送信」で説明しているように、RestServiceAdapterFactory
.createMcsRestServiceAdapter()
APIを使用します。
RestServiceAdapterFactory
およびRestServiceAdapter
の詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。
.... import oracle.maf.api.dc.ws.rest.RestServiceAdapterFactory; import oracle.maf.api.dc.ws.rest.RestServiceAdapter; .... RestServiceAdapterFactory factory = RestServiceAdapterFactory.newFactory(); RestServiceAdapter restServiceAdapter = factory.createRestServiceAdapter(); // Clear any previously set request properties, if any restServiceAdapter.clearRequestProperties(); // Set the connection name restServiceAdapter.setConnectionName("RestServerEndpoint"); // Specify the type of request restServiceAdapter.setRequestMethod(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"); // Following code snippets demonstrate how to use getHttpURLConnection to initialize // and return java.net.HttpURLConnection or javax.net.ssl.HttpsURLConnection. // The getHttpURLConnection injects all security headers based on the security policy // configured for the connection used to create this adapter. // The supported policies depend on the authentication server type that you use (HTTP Basic, OAuth, or Web SSO). // Get the type of request String requestMethod = RestServiceAdapter.REQUEST_TYPE_GET; // Get the connection end point from connections.xml String requestEndPoint = restServiceAdapter.getConnectionEndPoint("RestServerEndpoint"); // 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 HttpURLConnection connection = restServiceAdapter.getHttpURLConnection(requestMethod, request, httpHeadersValue); String response = ""; // Execute SEND and RECEIVE operation try { // For GET request, there is no payload response = restServiceAdapter.send(""); } catch (Exception e) { e.printStackTrace(); }
次の例は、POST
リクエストに対するRestServiceAdapter
の使用方法を示しています。
String id = "111"; String name = "TestName111"; String location = "TestLocation111"; .... restServiceAdapter.clearRequestProperties(); restServiceAdapter.setConnectionName("RestServerEndpoint"); restServiceAdapter.setRequestMethod(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; }
次の例は、PUT
リクエストに対するRestServiceAdapter
の使用方法を示しています。
String id = "111"; String name = "TestName111"; String location = "TestLocation111"; .... restServiceAdapter.clearRequestProperties(); restServiceAdapter.setConnectionName("RestServerEndpoint"); restServiceAdapter.setRequestMethod(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; }
次の例は、DELETE
リクエストに対するRestServiceAdapter
の使用方法を示しています。
.... restServiceAdapter.clearRequestProperties(); restServiceAdapter.setConnectionName("RestServerEndpoint"); restServiceAdapter.setRequestMethod(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
を使用して、java.net.HttpURLConnection
を取得し、カスタマイズしたり、HttpURLConnection
からのデータの読取りおよび書込み、さらにはサーバーへのアップロードが可能な接続の入力および出力ストリームと対話したりすることができます。
次の例では、指定されたリクエスト・メソッド、リクエストおよびHTTPヘッダー値を使用して、HttpURLConnection
を初期化して返しています。また、資格証明ストアから基本認証をリクエスト・ヘッダーに挿入し、入力ストリームを取得し、接続を閉じます。
.... // Get the connection HttpURLConnection httpURLConnection = restServiceAdapter.getHttpURLConnection(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
です。
次の例は、RESTサーバーにファイルのリクエストを送信し、ファイルをディスクに保存する方法を示しています。
RestServiceAdapterFactory factory = RestServiceAdapterFactory.newFactory(); RestServiceAdapter restServiceAdapter = factory.createRestServiceAdapter(); restServiceAdapter.clearRequestProperties(); restServiceAdapter.setConnectionName("JagRestServerEndpoint"); restServiceAdapter.setRequestMethod(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 and 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);
次の例は、前の例のコードによってコールされたメソッドを示しています。このメソッドでは、ファイルに対するbyte[]
レスポンスをディスクに保存します。
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では保護されたWebサービスと保護されていないWebサービスの両方がサポートされます。REST Webサービスが保護されている場合、REST Webサービスをサポートする事前定義済のセキュリティ・ポリシーにREST接続を関連付ける必要があります。
表17-1に、REST Webサービスへの接続に関連付けることができる事前定義済のセキュリティ・ポリシーを示します。「Webサービスへのアクセスを有効にする方法」では、事前定義済のセキュリティ・ポリシーに接続を関連付ける方法を説明します。
表17-1 RESTベースのWebサービスでサポートされるセキュリティ・ポリシー
認証タイプ | RESTポリシー | 説明 |
---|---|---|
HTTP Basic |
|
このポリシーは、アウトバウンド・クライアント・リクエストのHTTPヘッダーに資格証明を含め、Oracle Platform Security Servicesアイデンティティ・ストアに対してユーザーを認証します。また、このポリシーは、トランスポート・プロトコルがHTTPSであることを検証します。HTTPS以外のトランスポート・プロトコルを介するリクエストは拒否されます。このポリシーは、HTTPベースのクライアントで実行できます。 |
HTTP Basic |
|
このポリシーは、アウトバウンド・クライアント・リクエストのHTTPヘッダーに資格証明を含めます。このポリシーは、HTTPベースまたはHTTPSベースのクライアントで実行できます。 |
HTTP Basic |
|
このポリシーは、アウトバウンド・クライアント・リクエストのHTTPヘッダーに資格証明を含め、Oracle Platform Security Servicesアイデンティティ・ストアに対してユーザーを認証します。また、このポリシーは、トランスポート・プロトコルがHTTPSであることを検証します。HTTPS以外のトランスポート・プロトコルを介するリクエストは拒否されます。このポリシーは、HTTPベースのクライアントで実行できます。 |
HTTP Basic Web SSO |
|
このポリシーは、認証後に取得されたCookieをHTTPリクエスト・ヘッダーに挿入します(例: OAM Webgateリソース)。このポリシーでは、レスポンスCookieも設定します。このポリシーは、RESTベースのクライアントで実行できます。 |
OAuth |
|
このポリシーは、エンドポイントとの通信中にBearerトークン(OAuthアクセス・トークン)をHTTPリクエスト・ヘッダーに挿入します。このトークンは、任意のOAuth2サーバーから取得できます。このポリシーは、RESTベースのクライアントで実行できます。 |
これらのポリシーとその使用方法の詳細は、『Oracle Web Services ManagerによるWebサービスの保護とポリシーの管理』の使用する事前定義済ポリシーの決定に関する項と、事前定義済ポリシーに関する項を参照してください。
Webサービスが保護されており、認証トークンが予想される場合、Webサービスをサポートする事前定義済のセキュリティ・ポリシーにログイン接続を関連付ける必要があります。
maf-application.xml
概要エディタの「MAFログイン接続の作成」ダイアログを使用して、ログイン・サーバー接続を作成します。ログイン・サーバー接続の作成の詳細は、「MAFログイン接続の作成方法」を参照してください。Webサービスにセキュリティ・ポリシーを関連付けるには:
JDeveloperは、META-INF
ディレクトリ内のwsm-assembly.xml
ファイルに、Webサービス・ポリシー定義を保存します。
「データ・コントロール・ポリシーの編集」ダイアログ(図17-2を参照)を使用して、REST Webサービスにすでに関連付けられているセキュリティ・ポリシーを表示できます。「プロパティのオーバーライド」をクリックしてダイアログを開き、そのダイアログで、選択したポリシーのオーバーライドが許可されているプロパティの代替値を指定できます。
図17-2 Webサービス・データ・コントロール・ポリシーの編集
保護されたWebサービスにおけるユーザーの資格証明は、Webサービス・リクエストの起動時にそのリクエストに動的に挿入されます。
MAFではOracle Web Services Manager (OWSM) Mobile Agentを使用してWebサービス・リクエストによってユーザーIDを伝播させます。
Webサービスを起動する前に、ユーザーは、保護されたMAFアプリケーション機能の呼出しを試みるユーザーによってトリガーされた認証プロンプトに応答する必要があります。ユーザーの資格証明は、資格証明ストアに格納されます。この資格証明ストアは、認証プロバイダのサーバーURLおよびユーザーと関連付けられた資格証明の格納に使用される、デバイス・ネイティブかつローカルなリポジトリです。実行時に、MAFでは、すべての資格証明がその使用前にIDM Mobile資格証明ストアに格納されているものとみなします。
connections.xml
ファイルには、Webサービスの接続参照のadfCredentialStoreKey
属性に、ログイン・サーバー接続のadfCredentialStoreKey
の値を指定して、ログイン・サーバーをWebサービスのセキュリティに関連付ける必要があります(次の2つの例を参照)。
注意:
JDeveloperではconnections.xml
ファイルの概要エディタが提供されないため、「プロパティ」ウィンドウを使用して、<Reference>
要素のadfcredentialStoreKey
属性をログイン・サーバー接続のadfCredentialStoreKey
属性用に構成されている名前で更新できます。または、「ソース」エディタを使用して属性を追加または更新できます。
次の例は、adfCredentialStoreKey="MyAuth"
として参照されるWebサービス接続の定義を示しています。ここで、MyAuth
とは、ログイン接続の参照名です。
<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>
次の例は、ログイン接続の定義を示しています。ここでのMyAuth
は、ログイン・サーバー接続における資格証明ストア・キーの値として使用されます。
<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により適切な例外が戻され、適切なアクションが起動されます(「ロギングの使用方法と構成」を参照)。既存の例外で状況を適切に示せない場合は、新しい例外が追加されます。
「MAFアプリケーションで使用するエンド・ポイントの構成」で説明しているように、connections.xml
ファイルは構成サービスの下でデプロイされ、管理されています。
FAR内のconnections.xml
ファイルは、MAFアプリケーションのデプロイ時に集約されます。資格証明はデプロイメント固有のデータを表しており、FAR内に格納することは想定されていません。
MAFは、Cookieベースの認証のために、REST WebサービスのURLエンドポイントに関連付けられたログイン接続に対して、Cookieの挿入を実行します。
Cookieベースの認可のためにMAFアプリケーションがREST Webサービスを要求するたびに、MAFのセキュリティ・フレームワークは、REST Webサービスのトランスポート・レイヤーが、REST WebサービスのURLエンドポイントに関連付けられているログイン接続に対してCookieの挿入を実行できるようにします。これは実行時に処理され、MAF開発者によるMAFアプリケーションの構成は不要です。
企業のファイアウォールの外側に存在するWebサービスをコールするために、HTTPプロキシ・サーバーを使用するようにJavaのシステム・プロパティを構成します。このプロキシは、汎用接続フレームワークまたはjava.net APIのどちらかで定義できます。
デフォルトでは、MAFはアプリケーションのデプロイ先であるプラットフォームのシステム設定を使用してプロキシ情報を決定します。たとえば、iOSデバイスの設定ユーティリティを使用してプロキシ情報が設定されている場合、JVMは自動的にその情報を取り込みます。
注意:
MAFアプリケーションごとに異なるプロキシを定義できます。
デバイスの設定からプロキシ情報を取得しない場合は、最初に-Dcom.oracle.net.httpProxySource
システム・プロパティを追加する必要があります。このプロパティのデフォルト値はnative
で、プロキシ情報をデバイスの設定から取得することを意味します。これを無効にするには、user
など別の値を指定します(例: -Dcom.oracle.net.httpProxySource=user
)。
JVMは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
注意:
これらのプロパティはネットワーク・コールのJVM側のみに影響します。