概要
初心者用のSalesforceトリガーの仕組みを勉強するために作りました。
何を作る
書籍名が入力されたら、トリガーでGoogle Books API上の本を検索し、自動的に項目にセットする。
事前準備
- SFDC - トリガーの基本事例
- 上記の
Book
オブジェクトでWeb_Results__c
- データ型:リッチテキストエリア(32768)
、というカスタム項目をBookカスタムオブジェクトに追加する - YQL - Google Books API用のクエリ
実装した時に躓いたところ
- 外部APIを呼ぶためのウェブサービスのcalloutメソッドを実装する
- YQLからのデータを非同期で取得するので、@futureで書く
- @futureは独立クラスで実装する必要がある。
- JSONParserでいちいち取得するのが面倒なので、JSONからMapに変換。 Stackoverflow
-
Book
オブジェクトをそのまま渡せないので、Idのパラメーターで渡す。
global class YQLBridge {
@future (callout=true)
public static void searchGoogleBooks(String bookId) {
Book__c book = [SELECT Name, Id FROM Book__c WHERE Id=:bookId];
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('https://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20FROM%20google.books%20WHERE%20q%3D%22'
+book.Name+
'%22%20AND%20maxResults%3D1&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&format=json');
req.setMethod('GET');
HttpResponse res = http.send(req);
Map<String, Object> root = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
Map<String, Object> query = (Map<String, Object>)root.get('query');
Map<String, Object> results = (Map<String, Object>)query.get('results');
Map<String, Object> jsonItem = (Map<String, Object>)results.get('json');
Map<String, Object> items = (Map<String, Object>)jsonItem.get('items');
Map<String, Object> volumeInfo = (Map<String, Object>)items.get('volumeInfo');
String richStr = 'title :'+volumeInfo.get('title')+'<br >'+
'subtitle :'+volumeInfo.get('subtitle')+'<br >'+
'author :'+volumeInfo.get('authors')+'<br >'+
'thumbnail : <img src="'+((Map<String, Object>)volumeInfo.get('imageLinks')).get('thumbnail')+'" />';
book.Web_Results__c = richStr;
update book;
}
}
- コントローラーは以下で実装する:
public static void populateInternetBooks(Book__c book) {
YQLBridge.searchGoogleBooks(book.Id);
}
- トリガーには以下で実装する:
trigger PopulateWebResults on Book__c (before insert, before update) {
Book__c[] books = Trigger.new;
for (Book__c b :books){
if(b.Web_Results__c == NULL || b.Web_Results__c.trim().equals('')) {
BookController.populateInternetBooks(b);
}
}
}
完成したソース
Github上で公開していますので、ご自由にカスタマイズしてください。
Salesforceではまだ一ヶ月勉強したばかりの初心者なので、ご指摘があればぜひお願いします。