SalesforceのRest APIで思ったことのメモです。
まずSalesforceのRest APIは次の特徴を持ちます。(個人的に思っていることです。。詳細な仕様はSalesforceのヘルプを参照ください)
httpsの通信ができれば、SalesforceとAPIのやり取りが可能
TSL1.1以上でという制限はありますが、httpsの通信ができれば、SOAP APIのようにwsdlをソースコードに展開する仕組みがなくても簡単に利用できます。
なので、VBScriptや、Excelマクロ、PowerShell(Invoke-RestMethod
)から簡単に利用できます。
REST API以外のSalesforceのAPIを利用するには、ログインURLとログイン情報(ユーザ、パスワード)を指定してログインし、ログイン後Salesforceから返却されるインスタンスURLとセッションIDを使用してメソッドをコールします。
REST APIでも「https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=XXX&redirect_uri=YYY&state=mystate」というREST APIでの認証が用意されています。REST APIでの認証をするためには、コンシューマ鍵を別途設定して取得する必要があります。
ですが、認証後で必要な情報はセッションID(RESTではaccess_tokenという名前)とインスタンスURLなので、無理にコンシューマ鍵を用意してREST APIで認証する必要はありません。通常のSOAP APIでログインして、セッションIDとインスタンスURLを取得すればいいだけです。
APIの送受信の形式はJSON文字列かXMLか選べる
REST APIのリクエストとレスポンスの形式はJSON文字列かXMLを選べます。JSONのパーサーが利用できればJSONの方が使いやすいと思います。
デフォルトの形式はJSONですが、リクエストヘッダに「Accept: application/xml」とするか、リクエストのURLに「.xml」の拡張子をつけることでXMLに変更できます。
(URLでXMLを指定する例:https://apX.salesforce.com/services/data/v41.0/query.xml?q=~)
REST APIでのみ提供されている機能がある
SOQLやビューの実行プランはREST APIでのみ取得可能という記事を書いています。(記事内容は実行プランを取得するExcelマクロを作成したという内容です)
それ以外にも、大きなバイナリデータを取得する時は、SOAP APIよりREST APIの方が適している時があります。
静的リソース(StaticResource)、ドキュメント(Document)、添付ファイル(Attachment)は登録できるサイズが制限されているので、SOAP APIで取得できますが、ファイル(ContentVersion)やイベントログ(EventLogFile)は、サイズが大きくなってくるとSOAP APIで取得できない場合があります。
そんな時は、REST APIでバイナリデータを取得することになります。
例:ファイルの取得
https://apX.salesforce.com/services/data/v41.0/sobjects/ContentVersion/対象のSalesforceID/VersionData
例:イベントログの取得
https://apX.salesforce.com/services/data/v41.0/sobjects/EventLogFile/対象のSalesforceID/LogFile
上記のREST APIを実行すると、HTTPのレスポンスをストリームで受け取れるので大きなバイナリデータもファイルに出力することができます。
最後に
JavaでREST APIを扱うサンプルプログラムを書いておきたいと思います。
ちょっと長いのですが、通常のhttpsの通信だけでSalesforceのファイル(ContentVersion)からファイルを取得する処理です。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class RestSample {
public static void main(String[] args) throws Exception{
String loginendpoint = "https://login.salesforce.com/services/Soap/u/41.0";
String loginusername = "sampleuser@sample.user";
String loginpassword = "samplepassword";
String loginxml =
"<?xml version="1.0" encoding="UTF-8"?><env:Envelope " +
" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" " +
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> " +
" <env:Body> " +
" <m:login xmlns:m="urn:partner.soap.sforce.com" xmlns:sobj="urn:sobject.partner.soap.sforce.com"> " +
" <m:username>#sfusername#</m:username> " +
" <m:password>#sfpassword#</m:password> " +
" </m:login> " +
" </env:Body> " +
"</env:Envelope> " ;
URL url = new URL(loginendpoint);
HttpURLConnection loginhttp = (HttpURLConnection)url.openConnection();
loginhttp.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
loginhttp.setRequestProperty("SOAPAction", "login");
loginhttp.setRequestMethod("POST");
String loginenv = loginxml.replace("#sfusername#", loginusername);
loginenv = loginenv.replace("#sfpassword#", loginpassword);
loginhttp.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(loginhttp.getOutputStream());
out.write(loginenv);
out.close();
loginhttp.connect();
final int status = loginhttp.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) {
loginhttp.disconnect();
throw new Exception("通信エラーが発生 ResponseCode:" + status);
}
InputStream in = loginhttp.getInputStream();
DocumentBuilder doc = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = doc.parse(in);
in.close();
loginhttp.disconnect();
String serverURL = null;
String sessionId = null;
try{
sessionId = document.getElementsByTagName("sessionId").item(0).getTextContent();
serverURL = document.getElementsByTagName("serverUrl").item(0).getTextContent();
} catch(Exception e){
throw new Exception("ログインで失敗:" + e);
}
String instanceurl = serverURL.substring(0, serverURL.indexOf("/services"));
String resturl = instanceurl + "/services/data/v40.0/sobjects/ContentVersion/対象のSalesforceID/VersionData";
HttpURLConnection resthttp = (HttpURLConnection)new URL(resturl).openConnection();
resthttp.setRequestProperty("Content-Type", "application/octet-stream");
resthttp.setRequestProperty("Authorization", ":Bearer " + sessionId);
resthttp.setRequestMethod("GET");
resthttp.connect();
InputStream responseStream = resthttp.getInputStream();
BufferedInputStream bStream = new BufferedInputStream(responseStream);
BufferedOutputStream bFileStream = new BufferedOutputStream(new FileOutputStream("保存するファイル名"));
while(true){
int val = bStream.read();
if(val == -1){
break;
}
bFileStream.write(val);
}
bStream.close();
bFileStream.close();
}
}
補足ですが、ContentVersionは、自分の参照できるファイルしかアクセスできません。例えば他の人がアップロードしたファイルはシステム管理者であってもContentVersionからは取得できません。
Chatterファイルは、自分が参加しているChatterGroupであれば取得可能です。