2017年6月30日金曜日

Salesforce : Apex : SOQL : クエリの結果の受け取りかた

ApexでSOQLクエリを発行してた下記のように結果を受け取る。

// sObjectで結果を受け取る
Account a = [SELECT Id FROM Account];

// sObjectのリストで結果を受け取る
List<Account> li = [SELECT Id FROM Account];

どちらでもいいのだけれど、「sObjectで結果を受け取る」のほうの場合でクエリの結果が複数レコード取得出来てしまうとエラーとなってしまう。なので、使用できる箇所は限定的だ。

逆に言えば、クエリの結果が1件であることが保証できるのであればリストでクエリの結果を受け取る必要はないと言える。

ところが昨日、複数レコードデータが取得できるはずのないクエリでエラーとなってしまった。

これが問題のクエリ
ContentVersion content = [SELECT Title,VersionData FROM ContentVersion where Id = '06841000000LkfCAAS' LIMIT 1];

"Limit 1"を指定しているし、そもそもIDを条件句に入れているのだから、複数レコード取得できるはずがない。
List has no rows for assignment to SObject
昨日は勘違いしていたが、冷静になってこのメッセージを読み返すとクエリの結果がゼロ件だからエラーになっているようである。

これ、私にとっては新事実なのだけれど。

というわけで試してみる。

Account a = [SELECT Id FROM Account WHERE Name = '???'];

データを取得できない条件を指定してSOQLクエリを発行し結果を受け取る。
List has no rows for assignment to SObject
同じメッセージが得られたので、ゼロ件だとエラーになるみたいだ。

てっきり、ゼロ件でもエラーとはならないと思い込んでいた。もし本当なら「sObjectで結果を受け取る」なんてプログラムを書くメリットがまったくないと言える。

100%確実に、データが1件のときというの保証するのは難しい。"LIMIT 1"とすれば

Account a = [SELECT Id FROM Account WHERE Name = '???' LIMIT 1];

クエリは最大でも1件しかデータを返さない。

けれど、絶対に1件取得できる保証ができないケースのほうが多い気がする。とりあえず、必ずListを使って受け取るようにしようと思う。

2017年6月29日木曜日

Einstein Vision : 画像認識をアップロードファイルでやりたい4

見えないふりをしていたのだけれど、実はクイックスタート: Einstein Visionで使うプログラムには最初からコメントアウトされている部分がある。昨日、うまくアップロードした画像を認識できなかったので、この部分を少し調べてみたい。何か解決のヒントが得られるかもしれない。

<!--  <apex:pageBlock > -->
<!--      <apex:repeat value="{!callVisionContent}" var="prediction"> -->
<!--          <apex:outputText value="{!prediction.label}" />:<apex:outputText value="{!prediction.probability}" /><br/> -->
<!--    </apex:repeat> -->
<!--  </apex:pageBlock> -->

コメントアウトされているVisualforceの箇所が上記の部分。いかにも、そのまま動きそうな雰囲気を出している。こいつのコメントアウトをはずす。

こいつはVisionControllerクラスのcallVisionContentメソッドを呼び出している。

public List<Vision.Prediction> getCallVisionContent() {
 // Get a new token
 String access_token = getAccessToken();

 // Make a prediction for an image stored in Salesforce
 // by passing the file as blob which is then converted to base64 string
 ContentVersion content = [SELECT Title,VersionData FROM ContentVersion where Id = '06841000000LkfCAAS' LIMIT 1];
 return Vision.predictBlob(content.VersionData, access_token, 'GeneralImageClassifier');
}

よくみると、こいつはVisionクラスのpredictBlobメソッドを呼び出している。私が昨日作ったソースではエラーになったがこいつはどうだろうか。

エラーになってしまった。

気になるのはエラーの内容で、"List has no rows for assignment to SObject"。これはクエリの結果が複数件なのに、単一(リストではなく)オブジェクトで受け取ろうとしたときに発生するエラー(だったと思う)。

確かにプログラムはクエリの結果をリストではなく単一のオブジェクトで受け取っている。だが、クエリを見てみると、

ContentVersion content = [SELECT Title,VersionData FROM ContentVersion where Id = '06841000000LkfCAAS' LIMIT 1];

"LIMIT 1"となっているため、クエリの結果は複数件にはならないはず。謎のエラーである。

謎が増えてしまったわけだが、このあたりで今日は終わり。


1回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_26.html
2回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_27.html
3回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_28.html
4回目(今回):

2017年6月28日水曜日

Einstein Vision : 画像認識をアップロードファイルでやりたい3

ファイルアップロードできるようになったので、あとはそのデータをEinsteinに渡してあげるだけ。"predictBlob"というメソッドがいるので、そいつに渡してやる。

認識させるのは私の好きな花、準絶滅危惧種のチョウジソウ。


と思ったのだけれど、残念ながら失敗。


メソッドが用意されているから簡単にできると思ったのだけれど、うまくいかなかった。原因はよく分からない。もう少し調べる必要がありそうだ。

1回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_26.html
2回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_27.html
3回目(今回):

2017年6月27日火曜日

Einstein Vision : 画像認識をアップロードファイルでやりたい2

画像認識をアップロードファイルでやるには、ローカルのファイルをアップロードできるようにしないといけない。ファイルアップロードには<apex:inputFile>を使う。

<apex:inputFile value="{!uploadFile}"/>

こんな感じ。

"ファイルを選択"をクリックするとファイル選択ダイアログが表示されるので、ファイルを選ぶだけ。

valueは必ず指定する。valueに指定するのはBlob型。

こんな感じ。

public Blob uploadFile { get; set; }

今日はここまで。

1回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_26.html

2回目(今回):

3回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_28.html

2017年6月26日月曜日

Einstein Vision : 画像認識をアップロードファイルでやりたい

サンプルのEinstein Visionを動かすプログラムだと、画像ファイルをアップロードして画像認識は行えない。リンク先(こんな感じ)を指定すると画像を認識するという仕組みになっている。

画像ファイルをアップロードできるようにしたとしても、ファイルを認識させるやり方を調べないといけない。

と思っていたのだけど、ちゃんとメソッドが用意されていた。

public static List<Prediction> predictUrl(String url, String access_token, String model) {
    return predictInternal(url, access_token, model, false);
}

public static List<Prediction> predictBase64(String base64String, String access_token, String model) {
    return predictInternal(base64String, access_token, model, true);
}

public static List<Prediction> predictBlob(blob fileBlob, String access_token, String model) {
    return predictInternal(EncodingUtil.base64Encode(fileBlob), access_token, model, true);
}

Visionクラスに画像認識のメソッドがまとまっているだけれど、その中の"predictBlob"というメソッドがファイルを指定できるものになっている。ちなみに、"predictUrl"がリンクを指定するメソッド。

内部のソースをもっときちんと読めば色々とできるかもしれない。

1回目(今回):

2回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_27.html
3回目:
http://nodding-off-programmer.blogspot.jp/2017/06/einstein-vision_28.html

2017年6月25日日曜日

Einstein Vision : 画像を任意のものを選択できるようにする

この前Einstein Visionのページをタブ表示するようにした。普通にタブを作っただけだから何の工夫もないけど。
Einstein Vision をタブ表示

画像認識を使いやすくするには、せめて自分で好きな画像を選べるようにしたい。

<apex:image url="http://metamind.io/images/generalimage.jpg">
</apex:image>

Einstein VisionのVisualforceは固定値で画像を指定しているので、これを変更することで好きな画像を選べるようになる。さらに、画像のリンクを入力できる入力ボックスとボタンを配置。

画像を指定できるように修正
<apex:image url="{!imageLink}"/>

入力ボックス&ボタンを配置
<apex:outputText>画像のリンクを入力してください:</apex:outputText>
<apex:inputText value="{!imageLink}"/>
<apex:commandButton value="画像認識"/>

ここまでやったらVisionControllerを修正する。Visualforceのほうで{!imageLink}で画像のリンクアドレスをVisionControllerとやり取りするようにしているので、これに合わせて修正を行う。

追加
public String imageLink { get; set; }

VisionControllerは画像のリンクを固定値で持っている。

return Vision.predictUrl('http://metamind.io/images/generalimage.jpg',access_token,'GeneralImageClassifier');

こいつを先ほど追加した imageLink を参照するように変更

変更
return Vision.predictUrl(imageLink, access_token, 'GeneralImageClassifier');

あとは作ったものを試してみる。

リンクを入力してから画像認識ボタンをクリック。


指定した画像で画像認識できた。

2017年6月23日金曜日

Salesforce : Einstein Vision をタブ表示

TrailheadでEinstein Visionを試してみたものの、プレビュー表示だけでタブを作成したわけではない。画像認識で遊びやすくするための第一歩として、タブを作成した。


これだけだと、何もできないけれど画像を指定できるようにしたりしようと思う。それにしても、画像認識技術をどんなふうに活用すればいいのかというアイデアはまったくない。

Salesforceを使うのは個人よりかは断然、企業だろう。個人での利用は、開発者がDeveloper Editionを使うとか用途が限定されていると思われる。ビジネスにどう使うものなのか、何か事例でもないかなあ。

2017年6月22日木曜日

Salesforce : Einstein Visionで画像認識

クイックスタート: Einstein Visionで作成した画像認識のプログラムで少し遊んでみた。

Trailheadではサンプルとして1枚の画像しか認識してなかったので、画像認識やってるという実感が得られなかったし、プログラマのさがなのか、固定値を表示しても同じことが起こるとか考えてしまう。

プログラムをほとんど読まずに作成してしまったので、実を言うと、どういうプログラムになっているのか分かっていない。もう少し真面目に読み込んで、画像認識を試している実感を得られるようにしたい。

プログラムを読んでいくと、お手軽にいくつかの画像で画像認識を試そうと思ったら2か所ほど手を入れればいいことが分かった。

作成した"Predict"という名前のVisualforceの4~5行目に下記のような記述がある。

<apex:image url="http://metamind.io/images/generalimage.jpg">
</apex:image>

まず、ここで指定しているurlをブラウザに表示させたい画像に変更する。これだと表示画像が変更されるだけなので、Apexのほうにも手を入れて、認識させる画像も変えてあげないといけない。

それが"VisionController"クラス。29行目を変更する。

return Vision.predictUrl('http://metamind.io/images/generalimage.jpg',access_token,'GeneralImageClassifier');

Vision.predicUrlメソッドの第一引数を認識させたい画像に変更することで、Einstein Visionが読み込む画像が変わる。

試してみた結果は下記通り。


この花がデイジーであるかどうかは、残念ながら私には分からないのだが、ちゃんと認識している気がする。

次はこれ。


2羽が写っているからか、自信なさげな結果になっているけどガチョウでたぶんあってるんじゃないだろうか。あひるかな?ガチョウとあひるの違い分からないし、これでOK。

自分で好きな画像を指定できるようにプログラムを改造できそうだ。

2017年6月21日水曜日

Salesforce : クイックスタート: Einstein Visionをやってみた

Trailheadで簡単にEinstein Visionを試せるようなので、さっそくやってみた。

https://trailhead.salesforce.com/ja/trails/get_smart_einstein/projects/predictive_vision_apex

画像認識の技術がお手軽に試せるのは嬉しい。1時間足らず。


Access Tokenはのっけても大丈夫なものなのか不安なので塗りつぶした。

ちょっとだけ不満を述べると、画像一枚しかサンプルがなくて、これだと画像をちゃんと認識できているのか確信を持てなかったこと。

ここまで書いて気がついた。自分で似たような画像探してきてちゃんと認識できるのか、どこまで判断できるのか試してみればいいと。無償でこんな便利な物を公開してくれているのだから、あとは自分でやるべきだなと。

2017年6月20日火曜日

Salesforce : Trailheadの「SOQL および SOSL クエリの実行」がうまくいかない

Trailheadをやっていてうまくいかないところがある。SOSLクエリを使ってデータを取ってきてSystem.debugでログに出力するだけなんだけれど、なぜか「Challenge Not yet complete」と返ってくる。

https://trailhead.salesforce.com/ja/trails/force_com_dev_beginner/modules/developer_console/units/developer_console_queries

問題文、英語だから何か意味を取り違えてしまっているのだろうか。


書いたプログラムをのせようとしたけれど、冷静に考えるとTrailheadの課題に対するプログラムなのでまずいような。そんな規約があるかどうかは不明だけれど、やめておこう。

2017年6月19日月曜日

Salesforce : パースペクティブのカスタマイズ

開発者コンソールのパースペクティブはカスタマイズできるので、自分好みのものを作ることができる。

ログを開くとメニューから「View Log Panels」を選ぶことができるようになる。Debug > View Log Panels。


このパネルが表示されるので、表示したいビューにチェックを入れる。これだけで、好みのパースペクティブが完成。あとは、Debug > Save Perspective Asを選べばパースペクティブに名前を付けて保存できる。

保存したパースペクティブへはDebug > PerspectiveManagerから切り替えられる。

2017年6月18日日曜日

Salesforce : 開発者コンソールのパースペクティブ

開発者コンソールのログ表示でパースペクティブを設定できることを知った。

そもそもデフォルトで4つのパースペクティブがあったようなのだが、いままで気づきもしなかった。

  1. All
  2. Debug
  3. Log Only
  4. Analysis


開発者コンソールでログを開くと、こんなふうに表示されると思う。この表示が設定をまったく変更していない状態。「Log Only」で表示されている。

メニューで Debug > Perspective Manager を開くとログのパースペクティブの種類が確認できて、冒頭の4つが存在することが分かる。

パースペクティブに設定できるビューは7種類。

  1. Stack Tree
  2. Execution Stack
  3. Execution Log
  4. Source
  5. Source List
  6. Variables
  7. Execution Overview

Perspective Managerから「All」を選ぶと、すべてのビューが表示される。

「Debug」なら、Execution Log、Source、Variablesの3つ。

「Log Only」なら、Execution Logのみ。

「Analysis」だと、Stack Tree、Execution Stack、Execution Log、Execution Overviewの4つ。

こんなに色々見れるものだとは思いもしなかった。

2017年6月17日土曜日

Salesforce : Einstein Visionはどんな用途に?

SalesforceのEinstein Visionに興味を持ったので、手始めにどんな使い方するのかを調べてみたのだけれど、どうもピンとこない。どんなビジネスケースに使うのかのイメージが湧いてこないのだ。

この記事(https://www.salesforce.com/jp/blog/2017/03/einstein-ai-2017-vol1.html)を読んでみたのだけれど、よく分からない。

画像認識の精度がどうのこうのという話をしたいわけではないし、プログラマとしての私はとても面白そうなものだと思っている。AIなんかの先端技術に触れられるのはちょっとワクワクする。なので、Trailheadもあるのでちょっと使ってみようかと思っている。

本当はプログラマが良い技術をどんな風に使ってビジネスを変えていくのか創発すべきなのだけれど、よく考えるとEinstein Visionだけでなく画像認識という技術がどんなことに使われているのかすらよく知らない。そんな状態で何かアイデアが出せるわけがない。

というわけで、Einstein Visionの記事がどうのという話ではなく、どうも記事の受け手としての私のほうに、最低限必要な知識なんかが足りていないようだ。せっかくの機会なので、少し調べてみようかな。

2017年6月13日火曜日

Salesforce : Lightning Experience : カスタムホーム画面の作成

Lightning Experience におけるカスタムホーム画面の作成方法。

1. Lightning アプリケーションビルダー

設定から検索ボックスに「アプリケーションビルダー」と入力すると見つかる。


2. 新規ボタンをクリック


3. ホームページを選択して次へ


4. ラベルを入力

5. テンプレートを選択する

6. 左側のコンポーネントをドラッグアンドドロップすればカスタマイズ完了


最後は保存するだけ。

色々なコンポーネントがそろっており、カスタムコンポーネントの設置もできるので、ホーム画面があっという間に便利に変わる。

保存をするときに下記のようなダイアログが表示される。


特定のプロファイルに割り当てたりできるので、例えば会社の役職に応じてホームページを変えたりできる。

2017年6月12日月曜日

Superbadge - Lightning Experience Specialist

最近はLightning Experience SpecialistのSuperbadgeの獲得を目指してTrailheadをやっていた。といっても1日30分から1時間くらいしかやらないからなかなか進まない。Superbadge獲得にはいきなり挑戦できなくて、いくつかのTrailを完了させないといけないのが少し面倒なところ。


Lightning Experience Specialistを目指したのは、Apexでプログラミングして作りこむよりも、もっとSalesforceそのものを知ったほうがいいだろうと感じていたから。もちろん、Apexだって簡単なものじゃないし、私の知らないこともたくさんあるだろう。だけれども、優先順位をつけたときに私としてはApexではないなと思った。

今後は徐々にClassicからLightning Experienceに移行していくのだろうし、今後必要になるスキルでもあるだろうというのもある。

課題文がぜんぶ英語なのは辛いけれど、ようやくSuperbadge取得へのスタートラインに立てたので頑張ろうと思う。

2017年6月4日日曜日

Salesforce : Lightningと私のドメイン

先日Trailheadをやっていて、「私のドメイン」を設定するような単元があった。もちろん、私は素直に「私のドメイン」の設定を行ったのだけれど、そのあとが大変だった。

Classic表示であれば、私のDeveloper環境に入れるのだが、Lightning表示だとログインできないという謎の現象が発生したのだ。調べても原因が分からない。というか、そんな現象に見舞われた人はいないようで、事例が見当たらない。

はっきりとやる気を失った。

今日になってようやく、原因をちゃんと調べて、使えるようにしようと思えるくらいまでにはやる気を取り戻した。ふてくされててもしょうがない。むしろ、ちょっとネットで探したくらいでは、見つからないようなレアな現象である。調べて原因と対策をまとめることにはきっと意義があるだろう。

よし、まずは現象の再確認。不具合に見舞われたプログラマの基本だ。



うん、しっかりログインできてる。なんで?

やる気が失せるなぁ。

2017年6月2日金曜日

Salesforce : 数式でSalesforceのURLを取得

レコードが更新されときに通知するChatterに、更新がかかったレコードへのリンクを差し込む方法を調べた。

プロセスビルダーでやろうとしたのだけれど、レコードのIDは取得出来ても、SalesforceのURLの取得方法が分からない。Apex書くしかないのかと思ったら、数式項目でSalesforceのURLを取得する方法が見つかった。
http://tyoshikawa1106.hatenablog.com/entry/2015/11/24/233627

これを利用すればApexを書かなくてもリンクの差し込みを行える。

まずは数式項目の作成
LEFT($Api.Partner_Server_URL_390, FIND("/services/Soap/", $Api.Partner_Server_URL_390)) + Id
"$Api.Partner_Server_URL_390"の部分がポイントになる。最後の390はたぶんバージョンを表しているので、Salesforceがリリースされると変わっていくと思われる。とは言っても、過去のバージョンのものが削除されるわけではないので特に何か対処が必要なわけではない。

次に、プロセスビルダーでプロセスを作成して、差し込み項目に作成した数式項目を指定する。


プロセスを実行してChatterを確認すると、リンクが貼れていることを確認できる。


2017年6月1日木曜日

Salesforce : VisualforceがLightning Experienceの表示に切り替わらない

表示をLightning Experienceに切り替えると、Visualforceで作ったページのデザインも勝手に切り替わってくれるものだと都合よく思い込んでいたのだが、どうも違うらしい。

■Lightning(商談の一覧)

■先日作った項目のAPI名を一覧表示するページ


Classic用に作ったVisualforceページはClassic風なページになってしまう。他のページとアンバランスであまり格好良くない。使っているのは"apex:column"などのVisualforceのタグで、"div"タグといったHTMLタグを使っているわけではないのだから、勝手にCSS切り替わったりしないものなのかと期待していたのだけど。

下記のリンク、Trailheadなのだけれど、読むとLightningにはLightning用にデザインを作らないといけないような気がする。
https://trailhead.salesforce.com/ja/modules/lex_dev_visualforce/units/lex_dev_visualforce_design

そのためには、Lightning Design SystemというTrailheadもあるのでここで学習するといいようだ。日本語対応されてない。英語を読むしかないのか。
https://trailhead.salesforce.com/ja/modules/lightning_design_system