Apex RESTによる外部アプリケーションを意識したAPI拡張

はじめに

皆さんこんにちは。 Dreamforceレポートは以前に1回投稿していますが、正式な Tech Blogはデビュー戦の植松です。 さて、TerraSkyも新入社員が入社して4ヶ月が経ちました。 私自身もまだまだ至らない点が多々ございますが、OJT担当として奮闘しております! それでは、本題に入りましょう。 今回私が取り上げるのは「Apex REST」になります。 iOSのネイティブアプリの開発に興味があるので、Salesforce Mobile SDKを利用して社内アプリ等を作りたいと考えていて、その設計の予備知識としてREST APIに関して調べていて「Apex REST」が気になったので取り上げてみました。

サンプルアプリ設計

私はAppleのプログラミング言語Swiftを学習中なので、今回はSwiftを用いてiOSのサンプルアプリから「Apex REST」を使用する想定で設計していきたいと思います。 まずは、サンプルアプリの簡単な仕様をまとめていきたいと思います。

概要

  • Salesforceのユーザ情報を取得して、指定したユーザの行動情報を表示します。
  • 行動に関連する取引先情報に設定されている位置情報と現在地情報を用いて、距離情報を算出
  • 行動情報の取得はユーザ権限ではなくシステム権限で実行

デザインプロト

要件だけでは分かりにくいのでデザインプロトを作成してみました。 デザインセンスはありませんが、デザイン工程も自分でやってみたいので、いろいろと試行錯誤しています。 今回ははMacアプリの「Sketch 3」とWEBサービスの「inVision」を使用してみました。 ▼動くデザインプロト サンプルアプリ実装イメージは伝わりましたでしょうか。 上記の仕様を元に何故「Apex REST」を使用するのか確認していきましょう。

REST API

SalesforceはAPIファーストで構築されているのでSOAP APIやREST APIを始め、豊富にAPIが提供されています。 今回はモバイルアプリからSalesforce Mobile SDKを利用してREST APIをコール想定で設計します。

REST APIでできないこと

SalesforceのREST APIは強力なのでREST APIを使用すればほとんどの実装したい機能は実現可能かと思われます。 しかし、以下の点は制限事項であると考えています。

  • 実行権限は必ず実行ユーザ権限(Apexのwithout sharingでのコールができない)

検討事項

また、以下の様なケースにおいては、REST APIでデータを取得したうえで、クライアントサイド側で複雑なロジックを実装する必要があります。

  • 階層構造の複雑なリレーションを保ったデータの取得
  • 計算ロジックが必要な場合

同じような機能をAndroidアプリやHybridアプリ、WEBアプリケーション等に今後展開する可能性があります。 一度クライアントサイドで処理を実装してしまっていると、他のアプリを作成する際にまた同じ機能を別の言語で実装しなければいけないという状況になりかねません。

モバイル対策

モバイル開発においては以下の点を考慮して設計する必要があります。

  • クライアントサイド側で望ましいデータ構造でデータを取得して、通信やパフォーマンスを考慮してなるべくAPIコールは少なくしたい
  • アプリのリリース(ユーザがバージョンアップをしなければ、過去のソースでアプリケーションが動き続ける)

上記の様な点を考慮して、REST APIの制限やメンテナスに強いアプリケーションを構築するために、Apex RESTを検討致しました。

Apex REST

Apex RESTはREST APIを拡張し、Apexで実装したメソッドをコールすることができる機能となります。 まずは、サンプルを見て頂きましょう。

ポイントは「@RestResource(urlMapping='/sample/*')」と「@HttpGET」アノテーションとなります。※HELP:Apex REST Annotations上記の実装によって以下のエンドポイントでREST APIをコールすることができるようになります。

https://na8.salesforce.com/services/apexrest/sample/accounts

「/sample/」の部分がURLマッピングで指定したパスで、 「accounts」が「@HttpGET」アノテーションで実装したメソッド名になります。 早速、Workbenchを用いて確認してみましょう。

Apex RESTで実装したエンドポイント(without sharingなのでアクセス可。)
ApexREST_Sample_Account_withoutsharing_json
「.xml」を付加することでxml形式でレスポンスを取得することも可能
ApexREST_Sample_Account_withoutsharing_xml
通常のREST APIで取引先を取得(共有設定:非公開。アクセス権が無いため0件。)
REST_API_SOQL_Sample_Account_withsharing_json

終わりに

上記の要領で、こちらのドキュメントを元にサンプルアプリの要件を満たすAPIを実装してみました。 RESTScheduleController.cls 作成したAPIのレスポンスは以下のようになりました。 ApexREST_Sample_Schedule_withoutsharing_json

今回のサンプルのAPIを作成するにあたって意識したポイントは以下の点となります。

  • URIにバージョン番号を設定してバージョン管理できるように考慮
  • クライアント側のAPIコールを少なくするために、内部クラスを定義して返却するデータ構造をサーバサイドで定義
  • クライアント側で設定したパラメータで処理を分岐(現在地情報を渡すと行動に関連する取引先にある位置情報を参照し距離を算出する。[ロジックはサンプルなので未実装])
  • REST APIではできないアクセス権の無いレコードを取得するためにwithout sharingで実装
  • without sharingしているため、あえて取得項目はクライアント側で指定できないように実装

また、今回の様にApex RESTで実行ユーザ権限ではなく、システム権限でデータアクセスするような場合は実装によっては注意が必要になります。 しかし、Apex RESTはApexクラス単位での実装となりますので、権限セットを作成して、必要なユーザやプロファイルのみにAPIを公開するというようなカスタマイズで柔軟に制御することも可能です! RESTFullな設計に反する実装になるかもしれませんが、APIコール数やパフォーマンスを意識した設計も場合によっては必要かと思います。 外部アプリケーションやAPIを活用して、もっとSalesforceを活用していきましょう!