XPages SSJSで文字列から関数を動的に呼び出す方法

文字列から動的に関数を呼び出したいケースとは?

関数を文字列から動的に関数を呼び出したいケースってどんな時でしょうか? 例えばHTML GET/POSTメソッドのパラメーター値によって呼び出す関数を変えたい場合などが想定されます。

以下の例では、「http://mydomain.com/ApplyFuncXAgent.xsp?func=callMe」というような呼び出しに対してクライアントサイドJavascript(CSjS)でコールする関数を変更するというコードになります。

[code lang="javascript" highlight=""]
var strFunc = location.search.split('func=')[1];
switch(location.search.split('func=')[1]){
case "func1": func1(); break;
case "func2": func2(); break;
case "callMe": callMe(); break;
default: break;
}
[/code]

これを簡略化して文字列から動的に関数を呼び出したい場合、CSJSでは以下のような書き方ができます。

[code lang="javascript" highlight="2"]
var strFunc = location.search.split('func=')[1];
var funcObj = window[strFunc];
if (typeof funcObj === "function") funcObj();
[/code]

windowオブジェクトに登録されている関数オブジェクトを取得し関数としてコールしています。しかしながらXPagesのサーバーサイドJavascript(SSJS)ではwindowオブジェクトがありませんので別の方法で関数を呼び出してやる必要があります。

(1)windowの代わりにthisを使用する方法

[code lang="javascript" highlight=""]

var funcObj = this[strFunc];

[/code]

(2)eval()を利用する方法

[code lang="javascript" highlight=""]

eval(strFunc+"()");

[/code]

(1),(2)どちらでも同じ結果を得ることができます。

パラメーターを渡したい場合はcall()もしくはapply()を使用

SSJSでも文字列から直接関数として呼び出す方法は分かりましたが、次はその関数に引数を与えたい場合にどうするか。この方法はCSJSと同じになります。

例えば、「http://mydomain.com/ApplyFuncXAgent.xsp?func=callMe&args=aa,bb」というようにURLパラメータに[args=aa,bb]を追加して引数も渡す方法を想定します。この場合、以下のコードのようにcall()、もしくはapply()を利用してやることでパラメータを渡すことが可能になります。

[code lang="javascript" highlight="3"]
var argsAry = @Explode(args, ",");
var funcObj = this[func];
return funcObj.call(this, argsAry[0], argsAry[1]);
[/code]

apply()の場合はcall()の時の引数をカンマ区切りで指定するのではなく、第2引数にArrayとして指定してやります。

[code lang="javascript" highlight="3"]
var argsAry = @Explode(args, ",");
var funcObj = this[func];
return funcObj.apply(this, argsAry);
[/code]

XAgentと組み合わせたサンプル

今回自分が必要であったシチュエーションはAJAXによる非同期通信でビューの値をJSON形式で取得するための汎用的なロジックを作りたかったからでした。以下のサンプルコードはXAgentになっており関数名と引数値をURLパラメータで渡すことによって呼び出し関数を変えて目的のJSONの値を返すようになっています。
想定しているURLの呼び出しは「http://mydomain.com/hoge.nsf/ApplyFuncXAgent.xsp?func=testFunc&args=aa,bb」などです。

[code lang="xml" highlight="15,16,18"]
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.resources>
<xp:script src="/xpCommon.jss" clientSide="false"></xp:script>
</xp:this.resources>
<xp:this.afterRenderResponse><![CDATA[#{javascript:var externalContext = facesContext.getExternalContext();
var writer = facesContext.getResponseWriter();
var response = externalContext.getResponse();

// Set context type etc
response.setContentType("application/json");
response.setHeader("Cache-Control", "no-cache");

// read parameters
var func = context.getUrlParameter("func");
var args = context.getUrlParameter("args");

var retTxt = callFuncByString(func, args);
writer.write(retTxt);
writer.endDocument();}]]></xp:this.afterRenderResponse>
</xp:view>
[/code]

上記XAgentから呼び出されているcallFuncByString()を含んだxpCommon.jssのサンプルコードです

[code lang="javascript" highlight=""]
function callFuncByString(func, args){
try{
var argsAry = @Explode(args, ",");
var funcObj = this[func];
return funcObj.call(this, argsAry[0], argsAry[1]);
}catch(e){
print(e);
}
}

function testFunc(arg1, arg2){
return "[{\"arg1\":\""+arg1+"\", \"arg2\":\""+arg2+"\"}]";
}
[/code]

複数のビューのJSON値を非同期通信で取得する毎にXAgentを用意しなくて済むといのがこの汎用化コードの利点ですが、関数を動的に呼び出すことそのものはデバッグがしづらくなるという欠点もあるため使用には慎重になったほうがいいケースもあると思います。
※セキュリティーの観点からこのXAgentをそのまま使うとSSJSの標準関数を含む幾多の関数を呼び出すことが可能になるので危険です。実際には機能制限をするなどして意図した関数以外を呼び出されないように注意を払ってください。


IBM-Connect-2016

IBM Connect 2016 XPAGES 最新動向 Part 3 - XPAGESトラブルシューティング

前回2回に渡りIBM Championがスピーカーを務めるセッションにフォーカスを当てたレポートブログを紹介してきました。

今回はPaul Withers氏の「"Marty, You're Just Not Thinking Fourth Dimensionally": Troubleshooting XPages」のセッションに参加した内容を振り返りたいと思います。
このセッションではStackoverflowで寄せられた質問などをもとにXPAGESでの間違ったアプローチの紹介やトラブルシューティングの方法などノウハウ情報を満載の内容となっていました。

また、このセッションではXPAGESの基礎知識を持っていることが前提になっており「XPAGESを既に使っている人は挙手してください」と質問すると会場のほぼすべての人が手を挙げていたのも印象的でした。 そして前列に座ったIBM Champion達が突っ込みを入れながらさらに話がディープに進んで行くのもIBM Connectのセッションならではの光景です。

documentidプロパティでは常に式言語(EL)を使うこと

このセッション内の数あるトピックの中でも全てのXPAGES開発者が知っておくべきノウハウであり、知らずにやってしまいがちな落とし穴であると思ったのがこの「documentidプロパティなどでは常に式言語(EL)を使う」ということでしたので、私自身でテストしたサンプルコードを交えてこのトピックを掘り下げて紹介したいと思います。

※ちなみに式言語(EL)とは${...}もしくは#{...}で始まるコードの事で#{javascript:...}ではないことと区別しています。

Stackoverflowのこちらのリンク「Why does this code write out TWO documents?」でPaul氏が自ら回答している内容にも絡んでいるのですが、Paul氏が指摘するには、式言語(EL)を使わなければページロード時にdocumentidのプロパティ計算ロジックが4回も呼ばれてしまうと指摘しています。

まずはこちらに用意したサンプルコードを見てください。
[code lang="xml" highlight="5,10"]
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.beforePageLoad><![CDATA[#{javascript:
viewScope.selectedPage = "AllContacts";}]]></xp:this.beforePageLoad>

<xp:this.data>
<xp:dominoDocument var="document1" action="editDocument">
<xp:this.documentId><![CDATA[#{javascript:
var v:NotesView = database.getView(viewScope.selectedPage);
var doc:NotesDocuent = v.getFirstDocument();
if (doc == null){
print ("not found");
return null;
}
else{
print ("doc found");
return doc.getUniversalID();
}}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
<xp:panel>
<xe:widgetContainer id="widgetContainerHeader">
<xp:panel>
<!-- フィールドの表示 -->
</xp:panel>
</xe:widgetContainer>
</xp:panel>
</xp:view>
[/code]

Domino文書データソースを定義する箇所でdocumentIdプロパティに対して値の計算をしています。
UNIDを引っ張ってきたいのでViewを取得して文書を取得してそのUNIDを返すというロジックになります。

如何でしょうか? 皆さんもこれに似たロジックを書いた経験はないでしょうか?
このサンプルには1つの致命的な問題と2つの推奨されないコードが含まれています。

1つ目の致命的な問題とはbeforePageLoadにてviewScopeの変数をセットしデータソース内でそのviewScope変数を利用しているという箇所です。
これはデータソースのほうが先にプロセスが走りその後にbeforePageLoadのプロセスが走るため5行目のviewScope.selectedPageが意図したとおりに設定されずサーバーエラーを起こしてしまいます。

そこでひとまず問題を解決するために以下のようにコードを書き換えます。
[code lang="xml" highlight="8"]
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.data>
<xp:dominoDocument var="document1" action="editDocument">
<xp:this.documentId><![CDATA[#{javascript:
var v:NotesView = database.getView("AllContacts");
var doc:NotesDocuent = v.getFirstDocument();
if (doc == null){
print ("not found");
return null;
}
else{
print ("doc found");
return doc.getUniversalID();
}}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
<xp:panel>
<xe:widgetContainer id="widgetContainerHeader">
<xp:panel>
<!-- フィールドの表示 -->
</xp:panel>
</xe:widgetContainer>
</xp:panel>
</xp:view>
[/code]

beforePageLoadでのviewScopeの利用をやめ、8行目にビューの値をハードコードで渡してやりました。これでとりあえずサーバーエラーは回避され、見かけ上は意図したとおりにブラウザでこのコードを表示されるでしょう。

推奨されないコード その1

しかし、このコードにはまだ推奨されないコードが含まれており、試しにブラウザでこのコードを表示してみるとAdministratorのコンソールに以下のような出力があることが確認できます。

HTTP JVM: doc found
HTTP JVM: doc found
HTTP JVM: doc found
HTTP JVM: doc found

このように、documentIdの値の計算の処理が4回も呼び出されています。これこそが今回Paul氏が指摘する問題の箇所になります。
Paul氏によると4回も呼び出される理由は以下のようになります。

式言語(EL) 【${...}もしくは#{...}】を使わなかった場合、documentIdのようなプロパティを

  • Panel内に追加した場合、beforePageLoadの後に2回呼び出される
  • XPage内に追加した場合、beforePageLoadの前に2回呼び出される。(このときbeforePageLoadで追加したscope変数は使えない)
  • 常にrender response時に2回呼び出される

ということで、上記サンプルの場合4回呼び出されるということになります。
そこで回避策として式言語(EL)を利用することでこの問題は回避されます。

式言語(EL)の「動的に計算」を使用
式言語(EL)の「動的に計算」を使用

以下に1回のみ呼び出される式言語(EL)を利用したサンプルコードを追加します。
[code lang="xml" highlight="20"]
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.beforePageLoad><![CDATA[#{javascript:
javascript:viewScope.selectedPage = "AllContacts";
var v:NotesView = database.getView(viewScope.selectedPage);
var doc:NotesDocuent = v.getFirstDocument();
if (doc == null){
print ("not found");
viewScope.docId = null;
}
else{
print ("doc found");
viewScope.docId = doc.getUniversalID();
}}]]></xp:this.beforePageLoad>

<xp:this.data>
<xp:dominoDocument var="document1" action="editDocument"
documentId="#{viewScope.docId}">
</xp:dominoDocument>
</xp:this.data>
<xp:panel>
<xe:widgetContainer id="widgetContainerHeader">
<xp:panel>
<xc:beforePageLoad></xc:beforePageLoad>
</xp:panel>
</xe:widgetContainer>
</xp:panel>
</xp:view>
[/code]

このコードをadministratorコンソールで確認すると

HTTP JVM: doc found

のように1回しか呼び出されていないことが確認できます。

また、式言語(EL)で「動的に計算」を利用しているため、beforePageLoadで設定されたscope変数が利用できていることにも注目してください。
documentId="#{viewScope.docId}"
の箇所が
documentId="#{javascript:viewScope.docId}"
では意図した動作になりません。

推奨されないコード その2

Domino文書のデータソースを定義する際にignoreRequestParams="true"を明示的に定義してやらないとURLパラメータのdocumentIdで指定された値が常に優先されるため、このようなロジックを書くときはignoreRequestParams="true"を明示的に定義してやるべきです。

こんな事例が沢山

今回はこのブログを書くにあたってPaul氏の指摘を深堀して実証実験を行ってみましたが、実際にPaul氏のセッションではこれに似た内容がいくつもスライドとデモで紹介され、どれもがものすごいスピードで紹介されるためはっきり言ってついていくのがやっとな状態のかなりレベルの高い内容となっていました。

1年を通してStackoverflowでいくつもの質問に対して回答をしているPaul氏ならではのノウハウの詰まったセッションであっただけに、今回のセッションに参加できただけでもIBM Connectに来た甲斐があったと思える、そんなセッションでした。

なお、こちらのセッションのスライドは既に公開されており、こちらより確認できます。
http://www.idonotes.com/IdoNotes/IdoConnect2013.nsf/dx/1279a-marty-youre-just-not-thinking-fourth-dimensionally-troubleshooting-xpages-2016.htm
Chris Millerさんのサイトでその他のセッションを含めLotusphere 2013からのセッションがタイトル別にまとめられています。既に2016年のセッションもいくつか登録されているようなので確認してみてください。


IBM-Connect-2016

IBM Connect 2016 XPAGES 最新動向 Part 2 - 外部連携

前回のIBM Connect 2016レポートブログでIBM Championがスピーカーを務めるセッションが熱いと題し、Single Page ApplicationをXPAGESで作るセッションやモダンなXPAGESアプリケーションを作るためのライブラリ群などの紹介をしました。

XPages,Javaを使って外部システムと連携

今回はIBM ChampionであるJulian Robichaux氏とKathy Brown氏による「AD-1387 Outside The Box: Integrating with Non-Domino Apps using XPages and Java」のセッションに参加した内容を振り返ってみたいと思います。

AD-1387 Outside The Box: Integrating with Non-Domino Apps using XPages and Java

XPAGESとJavaを使ったDomino以外のアプリケーション連携ということでCSV、XML、JSONのデータを様々な手法で連携する方法を紹介していました。また後半ではIBM Social SDKやOAuthやQUICKBASEを使った連携、RDB連携にも触れまさに外部連携を網羅する内容になっていました。

CSV操作 - OpenCSV

手始めにCSVの扱い方から説明が始まりました。今更CSVの話なんて聞きたところでなにも面白くないだろうと思い、このセッションに参加したことを少し不安に思っていたところ、そこはやっぱりIBM Champion達。XPAGESでCSVに限らずメタデータを扱うときはJava Bean(Modelクラス of MVC)を作りましょう、とCSVは単なる滑り出しのためのトピックであり、実際はどんどんとディープな内容で進んで行きました。

Java Beanのサンプルは以下のようになります。
[code lang="java" highlight=""]
public class EasyBean {
private String name;
private int count;
public EasyBean() {}
public String getName() { return name; }
public void setName(String name) {
this.name = name;
}
public int getCount() { return count; }
public void setCount(int count) {
this.count = count;
}
}
[/code]
そして、CSVの読み込み自体はOpenCSVというライブラリを使うという内容でした。ここで注意点は最新版のVersion 3.6はJava 7+となっており、依存関係の問題からJava 6を使っているDomino 9.0.2 FP4ではVersion 2.3を使うことになります。

こちらにOpenCSVを使ったサンプルコードを載せておきます。
[code lang="java" highlight=""]
public static List convertCSV(String csvText) {
try {
CSVReader reader = new CSVReader(new StringReader(csvText));
ColumnPositionMappingStrategy<MovieBean> strat =
new ColumnPositionMappingStrategy<MovieBean>();
strat.setType(MovieBean.class);
String[] columns = new String[] {
"title", "studio", "year", "adjustedRevenue", "unadjustedRevenue"};
strat.setColumnMapping(columns);
CsvToBean csv = new CsvToBean();
List list = csv.parse(strat, reader);
return list;
} catch (Exception e) {
// log this!
return null;
}
}
[/code]

XMLをパースするためのJAXB

こちらのソリューションは既にJava 6+に含まれているためインストールの必要はありません。利用の仕方はJava Beanの記述にアノテーションを利用しどのフィールドがXMLのどのエレメントにマッピングされるかを明示してやります。

サンプルコードは以下のようになります。
[code lang="java" highlight=""]
public static MovieBeanList convertXML(String xml) {
try {
// see @XML annotations on Java beans
JAXBContext jc = JAXBContext.newInstance(MovieBeanList.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
MovieBeanList movies = (MovieBeanList)unmarshaller.unmarshal(
new StringReader(xml));
return movies;
} catch (Exception e) {
// log this!
return null;
}
}
[/code]

JSONのパース

JSONのパースにはXPAGESライブラリにあるcom.ibm.commons.util.io.json.JsonParserを使うことが出来ます。この時点でJavaカスタムオブジェクト(=上記で紹介したようなJava Bean)ではなくJava Maps、ListにJSONデータがパースされるためJava Beanを生成するには別途アンマーシャル(JSONからJava Beanを生成するプロセス)が必要ですが、ここではGSONやFlexJSONなどに触れつつDominoで利用する場合にセキュリティの問題が起こることになるため独自でアンマーシャルを記述する方法を紹介していました。

アンマーシャルのロジック自体はありませんが、JSONをパースする呼び出し部分は以下のようになります。
[code lang="java" highlight=""]
public static List convertJSON(String json) {
try {
Object stuff = JsonParser.fromJson(JsonJavaFactory.instance, json);
List list = buildObjectFromJSON(MovieBean.class, stuff);
return list;
} catch (Exception e) {
// log this!
return null;
}
}
[/code]
JAXBを使ったJSONのアンマーシャルもネットではいくつもサンプルコードが公開されていますので、それと合わせてXPAGES用の独自アンマーシャルコードを作ってみるのがいいと思います。

XAGENT, REST, SocialSDKと内容がてんこ盛り

CSV、XML、JSONのパースとJava Beanによるデータ格納を説明し終えた後は、実際のデータ取得方法としてXAGENTでInputStreamを使い外部システムへのアクセスの説明があり、取得後のObjectをXPAGESへ出力する説明があり、次にRESTでのアクセス方法からSocialSDKを使った連携ではOAuthに触れ、最後にQuickbaseと呼ばれるサービスを使った連携方法まで、まさにこれさえ聞けばXPAGESのシステム連携は基礎はしっかりと抑えられる内容になっていました。

このセッションの内容を全てブログに書き起こすとものすごいボリュームになってしまうため後半の説明は割愛しますが、もし興味があれば「AD-1387 Outside The Box: Integrating with Non-Domino Apps using XPages and Java」のセッション資料がいずれ公開されると思いますので時間をおいて確認してみてください。


IBM-Connect-2016

IBM Connect 2016 XPages最新動向

IBM Championのセッションがとにかく熱い!

日本からIBM Connect 2016に参加してい我々やIBM Championのチームスタジオ 加藤さんなどからIBM Connect 2016の最新情報などが少しずつ発表されていますが、Notes/Dominoに関するホットな最新情報は残念ながらほとんどありません。

そのため例年では当たり前のようにある、新しい機能を説明するセッションやDeep Diveと題して新しい機能を掘り下げて説明するセッションなどがさほど見当たらず、その代わりにIBM Championがスピーカーを務めるテクニカルセッションが多く用意されているように感じています。

XPAGESは進化を続ける!

Notes/Dominoの新機能がさほどないとしても、それはXPAGESの停滞を意味するものではない、ということをIBM Championのセッションを受けるとヒシヒシと感じることが出来ます。

すでにXPAGESはWEB技術と共に進化を続けることができ、XPages Extension Libraryに代表されるように、その進化は既にIBM Champion達を始めとしたコミュニティの力に委ねられていると言っても言い過ぎではないはずです。

IBM Championがスピーカーを務めるセッションでデモされるXPAGESアプリはDomino標準のXPAGES機能では実現することが出来ないようなモダンな作りになっており、どのセッションも観客の食いつき度合いが全く違います。

今回は、XPAGESのセッションに参加して得ることが出来た最新動向をザックリとですかお伝えしたいと思います。

 

The XPages of Things: Integrate Bluemix with Your XPages Applications for a World of Possibilities - 1075A

1月31日BP Summitのセッションです。 IBM ChampionのJohn Jardinさんによるセッションでした。

このセッションではBluemix、Node-RED、XPages、Websocketの技術を使いTwitterのつぶやきをつぶさに取得しXPAGESで作られたページに表示するというデモが行われました。

実はこのアプリの中にもモダンなWEB技術が多数盛り込まれていましたが、その技術の説明を次にあるセッションで詳しく解説してくれました。

 

Optimus XPages: An Explosion of Techniques and Best Practices - 1074A

2月1日のセッションで、このセッションもまたIBM ChampionのJohn Jardinさんによるセッションでした。

このセッションでは「Single Page Application」をXPagesで作成するという開発手法を説明していました。

「Single Page Application」というものはブラウザでページを一度読み込んだあとは、全て部分更新(AJAX)によりビュー表示、文書参照画面、編集画面、そしてその画面遷移をさせてしまう手法で彼のデモアプリにXPAGESは1つしかなく、全てインタラクティブに機能が構成されていました。

その技術を支える主な機能として、OpenNTF Domino API の利用を紹介していました。

OpenNTF Domino APIには以下の特徴があります。

  • Domino Object Classesの拡張
  • クイックインストールと設定
  • JavaでDomino Objectのリサイクルが不要
  • マルチスレッドプロセス
  • XOTS (これについては別の機会に説明したいと思います)

そして、「Single Page Application」を実装するためにJavaによるMVCモデルを採用しており、全てのドキュメントをModel Java Classで機能させるところから始まります。

個人的な意見としては、このアプローチは決して簡単な開発手法ではなく、フォームという考えようによってはそれ自体がModelと位置付けることが出来るものをわざわざJavaで格納しなおすためにModel Classを用意しています。

これにはなによりSingle Page Applicationの実現に必要であることと、MVCモデルによる開発は慣れるとModel Class1つ作るぐらいはささっと出来てしまえるので、その点でデメリットよりメリットが大きく上回るという判断であると思います。

ViewはXPagesを使いControllerをJavaとSSJSで実装していくというイメージです。

ただ、これだけではモダンなSingle Page Applicationを作ることは出来ないはずで、その肉付けとしてUX部分に様々なWEB技術を取り入れていましたので、以下にその機能の一覧を羅列します。

  • Twitter Bootstrap : いまやレスポンシブ対応の定番中の定番になってきていますね。
  • Animate.css : モダンなアプリにあるさりげなく表示されたりするアニメーションの実装に一役かっています。
  • Toastr : アラートダイアログのようにユーザーの処理をブロックすることのない通知機能
  • Font Awesome : Vectorアイコンの集合体で利用がとても簡単ですね。
  • Sweet Alert : アニメーションのある綺麗なアラートを実装することが出来ます。

 

ほかにもホットなセッションが目白押し・・・

BPセッションを含め3日間で5つ以上のIBM Championのセッションを受けましたが、John Jardinさん1人のセッションを紹介した段階で結構なボリュームになってしまいましたので、ほかのIBM Championの濃いセッションはまた別のブログ投稿でお伝えしたいと思います。

 

明日はクロージングセッションを含むIBM Connnectイベント最後の日です。

最終日はUserBRASTやGURUpalooza、Ask the Developerのようなお祭りのようなセッションが多数用意されているので最終日を楽しみたいと思います。


IBM Champion

IBM Champion 2016に任命されました

ibm champion

2015年11月24日にIBMよりメールが届き、自分がIBM Champion 2016に任命されたことを知りました。

今年でIBM Championとなるのは2年目となり、前年初めてIBM Championになった時の感動が思い起こされました。と同時にこれからもっとコミュニティの発展に寄与していけるようにと、改めて気が引き締まる思いです。

なお、日本から選出されたIBM Championは以下の4名です。

海老原 賢次 様 (リコーITソリューションズ株式会社)
加藤 満 様 (チームスタジオジャパン株式会社)
田付 和慶 (ケートリック株式会社)
御代 政彦 様 (株式会社エフ)

おめでとうございます! すでに皆さんがブログ等で言っていますが日本から選出された方が今年は6人から4人へ減ってしまいました。 IBM Championの選出基準がよりグローバルな視点へとシフトしたと聞いていますのでその影響は大きくあったのだと感じています。

自分は2015年、IBM Championとして初めての年を過ごしましたが、XPAGESDAYをはじめ、より積極的にスピーカーとしてセッションをさせて頂く機会がありました。

  1.  IBM XCITE 2015 Spring (05/20/2015 Day2 OGS)
  2.  XPagaesDay 2014 (11/18/2014 web session)
  3.  Tek Tek Lotus, Feb 2015 (02/25/2015 IBM ConnectEd 2015 feedback session)
  4.  Teamstudio Notes/Domino Web Seminar, April 2015 (04/22/2015 web session)
  5.  Notes Shikoku Festa 2015 (10/23/2015 XPages and IBM Verse session)

振り返ると5回のセッションを行いましたが、やはり一番大きく緊張したのはIBM XCITE 2015 Springの基調講演の数十分間でした。ただおかげ様で何か一回り大きくなる機会を頂いたのだと感じています。

2年目のIBM Championとしての抱負・・・

例年通り、IBM側でIBM Champion を選出するにあたり以下の様なことを基準にしているとあります。

  • IBM Collaboration Solutionsを広める
  • 知識と専門技術の共有
  • コニュニティへの貢献と成長の支援
  • IBM ポートフォリオ全体に範囲を拡大
  • ネガティブ、ポジティブ両方のフィードバックを建設的かつ専門的な方法で提供する

1年前、IBM Championとして日本発の情報を世界に発信することで、「日本のエンジニアもまだまだ世界に負けてませんよ!」という印象を世界に持ってもらいたい、ということを抱負として書かせていただきました。そこで行ったのが PlanetLotus.org へブログを登録し英語で情報発信を少しずつ行うということでした。 こちらの分はまだまだ不十分だったと反省点も残りますが、近いうちに英語でNotes/Dominoの技術を説明した動画配信なんてのも行いたいと考えています。

最近ではXPages on bluemixでドローンを操作するというセッションをXPagesDay2015で行ったので、それちらを英語で配信してもいいかもしれません。

2年目、引き続き”てくてくLotus”や”ノーツコンソーシアム”などをはじめコミュニティーへ貢献していきたいと考えております。 またNotes/Dominoを取り巻く環境もBluemixやXPagesの進化で様々なテクノロジーとの連携が強まり、より複雑さを増している気がします。沢山のエンジニアがNotes/Dominoを使い新しいものを生み出していけるよう、自分は新旧どちらのNotesエンジニアの視点にも立ち、少しずつ情報を発信し続けたいと思っています。

以上、2年目もどうぞよろしくお願い致します!


2015.11.18 XPagesDay 2015セッション 「XPagesとIoTでドローンを飛ばそう」

XPagesDayが今年も開催されます

2015年、今年のXPagesDayは11月17,18日にオンラインセッションが行われ、18日には、IBM箱崎で行われるNotesコンソーシアム「パートナーソリューションセミナー」に参戦する形で、昼から会場でのセッションが2つ用意されています。

Xpage on bluemixとIoT Foundationでドローンを制御!

弊社ケートリック 田付のセッションでは(株)ソルクシーズ吉田さんと共同で、Bluemix, XPages, IoTと旬のキーワードてんこ盛りにWebからジャイロ・モーションセンサー、WebGLを使いドローンを制御してみせます。
セッションで触れるテクノロジーの数々は以下の通りです。

  • XPages on Bluemix
  • IoT Foundations on Bluemix
  • JavascriptでのMQTT通信
  • Node.js
  • Node RED
  • WebGL
  • スマートフォン、タブレットのジャイロ、モーションセンサー

現在も開発中のプロジェクトですが、一部公開するとこんな感じです!
xdrone-webGL02xdrone-webGL01

お申込みは以下のリンクより「H1-3」をお選びください。
http://partner.cons20.info/portal.nsf/pages/pub

XPAGESDAY 2015 開催概要について

日時:2015年11月17日(火曜日)、2015年11月18日(水曜日)

場所:2015年11月17日オンライン、2015年11月18日はオンラインと 日本アイ・ビー・エム箱崎

スケジュール

11 月 17 日 (火)

10:30~11:30 【初心者】Notes 技術者のためのはじめての XPages 講座
13:30~14:30 【中上級】REST の総復習
15:00~16:00 【初心者】誰も教えてくれなかったXPages のデバッグ方法。どうやるの?

11 月18 日 (水)

10:30~11:30 【初心者】Bootstrapと@式で作る簡単&CoolなXPagesアプリ
13:30~14:30 【中上級】実践!XPages on Bluemix
【オフ会】
15:05~未定 第1部 XPages on Bluemix で IoT を実感!XPages でドローンを制御、モニタリング
15:05~未定 第2部 今年も!? どこよりも早い XPages 最新情報

XPagesDay 公式サイトhttp://xpagesday.com/xpagesday.nsf/home.xsp

■XPagesでドローンを飛ばす私のセッションは会場セッションになるため、こちらの申し込みフォームより「H1-3」を選択ください。
http://partner.cons20.info/portal.nsf/pages/pub


XPagesのラジオボタンをカッコいいデザインに変える方法

通常、ラジオボタンをCSSだけでデザインする場合によく使われる方法

通常、ラジオボタン、チェックボックスをデフォルトのブラウザの持つデザインではなくカスタマイズしようとした場合、HTMLソースコードを以下のように用意します。

[code lang="html" highlight=""]
<p>
<input type="radio" id="radio">
<label for="radio">ラジオボタン</label>
</p>
[/code]

ここでまず、ラジオボタンのINPUTタグとLabelタグを兄弟関係で持たせるということが重要になります。その後、CSSによって以下のように指定します。

[code lang="css" highlight=""]
input[type="radio"]{
opacity: 0;
}
[/code]

これにより、丸ポチを100%透過してしまい見えないようにしてやります。
次にLabelタグを使い、好きなようにボタンのデザインを作成してやります。

[code lang="css" highlight=""]
input[type="radio"]+label:before{
display: inline-block;
content: "";
background-color: lightpink;
color: crimson;
border-style: solid;
border-width: 0.1875em;
width: 0.625em;
height: 0.625em;
margin-top: 0.25em;
margin-right: 0.25em;
border-radius: 0.5em;
}
input[type="radio"]:checked+label:before{
border-style: double;
border-width: 0.5em;
width: 0;
height: 0;
}
[/code]

こうすることでこのようなラジオボタンにカスタマイズすることができます。

custom-radio

このCSSで重要なのは ”input[type="radio"]+label:before” としている点です。
つまり、+label とすることでinputタグの兄弟関係にある labelタグのデザインをカスタマイズしています。
なお、なぜこのような遠回りなことをしなければいけないかというと、input タグには「:before」が使えず、またinputタグ自体は非表示しなければならないため、labelを使ってこのような対応になってしまうわけです。

と、ここまではXPagesに全く関係のないHTMLとCSSのお話なので、ラジオボタンをカスタマイズしたい場合はググってみると色々なデザインを発見できると思います。
前置きがかなり長くなりましたが、XPagesで同等のことをしたい場合の説明をします。

XPagesのラジオボタン(ラジオボタングループ)はHTML構造が違う!?

同様のことをXPagesのラジオボタンで行いたい場合、まずXPagesが出力するHTMLソースコードをチェックします。ここではラジオボタングループを利用します。

[code lang="xml" highlight=""]
<xp:radioGroup id="radioGroup1">
<xp:selectItem itemLabel="Radio A" itemValue="A"></xp:selectItem>
<xp:selectItem itemLabel="Radio B" itemValue="B"></xp:selectItem>
</xp:radioGroup>
[/code]

すると出力されるコードは以下の通りです。(Domino 9.0.1)

[code lang="html" highlight="5,8,11,14"]
<fieldset id="view:_id1:radioGroup1" class="xspRadioButton">
<table role="presentation" class="xspRadioButton">
<tr>
<td>
<label for="view:_id1:radioGroup1:0">
<input type="radio" id="view:_id1:radioGroup1:0" name="view:_id1:radioGroup1" value="A">
Radio A
</label>
</td>
<td>
<label for="view:_id1:radioGroup1:1">
<input type="radio" id="view:_id1:radioGroup1:1" name="view:_id1:radioGroup1" value="B">
Radio B
</label>
</td>
</tr>
</table>
</fieldset>
[/code]

見て頂いて分かるようにinputタグを子にもつようにlabelタグで括られています。これがXPagesでラジオボタンのデザインをカスタマイズすることを難しくしています。

ラジオボタンがチェックされたか、親のタグのLabelから分からない

上記CSSで、"input[type="radio"]:checked+label:before"というセレクターがありますが、「ラジオボタンがチェックされたとき、その兄弟のラベルのデザインを変更する」という箇所になります。CSSでは「XXXという子要素を持つ親の要素」という逆順のセレクターを指定することが出来ないため、XPagesの「INPUTタグ(ラジオボタン)を選択された時の親のLabelのデザインを変更する」ということが技術的に不可能になります。
(jQuery等を使いJavascriptで処理する場合は可能であったりします。。。)

それでもCSSだけを使って頑張って実装する!

上記CSSによるラジオボタンのデザイン変更が出来ないため、別の方法による実装をする必要があります。

「box-shadow」を駆使して実装する!

XPagesのラジオボタン用のCSSは以下のようになります。

[code lang="css" highlight=""]
fieldset table td label{
cursor : pointer;
position : relative;
padding-left : 5px;
margin-right : 20px;
overflow : hidden;
height : 20px;
padding-left : 22px;
padding-top : 8px;
display : inline-block;
}
fieldset table td label:before {
position : absolute;
width : 15px;
height : 15px;
border : 2px solid lightpink;
border-radius : 50%;
left : 0px;
top : 4px;
content : '';
z-index : 3;
}
fieldset table td label:after {
content : '';
position : absolute;
width : 11px;
height : 11px;
border-radius : 100%;
left : 4px;
top : 8px;
background-color : crimson;
z-index : 1;
}
fieldset table td label input[type="radio"] {
-moz-appearance: none;
-webkit-appearance: none;
position : absolute;
z-index : 2;
width : 20px;
height : 20px;
left : -23px;
top : 1px;
margin : 0px;
box-shadow : 20px -1px #fff;
}

fieldset table td label input[type="radio"]:checked {
box-shadow : none;
}
fieldset table td label input[type="radio"]:focus {
opacity : 0.2;
box-shadow : 20px -1px #fff;
}
[/code]

こちらのCSSでは"label:before"でラジオボタンの外枠を描画、"label:after"で選択時の丸ポチを描画しています。キーはクリック時の丸ポチの表示・非表示を"box-shadow "でマスクすることで実装しています。
多少複雑ですが、こうすることでXPagesの出力するHTMLにCSSを被せるだけでデザインをカスタマイズすることができるようになりました。

なお、このCSSですが、IE8以前のブラウザでは残念ながら正しく動作しません。"box-shadow"がIE8ではまだサポートされていないためです。

おまけ

上記CSSの応用みたいなものですが、ラジオボタンに画像を使うなどアイデア次第でより大幅にデザインを変更することができるようになります。
以下のソースコードでは"box-shadow"を使い選択された値の画像を濃淡により表現しています。

[code lang="xml" highlight=""]
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

<style>
fieldset {border:none;}
fieldset table{
border:none;
width:30%;
padding:10px;
}
fieldset table td {width:50px;}
fieldset table td label{
position : relative;
width : 30px;
height : 30px;
overflow : hidden;
cursor : pointer;
}
fieldset table td label:before {
content : '';
display : block;
width : 30px;
height : 30px;
border-radius : 100%;
position : absolute;
z-index : 1;
}
fieldset table td:nth-child(1) label:before{background:url(./yes.png)
no-repeat;}
fieldset table td:nth-child(2) label:before{background:url(./no.png)
no-repeat;}
fieldset table td:nth-child(3) label:before{background:url(./maybe.png)
no-repeat;}
fieldset table td label input[type="radio"] {
-moz-appearance: none;
-webkit-appearance: none;
margin : 0px;
position : absolute;
z-index : 2;
left : -30px;
width : 0px;
height : 0px;
display : block;
box-shadow : 30px 0px 0 30px #fff;
opacity : 0.7;
}

fieldset table td label input[type="radio"]:checked {
box-shadow : none;
opacity : 1;
}
fieldset table td label input[type="radio"]:focus {
opacity : 0.0;
}
fieldset table td label input[type="radio"]:hover {
box-shadow : 30px 0px 0 30px #fff;
opacity : 0.5;
}
</style>

<xp:radioGroup id="yesno">
<xp:selectItem itemLabel="" itemValue="1">
</xp:selectItem>
<xp:selectItem itemLabel="" itemValue="0">
</xp:selectItem>
<xp:selectItem itemLabel="" itemValue="2">
</xp:selectItem>
</xp:radioGroup>
</xp:view>
[/code]

こちらのコードを実行した場合のイメージがこちらです。アイコン画像をクリックすると選択状態を表すように色が濃くなります。

custom-radio-img


ibm domino app on bluemix

2015年4月22日14時から「IBM Dominoアプリケーション on Bluemix」のセッションを行います

 

本日、2015年4 月 22 日(水) 14時からチームスタジオジャパン株式会社様が毎月ノーツ・ドミノユーザー向けにホットな話題を提供するWEBセミナー「月刊 Notes/Domino Webセミナー 」の4月号に、弊社代表の田付 和慶がセッションでお話させて頂きます。

内容は2月のテクテクLotusでも触れさせて頂いた、「IBM Dominoアプリケーション on Bluemix」に関してご紹介させて頂きます。

Session② 14:40-15:10

XPages開発者の挑戦は続く、「IBM Dominoアプリケーション on Bluemix」最新情報


 

当日のメインのセッションは14時から始まる日本IBMの平塚様の以下セッションになります!是非お見逃しなく!

Session① 14:00-14:40

「 IBM Notes/Domino 優良企業における活用事例・失敗しない製品選定術・活用TIPs 」

- あなたの会社をイキイキさせる!組織活性化に貢献できる「取り組み」や「画面設計」とは? -
講師>日本アイ・ビー・エム株式会社 
    コラボレーション・コンサルタント 平塚 博章氏

日時: 
    2015年4 月 22 日(水) 14時から

場所:
    オンラインのセッション

主催:
    チームスタジオジャパン株式会社

参加費:
    無料 / 事前登録制

詳細、申込みはこちらから » http://jp.teamstudio.com/webinar_20150422


XPagesでフィールドに"年月日のみ"、"時刻のみ"の値を設定する方法

XPagesでの日付の保存では常に年月日、時刻の両方が保存される

"年月日のみ"もしくは、"時刻のみ"と設定されているフィールドを持つ文書をNotesクライアントで保存をした場合と、XPagesで保存をした場合で保持されるデータの持ち方が変わってくるということが今回のブログのトピックになります。

例を上げると、以下のようなフィールド、日付の表示(年月日のみ)

年月日のみをもつフィールド

もしくは、時刻の表示(時分)

時刻の表示のみをもつフィールド

といったケースです。

これを試しにNotesクライアント(Ver 9.0.1 FP3)で保存してたところ、以下が通常のNotesクライアントでのデータの保存結果になります。

Notesクライアントで日付フィールドを保存

Notesクライアントで日付フィールドを保存

Dateフィールドでは「2015/03/02」、Timeフィールドでは「14:35:00」というようにそれぞれ年月日、時刻のみが格納されます。

では、このフォームを元にXPagesから文書作成をした場合どうなるか、簡単なXPagesを作成して試してみました。

XPagesで日付フィールドの保存

DateフィールドとTimeフィールドのXPagesソースコードは以下のとおりです。

Dateフィールド

[code lang="xml" highlight=""]
<xp:inputText value="#{document1.Date}" id="date1">
<xp:dateTimeHelper id="dateTimeHelper1"></xp:dateTimeHelper>
<xp:this.converter>
<xp:convertDateTime type="date" dateStyle="short">
</xp:convertDateTime>
</xp:this.converter>
</xp:inputText>
[/code]

Timeフィールド

[code lang="xml" highlight=""]
<xp:inputText id="time1" value="#{document1.Time}">
<xp:dateTimeHelper id="dateTimeHelper2"></xp:dateTimeHelper>
<xp:this.converter>
<xp:convertDateTime type="time" timeStyle="short"
timeZone="Japan">
</xp:convertDateTime>
</xp:this.converter>
</xp:inputText>
[/code]

それぞれ、フィールドのTypeをdate, timeと指定しています。

このXPagesで保存した後、フィールドに格納されたデータを見てみると、

XPagesから保存された文書のDateフィールド

XPagesから保存された文書のTimeフィールド

両方が「yyyy/MM/dd hh:mm:dd ZZ」のフォーマットで保存されていることが確認できます。

なぜ"年月日のみ"、"時刻のみ"が必要か?

上記の比較からどちらのデータの持ち方が正しいということが今回の主旨ではありません。

実際には、Notesクライアントで使ってきたNSFをXPagesを使ってWEB化したい、というケースが多いと思います。そしてNotesクライアントとXPagesの両方でNSFを使い続けるといった場合、やはりXPagesがNotesクライアントの仕様に合わせる必要が出てきます。

前置きが長くなりましたが、今回はXPagesでも"年月日のみ"、”時刻のみ”のフィールドを設定する簡単な方法をご紹介します。

NotesDateTimeを使って整形しよう

やり方は幾つかあるとおもいますが、

SSJSのNotesDateTimeクラスを使って整形してやることが出来ます。

[code lang="xml" highlight="6,8"]
<xp:this.data>
<xp:dominoDocument var="document1" formName="Form"
computeWithForm="both">

<xp:this.postSaveDocument><![CDATA[#{javascript:
var dt:NotesDateTime = document1.getItemValueDateTime("Date");
dt.setAnyTime();
var tm:NotesDateTime = document1.getItemValueDateTime("Time");
tm.setAnyDate();
var notesDoc:NotesDocument = document1.getDocument();
notesDoc.replaceItemValue("Date", dt);
notesDoc.replaceItemValue("Time", tm);
notesDoc.save();
dt.recycle();
tm.recycle();
notesDoc.recycle();
}]]></xp:this.postSaveDocument>
</xp:dominoDocument>
</xp:this.data>
[/code]

このコードではXPagesで一旦文書保存した後のPostSaveDocumentイベント内でNotesDateTimeクラスのsetAnyTime()、setAnyDate() を使うことで、思った通りのフォーマットに整形しています。

 

いかがでしたでしょうか?

今回は既存NSFをWEB化する際に躓きがちなDateTimeフィールドの情報でした。


IBM Domino Application on Bluemix について、ConnectED 2015にて

今回、もっとも興味があるセッションであった「IBM Domino Application on bluemix」セッションに参加してきました。

xpages on bluemix

通常、Bluemixで開発を行う場合、EclipseにCloudFoundryのプラグインをインストールしたり、DevOps サービスなどの開発管理システムと連携する形で行うため、開発環境の設定段階で以外と敷居が高くなってしまいます。
この点、IBM Domino Application on bluemixではどのように提供されるのかが自分の持つ関心の一つでした。

予想として、おそらくDesigner内のJavaパースペクティブ等を使ってデプロイをすることになるのかと考えていたのですが、今回のセッションで、その予想はいい意味で裏切ってくれました。

IBM Domino Designer上で専用のBluemixへのデプロイツールを使い直接デプロイを行えるようになります。

bluemix deployment tool
また、IBM Domino Designerの設定画面にBluemixのアカウントID、Passwordを入力する項目が用意されるため、デプロイ時に毎回ログイン情報を提供する必要がなくなります。

 

もう一つの関心として、オンプレミスのDominoとどのように連携できるのか、ということです。
Server IDが提供されたり、サーバー間の相互認証などを行ったり出来るのか?

この点に関して、セッションを行っていた開発者に"Meet the developer"にて直接質問をしてみたところ以下のような回答を聞くことが出来ました。

  • Bluemix上のDominoは特別に仕立て上げられたサーバーのためServer IDを開発者ごとに提供するという予定はない。
  • サーバー間の相互認証を行いオンプレミスのDominoとの連携を行えるようにすることはプランとしてある。

どちらも出来ないのかもしれないと想像していたため、相互認証等でオンプレミスDominoとの連携が行える可能性について聞き出せたのは大きな収穫でした。
ただ、"IBM Domino Application on bluemix"自体がまだ始まったばかりのため、今の時点ではあくまでプランとして挙がっているということみたいです。

IBM ConnectedED で得た情報まとめ

domino-bluemix-model

その他、"IBM Domino Application on bluemix"に関して得た情報として纏めると以下のような感じです。

  • XPages Bluemixランタイム(ビルドパック)が用意される。lightweight Domino Web Containerが用意されていてXPagesが実行されるイメージ。
  • ローカルレプリカはない。 サーバーへ同期をとるのではなく、専用のBluemixへのデプロイツール(Addonのようなもので提供?)から直接デプロイを行う。
  • Designerの設定画面にBluemixのアカウントID、Passwordを入力する項目が用意される。それによりデプロイ時に毎回ログイン情報を提供する必要がなくなる。
  • BluemixでXPagesのインスタンスを作成することで、NSFファイルをダウンロードすることができ、そのNSFを使い開発を進める。
  • BluemixでXPagesのインスタンスを作成することで、開発用のUser IDも同時に作成される
  • 複数の開発者で開発も可能
  • オンプレミスのサーバーとの相互認証をさせる等で連携をプランしている。
  • IBM Sametimes on bluemixはまだ開発に至っていないが、IBM内でサービスとして提供したいという話はある。
  • IBM Connections Cloud との連携として IBM Connections Cloud FileがBluemixで提供されるため、その連携は可能になる(予定)。

「IBM Domino Application on bluemix AD201」 デモ

「IBM Domino Application on bluemix AD201」セッションでは以下のようなデモが行われました。

  • XPagesとRDBMSサービスを使いNotesデータベース以外のデータソースと連携。
  • XPagesで作ったWebアプリケーションからWatsonと連携。
  • Bluemix上のインスタンスを2つにしたロードバランスにも対応出来ていることをデモ。(例)片方のインスタンスを落として、もう一つのインスタンスでで文書を更新、その後にインスタンスを立ち上げると、更新された文章が同期されていることが確認できる。

ロードマップ

最後に、「IBM Domino Application on bluemix」の今後のロードマップが発表されました。
2015年の下半期でようやくベータになることから、まだまだ開発が始まったばかりのサービスであることが伺えます。

domino-xpages-bluemix-loadmap