JP:Getting Started with the Force.com REST API

Force.com REST API 入門

概要

Force.com REST APIは、Force.comとやり取りするためのパワフルで便利でシンプルなWebサービスのインターフェースを提供します。このAPIの利点は簡単に統合・開発できることで、モバイルアプリケーションやWeb 2.0プロジェクトで利用するには非常に良いテクノロジーです。

REST APIは、どんなプログラム言語からも簡単にアクセスできるようにデザインされています。一旦このAPIの基本的なコンセプトを理解すると、PHP、Ruby、.NETなど様々な環境からも同じように利用できます。

このチュートリアルでは、REST APIの基本的な使い方を説明します。シンプルなJavaのWebアプリケーションを例に、OAuth2.0経由でForce.com上で認可を行い、このAPIを利用してForce.comの取引先レコードの作成、参照、更新、削除を行います。

注意: Winter ’11では、Force.com REST APIは開発者プレビューですので、将来のバージョンでGAになるまで本番環境ではご利用にならないでください。

サンプルアプリケーションのセットアップ

APIの概要を知りたい方は、OAuthを利用したWebサービスの認可Force.com REST APIの使い方にお進みください。このセクションと次のセクションでは、REST APIを利用するサンプルアプリケーションをどのように実行するかを説明します。

前提条件:

  • Javaアプリケーションサーバ。このサンプルコードは、Java Servlet 3.0 APIを利用しているため、これをサポートしているApache Tomcat 7.0.xやOracle GlassFish Server 3.0.xなどのアプリケーションサーバが必要です。しかし、これらのコードを古いServlet Specに合わせたコードに書き直すこともあまり難しくなくできると思います。
  • JSON.org Java実装
  • Force.com アカウント (EE, DE or FFE)

セットアップ

アプリケーションサーバでSSLエンドポイントを有効化します – instructions for Tomcat.

お好みのIDEでWebアプリケーションプロジェクトを作成します。Webアプリケーションのコンテキストパスを‘/RestTest’に設定します。

JSON.org Javaコードをダウンロードし、プロジェクトに追加します。

Apache HttpClient ライブラリをダウンロードし、プロジェクトに追加します。

REST APIのサンプルコード(OAuthServlet.java, DemoREST.java, index.html)をダウンロードし、プロジェクトに追加します。

日本語訳注
本サンプルコードでは、HTTP Client 3.xベースで説明していますが、現状のHTTP Clientは4.xベースに移行しています。HTTP Client 3.xと4.xのAPIは互換性がないため、ここでのコードはHTTP Cleint 4.xでは動作しません。 また、本サンプルコードでは日本語などの英語以外の言語への考慮もされていないため、このまま出力するとアルファベットや数字以外は?になってしまいます。 これら二つの点に対処したコードをこちら(JP:OAuthServlet.java, JP:DemoREST.java)においていきますので、こちらも合わせてご活用ください。 また、HTTP Client 4.xをご利用の際には、以下のライブラリへの依存がありますので、合わせて入手する必要があります。

開発者アカウントでSalesforce.comにログインし、設定 ➤ 開発 ➤ リモートアクセスに移動し、新規をクリックし、新規のリモートアクセスアプリケーションを作成します。

もし、アプリケーションサーバを自分のマシンで動かしている場合は(多くの開発環境ではそうだと思いますが)、URLはhttps://localhost:8443/RestTest/oauth/_callbackのようになります。設定によってはポート番号を変更する必要があります。

保存をクリックすると、アプリケーションの認証情報(クレデンシャル)が表示されます:

リンクをクリックすると、コンシューマシークレットが表示されます。 注意 – 現在のリモートアクセス画面では、OAuth 1.0 用語が使われています。OAuth 2.0の仕様では、‘コンシューマ’の代わりに‘クライアント’が使われます。

コンシューマキーとコンシューマシークレットをコピーし、OAuthServlet.javaのServletのinitParamsにペーストしてください:

/**
 * Servlet parameters
 */
@WebServlet(name = "oauth", urlPatterns = { "/oauth/*", "/oauth" }, initParams = {
        // clientId is 'Consumer Key' in the Remote Access UI
        @WebInitParam(name = "clientId", value = "xxxxxxxxxx...xxxxxxxxxx"),
        // clientSecret is 'Consumer Secret' in the Remote Access UI
        @WebInitParam(name = "clientSecret", value = "xxxxxxxxxxxxxxxxxxx"),
        // This must be identical to 'Callback URL' in the Remote Access UI
        @WebInitParam(name = "redirectUri", value = "https://localhost:8443/RestTest/oauth/_callback"),
        @WebInitParam(name = "environment", value = "https://login.salesforce.com"), })
public class OAuthServlet extends HttpServlet {

initParamsredirectUriは、リモートアクセス画面の‘Callback URL’と同じ値でなければいけません。

この時点で、サンプルをビルドし、アプリケーションサーバにデプロイできます。まずは、アプリケーションを実行し、その後でコードがどのように動くか見ていきましょう。

サンプルの実行

以下に説明する流れに沿ってサンプルを実行するためには、まずForce.comからログアウトしてください。セッションCookieをクリアするために、毎回サンプルを実行する前にブラウザを再起動することをお勧めします。

ブラウザから https://localhost:8443/RestTest/ (もしくは、 Webアプリケーションをデプロイした先)にアクセスします。すると、以下のように表示されます:

File:RestTest.png

もし、Webアプリケーションがセキュアなポートで実行されていなかったら、エラーとなります:

File:RestTest2.png

こうなった場合は、アプリケーションサーバでSSLが有効化されてブラウザからセキュアな方のURLにアクセスしていることを確認してください。 リンクをクリックすると、Salesforce.comのログインページへと遷移していきます:

ログインすると、サンプルアプリケーションがあなたのデータにアクセスすることを許可するかを確認する画面が表示されます:

これは、OAuthによるものです – これまでは、標準のsalesforce.comの認証ページのみで認証情報を入力していました – あなたのデータにアクセスしたいWebサイトからではなかったはずです。この認証ページは、最初にWebアプリケーションがアクセスを要求したときのみ表示されます。その後のセッションでは認証が求められますが、認可のステップはスキップされます。

データアクセスを認可すると、サンプルWebアプリケーションにコントロールが戻り、OAuthのプロセスで発行されたトークンを使ってForce.comのデータを利用できます:

File:Output.png

注意 – 以前に言及した通り、このWebアプリケーションはJavaのWebアプリケーションのデザインのベストプラクティスではありません。このサンプルは、OAuthを用いてForce.comのデータへのアクセスを得て、REST APIを用いてそのデータを取り扱うことを単純に説明したものです。

では、コードを見てみましょう。まずはOAuth Servletから始めます。

OAuthを利用したWebサービスの認可

OAuthが一般的に利用される場面として、このサンプルWebアプリケーションのWebサイトのような(OAuth 2.0の仕様ではクライアントと呼ばれる)3rdパーティのWebサイトへユーザに代わってユーザ名やパスワードなどの認証情報をそちらに与えることなく許可を与える場面が考えられます。クライアントはまず認証サーバ (この場合ではlogin.salesforce.com)にユーザを送り、ユーザを認証し、ユーザの認可を得て、クライアントがリソースサーバ (na1.salesforce.com、もしくはご利用のインスタンス)とやり取りをするためのアクセストークンを発行します。

OAuthに必要なコードを見てみましょう。

Servletが初期化されると、ユーザの認証とデータアクセスの許可を行うためのリダイレクト先のauthUrlを生成します:

authUrl = environment
		+ "/services/oauth2/authorize?response_type=code&client_id="
		+ clientId + "&redirect_uri="
		+ URLEncoder.encode(redirectUri, "UTF-8");

このURLはForce.comがこのアプリケーションを特定するための設定情報を含みます。

ServletはREST APIを利用するために必要なアクセストークンを取得するためのtokenUrlも生成します。

ユーザがサンプルWebアプリケーションのホームページにあるリンクをクリックすると、 https://localhost:8443/RestTest/oauth へアクセスし、以下のコードが実行され、Force.comの認証URLへリダイレクトされます:

// we need to send the user to authorize
response.sendRedirect(authUrl);

Force.comはユーザを認証し、必要に応じてユーザのデータにWebアプリケーションがアクセスする認可を得て、redirectUri(この例では、https://localhost:8443/RestTest/oauth/_callback )へとユーザをリダイレクトします。

Servletにコントロールが戻ると、戻り値として得たデータを用いてPOSTリクエストを生成し、tokenUrlにそのリクエストを送信します。注意 – その他のコードがこのガイドには含まれていますが、以下では分かりやすくするためにエラーハンドリングは割愛しています。サンプルコードには必要なエラーハンドリングは含まれています。

System.out.println("Auth successful - got callback");

String code = request.getParameter("code");

HttpClient httpclient = new HttpClient();

PostMethod post = new PostMethod(tokenUrl);
post.addParameter("code", code);
post.addParameter("grant_type", "authorization_code");
post.addParameter("client_id", clientId);
post.addParameter("client_secret", clientSecret);
post.addParameter("redirect_uri", redirectUri);

httpclient.executeMethod(post);

レスポンスには、認可サーバからJSON形式でアクセストークンとインスタンスのURLが送られてきます:

JSONObject authResponse = new JSONObject(new JSONTokener(
        new InputStreamReader(post.getResponseBodyAsStream())));

System.out.println("Auth response: " + authResponse.toString(2));

accessToken = authResponse.getString("access_token");
instanceUrl = authResponse.getString("instance_url");

これは、OAuthのプロトコルの重要なステップです。認可サーバがリダイレクト先のURLにそのまま直接アクセストークンを送ると、アクセストークンはユーザのブラウザを経由することとなり、そのパス上のあらゆる脆弱性を避けられなくなります。OAuthでは、代わりに認可サーバは生存期間が短い認可コードをクライアントに送り、クライアントからtokenUrlにアクセスすることによりこのコードと共有秘密キーを生存期間が長いアクセストークンに交換します。この方法によって、認証サーバ、クライアント、リソースサーバだけがアクセストークンを参照できることになります。

これでサンプルWebアプリケーションはアクセストークンを取得できたので、REST APIへアクセスすることができるようになりました。初めに、このアクセストークンをユーザのHTTPセッションに格納することにより、RESTデモServletが利用できるようにします:

// Set a session attribute so that other servlets can get the 
// access token
request.getSession().setAttribute(ACCESS_TOKEN, accessToken); 

// We also get the instance URL from the OAuth response, so set it
// in the session too
request.getSession().setAttribute(INSTANCE_URL, instanceUrl);

Cookieはユーザのブラウザとの間でやり取りされるため、アクセストークンをセッションの属性に保持する方がCookieに保持するよりも安全です。 ここで、REST APIがどのように利用されるかを紹介するRESTデモServletへユーザはリダイレクトされます。

response.sendRedirect(request.getContextPath() + "/DemoREST");

Force.com REST APIの使い方

次にDemoREST.javaを見てみましょう。まずは、ServletのdoGetメソッドのおおまかなつくりを見てみます(ここでもエラーハンドリングは説明を分かりやすくするため割愛しています):

String accessToken = (String) request.getSession().getAttribute(
		ACCESS_TOKEN);

String instanceUrl = (String) request.getSession().getAttribute(
		INSTANCE_URL);

writer.write("We have an access token: " + accessToken + "\n"
		+ "Using instance " + instanceUrl + "\n\n");

showAccounts(instanceUrl, accessToken, writer);

String accountId = createAccount("My New Org", instanceUrl,
		accessToken, writer);

showAccount(accountId, instanceUrl, accessToken, writer);

showAccounts(instanceUrl, accessToken, writer);

updateAccount(accountId, "My New Org, Inc", "San Francisco",
		instanceUrl, accessToken, writer);

showAccount(accountId, instanceUrl, accessToken, writer);

deleteAccount(accountId, instanceUrl, accessToken, writer);

showAccounts(instanceUrl, accessToken, writer);

取引先のリストを表示し、“My New Org”という名前の新しい取引先を作成し、その属性を表示し、その名前を“My New Org, Inc”に更新し、最後にこの取引先を削除します。それぞれの処理の後、変更の影響を確認するために再度取引先をリストします。We’ll look at each operation in turn.

REST APIを用いてSOQLクエリを実行する

SOQLクエリを実行し、すべての取引先の名前とIDを取得します。このサンプルでは、Apache HttpClientを使ってREST APIとやり取りをしますが、java.net.HttpURLConnectionやそのほかのHTTPクライアント実装も同様に利用可能です。

HttpClient httpclient = new HttpClient();
GetMethod get = new GetMethod(instanceUrl
				+ "/services/data/v20.0/query");

// set the token in the header
get.setRequestHeader("Authorization", "OAuth " + accessToken);

HttpClientとGetMethodオブジェクトを作成後、リクエストヘッダのAuthorizationOAuthの後にスペース、アクセストークンと続く値をセットします。これはすべてのREST APIとのやり取りで必須となります。もし、これを行わないと401 ‘Unauthorized’エラーがリクエスト送付後の返されます。

REST APIはSOQLクエリを/services/data/v20.0/queryリソースで受け取ります。SOQLクエリを単純に‘q’パラメータにセットします:

// set the SOQL as a query param
NameValuePair[] params = new NameValuePair[1];

params[0] = new NameValuePair("q",
		"SELECT Name, Id from Account LIMIT 100");
get.setQueryString(params);

httpclient.executeMethod(get);

GET呼び出しを実行する際のリクエストURLは、 http://na3.salesforce.com/services/data/v20.0/query?q=SELECT%20Name,%20Id%20from%20Account%20LIMIT%20100  になります。 - クエリパラメータはURLエンコードされなければいけないため、スペースは‘%20’に置き換えられます。

GETが成功すると、200 ‘OK’のレスポンスとJSONでエンコードされたクエリの結果を受け取ります。ここでは、JSONの中身をたどり、それぞれの取引先のIdNameを表示します:

JSONObject response = new JSONObject(
		new JSONTokener(new InputStreamReader(
				get.getResponseBodyAsStream())));
System.out.println("Query response: " + response.toString(2));

writer.write(response.getString("totalSize") 
+ " record(s)returned\n\n");

JSONArray results = response.getJSONArray("records");

for (int i = 0; i < results.length(); i++) {
	writer.write(results.getJSONObject(i).getString("Id")
			+ ", "
			+ results.getJSONObject(i).getString("Name")
			+ "\n");
}
writer.write("\n");

サンプルコードは最初にJSONのレスポンスを読みやすい形式にフォーマットして標準出力(一般的にはアプリケーションサーバログファイル – Apache Tomcatの場合はcatalina.out)に書き出します:

Query response: {
  "done": true,
  "records": [
    {
      "Id": "0015000000VALDtAAP",
      "Name": "GenePoint",
      "attributes": {
        "type": "Account",
        "url": "/services/data/v20.0/sobjects/Account/0015000000VALDtAAP"
      }
    },
    {
      "Id": "0015000000VALDuAAP",
      "Name": "United Oil & Gas, UK",
      "attributes": {
        "type": "Account",
        "url": "/services/data/v20.0/sobjects/Account/0015000000VALDuAAP"
      }
    },
    ...

そして、サンプルコードはクエリ結果のレコード件数を表示し、レコードの配列を順に処理し、それぞれのIDと名前をブラウザに送るHTTPレスポンスに書き出します:

12 record(s) returned  0015000000VALDtAAP, GenePoint 0015000000VALDuAAP, United Oil & Gas, UK 
...

REST APIを用いてレコードを作成する

JSONのコンテンツを作成し、それを適切なURLにPOSTすることにより新しい取引先を簡単に作成できます:

HttpClient httpclient = new HttpClient();

JSONObject account = new JSONObject();

account.put("Name", name);

PostMethod post = new PostMethod(instanceUrl
		+ "/services/data/v20.0/sobjects/Account/");

post.setRequestHeader("Authorization", "OAuth " + accessToken);
post.setRequestEntity(new StringRequestEntity(account.toString(),
		"application/json", null));

httpclient.executeMethod(post);

新規のJSONObjectを作成し、取引先のレコードを作成するために必要な最小限のデータ– Nameフィールドをセットします。取引先のレコードを表すURLを指定した新規のPostMethodを生成後、以前と同様にAuthorizationヘッダをセットし、setRequestEntityを利用してJSONコンテンツを追加し、POSTを実行します。

レコード生成に成功すると201 ‘Created’レスポンスコードと新しいレコードのIDを含むもっと詳しいJSONコンテンツが返されます:

JSONObject response = new JSONObject(new JSONTokener(
		new InputStreamReader(post.getResponseBodyAsStream())));

accountId = response.getString("id");

REST APIを用いてレコードを取得する

上記のSOQLサンプルのJSONコンテンツを見て分かるように、それぞれの取引先レコード(実際はシステムの各レコード)はSobject Row URLに関連付けられています。このURLは、そのレコードを読む、更新する、削除する目的で利用され、以下のようなフォーマットをしています:

http://na3.salesforce.com/services/data/v20.0/sobjects/SObjectName/id/

レコードを取得するには、適切なURLに単純にGETを実行します。Authorizationヘッダにアクセストークンを入れておくことを忘れないでください:

HttpClient httpclient = new HttpClient();
GetMethod get = new GetMethod(instanceUrl
		+ "/services/data/v20.0/sobjects/Account/" + accountId);

// set the token in the header
get.setRequestHeader("Authorization", "OAuth " + accessToken);

httpclient.executeMethod(get);

これまでと同じく、JSONフォーマットされたレスポンスを取得します:

Query response: {
  "AccountNumber": null,
  "Active__c": null,
  "AnnualRevenue": null,
  "BillingCity": null,
  "BillingCountry": null,
  "BillingPostalCode": null,
  "BillingState": null,
  "BillingStreet": null,
  "CreatedById": "00550000001fg6vAAA",
  "CreatedDate": "2010-10-24T20:49:11.000+0000",
  "CustomerPriority__c": null,
  "Description": null,
  "Fax": null,
  "Id": "0015000000WxaRrAAJ",
  "Industry": null,
  "IsCustomerPortal": false,
  "IsDeleted": false,
  "LastActivityDate": null,
  "LastModifiedById": "00550000001fg6vAAA",
  "LastModifiedDate": "2010-10-24T20:49:11.000+0000",
  "MasterRecordId": null,
  "Name": "My New Org",
  "NumberOfEmployees": null,
  "NumberofLocations__c": null,
  "OwnerId": "00550000001fg6vAAA",
  "Ownership": null,
  "ParentId": null,
  "Phone": null,
  "Rating": null,
  "SLAExpirationDate__c": null,
  "SLASerialNumber__c": null,
  "SLA__c": null,
  "ShippingCity": null,
  "ShippingCountry": null,
  "ShippingPostalCode": null,
  "ShippingState": null,
  "ShippingStreet": null,
  "Sic": null,
  "Site": null,
  "SystemModstamp": "2010-10-24T20:49:11.000+0000",
  "TickerSymbol": null,
  "Type": null,
  "UpsellOpportunity__c": null,
  "Website": null,
  "attributes": {
    "type": "Account",
    "url": "/services/data/v20.0/sobjects/Account/0015000000WxaRrAAJ"
  }
}

サンプルコードでは単純にJSONコンテンツのキーを順に処理しています。実際のアプリケーションでは、必要なデータを取得するために、getStringなどのメソッドを使うでしょう。

REST APIを用いてレコードを更新する

レコードの個々のフィールドを更新するために、HTTP PATCH methodを利用します。PATCHメソッドは最近標準化され、Apache HttpClientではまだ実装されていないため、ここではPostMethodを動的に上書きします:

PostMethod patch = new PostMethod(instanceUrl
		+ "/services/data/v20.0/sobjects/Account/" + accountId) {
	@Override
	public String getName() {
		return "PATCH";
	}
};

注意 – もしメソッドの上書きができないHTTPライブラリを使っている場合は、以下のように_HttpMethodクエリストリングパラメータにPATCHを指定してください:

PostMethod patch = new PostMethod(instanceUrl
		+ "/services/data/v20.0/sobjects/Account/" + accountId 
+ “?_HttpMethod=PATCH”);

どちらの場合でも、更新するデータをJSONコンテンツとして指定し、HTTPリクエストを実行してください – この例では、取引先のNameを変更し、BillingCityを追加しています:

JSONObject update = new JSONObject();

update.put("Name", newName);
update.put("BillingCity", city);

httpclient.executeMethod(patch);

更新が成功すると、成功したが解釈するデータがないことを表す 204 ‘No Content’ ステータスコードが返されます。

REST APIを用いてレコードを削除する

最後に取引先レコードを削除します。ご推測通り、Sobject Row URLに対して単純にDELETE HTTP メソッドを実行するだけです:

HttpClient httpclient = new HttpClient();

DeleteMethod delete = new DeleteMethod(instanceUrl
		+ "/services/data/v20.0/sobjects/Account/" + accountId);

delete.setRequestHeader("Authorization", "OAuth " + accessToken);

httpclient.executeMethod(delete);

Force.com REST API クイックリファレンス

この記事は、クエリとSObject 行リソースといったForce.com REST APIの表面的な部分を説明しただけです。以下のテーブルでは、URIのアルファベット順にサポートされるAPIのRESTリソースとその簡単な説明を一覧します。それぞれでは、リソースのURIは、http://domain/services/data のようなベースURIの後に続きます。domainは、ご利用のSalesforce.comインスタンス、もしくはカスタムドメインになります。たとえば、Accountオブジェクトの基本情報をバージョン20.0で取得する場合は、次のようになります: http://na1.salesforce.com/services/data/v20.0/sobjects/Account/

リソース名 URI 説明
バージョン / 利用可能なSalesforce.comのバージョンの概略をリストします。ここには、バージョン、ラベル、そのバージョンのRootへのリンクが含まれます。
バージョンごとのリソース /vXX.X/ 特定のAPIバージョンで利用可能なリソースをリストします。各リソースの名前とURIが提供されます。
グローバル情報 /vXX.X/sobjects/ その組織で利用可能なオブジェクトとそのメタデータのリスト
SObjectの基本情報 /vXX.X/sobjects/SObject名/ 特定のオブジェクトのメタデータ
SObject情報 /vXX.X/sobjects/SObject名/describe/ 特定のオブジェクトのメタデータの詳細情報
SObject Row /vXX.X/sobjects/SObject名/id/ オブジェクトIDを指定することにより特定のレコードにアクセスします。特定のオブジェクトの情報を取得、更新、削除できます。
SObject Blob取得 /vXX.X/sobjects/SObject名/id/blobField名 特定のレコードの指定したBlobフィールドの値を取得します。
クエリ /vXX.X/query/?q=soql SOQLクエリを実行します。
検索 /vXX.X/search/?s=sosl SOSL検索を実行します。検索文字列はURLエンコードされていなければいけません。

各リソースの詳細情報は、Force.com REST API Developer Preview Documentationをご参照ください。

まとめ

このチュートリアルでは、Force.com REST APIをどのように利用するか説明しました。ソースコードでは、JavaからAPIを使う方法を説明しましたが、他のすべてのプログラム言語でも同じように利用することができます。OAuth 2.0を用いてどのように認証しアクセストークンを取得するか説明したあとで、REST APIを用いてレコードを作成、閲覧、更新、削除する方法を説明しました。

Force.com REST APIは、Force.comとデータをやり取りするパワフルで便利でシンプルなWebサービスインターフェースです。開発者コミュニティがREST APIを用いて新しいイノベーションをForce.comプラットフォームにもたらしてくれることを楽しみにしています。

参考資料