| Oracle Enterprise Pack for Eclipse Oracle Mobile Application Framework (OEPE Edition)でのモバイル・アプリケーションの開発 リリース2.3.0 E77213-01 |
|
![]() 前 |
![]() 次 |
この章では、MAFアプリケーションからREST Webサービスにアクセスする方法について説明します。
この章には次の項が含まれます:
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ファイル(assembly_project/META-INFにあります)にエントリを構成することが必要になる場合もあります。
WorkBetterサンプル・アプリケーションは、RESTServiceAdapterを使用してRESTサービスをプログラムで消費する例を示します。WorkBetterサンプル・アプリケーションのソース・コードにアクセスする方法の詳細は、付録E「サンプルのMAFアプリケーション」を参照してください。
RESTサービス・アダプタRestServiceAdapterを使用して、RESTコールにより送信されたデータにアクセスし、Webサービス操作の実行をトリガーします。oracle.maf.api.dc.ws.restパッケージからのRestServiceAdapterFactory.createRestServiceAdapter() APIは、RestServiceAdapterを実装するアダプタを作成します。
サービスのURLエンド・ポイントへの接続がconnections.xmlファイルに存在することを確認し、次の例で示すようにコードをBeanクラスに追加します。
Mobile Cloud Serviceに診断情報を送信するアダプタを作成する場合は、第30.8項「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サーバーにファイルのリクエストを送信し、ファイルをディスクに保存する方法を示しています。
estServiceAdapterFactory 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サービスが保護されている場合、第15.3.1項「Webサービスへのアクセスを有効にする方法」の説明に従って、REST Webサービスをサポートする事前定義済のセキュリティ・ポリシーにREST接続を関連付ける必要があります。
表15-1に、REST Webサービスへの接続に関連付けることができる事前定義済のセキュリティ・ポリシーを示します。
表15-1 RESTベースのWebサービスでサポートされるセキュリティ・ポリシー
| 認証タイプ | RESTポリシー | 説明 |
|---|---|---|
|
HTTP基本 |
|
このポリシーは、アウトバウンド・クライアント・リクエストのHTTPヘッダーに資格証明を含め、Oracle Platform Security Servicesアイデンティティ・ストアに対してユーザーを認証します。また、このポリシーは、トランスポート・プロトコルがHTTPSであることを検証します。HTTPS以外のトランスポート・プロトコルを介するリクエストは拒否されます。このポリシーは、HTTPベースのクライアントで実行できます。 |
|
HTTP基本 |
|
このポリシーは、アウトバウンド・クライアント・リクエストのHTTPヘッダーに資格証明を含めます。このポリシーは、HTTPベースまたはHTTPSベースのクライアントで実行できます。 |
|
HTTP基本 |
|
このポリシーは、アウトバウンド・クライアント・リクエストのHTTPヘッダーに資格証明を含め、Oracle Platform Security Servicesアイデンティティ・ストアに対してユーザーを認証します。また、このポリシーは、トランスポート・プロトコルがHTTPSであることを検証します。HTTPS以外のトランスポート・プロトコルを介するリクエストは拒否されます。このポリシーは、HTTPベースのクライアントで実行できます。 |
|
HTTP基本 Web SSO |
|
このポリシーは、認証後に取得されたCookieをHTTPリクエスト・ヘッダーに挿入します(例: OAM Webgateリソース)。このポリシーでは、レスポンスCookieも設定します。このポリシーは、RESTベースのクライアントで実行できます。 |
|
OAuth |
|
このポリシーは、エンドポイントとの通信中にBearerトークン(OAuthアクセス・トークン)をHTTPリクエスト・ヘッダーに挿入します。このトークンは、任意のOAuth2サーバーから取得できます。このポリシーは、RESTベースのクライアントで実行できます。 |
これらのポリシーとその使用方法の詳細は、『Oracle Fusion Middleware Oracle Web Services ManagerによるWebサービスの保護とポリシーの管理』の「使用する事前定義済ポリシーの決定」と「事前定義済ポリシー」の各章を参照してください。
Webサービスが保護されており、認証トークンが予想される場合、Webサービスをサポートする事前定義済のセキュリティ・ポリシーにログイン接続を関連付ける必要があります。RESTベースのWebサービスに使用可能な認証タイプでサポートされている事前定義済のセキュリティ・ポリシーのリストは、第15.3項「セキュアなWebサービスへのアクセス」を参照してください。
MAFアプリケーション・エディタのモバイル・ログイン・サーバー接続ダイアログを使用して、ログイン・サーバー接続を作成します。ログイン・サーバー接続の作成の詳細は、第29.5.1項「MAFログイン接続の作成方法」を参照してください。
Webサービスにセキュリティ・ポリシーを関連付けるには:
永続接続を作成する手順:
RESTサービス・エディタのRESTクライアント・ページで、
をクリックして接続の管理ウィザードを開きます。
ダイアログで、図15-1に示すように、「ポリシーの表示」をクリックして適切なポリシーを選択します。
OEPEでは、Webサービス・ポリシーの定義は(アプリケーション・ワークスペースのMETA-INFディレクトリにある) wsm-assembly.xmlファイルに格納されます。
「データ・コントロールの編集」ダイアログ(図15-1を参照)を使用して、REST 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が果す役割の詳細は、第29.4項「コンテナ化されたMAFアプリケーションの認証プロセスの概要」を参照してください。
コンテナ化されたMAFアプリケーションのOMSSサポートの概要は、第2.8項「エンタープライズ配布のための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つの例を参照)。
次の例は、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により適切な例外が戻され、適切なアクションが起動されます(第30.6項「MAFアプリケーションでのロギングの使用および構成」を参照)。既存の例外で状況を適切に示せない場合は、新しい例外が追加されます。
connections.xmlファイルは構成サービスの下でデプロイされ、管理されています。詳細は、第14章「MAFアプリケーションで使用するエンド・ポイントの構成」を参照してください。
FAR内のconnections.xmlファイルは、MAFアプリケーションのデプロイ時に集約されます。資格証明はデプロイメント固有のデータを表しており、FAR内に格納することは想定されていません。
呼び出すWebサービスが自社ファイアウォールの外部にある場合は、HTTPプロキシ・サーバーを使用できるような適切な構成にJavaシステム・プロパティが設定されていることを確認する必要があります。
デフォルトでは、MAFはアプリケーションのデプロイ先であるプラットフォームのシステム設定を使用してプロキシ情報を決定します。
|
注意: 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ファイル(assembly_project/META-INFにあります)に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側のみに影響します。 |