Oracle® Mobile Application Framework Oracle Mobile Application Frameworkでのモバイル・アプリケーションの開発 2.3.1 E77215-01 |
|
![]() 前 |
![]() 次 |
この章の内容は次のとおりです。
MAFは、MAFアプリケーションにおけるJSONオブジェクトを使用したREST Webサービス(REST-JSON)の消費をサポートしています。MAFでこのタイプのWebサービスが他のWebサービスよりも推奨される理由は、REST-JSON 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アプリケーション」を参照してください。
RESTサービス・アダプタ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"); 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
メソッドを使用すると、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)
これらのメソッドは、RestServiceAdapter
のsend
メソッドおよびsendReceive
メソッドと同じ機能を実現しつつ、接続をカスタマイズする機会と、リクエストを送信し、レスポンスを受信するというプロセスを提供します。
次の例では、指定されたリクエスト・メソッド、リクエストおよびHTTPヘッダー値を使用して、HttpConnection
を初期化して返しています。また、資格証明ストアから基本認証をリクエスト・ヘッダーに挿入し、入力ストリームを取得し、接続を閉じます。
.... import oracle.maf.api.dc.ws.rest.RestServiceAdapterFactory; import oracle.maf.api.dc.ws.rest.RestServiceAdapter; .... RestServiceAdapterFactory factory = RestServiceAdapterFactory.newFactory(); RestServiceAdapter restServiceAdapter = factory.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
です。
次の例は、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サービスが保護されている場合、「Webサービスへのアクセスを有効にする方法」で説明しているように、REST Webサービスをサポートする事前定義済のセキュリティ・ポリシーにREST接続を関連付ける必要があります。
表17-1に、REST 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サービスの保護およびポリシーの管理』の「使用する事前定義済ポリシーの決定」および「事前定義済ポリシー」の各章を参照してください。
maf-application.xml
概要エディタの「MAFログイン接続の作成」ダイアログを使用して、ログイン・サーバー接続を作成します。ログイン・サーバー接続の作成の詳細は、「MAFログイン接続の作成方法」を参照してください。
Webサービスにセキュリティ・ポリシーを関連付けるには:
JDeveloperは、Webサービス・ポリシー定義をwsm-assembly.xml
ファイル(アプリケーション・ワークスペースのMETA-INF
ディレクトリにあります)に格納します。
「データ・コントロール・ポリシーの編集」ダイアログ(図17-2を参照)を使用して、REST Webサービスにすでに関連付けられているセキュリティ・ポリシーを表示できます。「プロパティのオーバーライド」をクリックしてダイアログを開き、そのダイアログで、選択したポリシーのオーバーライドが許可されているプロパティの代替値を指定できます。
図17-2 Webサービス・データ・コントロール・ポリシーの編集
デプロイメント時にMAFアプリケーションがコンテナ化されると、企業ファイアウォールの背後にある保護されたWebサービスは、Oracle Mobile Security Suite (OMSS)のコンポーネントであるMobile Security Access Server (MSAS)を利用して、モバイル・デバイスから企業のリソースへのトラフィックを保護する集中アクセス・ポイントを提供します。この場合、ユーザーの最初の認証で使用するために認証エンドポイントを実行するようにMSASインスタンスが構成されます。
また、バックエンド・サービス・エンドポイントは、1.) MSASで実行されるアクセス・ポリシーによってリソースのURLが保護されるようにするMSASプロキシ・アプリケーション、2.)シングル・サインオン(SSO)などのプロキシされたリクエストにMSASで追加されるクライアント・ポリシーに関連付ける必要があります。
MAFアプリケーションがMSASと通信できるようにするには、MSASインスタンスに構成されている認証のタイプのSecure Workspaceアプリケーションをインストールおよび登録します。次に、保護されたリソースへのアクセスをユーザー試みると、MAFアプリケーションおよびSecure Workspaceは、MSASにより生成されたプロキシ自動構成ファイルを利用して、MSAS AppTunnelを使用するプロキシに対するリクエストを決定します。
コンテナ化されたMAFアプリケーションの認証プロセスでのMSAS AppTunnelの役割の詳細は、「コンテナ化されたMAFアプリケーションの認証プロセスの概要」を参照してください。
コンテナ化されたMAFアプリケーション用のOMSSサポートの概要は、「エンタープライズ配布のためのMAFアプリケーションのコンテナ化」を参照してください。
MSASの事前定義済のセキュリティおよび管理ポリシーの詳細は、OMSSドキュメント・ライブラリのOracle Mobile Security Access Serverのポリシーおよびアサーション・テンプレート・リファレンスを参照してください。
保護された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により適切な例外が戻され、適切なアクションが起動されます(「ロギングの使用方法と構成」を参照)。既存の例外で状況を適切に示せない場合は、新しい例外が追加されます。
connections.xml
ファイルは構成サービスの下でデプロイされ、管理されています。詳細は、「MAFアプリケーションで使用するエンド・ポイントの構成」を参照してください。
FAR内のconnections.xml
ファイルは、MAFアプリケーションのデプロイ時に集約されます。資格証明はデプロイメント固有のデータを表しており、FAR内に格納することは想定されていません。
呼び出すWebサービスが自社ファイアウォールの外部にある場合は、HTTPプロキシ・サーバーを使用できるような適切な構成にJavaシステム・プロパティが設定されていることを確認する必要があります。
デフォルトでは、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側のみに影響します。