Force.com Advent Calendarに参加しましょう!!

by Mitsuhiro Okamoto on 12月 2, 2011 at 06:38 午後

Illust429 Force.com Advent Calendarが有志によって開始される事になりました。 Advent Calendarとは元々は12/1日から12月25日まで毎日めくってクリスマスを祝うカードですが、これをBlogに見立てて、1日1人づつ順番にForce.comに関する投稿をします。

アドベントカード - wikipedia

IT業界では2010年ごろからRubyやPerl等のLL言語コミュニティを中心に行われてきたそうです。

内容はForce.comのTipsや、Force.comへの愛、新機能の要望でもなんでも構いませんので、みなさん是非参加しましょう!!

http://atnd.org/events/22909

Force.com Workbook Version2

by Mitsuhiro Okamoto on 9月 17, 2009 at 06:44 午後

Force.com Workbookの最新日本語版が出来上がりました。
以下のURLからダウンロード頂けます。
http://wiki.developerforce.com/index.php/JP:Forcedotcomworkbook

今回は前バージョンで好評だったForce.com BuilderやIDE、Apex、Visualforceの基本的な作成方法に加えて以下の機能についても網羅されていています。

・数式や入力規則、ワークフロー
・電子メールサービス
・Apexコードのテスト
・Force.com Sitesを使った公開Webの作成
・アプリケーションのパッケージング

このWorkbookを一通り学習すれば、Force.comを使ってどのようなアプリケーションが作成できるかを理解できるようになっています。
是非お役立て下さい!!

「Force.com Cookbook」 日本語訳 公開

by atani on 10月 10, 2008 at 06:24 午後

英語版 developer.force.com サイトで公開してきた “Force.com Cookbook”の日本語版(PDF)ができました。
Cookbook_2

Force.com Cookbookにはオンデマンドアプリケーションを構築・改修するための「うまい」方法、パターン、解決策などの「レシピ」が満載されています。Visualforce、Apex、S コントロール、連携、データの検索、デバッグ、パッケージングなど広範囲にわたる内容をカバーし、salesforce.comの開発チームのエンジニアが提供する、Java, Ajax, Flex, Eclipseなどを使うためのコードも掲載しています。

PDF(ファイルサイズ:約22M)のダウンロードはこちらから。実習環境としてご利用いただける無償のDeveloper Editionアカウントをお持ちでない方は、ダウンロード画面に申込みボタンが表示されますので、続けてお申込み下さい。

「オンデマンドアプリケーション開発ガイド」日本語訳 公開

by atani on 2月 1, 2008 at 04:58 午後

“Creating On-Demand Applications: An Introduction to the Force.com Platform”(第2版/2007年発行)の日本語版(PDF)ができました。

Ondemand_apps_125x125 ステップを追ってForce.comプラットフォームの全容を解説しているので、Force.comプラットフォームでオンデマンドアプリケーションをどのように設計・開発していけばよいかを容易にご理解いただけます。「実習」を順にたどっていけば、サンプルアプリケーションの開発を体験することができます。

PDF(ファイルサイズ:約18M)とサンプルデータのダウンロードはこちらから。実習環境としてご利用いただける無償のDeveloper Editionアカウントをお持ちでない方は、ダウンロード画面に申込みボタンが表示されますので、続けてお申込み下さい。

(追記) P126 の表35に誤りがありました。申し訳ありません。
表の左端の列"[メンバーへのメールの送信]チェックボックスがオン" と "[メンバーへのメールの送信]チェックボックスがオフ" が逆でした。正しくは上段が「オフ」、下段が「オン」です。
ご指摘いただいたみなさま、ありがとうございました。

Visualforceをはじめよう(3)

by Shinichi Tomita on 11月 21, 2007 at 03:04 午後

カスタムコントローラの作成

いままでは標準コントローラを利用したVisualforceページの記述方法について学んできました。最後に自分で制御ロジックを記述ができるように、カスタムコントローラを作成してみましょう。

カスタムコントローラは、単純にApexコードのクラスです。たとえば以下のようなコードでもコントローラとして成立します(あまり意味はないですが)

public class MyController {

}

カスタムコントローラを作成するには、次のような方法があります。

  1. Visualforceページのエディタから apex:page タグの controller 属性に対して作成するクラスの名前を指定する方法。自動的にクラス作成を行う旨のメッセージが表示され、その場でコントローラを作成することができます。
    例)
    <apex:page controller="MyController">
        <apex:pageBlock title="Hello {!$User.FirstName}!">
            This is your new page.
        </apex:pageBlock>
    </apex:page>
  2. [設定][開発][コード]メニューから[新規]としてコントローラクラスを作成し、その後Visualforceページ中の apex:page タグに作成したクラスの名前を controller 属性に設定する方法。

apex:pageタグには一度に1つしかコントローラを参照できないことに注意してください。たとえば standardController 属性と controller 属性は共存できません。

controller 属性を指定してページを保存すると、Page Editorボタンの横にControllerボタンが表示されます。これによってページのマークアップ記述画面と制御ロジックを記述するApexコードエディタの画面を切り替えることができます。

S4_2

getter メソッドを定義する

まずVisualforceコントローラが行うことの第一に、ページ中に表示するためのデータベース値や計算結果の値を受け渡すという役目があります。このためにはいわゆるgetterメソッドと呼ばれるメソッドを定義する必要があります。これはget<Identifier>という形で定義され、<Identifier>にあたる部分がメソッドによって返されるレコードやプリミティブ値の名前になります。

たとえば以下のコントローラはgetterメソッドが1つ定義されており、コントローラの名前をあらわす文字列を返します。

public class MyController {

    public String getName() {
        return 'MyController';
    }

}

このgetterメソッドの結果をページに表示するには、プレフィックスとなっている get を取り除いたgetterメソッドの名前を指定します。たとえば、getName メソッドの結果を表示するには、{!Name} と記述します。

<apex:page controller="MyController">
    <apex:pageBlock title="Hello {!$User.FirstName}!">
        This is your new page for the {!Name} controller.
    </apex:pageBlock>
</apex:page>

以前の例では、取引先の標準コントローラを利用する際に、ページではURLに含まれる id クエリ文字列パラメータで指定した値を元に、{!Account.<fieldName>} という記述で取引先のレコードを表示することが可能でした。これは取引先の標準コントローラにはすでに指定された取引先のレコード情報を取得する getAccount というgetterメソッドが定義されていたためです。カスタムコントローラでこれを真似ると以下のようになります。

public class MyController {

    public String getName() {
        return 'MyController';
    }

    public Account getAccount() {
        return [SELECT Id, Name FROM Account
                WHERE Id = :System.currentPageReference().getParameters().get('id')];
    }

}

getAccount メソッドでは、埋め込みのSOQLクエリを利用して、ページのURLに含まれる id パラメータに指定された取引先を返しています。id パラメータ値にアクセスするためにグローバルの System クラスを利用しています。

  • 最初に currentPageReference メソッドを利用して、現在のページの PageReference インスタンスを取得しています。PageReference とは、Visualforceページがクエリ文字列パラメータの情報を含めた形でインスタンス化されたオブジェクトだと考えてください。
  • この PageReference オブジェクトを利用して、クエリ文字列パラメータの名前と値のマップを getParameters メソッドを呼び出すことで取得します。
  • 最後にgetメソッドを利用してidパラメータの値を取得しています。

SOQLで取得しているのは Name および Id フィールドだけなので、ページの中に埋め込むことができるのは取引先の名前とID項目のみになります。それぞれ {!Account.Name} および {!Account.Id} という記述を用います。

apex:page タグの属性として tabStyle 属性を指定することで、取引先ページに合わせたスタイルに統一することも可能です。以下のようになります。

<apex:page controller="MyController" tabStyle="Account">
    <apex:pageBlock title="Hello {!$User.FirstName}!">
        This is your new page for the {!Name} controller. <br/>
        You are viewing the {!Account.Name} account.
    </apex:pageBlock>
</apex:page>

アクションメソッドを定義する

カスタムコントローラには、たとえばレコードの保存や値のコンバートといった、ある特定のアクションを実行するためのメソッドを定義することができます。これらのアクションメソッドは、以下のコンポーネントの action 属性に結び付けることができます。

  • apex:commandButton - アクションの実行のためのボタンを作成
  • apex:commandLink - アクションの実行のためのリンクを作成
  • apex:actionPoller - 定期的にアクションを実行する
  • apex:actionSupport 他のコンポーネントのイベント(onclickやonmouseoverなど)に呼応してアクションを実行する

例として、以前ユーザの入力を受け取るページを作成した際には、取引先の標準コントローラに定義されている save メソッドを commandButton に結び付けていました。これを MyController カスタムコントローラで行うならば以下のようになります。

<apex:page controller="MyController" tabStyle="Account">
    <apex:form>
        <apex:pageBlock title="Hello {!$User.FirstName}!">
            You are viewing the {!Account.Name} account. <p/>
            Change Account Name: <p/>
            <apex:inputField value="{!Account.Name}"/> <p/>
            <apex:commandButton action="{!save}" value="Save New Account Name"/>
        </apex:pageBlock>
    </apex:form>
</apex:page>

上のページを保存すると、Visualforceエディタ上に、MyController クラスに save メソッドを追加するためのメッセージが現れます。リンクをクリックすると、MyController は以下のようになります。

public class MyController {

    public PageReference save() {
        return null;
    }


    public String getName() {
        return 'MyController';
    }

    public Account getAccount() {
        return [SELECT Id, Name FROM Account
                WHERE Id = :System.currentPageReference().getParameters().get('id')];
    }
}

生成された save メソッドはpublicとして定義されており、戻り値として PageReference を返し、引数をとりません。これはアクションメソッドとして成り立つために必要な特徴になります。

最終的には、この save メソッドは新規のアカウント入力についてもデータベースに変更を加えたいところですが、ここではまず以前データベースから取得した取引先の情報を保管するためのメンバー変数を定義することにします。取引先の情報を格納しておくメンバー変数がないと、データベースから取得したレコードの情報は画面のレンダリング後にはなくなってしまいます。そのためユーザが変更を行っても保存することができません。メンバー変数を利用するために、以下の2つの点についてコントローラに変更を加えます。

  • メンバー変数をクラスに追加する
  • メンバー変数の値は一番最初の getAccount 呼び出しで初期化する
public class MyController {

    Account account;

    public PageReference save() {
        return null;
    }

    public String getName() {
        return 'MyController';
    }

    public Account getAccount() {
        if (account == null)
            account = [SELECT Id, Name, Site FROM Account
                       WHERE id = :System.currentPageReference().getParameters().get('id')];
        return account;
    }

}

メンバー変数が作成されたので、save メソッドではこれをデータベースに更新するだけで大丈夫です。

public class MyController {

    Account account;

    public PageReference save() {
        update account;
        return null;
    }

    public String getName() {
        return 'MyController';
    }

    public Account getAccount() {
        if(account == null)
            account = [SELECT Id, Name, Site FROM Account
                       WHERE id = :System.currentPageReference().getParameters().get('id')];
        return account;
    }
}

もうすこし強固に行うなら save メソッドではさまざまな例外処理(たとえば重複チェックなど)を行うべきでしょうが、ここでは簡単な例を示すのが目的であるので省略しています。また、save メソッドの中にcommit文がないことにも注意してください。commit文は、アクションメソッドが成功したときにデータベースに自動的にコミットされるので必要はありません。

このページをテストするときには、Change Account Nameフィールドの値を更新して、Save New Account Nameボタンをクリックしてください。ここでは標準コントローラのときと同様にページがリフレッシュされるだけですが、次の例では現在のページをリフレッシュするのではなく、違うページに遷移するように拡張します。

ページ遷移のメソッドを定義する

データベースの更新やその他の計算処理などに加えて、カスタムコントローラのアクションメソッドでは PageReference オブジェクトを返すことによりユーザを異なるページに遷移させることが可能です。

PageReference とはインスタンス化されたページに対する参照をあらわしています。PageReference はURLおよびクエリパラメータの名前と値のセットからできています。他のVisualforceページであったり、外部のWebサイトなども示すことが可能です。カスタムコントローラでは、以下のような形で PageReference を参照したりインスタンス化したりすることができます。

Page.<existingPageName>
すでに作成済みのVisualforceページに対する参照を取得します。このように指定すると、コントローラがそのページに依存していることがプラットフォーム側で判別できるため、そのページが削除されてしまうことを防ぐことができます。
PageReference pageRef = new PageReference('<partialURL>');
Force.comプラットフォーム上の任意のページに対する PageReference を作成します。たとえばあるレコードの詳細画面を表示するときは <partialURL>'/'+'<レコードID> 'を指定します。Visualforceページに対しても <partialURL>'/apex/HelloWorld' と入力することによって指定することができますが、Page.<existingPageName>のほうがプラットフォームによって依存性を追跡できるため、より好ましい実装です。
PageReference pageRef = new PageReference('<fullURL>');
外部のURLに対してPageReferenceを作成します。例)
PageReference pageRef = new PageReference('http://www.google.com');

この例では、Saveボタンをクリックした後に異なるページを表示させたい、と仮定します。そのために、2つ目として以下のようなページ(mySecondPage)を作成します。

<apex:page standardController="Account">
    Hello {!$User.FirstName}!
    <p>You are viewing the {!Account.Name} account.</p>
</apex:page>

元のページ作成画面に戻って、コントローラの中の save メソッドが上で作成したページ(mySecondPage)への PageReference を返すように編集します。

public class MyController {

    Account account;

    public PageReference save() {
        update account;
        PageReference secondPage = Page.mySecondPage;
        secondPage.setRedirect(true);
        return secondPage;

    }

    public String getName() {
        return 'MyController';
    }

    public Account getAccount() {
        if(account == null)
            account = [SELECT Id, Name, Site FROM Account
                       WHERE id = :System.currentPageReference().getParameters().get('id')];
        return account;
    }
}

上のコードでは、PageReferenceredirect属性が true に設定されている点に注意してください。この属性が設定されていない場合でも PageReference はそのままブラウザに戻されますが、ページの遷移は発生しません。元のURLがそのまま同じ状態で残ります。もしURLを遷移の結果として変更したい場合には、redirect属性を true にしておく必要があります。

上のコードをテストすると、確かにSave New Accont Nameをクリックすると mySecondPage に遷移しますが、データのコンテキスト情報は失われてしまいます。つまり、Accont.Name で指定した値は表示されません。これはリダイレクトする際にコントローラがコンテキストの状態をクリアしてしまうため発生します。そのため id クエリ文字列パラメータを PageReference のパラメータマップに再設定する必要があります。

public class MyController {

    Account account;

    public PageReference save() {
        update account;
        PageReference secondPage = Page.mySecondPage;
        secondPage.setRedirect(true);
       secondPage.getParameters().put('id', account.Id);
        return secondPage;
    }

    public String getName() {
        return 'MyController';
    }

    public Account getAccount() {
        if(account == null)
            account = [SELECT Id, Name, Site FROM Account
                       WHERE id = :System.currentPageReference().getParameters().get('id')];
        return account;
    }
}
以上で、カスタムコントローラの作成方法も含め、Visualforceページについて一通り学びました。もっと高度な開発については、Visualforce Developer's Guideの各章をご覧ください。

Visualforceをはじめよう(2)

by Shinichi Tomita on 11月 13, 2007 at 04:59 午後

入力コンポーネントを使用する

これまではVisualforceページでデータを表示する方法について学びました。ユーザからの入力を受け取るためには、apex:form タグを利用し、その中に入力コンポーネントを記述します。フォームの送信には apex:commandLink あるいは apex:commandButton タグが利用できます。

入力コンポーネントとして最も多く用いられるのが apex:inputField タグです。このタグはオブジェクトの項目の型情報を利用して、適切な入力ウィジットを描画します。たとえば、日付型項目に対して apex:inputField を使用すると日付選択カレンダーがフォーム内に表示されますし、選択リスト項目に対して使用するとドロップダウンリストが代わりに表示されます。apex:inputField タグはすべての標準&カスタムオブジェクトの項目に対して利用でき、そしてその項目に定義されているメタデータ情報、つまり必須条件や一意制約、ユーザが参照あるいは編集権限を持っているかといった情報に従って適切にレンダリングを行います。

<apex:page standardController="Account">
    <apex:form>
        <apex:pageBlock title="Hello {!$User.FirstName}!">
            You are viewing the {!account.Name} account. <p/>
            Change Account Name: <p/>
            <apex:inputField value="{!account.Name}"/> <p/>
            <apex:commandButton action="{!save}" value="Save New Account Name"/>
        </apex:pageBlock>
    </apex:form>
</apex:page>

上の例では以下の点に注意してください

  • apex:inputField タグは取引先の取引先名(Name)フィールドに value 属性を通して結び付けられています。これはページ内に項目の値を表示したときと同じ表現方法です。
  • apex:commandButton タグは action 属性を持っています。これは標準の Account コントローラの save アクションを呼び出すように設定されています。save アクションは標準の取引先編集ページで保存ボタンを押したときと同様の働きをします。すべての標準コントローラは以下のようなアクションを行うことができます。
    • save : 新しくレコードを挿入するか、あるいはコンテキストにある既存のレコードの更新を行います。保存の終了後は指定された元のページに戻るか、あるいはそのレコードの詳細画面に遷移します。
    • edit : 現在コンテキストに存在しているレコードの編集画面に遷移します。操作が完了するとeditアクションを呼び出した元のページに遷移します。
    • delete : コンテキスト上にあるレコードを削除します。操作完了後は画面のリフレッシュを行うか、あるいはオブジェクトのタブ画面に遷移します。
    • cancel : 編集作業をすべてキャンセルします。操作の完了後はeditアクションを呼び出した元のページに遷移します。

06

テーブル形式でデータを表示する

Visualforceのコンポーネントの中には、複数のレコードを繰り返して表示するためのコンポーネントがあります。代表的なものは apex:dataTable です。以下のページは apex:dataTable を利用して現在コンテキストに指定されている取引先に紐付いている取引先責任者の一覧をリストするものです。

<apex:page standardController="Account">
    <apex:pageBlock title="Hello {!$User.FirstName}!">
        You are viewing the {!account.Name} account.
    </apex:pageBlock>
    <apex:pageBlock title="Contacts">
        <apex:dataTable value="{!account.Contacts}" var="contact" cellPadding="4" border="1">
            <apex:column>{!contact.Name}</apex:column>
        </apex:dataTable>

    </apex:pageBlock>
</apex:page>

07

apex:dataTablevaluevar という2つの属性を使用します。これは他の繰り返しをサポートしているコンポーネントについても同じです。

  • value 属性にはレコードのセットを指定します。上の例では {!account.Contacts} と指定することによって、現在コンテキストにある取引先レコードから関連をたどって取引先責任者のリストを取得しています。
  • var 属性には繰り返しの際の変数名を指定します。この変数は apex:dataTable タグの内部で用いることができ、各々の項目値にアクセスするために用いられます。この例では apex:column タグの中の {!contact.Name} という表記によって取引先責任者の名前をそれぞれ表示しています。

この例では apex:dataTable にはスタイル整形のための属性として cellPadding および border 属性が用いられています。これらはオプションであり、ちょうどHTMLのtableタグの属性に相当しています。サポートされている属性のリストについては マニュアル中の Visualforce Component Refernce からご覧いただけます。

apex:dataTable タグは1つ以上の apex:column タグを内部に保持します。テーブル内に表示される行の数は value 属性に指定されているレコードの数によって定まります。

クエリ文字列のパラメータを利用する

以前にも示したとおり、デフォルトのページコンテキスト(ページに表示されるデータの元となるレコード)はページURLにあるクエリ文字列のパラメータである id パラメータによって定まります。Visualforceページではこのほかにもクエリ文字列パラメータを利用することが可能です。

パラメータの取得

Visualforceのマークアップの中からクエリ文字列パラメータを参照するには、グローバル変数である $CurrentPageReference を利用します。これを利用することで、そのページに与えられたクエリ文字列パラメータの中からパラメータ属性を指定してその値を取得することが可能になります。

$CurrentPageReference.parameters.<parameter_name>

例として、ある取引先責任者の詳細情報を取引先のページに追加したいという場合を考えましょう。取引先のレコードIDはデフォルトの id パラメータで渡されますが、取引先責任者のレコードIDは cid というパラメータで渡されるものとします。

<apex:page standardController="Account">
    <apex:pageBlock title="Hello {!$User.FirstName}!">
        You are displaying values from the {!account.Name} account and a separate contact
        that is specified by a query string parameter.
    </apex:pageBlock>
    <apex:pageBlock title="Contacts">
        <apex:dataTable value="{!account.Contacts}" var="contact" cellPadding="4" border="1">
              <apex:column>{!contact.Name}</apex:column>
        </apex:dataTable>
    </apex:pageBlock>
    <apex:detail subject="{!$CurrentPageReference.parameters.cid}" relatedList="false" title="false"/>
</apex:page>

レンダリングを正しく行うためには適切な取引先IDと取引先責任者IDをパラメータに指定する必要があります。例として取引先のIDが 0017000000Lneby で、取引先責任者のIDが 0037000000Tc3m1 だった場合、以下のようなURLになります。

https://na5.salesforce.com/apex/HelloWorld?id=0017000000Lneby&cid=0037000000Tc3m1
08
パラメータの設定

リンク対してパラメータを設定する際には、apex:param タグを apex:outputLink タグの中に指定します。なお以下の2つの表現は同等になります。

<apex:outputLink value="http://google.com/search?q={!account.Name}">
    Search Google
</apex:outputLink>
<apex:outputLink value="http://google.com/search">
    Search Google
    <apex:param name="q" value="{!account.Name}"/>
</apex:outputLink>

apex:param タグはこの他にも、apex:include および apex:commandLink タグなどで利用することができます

1ページ内でのパラメータの利用

クエリ文字列パラメータの取得および設定の両方ができたので、今度は1つのページの中にこの2つのアクションをまとめてみましょう。テーブルに表示されている取引先責任者の名前のリストに、その下に表示されている取引先責任者の詳細情報を制御するためのハイパーリンクを設置します。以下の作業を行う必要があります。

  • 取引先責任者のリストを表示している dataTable を apex:form タグで囲む
  • 取引先責任者の名前を apex:commandLink タブで囲み、その中に cid パラメータを apex:paramタグで指定する

標準コントローラを利用する場合、commandLink は新しいパラメータ情報を付け加えた上で今のページをリフレッシュします。この場合は cid パラメータが更新されるので、取引先責任者の詳細を行っているコンポーネントの内容が書き換えられることになります。

<apex:page standardController="Account">
    <apex:pageBlock title="Hello {!$User.FirstName}!">
        You are displaying contacts from the {!account.Name} account.
        Click a contact's name to view his or her details.
    </apex:pageBlock>
    <apex:pageBlock title="Contacts">
        <apex:form>
            <apex:dataTable value="{!account.Contacts}" var="contact" cellPadding="4" border="1">
                  <apex:column>
                      <apex:commandLink>
                          {!contact.Name}
                          <apex:param name="cid" value="{!contact.Id}"/>
                      </apex:commandLink>

                  </apex:column>
            </apex:dataTable>
        </apex:form>
    </apex:pageBlock>
    <apex:detail subject="{!$CurrentPageReference.parameters.cid}" relatedList="false" title="false"/>
</apex:page>

09

Visualforceをはじめよう(1)

by Shinichi Tomita on 11月 7, 2007 at 04:06 午後

VisualforceはSalesforceのアプリケーションにカスタムユーザインターフェースを作成するためのForce.comプラットフォームの新機能です。Visualforceを利用することで、Salesforceのインターフェースを利用したコンポーネントや、まったく独自のインターフェースを利用することが可能になります。

サインアップとプレビュー申込み

VisualforceはまだDeveloper Editionのみのプレビューで、さらに利用にはプレビュープログラムへの申込みが必要です。まずこちらからDeveloper Editionのアカウントを取得してください。アカウントが取得できたら、こちらのページからVisualforce Developer Previewに申込みを行います。

申込みが終了したら、Salesforceにログインし、[設定]リンクをクリックし、左側の[開発]メニューから新しく[ページ]という項目が増えていることを確認してください。これでVisualforceの利用が可能になりました。

S1

開発者モードを有効化

Visualforceの開発を行うには、開発を行うログインユーザの開発者モードを有効にしておくと便利です。[設定] [私の個人情報] [個人情報]から[編集]をクリックし、[開発モード]チェックボックスにチェックを入れ、保存します。

S2

開発者モードを有効化すると、まるでWikiを編集するような感覚でVisualforceページの作成を行うことができます。ページを作成するには、ブラウザのアドレスバーに対して以下のようなURLを入力します。

https://<salesforceHost>.salesforce.com/apex/PageName

ここで、PageNameという名前のVisualforceページが存在しない場合、エラーメッセージとともに新たに同名のVisualforceページを作成するかどうかを問い合わせるダイアログが表示されます。作成リンクをクリックすると、同URLに対してデフォルトのVisualforceページが作成されます。たとえばHelloWorldというページを作成する場合、

https://<salesforceHost>.salesforce.com/apex/HelloWorld

というURLをアドレスバーに入力します。

VisualforceでHelloWorld

ページが作成されると、デフォルトのグリーティングメッセージとともに、画面のフッター部位にPage Editorというボタンを含むバーが現れます。これをクリックすると、上下に画面が2分割され、Visualforceページのレンダリング結果とページ定義のソース画面とを同時に表示することができます。Visualforceページの開発者は、ページ定義画面のマークアップを直接編集することで、Visualforceの画面を確認しながら開発を行います。

S3

デフォルトのグリーティングメッセージの代わりに、以下のようなコードを入力してみましょう。

<apex:page>
  Hello {!$User.FirstName}!
</apex:page>

以下のような形でログインユーザの名前が表示されるはずです。

01

このように、Visualforceページの中にはSalesforceの変数を{!変数名.プロパティ名}といった形で埋め込むことができます。これはSコントロールの差し込み項目と同様です。

標準コントローラを利用する

Visualforceではapex:pageマークアップタグの属性として、standardControllerという属性を指定できます。

<apex:page standardController="オブジェクト型名">

コントローラとは、Visualforceが利用するデータおよびビジネスロジックへのアクセスを提供するものです。標準コントローラはSalesforceアプリケーションのすべてのオブジェクトに備わっています。カスタムのビジネスロジックは記述できませんが、指定したオブジェクトの型に結びついて処理を行うことが可能です。

ここではこの標準コントローラを使用して、取引先責任者の詳細を表示するページを作成します。標準コントローラとは、どのデータを取得して表示するかというコンテキスト情報を指定するものだと考えてください。コンポーネントや差し込み項目の値はコントローラから渡されます。具体的なコードとして、HelloWorld Visualforceページに以下のような記述を追加します。

<apex:page standardController="Account">
    Hello {!$User.FirstName}!
    <p>You are viewing the {!account.Name} account.</p>
</apex:page>

この状態ではまだどの取引先を表示するかといったコンテキスト情報は指定されていませんので、レコードは表示されません。もっとも簡単にコンテキストを指定するためには、まず任意の取引先の詳細ページにアクセスして、そのURLを調べてください。例えば、詳細ページのURLが以下のような形式で与えられたとします。

https://na5.salesforce.com/0017000000Lneby

このURLから、取引先のIDが 0017000000Lneby であることがわかります。この値をコピーし、先ほどのVisualforceページのURLパラメータとして以下のような形で追加します。

https://na5.salesforce.com/apex/HelloWorld?id=0017000000Lneby

これによりVisualforceページにIDで指定された取引先の名前が表示されるのを確認してください。

02_2

Visualforceのコンポーネントライブラリを使用する

ここまでは、Visualforceのタグとして必須のタグであるapex:pageタグしか利用していませんでした。HTMLで画像や表を利用するのにimgタグやtableタグを利用するのと同様に、Visualforceのコンポーネントライブラリからさまざまなユーザインターフェースのコンポーネントをページの中で利用することができます。

Salesforceの標準詳細画面におけるセクションのような外観を実現する apex:pageBlock というコンテナタグがあります。先ほどのHelloWorldページを次のように変更してみましょう。

<apex:page standardController="Account">
    <apex:pageBlock title="Hello {!$User.FirstName}!">
            You are viewing the {!account.Name} account.
    </apex:pageBlock>
</apex:page>

すると以下のような結果が得られます。

03_2

Salesforceの標準インターフェースである詳細画面や関連リスト、入力項目などのコンポーネントを利用するためのタグもあります。詳細画面を表示するには、apex:detail タグを利用します。

<apex:page standardController="Account">
    <apex:pageBlock title="Hello {!$User.FirstName}!">
        You are viewing the {!account.Name} account.
    </apex:pageBlock>
    <apex:detail/>
</apex:page>

04

apex:detailの属性に何も指定しない場合、コンテキストにあるレコードの詳細情報をそのまま表示します。タグに属性値を指定することで、どのレコードを表示するか、関連リストを表示するか、タイトルバーを表示するかなどの制御が可能です。

<apex:page standardController="Account">
    <apex:pageBlock title="Hello {!$User.FirstName}!">
        You are viewing the {!account.Name} account.
    </apex:pageBlock>
    <apex:detail subject="{!account.OwnerId}" relatedList="false" title="false"/>
</apex:page>

05

その他利用可能なコンポーネントライブラリについて調べるには、Page EditorのComponent Referenceリンクをクリックするか、あるいは以下のURLから参照することも可能です。

http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref.htm

Apexアプリケーション開発をはじめよう - 第7章:アプリケーションの共有

by Shinichi Tomita on 4月 11, 2007 at 06:41 午後

以前にも多少触れましたが、Salesforceでは新規アカウントを申請するたびに、申請したアカウントを管理者とする仮想的なプライベートインスタンスが割り与えられます。

私たちはこのインスタンスのことをSalesforce組織と呼んでいますが、この組織内のアプリケーションやデータはすべてプライベートに隔離されており、その組織に属しているユーザのみしかアクセスすることができません。

つまり、みなさんがこれまで作成したカスタムオブジェクトの定義やSコントロールなどについても、まだ皆さんの組織内のみで有効なプライベートなものです。もし組織の枠を超えて作成したアプリケーションを使ってもらいたいのであれば、これらを共有するための作業が必要になります。

AppExchange

セールスフォース・ドットコムでは、皆さんが作成したアプリケーションを公開するための場所としてAppExchangeと呼ばれるディレクトリサイトを提供しています。共有されているアプリケーションのすべてはこのサイトからインストールすることができます。

71

上のような画面は2章や6章でも若干目にしているはずです。つまり今まで見てきたサンプルやチュートリアルアプリケーションなどは、すべてカスタムで作成され、その後パッケージ化されてAppExchange上にアップロードされたものなのです。

少し注意していただきたいのは、アプリケーションの説明の情報の上部にある「このアプリケーションは公開されているものではありません」という但し書きです。これは、共有はされているけれどもディレクトリの中にリスト公開はされていない、ということを意味しています。この状態のアプリケーションはAppExchangeでアプリケーションを検索した際にも検索対象となることはありませんが、URLさえ知っていれば誰でもこのアプリケーションをインストールすることは可能になります。

ここではとりあえず作成したアプリケーションをアップロードしてプライベートに共有するところまでを対象としています。AppExchangeのディレクトリに公開するためのプロセスについてはこちらをご参照ください。

パッケージの作成とアップロード

AppExchangeにアップロードするためには、作成したカスタムオブジェクト定義やSコントロールなどのコンポーネントを一つのパッケージにまとめておく必要があります。

パッケージを作成するには、画面上部の「設定」リンクをクリックして、左側のメニューから「Exchange>共有アプリケーション」のリンクをクリックしてください。パッケージ一覧の欄から「新規」ボタンを押してパッケージを作成します。最初にパッケージ名の入力を求められるので、アップロードするアプリケーションに適当な名前を指定し、「保存」ボタンを押します

72

これで空のパッケージが作成されました。あとはこの中にコンポーネントを追加していきます。パッケージアイテムの欄の「追加」ボタンをクリックし、アイテムを追加します。

アイテム種別からSコントロールやカスタムオブジェクトの定義などを選択し、パッケージの中に含めて行きます。このとき、Sコントロールを表示するためのカスタムWebタブなども忘れずに含めておいてください。

73

パッケージへもれなくコンポーネントを追加したことを確認したら、「AppExchangeにアップロード」ボタンを押してください。

最初にバージョン番号を求められますが、今のところ特に番号の付与基準はありません。管理しやすい番号を入力しておいてください。

再び「AppExchangeにアップロード」ボタンを押すと、パッケージのアップロードが開始されます。アップロードの完了には少し時間がかかりますが、しばらくするとメールアドレスにアップロード完了の連絡が通知されます。メールに記載されているURLをクリックして、アップロードの詳細画面を表示してください。

75

最後に「登録」ボタンを押すことでAppExchangeにアプリケーションが共有され、同時にアプリケーションをインストールするためのURLが発行されます。このURLを他の組織の管理者に知らせることで、作成したアプリケーションをインストールしてもらうことが可能になります。

76

パッケージに登録可能なSalesforceのコンポーネントの中に「カスタムアプリケーション」というものがあります。これは多少一般的なアプリケーションの概念と異なっており、複数のタブ表示を一つにまとめて取り扱うための単位になっています。

作成されたカスタムアプリケーションは画面右上のアプリケーション選択リストに表示されますが、このリストからアプリケーションを選択することで表示されるタブリストを切り替えることが可能になります。

上記の説明ではパッケージの中にはSコントロールやカスタムオブジェクト、カスタムWebタブのみしか指定しませんでしたが、カスタムアプリケーションを作成し追加しておくことによって、アプリケーションをインストールしたユーザがタブ画面に簡単にアクセスできるようになります。

無料トライアルの作成

Salesforceの中のアプリケーションはまずユーザにログインしてもらうことを前提としています。そのため、そのままではSalesforceのアカウントを持っていないユーザにはせっかく作成したアプリケーションを見てもらうことすらできません。

そのため、Salesforceではアプリケーションを公開する際に数多くの人にアプリケーションを試していただくことができるように、デモ用のSalesforce組織および参照権限のみのデモ用ユーザアカウントを作成して公開する機能を用意しています。

アプリケーションのアップロードが終了した状態で、AppExchange アップロードの詳細画面から「無料トライアル」ボタンを押してください。新たにデモ用のSalesforce組織が作成され、その組織の管理者ユーザアカウントとパスワードがメールで通知されます。なお、この組織にはすでにアップロードしたアプリケーションがインストールされた状態になっています。

こちらに、現在アップロード済みのアプリケーションパッケージがリストされていますので、先ほどアップロードしたパッケージ名の横にある「編集」リンクをクリックして編集画面を表示してください。「アプリケーションに関する追加情報」のセクションに「デモのユーザ名」および「デモパスワード」を入力する欄がありますので、こちらに先ほどのデモ組織の中の評価用ユーザ名(デフォルトではeval@{application_name}.demo)となります)とパスワードを入力します。

入力完了後、「保存」リンクを押すと、以下のような画面が現れます。画面に「トライアル」ボタンが追加されていることを確認してください。

78

「トライアル」ボタンをクリックすると、先ほど設定したデモユーザで自動的にSalesforceにログインされるので、パスワードが求められることはありません。このためSalesforceのアカウントを持っていないユーザであっても作成したアプリケーションを閲覧することができます。

おつかれさまでした。これで「Apexアプリケーション開発をはじめよう」シリーズは終了です。あとはこれをベースにさまざまなApexアプリケーションを作成してみてください。さらに深くSalesforceについて知りたい場合は、APIのドキュメントや各種サンプルコードが頼りになるかと思います。また、このブログでは折に触れてForce.comプラットフォーム開発者に有用な情報を取り上げていきますので、引き続きご注目くだされば幸いです。

Apexアプリケーション開発をはじめよう - 第6章:マッシュアップチュートリアル

by Shinichi Tomita on 4月 11, 2007 at 06:26 午後

この章では、Force.comプラットフォームを利用したマッシュアップアプリケーションについて、全くのスクラッチ状態からアプリケーションが完成するまでの道のりをチュートリアル形式でたどっていきます。

目標とするアプリケーション

このチュートリアルで作成するアプリケーションは、Salesforce内に格納されている取引先の住所情報を元に、Google Mapsの提供する地図上に取引先情報をプロットするアプリケーションです。

以下のURLから完成目標となるアプリケーションを参照できます。リンクをクリックした後の画面で「トライアル」ボタンを表示してみてください。

https://www.salesforce.com/jp/appexchange/detail_overview.jsp?id=a0330000002gBgGAAU

61

なお、このチュートリアルの実行に必要なツールはWebブラウザのみ、開発言語はHTML+JavaScriptのみです。データベースインスタンスやアプリケーションサーバなど、あらかじめ用意しておく必要は全くありません。

取引先デモデータのロード

チュートリアルではSalesforceの中に格納されている取引先データの住所情報を利用してマッシュアップを行うため、あらかじめログイン中の組織の中に取引先情報を含んでいる必要があります。

デベロッパーアカウントのサインアップを行った直後のSalesforce組織にはすでに何件かのデモデータがデータベース内に入っていますが、現在これらは英語圏のデータになっていますので今回のマッシュアップ用には不向きです。そのため、あらためて日本語のデモデータをデータベースにロードしておく必要があります。

以下のリンクは今回のチュートリアル利用するデータをデータベースにロードするためのアプリケーションです。

http://www.salesforce.com/jp/appexchange/detail_overview.jsp?id=a0330000002goJsAAI

インストールボタンをクリックして、指示に従ってインストールを行ってください。AppExchangeアプリケーションインストールの細かい手順はこちらに記載がありますが、今回は特に気にせずにウィザードをそのまま進めていただいもかまいません。これによりデータロード用のアプリケーションがインストールされます。

実際にデータのロードを実行するには、画面右上のアプリケーションメニュープルダウンリストから先ほどインストールした「チュートリアルデータロード用アプリ」を選択します。タブリストの中の「チュートリアルデータロード」タブをクリックすると、以下のような画面が現れます。

62

画面中の「デモデータを登録」ボタンを押すことで、デモ用の取引先データが現在ログイン中のSalesforceインスタンスにロードされます。ロード完了後「取引先」タブをクリックして実際にレコードが登録されているかどうか確かめてください。

デモデータのデータロード後にはこのアプリケーションは特に必要ありません。必要に応じてアンインストールを行ってください。

Google Maps 表示用Sコントロールの作成

それでは実際のアプリケーションを作成にとりかかります。今回作成するアプリケーションは、Sコントロールを使用してJavaScriptからApex APIにアクセスするネイティブアプリケーションです。詳しくは第3章で説明していますが、まずはHTMLを表示するためのSコントロールを作成することになります。

Salesforceにデベロッパーアカウントでログイン後、画面上部の「設定」リンクをクリックします。左側のメニューから、「開発>カスタムSコントロール」をクリックします。その後、画面中央の「新規カスタムSコントロール」をクリックし、Sコントロールの作成を開始します。

63

表示ラベルおよびSコントロール名には以下のように入力してください。

表示ラベル: Google Maps mashup チュートリアル
Sコントロール名: GoogleMapsMashupTutorial

コンテンツ欄のテキストエリアには、実際に表示するHTMLを記述します。まず Google Maps API のドキュメントを参考に、以下のようなコードを記述しておきます。

<html>
  <head>
    <script src="http://maps.google.co.jp/maps?file=api&v=2&key=ABQIAAAAYtWO2s_klJQZgGk9oArIARQzGTwzk7K_jsQk84g_OzUaojTBGhRU9ZkPbU9a5w_ZHgbyRGNd34orMg"
      type="text/javascript"></script>
    <script type="text/javascript">
var map;

/*
* エントリポイント
*/
function init() {
  // Google Map 初期化作業
  if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById("map"));
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    map.addControl(new GOverviewMapControl());
    map.setCenter(new GLatLng(35.683911, 139.75395), 13); // 東京都千代田区千代田
  }
}
    </script>
  </head>
  <body onload="init()" onunload="GUnload()">
    <div id="map" style="margin: 10 auto; width: 90%; height: 90%"></div>
  </body>
</html>

上記HTML中でGoogle MapsのAPIをロードしているURLの中の key パラメータに指定している値は、あらかじめGoogle Mapsから取得しておいたものに置き換えてください。なお、Keyの取得の際には、WebサイトのURLとして現在利用しているSalesforceインスタンスのURLを指定する必要があることに注意してください(例:https://na3.salesforce.com)。

またこのチュートリアルにおけるGoogle Maps APIを利用したコードはあくまでサンプルであり、Google Maps APIの規約においては企業環境での利用には Google Maps for Enterprise の利用が前提となると思われます。

以上の記述が完了したら、「保存」ボタンをクリックしてください。

次に今作成したSコントロールを表示するためのカスタムWebタブを作成します。

左のメニューにある「開発>カスタムタブ」を選択し、「Webタブ」セクションから「新規」ボタンをクリックしてください。Webタブ作成のためのウィザードが始まります。ウィザードには以下の値を入力します。

Webタブのページレイアウト: ページ幅全体
タブの種類: カスタムSコントロール
タブラベル: GoogleMapsマッシュアップ(チュートリアル)
タブスタイル: (任意)
コンテンツフレームの高さ(ピクセル): 600
カスタムSコントロール: Google Maps mashup チュートリアル[GoogleMapsMashupTutorial]

入力が終わったらすべて「次へ」をクリックしてください。最後に「保存」をクリックした後、画面上部のタブリストの右端に作成したWebタブが追加されていれば成功です。クリックして地図が表示されることを確かめてみましょう。

64

位置情報のマッシュアップ

ここまでで、Google Mapsの地図をSalesforceの画面に表示することができたかと思います。ただし、このままではマッシュアップとはまだいえません。以下では、実際にSalesforceからデータを取得して、地図上に重ねあわせ表示することができるようにしていきます。

Google Mapsに取引先情報をプロットしていくためには、取引先の位置情報として緯度・経度の情報が必要になります。緯度・経度の情報はジオコーディングと呼ばれる外部サービスを利用することで住所情報から変換することができますが、このチュートリアルでは取引先オブジェクトにあらかじめカスタムのフィールドを定義しておくことで、変換された情報をレコード内にキャッシュしておけるようにします。

では、取引先(Account)オブジェクトに対して、カスタム項目を作成していきましょう。第5章ではカスタムオブジェクトに対してカスタム項目を作成する手順を学びましたが、これは標準オブジェクトについても同様の操作が行えます。

画面上部の「設定」リンクをクリックして、右側に表示されるメニューから「カスタマイズ>取引先>項目」をクリックします。「取引先カスタム項目&リレーション」セクションの「新規」ボタンをクリックして、新たに項目を作成します。

カスタム項目作成のウィザードが開始されますので、以下の情報を入力します。

         
データ型: 数値
項目の表示ラベル: 緯度
文字数: 12
小数点の位置: 6
項目名: Lat

以上の入力が終わったらすべて「次へ」をクリックしてウィザードを進め、最後に「保存&新規」ボタンを押します。続いてもう一つのカスタム項目として以下の情報を入力します。

         
データ型: 数値
項目の表示ラベル: 経度
文字数: 12
小数点の位置: 6
項目名: Lng

以上の入力が終わったらすべて「次へ」をクリックしてウィザードを進め、最後に「保存」ボタンを押します。「取引先カスタム項目 & リレーション」セクションに以下の画面のようにカスタム項目が作成されていることを確認してください。

65

マッシュアップコードの記述

位置情報をキャッシュするカスタム項目を追加定義したら、実際にSalesforceのデータとGoogle Mapsをマッシュアップするコードの記述にとりかかります。

先ほど作成したSコントロールのコンテンツを再び編集します。左側の「開発>カスタムSコントロール」メニューを選択し、リスト中の「Google Maps mashup チュートリアル」の左端の「編集」リンクをクリックします。その後コンテンツ欄のテキストエリアに表示されているHTMLを編集します。

まず、HTMLのHEAD部分に、AJAX Toolkitをロードするscriptタグを追加します。

<html>
  <head>
    <script type="text/javascript" src="/soap/ajax/9.0/connection.js"></script>     <script src="http://maps.google.co.jp/maps?file=api&v=2&key=ABQIAAAAYtWO2s_klJQZgGk9oArIARQzGTwzk7K_jsQk84g_OzUaojTBGhRU9ZkPbU9a5w_ZHgbyRGNd34orMg"       type="text/javascript"></script>

次に、エントリポイントである init() 関数の最後に、以下のコードを追加します。

/* 
* エントリポイント
*/

function init() {
  // Google Map 初期化作業
  if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById("map"));
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    map.addControl(new GOverviewMapControl());
    map.setCenter(new GLatLng(35.683911, 139.75395), 13); // 東京都千代田区千代田
   
    // Apexデータベース内の取引先オブジェクト(Account)を検索     queryAccounts();   } }

これにより、Google Mapsの表示の初期化処理を行った後に queryAccounts() という関数が呼び出されるようになります。

続いて init() 関数の下に queryAccounts() 関数を定義し、ここにApexデータベースからデータを検索する処理を記述します。

/* 
* 取引先の情報をApexデータベースから取得
*/
function queryAccounts() {
  var soql = "SELECT Id, Name, BillingStreet, BillingCity, "+
             "       BillingState, BillingPostalCode, BillingCountry, "+
             "       NumberOfEmployees, AnnualRevenue, "+
             "       Lat__c, Lng__c "+
             " FROM Account "+
             " WHERE BillingCountry='日本' "+
             " LIMIT 50 ";

  // var result = sforce.connection.query(soql);
  sforce.connection.query(soql, function(result) {
    var accounts = result.getArray('records');
    for (var i=0; i<accounts.length; i++) {
      getAccountGeopoint(accounts[i]);
    }
  });
}

ここで少し注意していただきたいのが、AJAX Toolkitを利用したAPIの呼び出し方についてです。第3章のAJAX Toolkitの使い方の説明の中では、以下のような記述でSOQLクエリを実行していたと思います。

var result = sforce.connection.query(soql);

しかし、上記のコードでは以下のようにコールバック関数を利用した呼び出しになっています。

sforce.connection.query(soql, function(result) { ... });

このような違いがあるのは、前者では内部的にXMLHttpRequestを同期的に呼び出しているのに対して、後者は非同期で呼び出しているためです。同期的な呼び出しはコードの記述・閲覧上は大変わかりやすいのですが、呼び出しの処理を行っている間応答待ちの状態に入るため、ユーザの操作入力をブロックしてしまいます。特にレスポンスに時間のかかる処理では、ユーザの操作を長時間ブロックしないようにバックグラウンドで非同期にAPI呼び出しをすることをおすすめします。

次にジオコーディング処理です。getAccountGeopoint()関数を以下のように定義します。

/* 
* 取引先の位置情報(緯度・経度)を取得する
*/
function getAccountGeopoint(account) {

  if (account.Lat__c && account.Lng__c) {
    // 位置情報がキャッシュされていればそのまま地図上へプロット表示
    plotAccount(account);
  } else {
    // Googleのジオコーディングサービスを利用して住所から位置情報を取得
    var geocoder = new GClientGeocoder();
    var address = account.BillingState+account.BillingCity+account.BillingStreet;
    geocoder.getLatLng(address, function(point) {
      account.Lat__c = point.lat();
      account.Lng__c = point.lng();
      sforce.connection.update([ account ], noop); // 位置情報をキャッシュして保存
      plotAccount(account);
    });
  }

  /*
   * updateの非同期処理完了を受け取るコールバック関数。ここでは何もしない。
   */
  function noop() {}

}

ここではジオコーディングにGoogle Maps API のGClientGeocoderを利用しています。同じ住所情報に対して再び問い合わせをしなくても済むように、いったん取得した位置情報は先ほど定義した取引先オブジェクト内のカスタム項目に保存しています。保存の際に用いられている update APIにもクエリの場合と同様に非同期呼び出しの形が用いられていることに注意してください。

住所情報から位置情報が得られたら、あとは地図上にプロットするだけです。この作業はplotAccount()関数で行います。

/* 
* 取引先を地図上にプロットする
*/
function plotAccount(account) {
  var html = '<a href="/'+account.Id+'" target="_top">'+account.Name+'</a>' +
             '<div>住所:'+account.BillingState+account.BillingCity+account.BillingStreet+'</div>' +
             '<div>従業員数: '+account.NumberOfEmployees+'</div>' +
             '<div>年間売上:¥'+(account.AnnualRevenue/1000000)+'M</div>';
  var marker = new GMarker(new GLatLng(account.Lat__c, account.Lng__c));
  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(html);
  });
  map.addOverlay(marker);
}

以上のコードを追加したら、編集中のSコントロールを保存します。

再び画面上のタブリスト中にある「GoogleMapsマッシュアップ(チュートリアル)」タブをクリックします。今度はマーカーアイコンが地図上に並べられているのがわかると思います。

66

アイコンをクリックすると取引先の情報が表示されます。

67

リンクをクリックすると、Salesforceの取引先詳細ページに飛ぶことができます。

68

以上でマッシュアップアプリケーションのチュートリアルは終了ですが、開発者のみなさんはこれを元にさらなる自分独自のアプリケーションを作成してみてください。例えばSOQLの検索条件などを工夫したり、あるいはその他の外部Webサービスと組み合わせたりすることで、さらに興味深いアプリケーションになるかもしれません。

このような動的に変化するデータベースアプリケーションを作成するのに費やしたコードの量は、HTMLとJavaScriptをすべて含めても100行以下です。さらにこのアプリケーションはサーバ環境を自分で保守する必要もなく、共有することですぐに他の人に使ってもらうこともできるのです。次の章ではみなさんが作成したアプリケーションを共有する方法について説明する予定です。

Apexアプリケーション開発をはじめよう - 第5章:カスタムオブジェクトの作成

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

Force.comプラットフォーム上で可能なこと

これまで、JavaScript(AJAX) および Java言語を使って、ネイティブアプリケーションおよび連携アプリケーションを作成する方法について学んできました。その中で、Salesforceのデータベース内にクエリを投げたり、レコードを作成、更新、削除するアプリケーションプログラムが記述できるようになったかと思います。

今までの例では、すべてSalesforceに標準で定義済みのオブジェクト(AccountContact など)に対してアクセスするプログラムを記述してきました。しかし、Force.comプラットフォームで可能なことはこれだけにとどまりません。初めの章で述べたように、Force.comプラットフォームではForce.comデータベース内に格納することができるオブジェクトの定義を、アプリケーションごとに独自に設計/追加することが可能になっているのです。

このアプリケーション開発者が独自に追加するオブジェクト定義のことを、Salesforceがあらかじめ用意している標準オブジェクトに対し、カスタムオブジェクトと呼んでいます。カスタムオブジェクトが定義できることで、アプリケーションに必要なデータのすべてをForce.comデータベース内に構造的に保持することが可能になります。

カスタムオブジェクトの作成

それでは実際にカスタムオブジェクトをSalesforceに定義してみましょう。カスタムオブジェクトの定義は、すべてSalesforceのWebインターフェース上から行います。

Salesforceにログイン後、画面上部の「設定」リンクをクリックして、左メニューから「開発>カスタムオブジェクト」リンクをクリックしてください。画面中央の「新規カスタムオブジェクト」ボタンをクリックして作成を開始します。

「表示ラベル」にはカスタムオブジェクトを表示する際に適当なラベル名を、「オブジェクト名」にはオブジェクトの名称を英数字で入力します。ここでは表示ラベルに「部署」、オブジェクト名を「Department」としています。

Ws000001

「レコード名」にはレコードのラベルとなる名前を設定します。データ型としてテキストもしくは自動採番が選択できます。レコード名はレコード作成の際には入力が必須となります。一つ一つのレコードに名称を設定する必要がない場合は、データ型として自動採番を選択してください。ここではレコード名として「部署名」、データ型は「テキスト」とします。

52

画面下部のオブジェクト作成オプションセクションで「カスタムオブジェクトの保存後、新規カスタムタブウィザードを起動する」にチェックを入れておくと、カスタムオブジェクトを表示するためのタブを作成することができます。このタブを作成しておくと、オブジェクトに対して、検索、表示、作成、編集、削除といった基本的なデータ操作を行うための画面が自動的に作成されます。

ここでは「タブウィザードを起動する」にチェックを入れて、「保存」ボタンを押します。

53

その後、タブ作成のためのウィザードが起動されますが、設定が必要なのはタブスタイルなどの表示にかかわる項目だけです。それを自由に選択した後は、すべて「次へ」をクリックして「保存」ボタンを押します。ウィザードが終了した後に、画面上部のタブリストの右端に「部署」タブが作成されていることを確認してください。

以上の作業によってカスタムオブジェクトがSalesforce上に定義できましたが、まだ肝心のカスタムオブジェクトに格納するデータ構造を決定していません。これは今から設定していくことになります。

データ構造の定義は、作成されたカスタムオブジェクトに対して、適当なデータ型のカスタム項目(フィールド)を追加していくことで行われます。カスタムオブジェクトがRDBで言うテーブルに相当するならば、カスタム項目はカラム(列)に相当すると考えてください。

画面上部の「設定」リンクをクリックして、左メニューから「開発>カスタムオブジェクト」リンクをクリックしてください。 先ほど作成したオブジェクト(「部署」オブジェクト)がリスト内に表示されているかと思います。この表示ラベルのリンクをクリックすると、以下のような画面が現れます。

541

「標準項目」と書かれているセクションには、すでにカスタムオブジェクトに対して標準で定義されている項目(フィールド)がリスト表示されています。リストを見てわかるように、カスタムオブジェクトは常に標準で「作成者」「所有者」「最終更新者」といった項目を保持しています。これらはそれぞれ、そのレコードに関連しているSalesforce内のユーザを指し示しています。

「カスタム項目 & リレーション」と書かれたセクションで、このカスタムオブジェクトに対して項目(フィールド)を追加することができます。「新規」ボタンを押してカスタム項目を追加するウィザードを開始します。

55

まずこの項目のデータ型を決定します。ここでは「テキスト」を選択し、「次へ」をクリックします。

56

項目の詳細を入力します。「項目の表示ラベル」にはカスタム項目を表示する際に適当なラベル名を、「文字数」にはテキスト入力可能な最大文字数を、「項目名」にはカスタム項目の名前を英数字で入力します。ここでは項目の表示ラベルとして「拠点」、文字数を「20」、項目名を「Location」としています。

Ws000000_2  

ここでは、あとはすべて「次へ」をクリックして、最後に「保存」をクリックします。

これによって、カスタムオブジェクトにカスタムの項目を追加することができました。この作業を繰り返すことで、さまざまなデータ型をカスタムオブジェクトに項目として追加していくことが可能です。

カスタムオブジェクトおよびカスタム項目が定義できたら、実際にデータを入力してみましょう。すでに画面上部のタブリストに「部署」タブが作成されているはずです。このタブをクリックすることで部署オブジェクトの情報が表示されます。

58

まだデータベース内にはレコードは何も登録されていません。「新規」ボタンをクリックすることで、レコードを新規作成することができます。

「部署名」および「拠点」に情報を入力して「保存」ボタンを押すと、レコードがデータベース内に登録されます。

59

510

カスタムリレーションの定義

カスタムオブジェクトでは、オブジェクトの間にリレーションを定義することも可能です。これによって、リレーションでつながった2つのオブジェクトに対して同時にレコードを取得することが可能になります。

ここでは先ほど作成した「部署」オブジェクトに関連するオブジェクトとして、「従業員」オブジェクトを定義します。

画面上部の「設定」リンクをクリックして、左メニューから「開発>カスタムオブジェクト」リンクをクリックしてください。画面中央の「新規カスタムオブジェクト」ボタンをクリックして作成を開始します。

先ほどと同じように、カスタムオブジェクトの情報を入力します。表示ラベルは「従業員」、オブジェクト名を「Employee」、レコード名を「従業員名」、データ型を「テキスト」とします。「カスタムオブジェクトの保存後、新規カスタムタブウィザードを起動する」のチェックボックスもチェックしておいてください。

Ws000001_2

「保存」ボタンをクリックすると、タブ作成のためのウィザードが起動されます。先ほどと同様に、設定が必要なのはタブスタイルなどの表示にかかわる項目だけです。それを自由に選択した後は、すべて「次へ」をクリックして「保存」ボタンを押してください。ウィザードが終了した後に、画面上部のタブリストの右端に「従業員」タブが作成されていることを確認してください。

次に、作成された従業員オブジェクトに対して、部署オブジェクトへのカスタムリレーションを作成します。この場合、部署オブジェクトと従業員オブジェクトは1対多の関係となります。

画面上部の「設定」リンクをクリックして、左メニューから「開発>カスタムオブジェクト」リンクをクリックしてください。先ほど作成したカスタムオブジェクト(「従業員」オブジェクト)がリスト内に表示されていると思います。この表示ラベルのリンクをクリックすると、以下の画面が表示されます。

5121

カスタムリレーションを追加するには「カスタム項目 & リレーション」のセクションから、「新規ボタン」をクリックします。

最初にカスタム項目のデータ型を選択しますが、リストのうち「参照関係」および「主従関係」となっているものがリレーションの設定に相当します。参照関係と主従関係はどちらも他のオブジェクトへのリレーションを定義しますが、主従関係の場合は関連先のオブジェクトに完全に属したデータとなり、関連先のオブジェクト(主)が削除されると関連元のオブジェクト(従)は自動的に削除されることになります。

5131

ここでは「参照関係」を選択して「次へ」と進みます。

次に関連するオブジェクトを選択します。選択リストには、標準オブジェクトを含め、リレーションを定義することが可能なオブジェクトがリストされています。ここでは先ほど作成した「部署」オブジェクトを選択します。

5141

リレーションの名前を入力します。ここでは項目の表示ラベルとして「所属部署」、項目名として「Department」と入力します。

Ws000002

あとはすべて「次へ」をクリックしてウィザードを進めてください。最後に「保存」をクリックします。

これで「部署」オブジェクトに関連する「従業員」オブジェクトを定義することができました。あとは実際にデータを入力し、リレーションが機能していることを確かめましょう。

画面上部のタブリストには「従業員」タブが作成されているはずです。このタブをクリックすると従業員オブジェクトの情報が表示されます。「新規」ボタンをクリックして新しく従業員レコードを作成します。

5161

新規入力画面には「従業員名」という項目のほかに「所属部署」とラベルのついた項目が存在しているのがわかります。この項目の左端のアイコンをクリックすることで、部署オブジェクトから関連付けるレコードをルックアップすることができます。

5171

従業員名に適当な名前を入力し、所属部署にはルックアップ選択ダイアログから先ほど作成した部署レコード「開発本部」を選択して、「保存」ボタンをクリックします。

カスタムオブジェクトへのアクセス

以上で、カスタムオブジェクトおよびリレーションをWebインターフェースから定義することができました。最後にこのカスタムオブジェクトに対してアプリケーションプログラムからアクセスする方法について簡単に紹介します。

カスタムオブジェクトは、作成時に定義したオブジェクト名によってアクセスすることが可能です。ただし、この場合常にオブジェクト名に'__c'という文字列が後ろに付加された形になります。先ほどの例では、部署オブジェクトは "Department__c"、従業員オブジェクトは "Employee__c" という名前によってアクセスすることになります。カスタム項目名についても同様に'__c'が項目名の後ろに追加されます。これはAPI参照名とよばれており、カスタムオブジェクトの詳細表示画面から参照できます。

例:

SELECT Id, Name, Location__c FROM Department__c

リレーション項目にアクセスするためには、項目名に対して'__r'を追加した名前でアクセスします。

例:

SELECT Id, Name, Location__c, (SELECT Id, Name FROM Employee__r) FROM Department__c
SELECT Id, Name, Department__r.Name FROM Employee__c

プログラムからレコード間のリレーションを設定する場合は、参照する側のオブジェクトのリレーション項目の値に参照される側のレコードの Id 値をセットすることになります。Id 値の設定はリレーション項目名に対して'__c'を追加したプロパティに対して行います。

例(AJAX Toolkit):

var res = sforce.connection.query('SELECT Id, Name FROM Department__c LIMIT 1');
var dept = res.getArray('records')[0];
var emp = new sforce.SObject('Employee__c');
emp.Name = '鈴木 一郎'
emp.Department__c = dept.Id;
sforce.connection.create([ emp ]);

JavaでエンタープライズWSDLを用いてプログラムを記述している場合は、カスタムオブジェクトを定義した際には再びWSDLをダウンロードしてスタブクラスを作成する必要があります。このときカスタムオブジェクトも標準オブジェクトの場合と同様にJavaクラスとして取り扱うことができます。

例:

Department__c dept = new Department__c();
dept.setName("営業本部");
dept.setLocation__c("東京");
binding.create(new Department__c[]{ dept });

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内のツールキットにあるサンプルコード等をご覧ください。

Apexアプリケーション開発をはじめよう - 第3章:AJAX Toolkitを使ったアプリケーションの作成

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

デベロッパーアカウントの作成

もっと深くForce.comプラットフォーム上での開発について知りたくなったときは、すぐにApex Developer Networkから開発者用アカウントを申し込んでください。無料でサインアップできます。

無料サインアップ

サインアップが終了すると、デベロッパー用の管理者アカウントとログインのための仮パスワードが登録したメールアドレスに送信されます。

アカウントが作成されると同時に、そのアカウントによってアクセス可能なSalesforceのインスタンスがそれぞれ割り与えられます。このインスタンス内のデータはすべてプライベートに隔離されており、管理者もしくはその管理者アカウントによって作成されたユーザのみしかアクセスできません。

セールスフォース・ドットコムでは、このSalesforceが割り当てるインスタンスのことを「組織」と呼んでいます。

ネイティブアプリケーションについて

アプリケーションをForce.comプラットフォームで作成し、公開するためには、特別なサーバインフラの構築は必要ありません。望むならばアプリケーション開発から実行および公開まで、Salesforceの中ですべてまかなうことができます。

このような特徴は、オンデマンド型のアプリケーションプラットフォームが持つ可能性の一端を示しています。Force.comプラットフォーム上で開発する開発者は、提供するアプリケーションサービスのために特別なコストを負担する必要がありません。

セールスフォース・ドットコムでは、このようにすべてSalesforceの中で完結できるアプリケーションをネイティブアプリケーションと呼んでいます。

SコントロールとAJAX Toolkitについて

Sコントロールとは、SalesforceがホスティングするHTMLおよびJavaScriptが記述された表示用コンポーネントです。典型的なネイティブアプリケーションでは、アプリケーションが取り扱うデータをSalesforce上にオブジェクトとして定義した後、そのデータを取得・表示するビューを作成するのにこのSコントロールを利用することになります。

Sコントロールに表示するデータを取得するためには、JavaScriptからApex Webサービス APIにアクセスするAJAX Toolkitを利用することになります。AJAX ToolkitはApex WebサービスのSOAPメッセージのやり取りをXMLHttpRequest上に既に実装しているため、開発者はメッセージレイヤーで行われていることについて特別に意識する必要なくApex APIを利用できます。

注意:AJAX Toolkit はSalesforceの外部サイトに置かれているHTMLから利用することは出来ません。
これは、一般的にブラウザ上のXMLHttpRequestでは、HTMLが配置されているサイト以外のドメインに対してリクエストを送信することができないようになっているためです。
Sコントロール内のHTMLはSalesforceのドメイン上でホスティングされるため、同一ドメインで提供されるApex Webサービスに対してJavaScriptからアクセスすることが可能になります。

Sコントロールの作成

Sコントロールを作成するには、WebインターフェースからSalesforceにログインする必要があります。

画面上部の「設定」リンクをクリックし、左側のメニューから「開発>カスタムSコントロール」を選択します。「新規カスタムSコントロール」ボタンを押してSコントロールを新規に作成します。

31_1

「表示ラベル」欄には表示用に適当な名前、「Sコントロール名」には英数字でSコントロールの名前を、「コンテンツ」テキストエリアには表示するHTMLを貼り付けて保存します。ここでは以下の簡単なHTMLを入力しておくことにします。

<html>
  <head></head>
  <body><h1>Hello, World</h1></body>
</html>

次にこのSコントロールをSalesforceの画面上に表示するために、カスタムWebタブを作成します。タブはユーザがSalesforceにログインした後、画面の上部にタブリストとして表示されることになります。なお、タブの順番やどのタブを表示するかは、アプリケーションごと、あるいはユーザごとにカスタマイズが可能です。

左のメニューにある「開発>カスタムタブ」を選択し、「Webタブ」から「新規」ボタンをクリックしてください。Webタブ作成のためのウィザードが始まります。

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

タブの中身に埋め込むコンテンツとして、ここではSコントロールを表示するので、「タブの種類」選択リストから「カスタムSコントロール」を選びます。「タブラベル」および「タブスタイル」は、タブの表示に関するプロパティですので、適当に入力して「次へ」ボタンをクリックします。

32_1

先ほど作成したカスタムSコントロールを選択ボックスから選択します。

33

あとはすべて「次へ」をクリックして、最後に「保存」をクリックします。

画面上部のタブリストの右端に作成したWebタブが追加されていれば成功です。クリックして内容を確かめてみましょう。

34

35_1

AJAX Toolkitを使う

Sコントロールをタブとして表示できることを確認したら、Sコントロール内のHTMLにAJAX Toolkitを使ったJavaScriptコードを実際に記述していきます。

まず以下のコードをSコントロールのコンテンツに記述してみましょう。

(Sコントロールのコンテンツを編集するには、「設定」リンクから「開発>カスタムSコントロール」をクリックして、先ほど作成したSコントロールを選んで「編集」リンクをクリックします)

<html>
  <head>
    <title>AJAX Toolkit Hello World</title>
    <script type="text/javascript" src="/soap/ajax/9.0/connection.js"></script>
    <script type="text/javascript">
function sayHello() {
  document.body.innerHTML='<h1>Hello, '+sforce.connection.getUserInfo().userFullName+'</h1>';
}
    </script>
  </head>
  <body onload="sayHello()">
  </body>
</html>

保存した後、先ほどのタブを再び参照すると、ログインしたユーザのユーザ名が表示されているのがわかります。

36_1

上記のHTML中では、以下のタグをheadタグ中に含めることで、AJAX Toolkitをロードしています。

<script type="text/javascript" src="/soap/ajax/9.0/connection.js"></script>

このスクリプトの中で、AJAX Toolkitの本体となるsforce という変数名のJavaScriptオブジェクトが定義されます。実際のAPIへのアクセスは、sforce.connection オブジェクトに定義されたメソッドを中心に行います。

サンプルコード

では、実際にApex APIへの呼び出しを行うAJAX Toolkitのサンプルコードを見ていきましょう。

最初にSOQLクエリによってApexデータベース内のレコードを取り出すコードです。query メソッドを利用します。

var result = sforce.connection.query('SELECT Id, Name FROM Account');
var accounts = result.getArray('records');
var html = '<ul>';
for (var i=0; i<accounts.length; i++) {
  html += '<li>'+accounts[i].Id + ', '+accounts[i].Name+'</li>';
}
html += '</ul>';
document.body.innerHTML = html;

次にApexデータベースに対して新規にレコードを追加するコードを見てみましょう。APIではcreate メソッドを利用します。パラメータにはsforce.SObject オブジェクトに項目値をプロパティとして設定したものを渡します。複数同時にレコードを作成することも可能なため、配列として渡す必要があることに注意してください。

var account = new sforce.SObject('Account');
account.Name = '株式会社セールスフォース・ドットコム';
account.BillingState = '東京都';
account.BillingCity = '渋谷区';
account.BillingStreet = '恵比寿1-19-19';
var results = sforce.connection.create([ account ]);

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

var account = new sforce.SObject('Account');
account.Id = '0015000000GaX8UAAV';
account.NumberOfEmployees = 1000;
var results = sforce.connection.update([ account ]);

deleteIds メソッドは、Apexデータベース上の指定のIdを持つレコードを削除します。パラメータには削除するレコードのId 属性を配列で渡します。

var results = sforce.connection.deleteIds([ '0015000000GaX8TAAV', '0015000000GaX8UAAV' ]);

もともとのApex Webサービス APIでは削除のためのメッセージ名は delete となっているのですが、JavaScriptでは delete は予約語であるため AJAX Toolkitでは deleteIds とされています。

定義されているオブジェクトにどのような項目が含まれるかについても、APIから取得することができます。describeSObject メソッドはオブジェクトの定義情報に関するメタデータを取得するAPIメソッドです。

var result = sforce.connection.describeSObject('Account');
var fields = result.getArray('fields');
var html = '<ul>';
for (var i=0; i<fields.length; i++) {
  html += '<li>'+fields[i].name + ', '+fields[i].label+'</li>';
}
html += '</ul>';
document.body.innerHTML = html;

以上でAJAX Toolkitと主要なAPIメソッドについて説明しました。その他のAPIの詳細については、Ajax Toolkit API 8.0およびApex API 8.0をご参照ください。

すでにお気づきの方もいらっしゃるかもしれませんが、前章で触れた開発者向けの学習用デモアプリケーションは、このAJAX Toolkitを利用して作成されたネイティブアプリケーションの一例です。特に「AJAX Toolkit Shell」は、AJAX Toolkit APIを対話的に操作できるシェルアプリケーションになっています。API習得の際にはぜひご活用ください。

Apexアプリケーション開発をはじめよう - 第2章:Salesforceのデータベースにアクセスしてみよう

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

学習用デモアプリケーション(トライアル)

Salesforceのプラットフォーム(Force.comプラットフォーム)に興味が湧いてきましたか?

それでは早速Salesforceのデータベースにアクセスしてみましょう。

まず皆さんにForce.comプラットフォームがどのようなものであるかを実感していただくために、開発者向けの学習用デモアプリケーションを用意しました。以下のリンクからアクセスが可能です。

http://www.salesforce.com/jp/appexchange/detail_overview.jsp?NavCode__c=&id=a0330000002fF8SAAU

21

リンクで飛んだ先は、セールスフォース・ドットコムが提供しているAppExchangeと呼ばれるアプリケーションディレクトリサイトです。セールスフォース・ドットコムでは開発者が作成したアプリケーションをこのサイトを通して公開しています。

Salesforceのアカウントをすでにお持ちの方は「インストール」ボタンをクリックすることでこのアプリケーションを自分の環境にインストールできますが、まずは「トライアル」ボタンをクリックして実際にこのデモアプリケーションを触ってみましょう。トライアルだけであればまだSalesforceのアカウントは必要ありません。

22

このアプリケーションはApex WebサービスAPIを利用して作成されたカスタムのアプリケーションです。Apexデータベースに対してブラウザから直接クエリ文(SOQL)を投げてデータベースのレコードを検索することが可能です。

SOQLクエリの送信

それでは実際にApexデータベースに対してSOQL文を発行してみましょう。「SOQL Explorer」と書かれているタブをクリックした後、画面中のテキストエリアに以下のSOQL文を入力してください。

SELECT Id, Name FROM Account

以上の文を入力した後で「Run Query」ボタンを押すと、Apexデータベースにクエリが送信され、結果セットが返されます。

23

このSOQL文はSalesforceが標準で定義している Account (日本語名は"取引先")オブジェクトに対して IdName 列の値を取得してくるクエリ文でした。

Salesforce内部にはこの他にも標準定義のオブジェクトが存在しています。その中の Contact (日本語名は"取引先責任者")オブジェクトは、Account オブジェクトと多対1で関連付けられています。

24_5

では次にこの2つのオブジェクトに対して同時にデータを取得するようなクエリを投げてみましょう。テキストエリアに以下のSOQL文を入力して「Run Query」ボタンを押してください。

SELECT Id, Name, (SELECT Id, LastName, FirstName FROM Contacts) FROM Account

表示された結果セットの中の をクリックすると、Account オブジェクトに結びついた Contact オブジェクトのデータが展開されて表示されます。

25

SOQL構文について

SOQLは、SQLと似ていますが、さまざまな面で異なります。以下ではSOQLの構文について例を交えて紹介します。

最も単純なSOQL文の例の一つとして、Account オブジェクトから Id および Name 属性を取得するものを以下に示します。

SELECT Id, Name FROM Account

WHERE 句を付加することによって、検索するレコードを条件で絞込むことができます。

SELECT Id, Name FROM Account WHERE BillingState = '東京都' AND NumberOfEmployees > 500

項目リストの指定を count() とすることによって、レコードの件数を取得することも可能です。

SELECT count() FROM Account

検索結果として得られる件数が多い場合、件数の上限を LIMIT 句で指定しておくこともできます。

SELECT Id, Name FROM Account LIMIT 10

また ORDER BY 句によって結果を指定した項目であらかじめソートして取得することもできます。

SELECT Id, Name FROM Account ORDER BY CreatedDate DESC

SOQLではSQLのような表結合はありませんが、オブジェクト間にリレーション関係がある場合には、リレーションをたどって一つのクエリで結果を取得することができます。例えば Contact オブジェクトには Account オブジェクトに対してのリレーションが関連付けられていますので、以下のクエリでSQLの表結合に相当する結果を取得することが可能です。

SELECT FirstName, Account.Name FROM Contact

上記では子供から親(多→1)へのリレーションをたどりましたが、親から子供(1→多)へのリレーションをたどるクエリも記述できます。

SELECT Name, (SELECT FirstName, LastName FROM Contacts) FROM Account

SOQL構文の詳細については、APIドキュメント内のSOQLのセクションをご覧ください。

Apexアプリケーション開発をはじめよう 第1章:Salesforceのプラットフォームについて

by Shinichi Tomita on 4月 11, 2007 at 04:52 午後

Web上のデータベースとしてのSalesforce

セールスフォース・ドットコムでは、その名が示すとおり、企業向けに営業活動を支援するためのアプリケーション(SFA)や、それに伴う顧客とのリレーションを管理するためのアプリケーション(CRM)を提供しています。

ただ、これらのアプリケーションが動作しているプラットフォームが、実はSFAやCRMのみならず、あらゆるアプリケーションサービスを構築可能な柔軟性を持っていることを理解されている方は少ないのではないでしょうか。

実は、Salesforceは、一言で言うと「Web経由でアクセスできるデータベースサービス」を提供しているのです。

少々補足しておきますと、これはユーザ自身がWebブラウザからサーバ上のデータを閲覧し更新できる、ということはもちろんですが、それだけではありません。重要なポイントは、外部のプログラムからもデータベースが格納しているデータにアクセスできるという点です。つまり、Salesforce内のデータへアクセスするためのWebサービスAPIが提供されているのです。

アプリケーション独自のテーブル定義

一口にデータベースサービスといっても、Salesforceが提供しているのは、データがあらかじめ用意されていて、それに対して検索、参照ができるようなサービス、といった類のものではありません。

Salesforceでは汎用的な「データの入れ物」のプラットフォームを提供しています。そこでは参照だけでなく、作成、更新、削除といったデータに対する基本的なCRUD操作がサポートされています。

さらに特筆すべき点は、データの入れ物自体の構造を自分で決定することができるというところです。つまり、データベース内に格納することができるオブジェクトの定義(多くのRDBではテーブルに相当します)を、アプリケーションごとに独自に設計/追加することが可能になっています。

従来のWebサービスでは、あらかじめサービスで扱うデータの種類は決まっていることが多く、しかもそのデータ構造はサービスに依存していることが多かったのですが、Salesforceではアプリケーションが必要とするデータ構造を開発者自身で定義できることが大きく異なっています。

RDBの場合と同様に、開発者は独自に定義したオブジェクトの間にリレーション(参照関係、主従関係)を定義しておくこともできます。リレーションはSalesforceのCRMアプリケーションが標準で定義しているオブジェクトに結びつけることも可能で、たとえば”取引先A”に関連しているオブジェクト”XXX”、というデータを格納しておくことができます。

以上のようなデータベース設計にまつわる操作は、すべてWebのインターフェースから実行することが可能です。

クエリ言語を使ったデータアクセス

このようにSalesforceでは汎用的なデータを格納することが可能であるため、格納されるデータへのアクセス手段についても汎用的なアプローチをとっています。SalesforceではSalesforce内のデータにアクセスするためのクエリ言語である(SOQL:Sforce Object Query Language)を用意しており、SOAP Webサービスを利用してアクセスします。

SOQLはSQLに似ていますが、SQLと異なるのは、結果セットをオブジェクトとして返すため、リレーション項目についても階層的なオブジェクトとして扱うことができるという点です。

例:

SELECT c.FirstName, c.LastName, a.Name FROM Contact c, c.Account a
SELECT Id, Name FROM Opportunity o WHERE o.Account.Name LIKE 'A%'
SELECT a.Name, (SELECT c.LastName FROM a.Contacts c) FROM Account a

マッシュアップアプリケーション

このような高い柔軟性を持つSalesforceのプラットフォームを利用すれば、自分で特別にデータベースサーバを保守・運用することなく、必要なデータをすべてWebサービス APIで取得し保存するアプリケーションサービスを構築することもできるでしょう。

もちろん、あらかじめSalesforceが標準で提供しているオブジェクトを利用することによって、エンドユーザがSalesforceのSFA/CRMアプリケーションで利用しているデータと連動したアプリケーションも作成できます。

さらに、SalesforceのAPIに加えてさまざまな既存のWebサービスを組み合わせて用いることで、開発者はダイナミックなマッシュアップアプリケーションをほとんどコストをかけることなく作成できるようになるのです。

これらのアプリケーションを開発するための言語プラットフォームとしては、Java、Javascript(AJAX)、.NETなどの言語に加え、PHP、Perl、Ruby on Railsなどからの利用も可能です。

私たちは、このSalesforceが提供しているプラットフォームのことを「Force.comプラットフォーム」と呼んでいます。Force.comプラットフォームには、データベースサービスとしてのForce.comデータベース、WebサービスAPIとしてのForce.com Web Services API、およびSalesforceのサーバ内でのロジックを記述するためのApexコード(近日中に利用可能になります)などが含まれています。