Apexアプリケーション開発をはじめよう - 第4章:JavaからSalesforceにアクセスする

by Shinichi Tomita on 4月 11, 2007 at 05:38 午後

連携アプリケーションについて

これまでは、すべてSalesforceの内部だけで完結するネイティブアプリケーションと呼ばれるアプリケーションの作成方法について説明してきました。しかし、Salesforce外部にある既存のデータ資産を利用したり、外部Webサービスとのマッシュアップを行うためには、基本的に外部のサーバにアプリケーションプログラムを配布しておく必要があります。

外部のアプリケーションサーバなどからAPIを介してSalesforceにアクセスするアプリケーションのことを、セールスフォース・ドットコムではネイティブアプリケーションに対して連携アプリケーションと呼んでいます。

この章ではJava言語を使って外部プログラムからApex WebサービスAPIを利用する方法について説明します。なお、この説明ではJDK 1.5 および Apache Axis 1.4の利用を前提としています。現在ADN(Apex Developer Network)からApache Axis 1.4が同梱されたJavaクイックスタートおよびサンプルがダウンロードできますので、お急ぎの方はそちらを利用していただいてもかまいません。

WSDLのダウンロードとスタブクラスの作成

Apex WebサービスAPIにアクセスするためには、WSDL(Web Service Description Language)ファイルが必要になります。このWSDLファイルはSalesforceのWebユーザーインターフェースからダウンロードが可能です。

Salesforceにデベロッパーアカウントでログインしたら、画面上部の「設定」リンクをクリックし、その後左サイドバーの「統合 > AppExchange API」リンクをクリックします。

41

Apex WebサービスAPIにアクセスするためのWSDLには、エンタープライズWSDLとパートナーWSDLの2つがあります。

エンタープライズWSDLは、組織内で独自に定義したオブジェクト定義なども含め、Salesforceのオブジェクトモデルについての型情報を含んでいるため、Javaなどの強い型付けがされた言語プログラムからは扱いやすくなります。

パートナーWSDLでは反対に型の情報が含まれないため、一つのアプリケーションを複数の異なる組織に対してダイナミックに利用することができます。

どちらのWSDLを利用するかは開発方法・目的によって使い分けることができますが、ここではエンタープライズWSDLを使ってWebサービスにアクセスする方法について説明していきます。

さて、WSDLのダウンロードが完了したら、スタブとなるクラスのJavaソースコードを生成します。

コマンドライン上で

java -classpath pathToJARs org.apache.axis.wsdl.WSDL2Java -a enterprise.wsdl

と実行してください。pathToJARsにはaxisなどのライブラリへのパスを記述します。

以上の作業でApex Webサービスへのスタブとなるクラスを記述したソースファイルが生成されます。

サンプルコード

これでJavaのプログラムからApex WebサービスAPIにアクセスする準備が整いました。さっそくAPIにアクセスするJavaプログラムを書いてみましょう。

まず必要となるクラスのインポートを行った上で、以下のコードによって SoapBindingStub インスタンスを取得します。

SoapBindingStub binding = (SoapBindingStub) new SforceServiceLocator().getSoap();

その後、SoapBindingStubインスタンスに対してSalesforceのアカウントとパスワードをloginメソッドに渡すことでSalesforceへの認証を行います。

LoginResult loginResult = binding.login("user@example.org", "mypassword123");

ログインが成功すると、ログイン結果として有効なセッションIDおよびSOAPエンドポイントのURLが取得されます。これらを以下のコードを参考にスタブインスタンスのプロパティおよびヘッダに設定します。

// set the session header for subsequent call authentication
binding._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY,
                     loginResult.getServerUrl());

// Create a new session header object and set the session id to that
// returned by the login
SessionHeader sh = new SessionHeader();
sh.setSessionId(loginResult.getSessionId());
binding.setHeader(new SforceServiceLocator().getServiceName().getNamespaceURI(),
                  "SessionHeader", sh);

これでForce.comプラットフォームへのセッションが構築され、APIメソッドを呼び出す準備が整いました。

では最初にSOQLクエリを投げてみましょう。コード記述は以下のようになります。

QueryResult queryResult = binding.query("select id, Website, Name from Account where Name = 'Golden Straw'");

クエリ結果からレコードを抽出するためのコードは以下のようになります。

if (queryResult.getSize() != 0) {
  Account account = ((Account) queryResult.getRecords()[0]);
  System.out.println("Retrieved "
                        + new Integer(queryResult.getSize()).toString()
                        + " account(s) using Name = 'Golden Straw', ID = "
                        + account.getId() + ", website = "
                        + account.getWebsite());
}

ひとつのAPIコールで、常に条件に合致するすべてのレコードが返されるわけではないことに注意してください。問い合わせが終了しているかどうかは QueryResult#isDone メソッドで確認できます。まだレコードが残されている場合には、 SoapBindingStub#queryMore メソッドにより残りのレコードを取得可能です。

if (!queryResult.isDone()) {
  queryResult = binding.queryMore(queryResult.getQueryLocator());
  ....
}

レコードのキーとなるIdがわかっている場合には、SoapBindingStub#retrieve メソッドが利用できます。第1引数で取得する項目のリスト(カンマ区切り)、第2引数でオブジェクト名、第3引数にIdの配列を指定します。Idを複数指定することで、一度に複数のレコードの取得が可能です。

Account[] accounts = (Account[]) binding.retrieve("Id, Name", "Account", new String[]{ id1, id2 });

Salesforceのデータベース内に新たにレコードを作成するためには、SoapBindingStub#create メソッドを利用します。メソッドの引数に複数インスタンスを配列として渡すことで、バルクでレコード作成を行うことも可能です。

Contact contact = new Contact();
contact.setAccountId(account.getId());
contact.setFirstName("Joe");
contact.setLastName("Blow");
SaveResult[] createResult = binding.create(new Contact[]{ contact });

更新には SoapBindingStub#update メソッドを利用します。更新するレコードのキーとして Id 属性を設定しておく必要があります。

Account account = new Account();
account.setId(accountId);
account.setName("New Account Name");
SaveResult[] updateResult = binding.update(new Account[]{ account });

レコードを削除するためには SoapBindingStub#delete メソッドを利用します。引数には削除するレコードのキーとなる Id を配列で指定します。

String[] ids = new String[contacts.length];
for (int i=0;i<ids.length;i++) {
  ids[i] = contacts[i].getId();
}
binding.delete(ids);

ここでは一通り参照、作成、更新、削除などのCRUD操作のメソッドに触れました。この他にもApex APIにはメタデータの参照などのAPIメソッドが用意されています。詳細については、APIドキュメントをご覧ください。

シングルサインオン

簡略化のために前述のプログラム中ではApexデータベースに問い合わせを行うユーザアカウントを固定していましたが、Salesforceを利用するマッシュアップアプリケーションにおいては、ユーザは自分の所属する組織内のデータベースにアクセスする必要があるため、一般的にAPIにアクセスするユーザは一つには限定できません。

これに対する第一の方法としては、ログイン画面を表示して、エンドユーザに自分のSalesforceアカウント名とパスワードを入力してもらうことです。アプリケーションプログラムはエンドユーザのアカウント/パスワード情報でApex Webサービスにログインすることになります。

ただしこの方法では、ユーザにSalesforceの資格証明の提示を要求するため、そのサイトが悪質なフィッシングサイトなどではないことをあらかじめユーザに説得しておく必要があります。また、Salesforceが標準で提供しているCRMアプリケーションとは別にセッションが管理されるため、2つのサイトの間の移動に際してエンドユーザはログイン情報を再度入力することになり、アプリケーションの統合レベルが下がってしまいます。

もう一つの有力な方法は、Salesforceからエンドユーザのセッションの情報を引き渡してもらうことです。この場合、エンドユーザにはログインの違いを全く意識させることなくアプリケーションを統合することが可能です。

Salesforceにはログイン済みのエンドユーザのセッション情報を外部のWebアプリケーションに引き継ぐための仕組みが用意されています。この仕組みを利用すると、ユーザがSalesforceから外部サイトのサービスに移動する際に、APIにアクセスするためのセッションID(およびSOAPエンドポイントとなるサーバURLの情報)をURLパラメータとしてWebアプリケーションに引き渡すことができます。

以下に、JavaサーブレットでSalesforceからのセッション情報を受け取る場合のサンプルコードを示します。

public void doGet(HttpServletRequest request, HttpServletResponse response) {

  String sessionId = request.getParameter("sid");
  String serverURL = request.getParameter("serverURL");

  SoapBindingStub binding = (SoapBindingStub) new SforceServiceLocator().getSoap();
  binding._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY, serverURL);

  SessionHeader sh = new SessionHeader();
  sh.setSessionId(sessionId);
  binding.setHeader(new SforceServiceLocator().getServiceName().getNamespaceURI(),
                  "SessionHeader", sh);

  ...

ヘッダにセッション情報を設定した後は、先ほどのプログラムとまったく同じ形でAPIを利用することが可能です。

Salesforce側から外部サイトへセッションの引き継ぎを設定する方法は何種類かありますが、ここではカスタムWebタブを利用する方法について説明します。

前章では、AJAX Toolkitのコードを記述したSコントロールを作成し、それを表示するためのカスタムWebタブを作成しましたが、実はカスタムWebタブは、Sコントロール以外にも、任意のWebサイトをURLを指定してインクルードすることが可能になっています。

Salesforceにログインし、画面上部の「設定」リンクをクリックした後、左のメニューにある「開発>カスタムタブ」を選択します。 「Webタブ」セクションの「新規」ボタンをクリックしてWebタブ作成のためのウィザードを開始します。

最初にタブの表示レイアウトに関する画面が現れますが、ここではそのまま「次へ」をクリックしてください。

「タブの種類」選択リストから「URL」を選びます。「タブラベル」および「タブスタイル」は、タブの表示に関するプロパティですので、適当に入力して「次へ」ボタンをクリックします。

42

ボタンまたはリンクの URLのテキストボックスに、先ほど記述したサーブレットが配置されているURLに対して以下のように入力します。

https://www.example.com/servlet?sid={!API_Session_ID}&serverURL={!API_Enterprise_Server_URL_80}

43

ここで、https://www.example.com/servlet の部分は、適宜自分が配置したサーブレットのURLに置き換えてください。sid および serverURL パラメータは、先ほどのサーブレットコードの中でパラメータとして参照しているものに相当しています。

あとはすべて「次へ」をクリックして、最後に「保存」をクリックします。画面上部のタブリストの右端に作成したWebタブが追加されていれば成功です。

タブをクリックすると、URLで指定された外部Webアプリケーションがタブコンテンツ中のフレーム内に表示されます。サーブレットにURLパラメータ値としてAPIにアクセスするためのセッションIDおよびサーバURLが渡っていることを確認してください。

以上、Javaを使った連携アプリケーションの作成方法について説明しました。言語の違いはありますが、.NETやその他のスクリプト言語でのアプリケーション作成方法もこれに似た形になります。詳細についてはADN内のツールキットにあるサンプルコード等をご覧ください。

トラックバック

このページのトラックバックURL: http://www.typepad.jp/t/trackback/7240/6909466

このページへのトラックバック一覧 Apexアプリケーション開発をはじめよう - 第4章:JavaからSalesforceにアクセスする:

コメント

Posted by sasamoto on 11月 28, 2007 01:49 午後:

知りたい情報が見つかったが、1ページの内容が多すぎて見辛い。せめて、ページの最初にページ内リンクの目次が欲しい。

コメントを投稿

コメントは記事の投稿者が承認するまで表示されません。