スポンサーサイト

--年--月--日 --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

また紹介していただきました

2008年11月28日 20:53

 Notes/Domino のブログでは大御所になると思うのですが、岩間さんからも紹介して頂きました。

IBMのサポートの方のBlogが開設 !!

僕がブログを書き始めようと思った大きな動機の一つには、岩間さんのブログが余り更新できなくなりそうだ、と言う事を聞いた事もあります。
 非常に残念がるお客様の声などを聞くと、やはりIBMとしてこのようなコミュニケーションを保っていく努力をしないといけないのではないかな、て思って自分の知っている事だけでもいいからブログにしてみよう、と思うようになりました。

まだまだどんな記事を書いていくのがよいのか悩んでいるところはあるのですが、少しでも長い間継続出来るように頑張ります。
スポンサーサイト

ローカルアクセスアプリケーションに書き換える

2008年11月28日 08:27

NotesでJavaを利用している際に発生した問題を調査する場合、始めに切り分けないといけないのは、Java アプリケーションがローカルアクセスアプリケーションかリモートアクセスアプリケーションか、と言う点です。

 リモートアクセスアプリケーションと言うのはいわゆるDIIOP経由でのアクセス、ローカルアクセスアプリケーションと言うのはNotes.jarを介してノーツクライアントのモジュールを利用してアクセスする方式です。 したがって、ローカルアクセスアプリケーションを動かすには、ローカルにNotesクライアントが導入されている必要があります。よく、「私のアプリケーションはリモートのドミノサーバーにつなぐのでローカルアクセスではありません」と思ってしまう方も多いのですが、Sessionクラスのオブジェクトをリモートに持つかローカルに持つかの違いで、どちらもリモートのデータベースを開いたり処理する事が出来ます。

 以前このブログでDIIOPのサンプルを紹介しましたが、あのNABにアクセスするだけのサンプルをローカルアクセスに変えてみましょう。

 変更したコードでは、createSession()の呼び方が少し変わった(引数がなくなっています)のと、sinitThread()やstermThread() と言うおまじないのような処理が入っているのに気付いて頂けたら十分です。他にもローカルアクセスアプリケーションを使う方法はあるのですが、それは後日紹介します。

# そろそろ「このくらいのサンプルはデザイナーヘルプにあるじゃないか・・・」とか言われそう
# ですが、チュートリアル目的のエントリなので。。
# 一応コンパイル方法までフォローしているので。。。。

NABTest1.java

import lotus.domino.* ;

public class NABTest1
{
static String domsrv = "ServerName/Org" ; // server name
static String dbname = "names.nsf"; // database (e.g. mail\\hnagashi.nsf)


public static void main(String args[]){
try{
NotesThread.sinitThread();
Session s = NotesFactory.createSession() ;
Database db = s.getDatabase(domsrv, dbname );
if(!db.isOpen()){
db.open();
}
String title = db.getTitle();
String uname = s.getUserName();

System.out.println("UserName: " + uname );
System.out.println("ServerName: " + db.getServer());
System.out.println("Title: " + title);


}catch(NotesException ne){
System.out.println(ne.id + ne.text);
ne.printStackTrace() ;
}catch (Exception e){e.printStackTrace() ;
}finally { NotesThread.stermThread();}
}

}



コンパイル用バッチファイル (C:\MyJava を作業フォルダと仮定しています。)
compile.bat

set Java_HOME=D:\Java\JDK6.0\bin
set PATH=%Java_HOME%;%PATH%
set CLASSPATH=C:\lotus\Notes\jvm\lib\ext\Notes.jar;C:\myjava
javac -target 1.5 NABTest1.java

# 7.x をご利用の場合は、-target を 1.4にして下さい。。

run.bat
java -cp c:\MyJava;C:\lotus\Notes\jvm\lib\ext\Notes.jar NABTest1

接続文書を作るボタンスクリプト

2008年11月26日 22:42

今日はこの記事から接続文書の話をしようと思います。

LotusScript で接続文書を作成・更新する方法 (#732059)

あまり使われないサーバーのリンクを送ったら「そのリンクが開けない」と返されてしまった、と言う経験がある方は多いのではないでしょうか。 サーバーが移転していたり、自分と微妙にネットワーク環境が違うために名前解決できなかったり、サーバーのIPが変わっていたり原因は様々ですが、接続文書を作ってもらえば解決する事は多いのではないかと思います。
 しかし、リンクが開けない理由も分からないユーザーに、接続文書をメールで手順を示して作ってもらうのはちょっと大変ですよね。

そんなときに一番簡単な方法は、Ctrl+0や[ファイル]-[サーバー]-[開く]で出てくるダイアログのサーバー名にIPアドレスやFQDN形式のネットワークアドレスを入力する事です。サーバーのIPが変わっていたら接続文書や接続キャッシュを更新してくれるので多くの場合接続の問題を回避することが出来ます。接続情報が無い場合には接続文書がそのIPアドレスで作られた事がステータスバーのメッセージなどで確認出来ると思います。

 この方法の問題点は、このときローカルのNames.nsf に作られる接続文書は[詳細]タブにある「使用優先度」フィールドを見ると、優先度が「低」で設定されてしまっているために次回接続時はまた間違った情報でつないでしまったり、その接続文書を参照するまで無駄なネットワーク参照を行ったりして接続に時間がかかってしまうこともあるので、次回以降の接続時に意外とうまくいかないことがあります。


そういうときは、この記事にあるような接続文書作成ホットスポットボタンを作成してリンクと一緒に付けておくと便利です。
 これは既存の接続文書があれば更新してアドレスをIPにしたり、使用優先度を「普通」に変えたりしますし、存在しなければ新規に作成します。
TCPIPポートにしか対応していないですが、特に開けない人が多いと予想されるサーバーなどにつなぐときにはこのボタンも付けておくと便利なのではないかと思います。

自分の場合新規にセットアップした環境などにまとめて接続文書を作っておきたいのでまとめて接続文書を作っておくホットスポットボタンを持っておいてセットアップと同時に接続文書を一気に作ってしまいます。


 このくらいのスクリプトは、必要になったら自分で作ってしまってもそれほどの負担ではないと思うのですが、サーバーのIPが変わったときなどの通知に付けるなど、色々な場面で使ってもらえるとうれしいです。

スマートアイコン: 現在のフィールド値を使って別フォームに文書を作る

2008年11月26日 01:50

 今日もまたスマートアイコンの紹介をしてみます。

 あるノーツデータベースの情報を使って別ノーツデータベースに新規文書を作らないといけないようなデータベースがありました。
 元DBの情報を引き継ぐために手作業ででデータを引用していかないといけないので、単純で煩雑な作業が多い、と言う声が結構あったのですが、自分は設計者権限も無い事もあって、フォームレベルで連携して操作を簡易化することは出来なさそうでした。

 そこで考えたのが、こんな感じのスマートアイコンです。元文書をビューレベルで選択するか、フォームで開いた状態でスマートアイコンを押すと、新規文書が作成されます。ここで書かれている処理はそんなに奇抜でもなければ、難しい処理はしていないのですが、ノーツアプリケーションの機能がちょっと足りていないときなどにスマートアイコンで拡張していくと道が開ける事が多いのではないかと思います。実用的であればプロトタイプとして設計者に渡せば実現も早いのではないでしょうか。

出来るだけ汎用的に書き直してみたのですが、始めに青字のコピー先のデータベースやフォーム情報を入力して tmp_xxxのところにコピーしたいフィールド名をリストして、EditGotoField の行にコピー先のフォームでのフィールド名を指定していけばコピーするフィールドはいくつでも増やす事が出来ます。ただし、EditGoToFieldのようなUIの操作を前提にしているので隠しフィールドなどに入力する事は想定していないのと、文書リンクを貼る場合、操作以前にクリップボードに入っていた値は消えてしまうのであらかじめご注意下さい。

サンプル
Dest_Server := "ServerName/Org";
Dest_DBPath := "apps\\test.nsf";
Dest_Form := "MainTopic";


@Command([OpenDocument]);

REM{コピー先で文書リンクが必要な場合(クリップボードの値が失われるので注意!)};
@Command( [EditMakeDocLink] );

REM {右辺にコピーしたいフィールド名を指定して下さい};
tmp_idnumber := IDNumber;
tmp_subject := Subject;
REM {日付だけをコピーしたい場合の加工例};
tmp_date := @Text(Date_Created; "D0S0") ;

@Command([Compose];Dest_Server:Dest_DBPath;Dest_Form);

REM {フィールド値のセット};
REM {EditGotoField の行にコピー先のフォームでのフィールド名を指定して下さい};


@Command([EditGotoField];"Subject");
@Command([EditInsertText]; tmp_subject);

@Command([EditGotoField];"HNumber");
@Command([EditInsertText]; tmp_idnumber);

@Command([EditGotoField];"DateOpened");
@Command([EditInsertText];tmp_date);

REM {文書リンクを貼る場合には、EditPasteを使用します};
@Command([EditGotoField];"TelHistoryDocLink");
@Command([EditPaste]);

定型文書を貼り付ける

2008年11月24日 23:33

Notes に限らず、メールや業務で使用しているNotesアプリケーションで、提携文や決まったリッチテキストデータを入れればよいような処理に遭遇することはないでしょうか。

今日は、Alan Lepofsky氏のブログから、そんな方のために応用範囲の広い、すばらしいTips を紹介します。Tipsというよりも、ローカルのNotes アプリケーションと言った方が適切かもしれません。

Paste Information Application

「Install Instructions」より下のセクションの指示に従って頂ければよいのですが、大まかには、
1. Quote.gifとPasteInformation.nsf をローカルのNotesデータディレクトリにダウンロード
2. クライアントのメニューより、[ファイル]-[プリファレンス]-[ツールバーの設定]を選び、左側のペインから「カスタマイズ」を選択してください
  (Notes 8 Standard 版の場合、メニューから、[ファイル]-[プリファレンス]を選択し、ノーツプリファレンスの画面から[ツールバー]-[カスタマイズ]を選択します。)
3. [新規]-[ボタン]を選択します。
4. 「アイコンの変更」ボタンを押します。
5. さきほど保存したアイコンを選ぶため、「作成」ボタンを選び、「イメージリソースの挿入」画面に移動します。
6. データディレクトリを選択し、quote.gif を選び、「OK」を押してイメージリソースの挿入画面を閉じます。
7. 以下の値をスマートアイコンに入れます。
ボタンの表題文字: 定型句の挿入
ポップアップヘルプ文字: 定型句の挿入
式:(リンク先にある式をコピーしてください)

という流れになります。
 これでメールのBodyフィールドにフォーカスがあたっているときにスマートアイコンを押すと自分の定型句が挿入できるようになります。

彼のBlogではオフィスまでの地図(画像つき)などを貼る例などが紹介されていますが、作業用のブランクの表データのようなものを入れたり、文字通りいつも使う提携文に使用したり、他にも応用範囲が広いのではないでしょうか。

 このデータベースは、ローカルで使用することを想定していますが、このデータベースをサーバー上に置いて、Notesデータベースのアクションとして実装すれば面倒なスマートアイコンのセットアップなしに全ユーザーが利用することができるし、サーバー上でデータベースの定型句を管理していれば、何かの変更があったときにも迅速に対応することができるようになるかもしれません・・・
 と、どのように使うかは色々あると思いますが可能性があるのではないかと思います。登録用のデータベースを日本語化するのもそれほど大変な作業ではないので(アクション、フォーム、ビューくらいをやれば十分なのではないかと。。)

直接使っても十分便利なツールですが、もし、こんな風に使ってみた!という例があったら、AlanのBlogでもよいですし、このBlogでもよいので是非教えて頂けると読者の参考にもなるのではないかと思います。

# 詳細な原因まで調べていないのですが、Notes8.xのStandardクライアントを使用すると貼り付け時に画面がうまく遷移せずにPasteInformation.nsfが開いたままになってしまうことがあるようです。
クリップボードにはデータは入っているのでそのまま貼り付けてください

RSS Feed を自分のDBに付ける

2008年11月20日 21:39

 RSS もサポートしているブラウザも増えてきたし、RSS Readerも機能が充実してきて、RSS リーダーを使って更新されたサイトだけ情報収集する、と言った事が定着している方も増えてきたのではないでしょうか。それに伴って自分が管理しているNotes/Domino ベースのWebアプリもRSS Feedを提供したい、と言う方も増えてきているのではないかと思います。 Lotus のサポート技術情報のページもRSS フィードが提供されていることに気がついている方も多いのではないかと思います。

 さて、Lotus Notes/Domino では7.0.2 から、RSS Feed Generator のTemplateが提供されていますが、これらは他のデータベースの情報をRSS Feedとして提供するものです。
 コーディング無しで複数のデータベースに対して出来るので手軽に出来る反面、自分のデータベースにRSS Feedの機能を付けたいだけでデータベースを一個余計に作るのもどうかな・・・・て思う人もいるかもしれないですし、自分のDB だけにRSS Feed を付けるには少し大げさな仕組みに思えてしまう人もいるかもしれません。

このような場合、Notes アプリケーションにRSS フィードを実装するには以下の方法がエレガントなのではないかと思います。
Lotus Notes/Dominoを使ったRSS配信アプリケーションの実装解説

ビューとページを追加するだけで実装できるので、ディスカッションのAll DocumentsのようなビューがあるDBであれば、それほど既存の設計に依存せずに追加する事が出来ます。実はサポート技術情報のRSS フィードもこの方法で実装されています。

一点だけ気をつけたほうがいいのは、タイトルなどに、 &、<、>、[、] が含まれていると正しく動かないようなので、このような文字を含むときに何らかの対処をしておいたほうがいいと思います。
このような文字を含む場合に保存しないようにしたり、エスケープ文字を使用したりする運用が必要になります。
 (このような文字をRSSフィードのcdata セクションで使えない理由がよく分からなかったので、本当にフィードの問題なのかどうかは分からなかったのですが、事実動かないようなので。。。。)


Template で提供されているRSS Feed Generatorに興味がある方は以下の記事も参考にしてみてください。
RSS Generator を利用して、Lotus Domino の資産を RSS 化する

スマートアイコン: アイテムの変更と削除

2008年11月20日 00:59

 文書の問題を調査するときに特定のアイテムの値を変えたり削除する、て事をよくします。
極端な話怪しい文書をもらってアイテムを1つずつ削っていけば最終的に問題が起こるアイテムまでは特定できますよね?もちろんフォームがエラーで開けなくなったり別の問題も起きると思いますが。
 そういうときにどういう方法を使うでしょうか?

こういうのはいちいちエージェントを作るのが面倒なので、スマートアイコンを作っておくと便利です。
今日はそんなときに必要になる処理がまとめて出来るスマートアイコンを紹介します。
昔似たようなスマートアイコンが各所で紹介されていたのですが、ここで見つけたのはその頃より色々と機能増強されていて、複数値や色々なアイテム型に対応していたので。以下のサイトにある例を日本語化して紹介しておきます。

一覧からフィールドを選んで、フィールドの型とかを指定して変えたい値を選ぶだけなので使い方は入れてみれば分かるんじゃないかと思います。
 
 僕はあるノーツアプリケーションがサービスインしたときに、特定のフィールド値を持つときに問題が発生する事が当日になって分かったので、暫定処置として問題が発生した文書をスマートアイコンで手当たり次第に修正して復旧していたことがあったのですが、そんな暫定処置にも使えます。

Modifying document item values

※ この辺の画面やUIはバージョンによって違いが大きいので、多少メッセージやメニューが異なる可能性がある点はご容赦下さい。
手順:
1. メニューから [ファイル] - [プリファレンス] - [ツールバーの設定]を選択します。
2. [カスタマイズ] タブを選択します。
3. [新規] - [ボタン] を選択し、ツールバーボタンを作成します。
  アイコンなどは必要に応じて分かりやすいものに変更して下さい
4. 以下の値を使用して下さい。
 ボタンの表題文字: 「フィールドの変更と削除」
 ポップアップヘルプ文字: 「フィールドの変更と削除」
 式; 以下の「スマートアイコン式」にあるものを使用して下さい。
5. ツールバーを保存します。


スマートアイコン式
REM {フィールドの一覧の取得};
List := @DocFields;
REM {Possible data types to
choose from.};
DataTypes := "テキスト型" : "日付型" : "数値型" : "Password" : "名前" : "共通名" : "フィールドの削除" : "テキスト複数値" : "日付型複数値" : "数値型複数値" : "名前 複数値" : "共通名 複数値";


DataType := @Prompt( [OkCancelList] : [NoSort] ;
EditField + " フィールドのアクションまたはデータ型の指定" ;
EditField + " フィールドのアクションまたはフィールドのデータ型を指定して下さい " ;
"テキスト型" ; DataTypes );


EditField := @Prompt( [OkCancelList] ; "変更するフィールドの選択" ; "変更するフィールドを選んでください:" ; "CustomerReply" ; List );


REM {Based on what type of data is being entered
different prompts will happen if any at all.};
RawValue := @If( @Contains( DataType ; "名前 複数値" );
@PickList( [Name] ); @Contains( DataType ; "名前" ) ;@PickList( [Name] : [Single] );
DataType = "フィールドの削除" ; "" ;
@Contains( DataType ; "Multi Value" );
@Prompt( [OkCancelEdit] ;
"新しい値: " + EditField ;
EditField + " フィールドの新しい値を : 区切りで入力してください" ; @Abstract([TextOnly] ; 254 ;
"" ; @Implode(@Text( @GetField(EditField) );":") ) );
@Prompt( [OkCancelEdit] ;
"新しい値: " + EditField ;
"新しい値を入力してください。(複数値は : 区切り)" ; @Abstract([TextOnly] ;
254 ; "" ; @Implode(@Text( @GetField(EditField) );":") ) ) );

REM {If data conversion doesn't work then don't set field.};
@If( DataType = "日付型" ;
@If( @SetField( EditField ;
@TextToTime( RawValue ) ) );
DataType = "数値型" ;
@If( @IsError( @TextToNumber
( RawValue ) ) ; "" ;
@SetField( EditField ;
@TextToNumber( RawValue ) ) ) ;
DataType = "共通名" ;
@SetField( EditField ;
@Name( [CN]; RawValue ) ) ;
DataType = "Password" ;
@SetField( EditField ;
@Password( RawValue ) ) ;
DataType = "フィールドの削除" ;
@SetField( EditField ; @DeleteField ) ;
DataType = "テキスト複数値" ;
@SetField( EditField ;
@Explode( RawValue ; ":" ) ) ;
DataType = "日付型複数値" ;
@SetField( EditField ;
@TextToTime( @Explode( RawValue ; ":" ) ) ) ;
DataType = "数値型複数値" ;@If( @IsError
( @TextToNumber( @Explode
( RawValue ; ":" ) ) ) ; "" ;
@SetField( EditField ; @TextToNumber
(@Explode( RawValue ; ":" ) ) ) ) ;
DataType = "名前 複数値" ;
@SetField( EditField ;
@Explode( RawValue ; ":" ) ) ;
DataType = "共通名 複数値" ;
@SetField( EditField ; @Name( [CN];
@Explode( RawValue ; ":" ) ) );
@SetField( EditField ; RawValue ) ); ""

Domino On Solaris: カーネルパッチ適用時の問題

2008年11月19日 09:02

USのサポートのブログサイトでもアナウンスされていたのですが、以下の問題のSolaris側のパッチが作成されました。Solaris 10上でドミノをご利用になっているお客様は一度ご確認下さい。

Lotus 技術情報のサイトより
Solaris のカーネルパッチを適用すると Lotus Domino サーバーが起動できない(#731990)

サポートのブログサイト
Domino on Solaris Solaris patch now available to avoid segmentation fault

US 技術情報
Domino segmentation fault with Solaris kernel patch 137111 (#1308624)


Kernel Patch 137137-09を適用する事によって解決できます。日本語の技術情報も更新するので 今しばらくお待ち下さい。

8.0.2 CCH1 がリリースされました。

2008年11月18日 01:59

 Lotus Notes 8.0.2 のCCH1がリリースされました。
# 尚、2009年1月9日現在では8.0.2はCCH2が入手可能になっていますのでそちらをご利用ください。

CCHと言うのはCumulative Client Hotifxes (累積クライアント用修正モジュール)の事で、今回始めてFix Cetnral から入手可能になりました。

全言語のNotesクライアントに対して適用可能ですが、詳細については以下の文書も参考にして下さい。日本語のドキュメントは現在準備中ですのでもう少しお待ち下さい。

Lotus Notes 8.0.2 クライアントの Cumulative Client Hotfix 1 (CCH1) について
Lotus Notes Standard Client Cumulative Client Hotfix 1 (CCH1) for 8.0.2 (# 7014028)

特に以下の問題に対する修正が入ったのが大きいと思っています。

Notes 8.0.2 Standard Configuration hangs at splash screen upon authentication (#1321303)
インターネットメールの文末に意図しない文字が追加される (#731709)
クイック検索を行うと 2 文字目から IME が半角英数からひらがなに戻ってしまう (#732203)

8.0.2 をご利用の方やご利用予定がある方はは一度ご確認されておくといいのではないかと思います。

更新: 
12月3日:  #732203 の情報を追加
1月9日: CCH1 へのページのリンクを追加。CCH2の情報を追加

LS2J: 正規表現を使った文字列置換

2008年11月17日 03:01

 前日の例は、「これなら@ContainsとかをLotusScriptで呼び出せば出来る!」とか思う人も多いと思うので、正規表現の力をアピールするならもうちょっと複雑なマッチングの方がよかったのかもしれません。

なので今日は正規表現らしい文字列処理の例として、文字列置換の例を出しておきます。ログのスレッドIDを消すようなパターン。
あとは、1行に複数の値がマッチする場合も例として挙げておくと、一度に全部置換してくれるので、正規表現の力が分かってもらえる気がしたのですが。。実際LotusScriptでこのような処理はどうやって対処しているのでしょうか。自分が開発する事になってこの手の処理をしようと思ったら専用のライブラリを作ってしまうのかなあ・・・と思ってしまうのですが、実際使われている方の話などが聞けたらいいな、と思います。

シェルとかで文字列処理をしていると、スクリプト言語の文字列処理が物足りなくなってしまうので、正規表現に恋しくなって、案外本気でこの処理を組み込みたい・・・、て思う人もいるのかもしれません。



Uselsx "*javacon"

Sub Click(Source As Button)
Dim b As Boolean
teststr$ = "[09D4:000D-0D50] 2008/09/18 15:45:26 HTTP Server: Error - Memory allocation error"
' Thread ID部分([09D4:000D-0D50])にマッチする正規表現
regex$ = "\[[\p{Alnum}:-]*\]"
' regex$ = "\[[a-zA-Z0-9:-]*\]"
replacedstr$ = ""
result$ = ReplaceString(testStr$,regex$, replacedstr$)
Msgbox "Input: " & teststr$ & Chr(13) & "Pattern: " & regex$ & " -> " & replacedstr$ & Chr(13) & result$
End Sub

Function ReplaceString(InputStr As String , RegEx As String, ReplacedStr As String) As String
' RepleaceString: 正規表現を利用した文字列置換関数
' InputStr: 置換を行う元の文字列
' RegEx: 置換を行う文字列パターンをあらわす正規表現
' ReplacedStr: 置換する文字列
' 戻り値: 置換を行った文字列
' 注: 必ず Uselsx "*javacon" の宣言を行う事
Dim j As JavaSession
Dim c As JavaClass
Dim pattern As JavaObject
Dim matcher As JavaObject
Dim e As JavaError
Set j = New JavaSession
Set c = j.GetClass("java.util.regex.Pattern")
Set pattern = c.compile(RegEx)
Set matcher = pattern.matcher(InputStr)
ReplaceString = matcher.replaceAll(ReplacedStr)
End Function

LS2J : LotusScript でJavaのクラスを呼び出してみる

2008年11月13日 23:29

 意外とDIIOPの話が受けがよかったので今日も少しJavaの話をしてみます。

 LotusScript だけを書いている人はあまり意識しないのかもしれませんが、Javaなら標準で出来るこんな事がLotusScript で出来ればいいのに・・・て思うときはないでしょうか。
 前回はそういう人のためにDIIOPを紹介したつもりですが、今自分が使っているアプリケーションのエージェントをJavaで書く、となるとなかなか勇気がいるのではないでしょうか。今回はそういう方のために簡易なJavaへの接続方法としてLS2J を利用した方法を紹介します。

「また新しい技術か・・・」と思った方もいるかもしれませんが、実質9つしかクラスが無いものですのでサンプルを見るだけでだいたい使い方が分かるのではないかと思います。

LotusScript ではLS2Jと言うLSXモジュールを使うことによってJavaのクラスを呼び出すことが出来ます。僕はLotusScript を使っていると文字列処理が弱いな、と思うことが多いのでLotusScript正規表現を使用した文字列処理が出来るように、java.util.regex.Pattern クラスやjava.util.regex.Matcher クラスを呼んで正規表現を処理させてみましょう。

とりあえず今日は正規表現を行ったマッチングを行うサンプルですが、明日は置換を行う例も紹介して、コードの解説もしてみます。(ほとんど自明ですが。。。)
 正規表現を使う意味がピンと来ない方もいるかもしれないので、LotusScript で処理しづらい例として「入力文字列が全角文字だけを含む」と言うチェックが行えるような例を取り上げてみます。利用しやすいようにLS2J を使用したマッチング処理の部分は関数化しておきました。

# あわてて自分のDBにコピペするとUSELSX宣言のところをコピーし忘れるので気をつけて下さい。。

以下はボタンスクリプトなので、デザイナーがある方は新規メールなどでメニューから[作成]-[ホットスポット]-[ボタン]等を選択する事によって利用する事が出来ます。


' LS2J で使うモジュール
Uselsx "*javacon"

Sub Click(Source As Button)
Dim b As Boolean
teststr$ = "あああ"
'「ASCII 文字を含まない」=「全角文字(半角カナを含む)のみの文字」であるかをチェック
regex$ = "[^\p{ASCII}]*"
replacedstr$ = "Test"
b = MatchString(teststr$ ,regex$)
Msgbox "Input: " & teststr$ & Chr(13) & "Pattern string: " & regex$ & Chr(13) & "Result: " & Cstr(b)
End Sub

Function MatchString( InputStr As String, RegEx As String) As Boolean
' InputStr: テストする入力文字列
' RegEx: マッチングする正規表現
' 戻り値: マッチしたらTrue を返します。
Dim j As JavaSession
Dim c As JavaClass
Dim pattern As JavaObject
Dim matcher As JavaObject
Dim e As JavaError
Set j = New JavaSession
Set c = j.GetClass("java.util.regex.Pattern")
Set pattern = c.compile(RegEx)
Set matcher = pattern.matcher(InputStr)
MatchString = matcher.matches()
End Function




 比較的呼びやすいJavaクラスを例として取り上げたので、すごく簡単に思った方もいるかもしれないですが、実際はコンストラクタとか呼ぶと案外表記が面倒だったりします。本格的に使う場合には、デザイナーヘルプにあるJavaClassクラスのcreateObject メソッドや「データ型のマッピング」の項はよく読んでおいて下さい。

 また、今までのLotusScriptと違って、JVMを使用しないといけないので実行時間やメモリ使用量には影響が出るのでパフォーマンスなどが懸念されるエージェントでは特に気をつけて使う必要があります野でその点は十分注意してご利用下さい。

参考:
Javaで使用可能な、正規表現は以下をご参照下さい。
java.util.regex Class Pattern (SDK Document)

8.0.2

2008年11月13日 01:38

今日はちょっと疲れているのもあるので、息抜きっぽい話題にします。。。

サポートセンターでもだいぶ8.xの問い合わせが増えてきました。
WindowsとかでもSP1が出てから急に利用者が増える、て言いますがやはりNotes/Dominoも8.0.1が出てから検討を始める、と言う方が多いのでしょうか。今日はこんな記事から何か書いてみようと思います。

第3回 クライアントのパフォーマンスが大幅に向上する Lotus Notes 8.0.2

こんな事が書いてあります。
・ コールド・スタートアップ: 8.0に比べて52%改善
・ ウォーム・スタートアップ: 8.0に比べて73%改善
・ メモリー消費量: 8.0に比べて21%改善
・ 応答速度: 15%改善


あくまで1つの計測値ですが、8.0.2の起動スピードに有意な違いがあることは伝わるのではないかと思います。実際私のX31はスタンダードクライアントを使うにはかなり厳しいスペックですが、8.0.2にしてから起動時間が10秒ほど早くなっているのではないかと思います。

これはJVMのアップデートや種々のパフォーマンス関連の修正を行った結果なのですが、
「でも結局Standardクライアントは重いし、結局あまり変わらない気がする・・・」と思う方も多いのではないでしょうか。そんな疑い深い方のために8.0.2の起動時間が早くなったと思えるもう1つの理由を紹介します。

一度起動してもらえれば分かるのですが、8.0.2のStandard版はスプラッシュスクリーンが表示されるとNotesのWindowが出てくるより早くすぐにパスワード入力ウィンドウだけ出てきます。
 下らない変更だと思う方も多いかもしれませんが、これが意外と大きいのです。裏でNotesの起動処理をしている間にパスワードを入力している事になるので、パスワードの入力時間だけ早くなったように感じます。パスワードの入力に3-4秒かけている人にとって見れば、たとえ今までと実質的な起動時間同じであったとしても3-4秒の改善はしていることになります。

 だからワークスペースを表示するまでの時間は8.0.2は改善している、と言うのはかなりのユーザーで体感できる可能性が高いのです。
環境によって差異が大きそうな内部処理の最適化よりもこういう変更の方が分かりやすいのではないかな・・・て思います。 

 残念ながらこのパスワード入力ダイアログのタイミング変更はStandard版のみで、Basic版では今まで同じ通りNotesのウィンドウを表示した後に出てきます。

記事では、この他にも8.0.2の新機能の話が出てくるので是非ご一読下さい。

注: パスワード入力中に進行される処理は限定されているようです。
入力せずに放置しても起動処理は止まっているようなので・・・

ディスカッションデータベースに文書を大量に作る

2008年11月12日 01:35

 開設して二週間くらい経ちますが、ちょっとずつアクセスも増えてきてうれしいです。
しばらくアプリケーション開発系の小ネタを書いてから、DWAとかの話もしていきたいと思っているのですが、出来るだけ評判のよい記事を参考にしながら投稿していきたいと思うので、率直な感想とかコメントを社内外問わず頂けるととても助かります。コメント恥ずかしい方は拍手とかでも参考になるので是非是非フィードバックよろしくお願いしいます。

 今日は以前投稿したエージェントプロファイルの紹介をしたときに少し触れたのですが、テスト用にとにかく文書数の多いデータベースを作りたいときに使うコードです。僕でさえ、10分くらいで作り終わったサンプルなので、必要になってから書いても大した手間じゃないと思うのですが、あるに越した事は無いと思うので。。 文書にアクセスするようなコードのパフォーマンスの差をみたいときとかに、こういうスクリプトで10万文書くらい作ってから、そのDBにScriptを回してみたりします。

 とりあえず、文書を作るだけだとあんまりなので、他の場面で応用できるようにSubjectに乱数を二桁ほど入れるコードと、20文書毎に途中結果を出力するような処理も入れてみました。

あと、この手のコードを作るときには、実行時間は長くなりますが、ComputeWithForm() メソッドは絶対呼んでおいたほうがいいと思います。

・ フィールドの型の調整をやってくれる。
  (文字列が入っているけど本当は数値型じゃないとダメ、とか。)
・ 計算可能なフィールドの計算をしてくれる

これをしないと、本当にコードで書いたフィールドだけしか出力されなくなってしまったり、フォームとつじつまの合わないフィールド値を持つ文書が出来てしまったりします。


Sub Initialize
Dim ses As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument

Set db = ses.CurrentDatabase
n = Cdbl(Inputbox("作成する文書数を入力して下さい"))
bodystr$ = "this is body"

For i = 1 To n
Set doc = db.CreateDocument
Randomize
doc.subject="test " & Cstr(Cint(Rnd() * 100))
doc.Form = "MainTopic"
doc.body=bodystr$
Call doc.ComputeWithForm(True,True)
Call doc.save(False,False)

If ( i Mod 20 = 0 ) Then
Print i & " 文書作成しました"
End If
Next
End Sub



もうちょっと便利なものをアップしたいな、と思うのですが、手持ちが少ないので。。。

なぜGetNextdocumentなのか?

2008年11月11日 02:21

 そういえば、なぜLotusScriptでビューをループするときはWhile ループ+GetNextDocumentで書くのでしょう。
別にGetNthDocument メソッドを使ってFor ループで書いてもいいじゃないか、て僕はよく思っていました。

これをしないのはForループととWhileループの違いではなくて、単純にGetNthDocumentよりGetNextDocumentの方がパフォーマンスがよいからです。とはいえこのことを検証したことは無かったので、エージェントプロファイリングを使って分析して見てみましょう。該当メソッドだけを抜粋しているので完全な形式で無い点はご容赦下さい
 データベースやサンプルコードはは昨日使用したものと同じです。GetNextDocumentのWhileループをview.count を使ってForループに変えるのは自明な変更なので省略させてください。
同じデータベースに対して、ループでアクセスしてメソッドの所要時間を比較してみましょう。

 

全ての文書にアクセスする(Use GetNextDocument)プロフィール

クラス          メソッド オペレーション コール 時間
DocumentCollection  GetNextDocument  1907 40

ここではGetnextDocumentは40msしか消費していません。

全ての文書にアクセスする(Use GetNthDocument)プロフィール
クラス         メソッド オペレーション コール 時間
DocumentCollection  GetNthDocument  1906 1665

結構違いますよね。。。なのでWhileループじゃないといけない理由は分かりませんが、とりあえずGetNextDocumentを使う理由はパフォーマンスが理由にある、と言う事は分かってもらえたのではないかと思います。

プロファイリングを使用したエージェントのボトルネック調査

2008年11月10日 00:43

 エージェントのパフォーマンス分析をするときにどんな方法を使っているでしょうか?
単純にサーバーのログを調べたり、NotesTimerクラスを使ったり色々なアプローチをしている方がおられるのではないかと思います。

今日は、プロファイリングを使用したエージェントのパフォーマンス分析の方法について紹介します。
エージェントのプロファイリングはLotus Domino 7.x 以降でサポートされた機能なのですが、バックグラウンドエージェントでもローカルのエージェントでも使用でき、使い方も簡単なので非常に便利です。
 結論から言うとプロファイリングは、エージェントのプロパティでプロファイルを有効にして、実行後に"プロファイル結果の表示"を選択するとエージェントの分析結果が表示される」ので非常に簡単に使用できるのですが、ディスカッションデータベースを使用して具体的に触ってみましょう。
ローカルで使えるのでデザイナーを持っている人なら比較的簡単に試せるのではないかと思います。

※ 私は以下のエージェントをNotes 8.0.2 の日本語版を使用して作成・実行しています。
他の環境でUIや操作手順が違う部分もあると思いますが、ご容赦下さい。

■ 環境の準備
1) ディスカッションデータベースの準備
 テンプレートは無しでもいいのですが、一般的なアプリケーションを想定してディスカッションデータベースを作ってみましょう。

2) 文書の作成
 何でもいいのでディスカッションデータベースに文書を作ってみましょう。
性質上100文書以上はあった方がいいのではないかと思います。
僕はここで紹介したようなエージェントを使用して作成したので、参考にしてみて下さい。

3) エージェントの作成
 何でもいいのですが、以下のような簡単な共有エージェントを実行してみます。Initializeルーチンに以下のようなスクリプトを作成します。

使用したエージェント

Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Dim col As NotesDocumentCollection
Dim doc As NotesDocument

Set db = s.CurrentDatabase
' エージェントのプロパティで対象を「ビューの全ての文書」に指定して下さい
Set col = db.UnprocessedDocuments
Set doc = col.GetFirstDocument

While Not (doc Is Nothing)
Print doc.subject(0)
Set doc = col.GetNextDocument(doc)
Wend

End Sub


見ての通り、全文書にアクセスしてSubjectフィールドをステータスバーまたはサーバーコンソールにprintするだけのものです。

エージェントの名前だけは何でもいいのですが、エージェントのプロパティでは以下のように対象を「ビューの全ての文書」になるようにして下さい。そうしないと、エージェント中のUnprocessedDocumentsが正しく動作しません。

エージェントのプロパティ(基本タブ)
エージェントのプロパティ

セキュリティタブの設定が重要です。ここで「プロファイルの結果の表示」を選択するとプロファイリングが有効になります。
エージェントのプロパティ(セキュリティタブ)
プロファイルの設定

ここまで言ったらエージェントを保存して終了し、Notesクライアントでディスカッションデータベースを開いて下さい。

■ エージェントの実行とプロファイルの表示

1. エージェントの実行
  全ての文書ビューを開いたら、アクションメニューから[アクション]-[全ての文書にアクセスする(Use GetNextDocument)]を実行して下さい。

2. プロファイル結果の表示
 デザイナーからエージェントを選択して右クリックメニューから「プロファイル結果の表示」と言うメニューを選択しましょう。

右クリックメニュー
 プロファイル結果の表示

以下のようなプロファイル結果がノーツ文書形式で開かれます。

プロファイル結果
プロファイル結果

明日はこの辺で少し具体例を挙げてエージェントプロファイリングを使用したパフォーマンス分析について考えてみます。




DIIOP サンプル: ループ処理も加えてみる

2008年11月07日 21:19

やはりNotes のエージェントで一番典型的にはビューにアクセスして文書を取得したりアイテムを書き換えたりする処理なのではないかと思います。

 せっかくだから以前に使ったサンプルをちょっとだけ拡張して PeopleビューにアクセスしてFullNameフィールドの値をコンソールに表示するようにしてみると少し成長した気分になれるのではないかと思います。

私のテスト環境では10ユーザー程度しかいないので全ユーザー出力もたいした事無いですが、数千ユーザーいる環境でこんなことをすると大変なので、あくまでサンプルコードだ、という事をご理解いただけると助かります。。



NABLoop.java
import lotus.domino.* ;

public class NABLoop
{
static String host = "xxx.xxxx.com" ; // server address
static String cName = "notes admin" ; //username
static String dbname = "names.nsf"; // database (e.g. mail\\hnagashi.nsf)
static String password = "password" ; // internet password

public static void main(String args[]){
try{
Session s = NotesFactory.createSession(host,cName,password) ;
Database db = s.getDatabase("", dbname );

if(!db.isOpen()){
db.open();
}
View view = db.getView("People");
Document doc = view.getFirstDocument();
Document temp = null;
String title = db.getTitle();
String uname = s.getUserName();

System.out.println("Session User Name: " + uname );
System.out.println("ServerName: " + db.getServer());
System.out.println("Title: " + title);

while (doc != null)
{
System.out.println("User Name: " + doc.getItemValueString("FullName"));
temp = view.getNextDocument(doc);
doc.recycle();
doc = null;
doc = temp;
}

}catch(NotesException ne){
System.out.println(ne.id + ne.text);
ne.printStackTrace() ;
}catch (Exception e){e.printStackTrace() ;}
}
}

紹介記事書いて頂きました

2008年11月07日 21:12

大川さんと村上さんから紹介記事書いて頂きました。

http://domblogjp.blogspot.com/2008/10/notesdomino.html
http://d.hatena.ne.jp/munesora/20081106/1225989311


どっちももったいないような紹介記事で恐縮ですが、もう少し役に立ちそうな話を書けるように頑張ります。。

Sendkeys

2008年11月07日 01:12

 まだ開設一週間くらいなのに、こんなサンプルばかり載せていると訪問者がいなくなってしまうのではないかと心配してしまうのですが、このエントリは息抜き程度に読んでもらえるとうれしいです。


 追加のサーバーは起動時にパスワードを聞かれるのでどうにかしたいと考えた事がありました。
IDファイルが作られたあとにサーバーIDのパスワードを解除すればいいだけの話なのですが、こんなWSHスクリプトを書いてみた事があります。

以下のようなVBSファイルをドミノのプログラムディレクトリに入れておくと、起動したら何も考えずに「password」と言うパスワードを送り込んでくれます。

StartServer.vbs
Dim WshShell
set WshShell = CreateObject("WScript.Shell")
WshShell.Run("nserver.exe")
WScript.Sleep(100)
WshShell.AppActivate("Lotus Domino Server")
WshShell.SendKeys("password")
WshShell.SendKeys("{Enter}")

 パスワードがテキストファイルに保存されることになるので、セキュリティ上は重大な問題があるので、実環境で使う人はいないと思うのですが何となくこの人間の操作まで代理してくれるような感じがするSendkeys メソッドと言うのはとても魅力的に映って色々遊んでいました。

こんな感じでノーツを起動して、データベースを一個開いてから閉じる、と言う簡易なテストツールに使うことも出来る!とか思ったりしました。

StartNotes.vbs
※ 斜体にしたところは環境に応じて適切な値を入れて下さい。
Dim WshShell
set WshShell = CreateObject("WScript.Shell")
WshShell.Run("notes.exe")
WScript.Sleep(8000)
WshShell.AppActivate("Lotus Notes")
WshShell.SendKeys("password")
WshShell.SendKeys("{Enter}")
WScript.Sleep(4000)
WshShell.SendKeys("^o")
WshShell.SendKeys("%i")
WshShell.SendKeys("mailserver")
WshShell.SendKeys("{Enter}")
WshShell.SendKeys("%f")
WshShell.SendKeys("mail/xxxx.nsf")
WshShell.SendKeys("%o")
WScript.Sleep(10000)
WshShell.SendKeys("%(fx)")

Windowの文字とかオブジェクトを取ったりエラーハンドリングをして精度を高められる有償のテストツールみたいにはいかないのですが、ちょっとプログラムっぽくないノリでソフトウェアを動かしている感じが楽しくて色々触ってみたりしました。

とりあえず書いてみたけど、やっぱりNotes技術者の役には立たないですね。。。

サンプルコードの補足

2008年11月06日 23:01

 初心者向けに書いたのに何の説明もしていませんでした。。。
解説するほどのコードでは無いのですが、リモートアクセスアプリケーションでは以下のような行が特徴です。

Session s = NotesFactory.createSession(host,cName,password) ;

よくよく考えると当たり前なのですが、リモートアクセスアプリケーションの場合にはリモートに対してセッションを張るので、createSession()メソッドではhostを指定しないといけないのです。
ローカルアクセスアプリケーションでは、以下のようにhost無しでcreateSession() を呼びます。

Session s = NotesFactory.createSession() ;

それと、あのサンプルを見て、「定数宣言しているhostやユーザーネームの値が格好悪い」て思った人は多いと思います。
 接続先を変える度にコンパイルしなくてもいいように引数にして処理すればいいのに・・・て言うのはごもっともな意見なのですが、この手のテストコードでは僕はあまり気にしていないです。
引数の順番とか数を覚えるの面倒くさいし、コンパイル環境が整っていないと十分な調査はどうせ出来ないので効率よくコンパイルできるようにしておいたほうがデバッグコードとかを入れる上でも都合がいいし、この手のコードは出来るだけコードを短くしたいので、引数チェックや引数処理のコードを入れるのがどうしても好きになれない、て理由なのですが好みの問題だと思って流してください。。


ところで、リモートアクセスアプリケーションではNCSO.jarしか使いません。
Notes JavaクラスはLSXBEを使う、と言っていたのですがnlsxbe.dllやliblsxbe.so などはどのようにして使われるのでしょうか。
 この場合、LSXBE はサーバー上でDIIOPタスクが代理で呼び出すような形式になります。当然DIIOPタスクには通信の媒介となる役目もあるので、サーバー上でDIIOPタスク上で作られたORBスタブとクライアントのORBスタブ同士で通信を行う訳ですが、DIIOPタスク上ではこのために、以下の二つのオブジェクトが存在する事になります。

1. 主にクライアント通信のために必要になるJavaオブジェクト
2. LSXBEのために必要になる C++ オブジェクト

1.と2.のオブジェクトは当然相関があるのですが、Garbage Collectionの対象になるのは1.だけなのでここで2.のC++ オブジェクトだけが浪費されてしまう事があります。(もちろんこれは一時的な浪費で、エージェントが終了すれば解放されるべきものです。)
 これが、いわゆるNotes Javaクラス特有の recycle() が必要になる背景です。
この話も以下のTechnoteの4章に詳細が述べられています。LotusScriptではあまり意識する必要が無いのですが、Javaアプリケーションで大きなループをするときには必ずこの点について一度は考慮した方がよいと思います。たまにこういう問題に遭遇するとNotes のJVMはGCがちゃんと動かないような理由があるのではないか?と考えて、System.gc() を呼んでみようと考える人もいますが、これは予期しない結果を引き起こすのでしないようにして下さい。

Lotus Notes/Domino における Java 実行環境とその問題判別について (#729912)

DIIOPの動作確認用サンプルコード

2008年11月05日 22:06

 テンプレートのデザイン変えてみました。こだわりはないのですが、どうしても2カラムのものに変えたかったので。。やっぱり3カラムだと横幅の狭さが読んでて気になります。。

昨日も書いたとおり、今日はDIIOPのサンプルコードと簡単な動かし方です。
本格的な開発ではEclipseのようなGUIの開発環境があると便利ですが、ちょっとDIIOPの動きを知りたいだけであれば、JDKを使って手でコードを書いたほうが楽なのではないかな、と個人的には思います。

■ 準備
 ノーツデータベースを作ったらいきなり使えるわけではないのでクライアントとサーバーについて以下の準備だけは最低限必要なのでお願いします。

1) DIIOPタスクの稼動
 ドミノサーバーはDIIOPタスクとHTTPタスクを稼動しておいてください。
必要に応じて、Load DIIOP コマンドで起動してもよいですし、Notes.ini のServerTasks行に加えておいても構いません。あとDIIOPはインターネットパスワードでつなぐので、接続するNotesユーザーにはインターネットパスワードを設定しておく必要があります。

2) JDKの導入
 接続を行うクライアント環境ではJDKを導入しておく必要があります。
コンパイルの必要があるため、JREだけではなく、JDKを導入しておく必要があります。

JDKはどこのものでもいいのですが、一応SunのJDKダウンロードサイトと、IBMのJDKダウンロードサイトのリンクをつけておきます。
IBM JDK Download
SUN JDK Download

今回のサンプルくらいではJDKのバージョンはそれほどこだわる事は無いのですが、Notes 8でも 1.5.0 なので、ちゃんとした開発を行う際には最新のJava 6 ではなく Lotus Notes/Dominoの JRE のバージョンにあわせてください。
 現在利用しているNotes のJREのバージョンが知りたい場合にはNotesのJVMディレクトリの下にあるbin\java.exeを使用して確認をする事が出来ます。

C:\lotus\notes\jvm\bin>java -fullversion
java 完全バージョン "J2RE 1.5.0 IBM Windows 32 build pwi32devifx-20071025 (SR6b)"


3) NCSO.jarのコピー
 Notesクライアントの入っている環境下であれば直接そこをサーチパスに指定すればよいので問題ないのですが、本来リモートアクセスの Java アプリケーション(DIIOPを使用した接続を行うもの)ではNotesクライアントが導入されていない端末で接続を行うことが前提なので、その場合にはNCSO.jarを事前に端末上にコピーしておく必要があります。
NCSO.jarは <データディレクトリ>\domino\java にあります。


■ サンプルコード

サンプルデータベースを用意するのも面倒だと思うので、サーバー上のNames.nsf につないでサーバー名とデータベースタイトルだけを出力するものです。

NABTest.java (青字は適当に変えて下さい。)

import lotus.domino.* ;

public class NABTest
{
static String host = "xxxx.xxx.com" ; // server address
static String cName = "notes admin" ; //username
static String dbname = "names.nsf"; // database (e.g. mail\\hnagashi.nsf)
static String password = "password" ; // internet password


public static void main(String args[]){
try{
Session s = NotesFactory.createSession(host,cName,password) ;
Database db = s.getDatabase("", dbname );
if(!db.isOpen()){
db.open();
}
String title = db.getTitle();
String uname = s.getUserName();

System.out.println("UserName: " + uname );
System.out.println("ServerName: " + db.getServer());
System.out.println("Title: " + title);

}catch(NotesException ne){
System.out.println(ne.id + ne.text);
ne.printStackTrace() ;
}catch (Exception e){e.printStackTrace() ;}
}
}


■ コンパイルと実行
 恐らく初めてDIIOPアプリケーションを作るときに一番緊張するのはコンパイル作業ではないでしょうか。言葉で説明すれば、「NCSO.jarをクラスパスに指定してコンパイルして下さい」と言うだけの話なのですが毎回混乱するので僕は以下のようなバッチファイルを用意しています。
(以下、作業ディレクトリをC:\MyJava としています。)

Compile.bat (青字は編集してください。)
set Java_HOME=C:\SUN\Java\jdk1.6.0_06\bin
set PATH=%Java_HOME%;%PATH%
set CLASSPATH=C:\lotus\notes\data\domino\java\NCSO.jar;C:\myjava
javac -target 1.5 NABTest.java

Java_HOME: JDKのbinディレクトリへのパス
CLASSPATH: NCSO.jarへのパスとNABTest.javaを置いているディレクトリ
8.xのJREはjava 1.5なので -target を1.5にしていますが、7.xのNCSO.jarなどを使っているのであれば1.4などにしましょう。
 僕の環境ではNotesクライアントが入っているのでNCSO.jarのパスがいかにも、と言うところになっていますが、これもどこに置いても構いません。ClassNotFoundException になるのはほとんどの場合NCSO.jarへのパスが通っていない場合です。CLASSPATHが色々通り過ぎていると逆に変なjarファイルを見てエラーになってしまう事もあるのでこのバッチの例のように新たにセットしてしまった方が簡単な気がします。

僕は実行のコマンドも考えるの面倒なので以下のような一行のバッチファイルを作っています。
こっちはJava_HOMEへのパスが通っていることが前提なので、そうでない場合は上の例を参考にパスを加えて下さい。

run.bat
java -cp c:\MyJava;c:\lotus\notes\data\domino\java\NCSO.jar NABTest

■ 実行結果

C:\MyJava>run
C:\MyJava>java -cp c:\MyJava;D:\lotus\notes\data\domino\java\NCSO.jar NABTest
UserName: CN=notes admin/O=LTS
ServerName: CN=xxxx/O=LTS
Title: LTS's Directory


コマンドプロンプトからcompile.batとrun.batを実行して、ユーザー名、サーバー名、データベース名(Names.nsf)のタイトルが表示できたら成功です。
 DIIOPの最大のメリットは、NCSO.jarさえあればクライアント環境が無くてもNotesデータベースにアクセスできる事なのですが、何となく概要がつかめたのではないでしょうか。

 僕はこういうコードをHello World みたいな感じで使ってDIIOP環境がセットアップできた事を確認するのに使っています。

 こういう安っぽいコードはなかなかTechnoteとして公開することも難しいし、上級者にはあまり役に立たない情報なのではないかと思うのですが、このような場所で共有してDIIOPやNotes Javaクラスの勉強の入り口になる事が出来たら幸いです。

LotusScript のBackend クラスと Notes Javaクラスはよく似ている

2008年11月05日 00:39

 今日は、Notes Javaクラスについて話そうと思います。サポートとしては、Notes Javaクラスの仕組みを理解しようと思ったのであれば一度は以下の文章を読んでほしいです。

Lotus Notes/Domino における Java 実行環境とその問題判別について (#729912)

ここで仕組みの部分でよく理解してほしいのは、Notes Javaクラス、COM、LotusScriptが並列に並んで、Lotus Script Backengine を経由してNotesのNativeオブジェクトにアクセスしていることです。
 これがタイトルでも書いている通り、「Notes JavaクラスとLotusScript Backengine クラスはよく似ている」と言う事です。DIIOP接続などJARファイルを使っていると忘れがちですが、これらの処理は全てnlsxbe.dll (WindowsでのDLL名)を使用してNotesに接続している、と言う点では同じなのです。

もう1つ重要な点は、Notes Javaクラスも LotusScriptも直接Nativeオブジェクトを介してアクセスしているわけではない点です。これらの処理は共通のインターフェースを使用しているのでほぼ同等の結果を得ることが出来る反面、どちらもLSXBEの制限に縛られますし、同じ問題に遭遇する可能性があります。

 例えばHTTPタスクの場合は、このようなインターフェースを介さず直接Nativeオブジェクトにアクセスします。だからNotes JavaクラスとLotusScriptの機能拡張は同時に行われる事が多いのですが(8.0からの未読文書へのアクセスなど)、これとWebアクセスの拡張はお互いに独立なのです。

このような仕組みを理解する事ははサポートのシーンでも重要になります。
Notes Javaクラスの問題は、LotusScciptでも問題になる事が多いので、調査の際にはこの視点を最大限に生かす必要があるのです。

1. 一般的に再現環境の構築や試行は、Javaのリモートアクセスアプリケーション > Java エージェント > LotusScript の順で容易になる。繰り返しテストが必要な場合には、LotusScript で再現させる事も大事

2. LotusScriptの問題はほとんどLSXBEの問題である可能性が高いが、JavaエージェントではJVMの問題が起因であることがある。LotusScriptで問題が再現出来ないことが分かると、JVM の問題、メモリの使用状況、コーディングの問題などを疑う必要が出てくる。(Javaの recycle()の問題などはこの典型ではないかと思います。)

3. Javaアプリケーションの問題調査を行うときには、LotusScriptでの問題発生事例についても、ヒットしている可能性を考慮する必要がある


アプリケーション開発者の視点で考えると、たとえば 、Javaでコードを書いている人にしてみれば、「どのような条件で問題が起きるか」と言う事には詳細について知りたいと思うのではないかと思うのですが、1. のように「同じ問題がLotusScriptでも起きるかどうか?」と言うのは何の役にも立たない情報なので多くの場合興味を持っていないことが多いのではないかと思うので、これはサポート固有の視点ではないかと思います。
 もちろん条件を絞る事によって十分な情報が得られる事も多いので、自分自身このような観点での調査までするのは限られたケースだけです。

なんか今日は堅い話になってしまったので、明日はアプリ開発には役に立たないかもしれないけど、「DIIOPとか聞くとNotes開発者なのにJava使わないといけなくなりそうで怖いんだけど、どんなものなのかは知りたいから触ってみたい」と言う人向けの簡単DIIOPテストコードを紹介します。
繰り返しますが、リモートアクセス用の本格的アプリ開発には何の役にも立たないと思います。 。

8.0.2 Standardクライアントでの未既読の色を変更する

2008年11月04日 00:23

Standard版のNotes には賛否両論色々あると思うのですが、Standard版の未既読のメールの色についての不満はよく聞きます。どの色がいいか、と言う議論はさておきこの部分はBasicと違う色にするのであれば、せめてGUIで変更可能になっていると使い勝手も違ったのではないかと思うのですが。。
と言うわけで今日は以下のTechnoteからの話題です。

Lotus Notes 8.0.x Standard 版クライアントで未読メールの色を変更する方法 (#731199)

 色を変更するために、CSSファイルを編集しているうちはまだよかったのですが、8.0.2からはCSSファイルがjarファイルに入って更に話がややこしくなってしまいました。
このCSSファイルの編集も思ったより難しかったので、今日は8.0.2でのCSSファイルの編集方法についてもう少し説明します。
(以下説明でファイルパスが長い関係で、段組をはみ出して文字が表示されている部分があるのですがいい対処方法が思いつかなかったので、大変見苦しいのですが、その点はご容赦下さい。)

以下の説明は、JDKがクライアント端末に導入されていて、\binディレクトリにパスが通っているのが前提です。通っていない場合はjar.exeなどはフルパスで指定して下さい。

今回編集するjar ファイルは以下のディレクトリにあります。
<プログラムディレクトリ>\framework\shared\eclipse\plugins
\com.ibm.notes.branding_8.0.2.20080809-0430.jar


notes.cssファイルさえ取り出せればいいので、zipにリネームしてしてから取り出してもいいのですが、jarコマンドで解凍する場合は以下のコマンドを使用します。

C:\work> jar.exe xvf com.ibm.notes.branding_8.0.2.20080809-0430.jar

ここで解凍されたファイルからCSSファイルを編集します。
Technoteでは未読を赤にする方法が説明されていますが同じでは面白くないので、以下のようにして見ましょう。

・ 未読は赤 (Boldは使用しない)
・ 既読メールは灰色ではなく黒

CSSファイルの編集内容は以下のとおりです。 (変更部分を黒字にしました)

/* this sets the style for messages that have been marked as "unread" */
mailtable>row>unread {
color: #FF0000;
font-family: Tahoma, Times, Helvetica;
font-size: x-small;
font-style: normal;
font-weight: bold;
}


/* this sets the style for messages that have been marked as "read"
mailtable>row>read {
color: black;
font-style: normal;
}
*/


mailtable.Inbox>row>read {
color: black;
font-style: normal;
}

mailtable.Drafts>row>read {
color: black;
font-style: normal;
}

mailtable.Sent>row>read {
color: black;
font-style: normal;
}

mailtable.FollowUp>row>read {
color: black;
font-style: normal;
}

mailtable.AllDocuments>row>read {
color: black;
font-style: normal;
}

mailtable.Trash>row>read {
color: black;
font-style: normal;
}

mailtable.Junk>row>read {
color: black;
font-style: normal;
}

編集が終わったら、notes.cssファイルはjar ファイルのあるディレクトリから、themes\notes.css と言う相対パスになるように置いて下さい。以下のコマンドでアーカイブファイルを更新しましょう。

C:\work>jar.exe uvf com.ibm.notes.branding_8.0.2.20080809-0430.jar themes\notes.css
追加中: themes/notes.css(入力 = 17491) (出力 = 3580)(デフレート圧縮率 79%)


この作業が終わったら以下のファイルのバックアップを取り、先ほど作成したjarファイルで上書きしましょう。

<プログラムディレクトリ>\framework\shared\eclipse\plugins
\com.ibm.notes.branding_8.0.2.20080809-0430.jar


最後に以下のファイルを削除します。

<データディレクトリ>\workspace\.config\org.eclipse.update
\platform.xml

このファイルを削除しないと更新されたjarファイルは再起動時に読み込まれないのですが、このため変更後のNotesクライアントの起動はやや遅くなります。

私がテストに使用したJarファイルはSkyDrive上に置いてみましたのでファイルを直接ダウンロードしたい方はこちらからどうぞ。

またこのトピックについては以下の記事も参考になると思うのでご参照下さい。


第8回 Standard版で未読を赤色で表示させる方法
How to modify font and color properties of unread/read documents in Notes 8.0.x (#123378)


その他のバージョンのJarファイルなどについては以下のエントリをご覧ください。
Lotus Notes 8.5J
Lotus Notes 8.0.2 FP1

複製の仕組み

2008年11月01日 08:30

複製をしたときに、「こっちの方が新しいはずなのになぜか逆の方が反映された!」とか「何でこの文書って競合になったの??」て思うときはないでしょうか。

複製の仕組みは簡単で、文書のOIDと言う一意のIDを比較する事でほとんどの場合どうして複製の勝者が決まるのかを理解する事が出来ます。

大まかに言うと複製では以下の3つの比較がキーになります。

・ UNIDがなければ新規文書を作成
・ 更新回数を比較する
・ 最終更新時間を比較する

と言うロジックで成り立っているのですが、複製の勝者の判定は、最終更新時間より最終更新回数を優先するので、ここで最終更新時間にこだわっていると少し混乱する事が出てくるのです。
 要は12-3時の間に30回更新された文書と4時に一度だけ更新された文書を複製すると当然複製競合になりますが、勝者は30回更新した方になるのです。これが理解できると複製のロジックはだいぶ見通しがよくなるのではないかと思います。

以前はこの複製のロジックはインサイドノーツに掲載されていたのですが、R5の情報になってしまうので一度このロジックについて整理して説明した文書があった方がいいのではないか、と言う事で以下の文書を公開することにしました。一度複製について悩む事があったら目を通してもらえるとうれしいです。

複製はどのようにして文書の変更を同期しているのか (#731993)


最新記事


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。