まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

これらの記事の続きです:
nsf2dxl2web の挑戦(1)
nsf2dxl2web の挑戦(2)
nsf2dxl2web の挑戦(3)
nsf2dxl2web の挑戦(4)
nsf2dxl2web の挑戦(5)


ノーツデータベースのウェブ化ツールである nsf2dxl2web を紹介しています。5回目となる今回は検索編と位置付けています。 nsf2dxl2web そのものの機能紹介ではないのですが、nsf2dxl2web でウェブ化したデータベース内のビュー/フォルダや各文書を検索する仕組みをオープンソース全文検索サーバーである Fess を使って構築する手順を紹介します。なお一般的な Fess の使い方となるクイックスタートはこちらを参照ください:
https://fess.codelibs.org/ja/quick-start.html


まず、今回のために nsf2dxl2web を使って2つのノーツデータベースをウェブ化したサイトを以下に公開しました:
https://dotnsf.github.io/nsf2dxl2web_githubpages/

2023112602


アクセスすると上図のように2つのノーツデータベース(「NSF2DXL2WEB サンプル」と「サンプルDB」)をウェブ化したサイトが表示されます。この2つのノーツデータベースは私が nsf2dxl2web の動作テスト用に UI 含めて作ったものです(「サンプル DB」はリンク先のテスト目的で作ったものなので1文書だけのシンプルなものです。「NSF2DXL2WEB サンプル」にはサブフォームや添付ファイルを含めた様々なリッチテキスト要素が含まれています。前回説明しましたが、検索対象となることを想定してどちらも Standard UI のビュー/フォルダ形式にしています)。もともとノーツのワークスペース上に存在していた時の様子は以下なので、データベースアイコン含めて再現されていることが改めて確認できると思います:
2023112603


"NSF2DXL2WEB サンプル" と書かれたアイコンをクリックすると、選択したノーツデータベースを nsf2dxl2web を使ってウェブ化したページが表示されます:
2023112609


ではこのノーツデータベースをウェブ化した上記サイトを Fess で全文検索する手順を以下に紹介します。このサイトはパブリックに公開しているので、よかったら皆さんの Fess 構築作業(後述)の練習にも使ってみてください。


【Fess について】
FessJava で開発されたオープンソースの全文検索エンジンです。商用サポートのついたソフトウェアである N2SM Search のコミュニティ版、という位置づけです。

Fess は主に以下の機能が提供されています:
・ウェブのデータ収集と、収集したページの全文検索エンジン(今回紹介する機能)
・ファイルサーバーのデータ収集と、収集したファイルの全文検索
・データストア(CSV や RDB など)のデータ収集と、収集したデータの全文検索エンジン

Fess には Windows 版と Linux 版があり、Linux 版は rpm 形式や deb 形式でのパッケージ配布に加え、docker に対応したコンテナイメージも提供されています。本ブログエントリでは docker 版を使って構築手順を紹介します。


【Fess のインストール】
以下では docker 版の Fess をインストールする手順を紹介します。前提として docker (と docker-compose)がインストールされた x86_64 版の Linux 環境が必要になるため、自分の PC やクラウドサーバー上に用意しておいてください。

そして docker 導入済みの環境で以下のコマンドを実行して Fess を(正確には OpenSearch 版の Fess を)インストールします:
$ git clone https://github.com/codelibs/docker-fess.git

$ cd docker-fess/compose

$ sudo sysctl -w vm.max_map_count=262144

$ docker compose -f compose.yaml -f compose-opensearch2.yaml up -d
 または 
$ docker-compose -f compose.yaml -f compose-opensearch2.yaml up -d 

補足として、3つ目のコマンドを実行する理由はこの設定が推奨されていたためです。また4つ目のコマンドで実際に Fess を起動するのですが、Fess の検索機能で CORS の有効/無効を切り替えたい場合(Fess サーバーの外部から JavaScript で検索した場合などは有効にする必要があります)は4つ目のコマンドを実行する前に compose-opensearch2.yaml ファイルを編集して CORS コマンドの有効/無効を切り替えておく必要があります:
  :
services:
  es01:
    environment:
      - "api.cors.allow.origin=*"
      - "api.cors.allow.methods=GET, POST, OPTIONS, DELETE, PUT"
      - "api.cors.max.age=3600"
      - "api.cors.allow.headers=Origin, Content-Type, Accept, Authorization, X-Requested-With"
      - "api.cors.allow.credentials=true"
  :

最後のコマンドを実行すると Fess が起動します。初回のみイメージのダウンロードを伴うため時間がかかりますが、(イメージのダウンロードが済んだ)2回目以降はすぐに起動できるはずです。

Fess は 8080 番ポートで起動します。コマンド完了後に docker ホストの 8080 番ポートにアクセスし、以下のような画面が表示されればインストールが成功しています:
2023112604


デフォルトでは
 ユーザーID: admin
 パスワード: admin
のアカウントが作成されています。「ログイン」と書かれたリンクからログインします:
2023112605


初回ログイン時のみパスワードの更新が求められるので、新しいパスワードに更新します。以後、この新しいパスワードでログインしているものとして説明を続けます:
2023112606



【Fess で nsf2dxl2web サイトの全文検索インデックスを作る手順】
では Fess に(nsf2dxl2web で作ったウェブの)新しい検索インデックスを登録します。ログイン名の所をクリックし、「管理」を選択します:
2023112601


下のような管理画面が表示されます。画面左上にハンバーガーメニューがあることを確認します:
2023112602


ハンバーガーメニューから 「クローラー」-「ウェブ」 を選択します:
2023112603


ウェブのクローラー設定の一覧画面が表示されます(最初の状態では何も登録されていません)。ここに新しいウェブを追加するので、画面右上の「新規作成」をクリックします:
2023112604


ウェブクロールの新規設定画面が表示されます:
2023112605


ここに以下の内容を入力していきます(書かれていない項目はデフォルト値のまま):
・名前:(任意の設定の名称 例えば "NSF2DXL2WEB サンプル")
・URL:検索先ページの URL、上記例であれば "https://dotnsf.github.io/nsf2dxl2web_githubpages/49258A000002200B/index.html"
・クロール対象から除外する URL:(デフォルトから "|xml" を削除したもの)
・深さ:3

2023112606


なお、除外する URL から "|xml" を除いた理由ですが、デフォルト設定のままだと "xml" で終わる URL はクロールされないことになります。nsf2dxl2web でウェブ化したサイトの場合、各文書の URL は ".xml" で終わるので、このデフォルト設定のままだと文書データが検索インデックスに含まれなくなってしまいます。この状況を回避する目的でこの設定にしています。

また「深さ=3」を指定する意味ですが、ここでの「深さ」とは「ページ内のリンクを何段階まで辿るか」を意味しています。nsf2dxl2web でウェブ化した場合、対象 URL は index.html を指しているので、
 深さ=0:index.html のみ
 深さ=1:views.html (ビュー/フォルダ一覧)まで
 深さ=2:各ビュー/フォルダの HTML まで
 深さ=3:各文書まで(Standard UI の場合のみ)
を対象にクロールすることになります。というわけで、各文書のデータまで検索できるよう、ここでは「3」を指定しています。

設定できたら最後に「作成」ボタンをクリックします:
2023112607


ウェブのクローラー設定の一覧画面に戻ります。いま作成した設定が追加されていることを確認してクリックします:
2023112608


自動で付与された ID などを含め、作成した内容が表示されます。この登録内容を使い、「ジョブ」という単位でクロールを実行することになります。そのジョブを新規に作成するため、最下部の「新しいジョブの作成」ボタンをクリックします:
2023112601


画面に色々表示されますが、すべてデフォルト値のままで構いません。最下部の「作成」ボタンをクリックします:
2023112602


すると「ジョブスケジューラ」画面に切り替わり、今作成したジョブが追加されていることが確認できます。この作成されたジョブを選択します:
2023112603


※なお、このジョブスケジューラの一覧画面はハンバーガーメニューから 「システム」-「スケジューラ」 を選択することでも表示することができます:
2023112602


作成したジョブの内容が表示されます。ジョブの実行タイミングやスケジュールを指定することができるのですが、nsf2dxl2web でウェブ化したノーツデータベースの場合は(このシリーズの初回に背景として説明したように、ノーツデータベース側の変更が加わることはほとんどない想定でウェブ化されていることが多いと思うので)1回実行しておけば2度目は不要ということがほとんどだと思っています。ほぼこのままで問題ないはずですが、必要に応じて実行スケジュールを変更してください。

このジョブを実行するには最下部の「今すぐ開始」をクリックします:
2023112604


ジョブの実行が開始された、という旨のメッセージが表示されます。これで指定した内容でのクローリングが開始されています:
2023112601


ジョブの実行状況を確認する場合はハンバーガーメニューから 「システム情報」-「ジョブログ」 を選択します:
2023112602


過去に実行したジョブのログが一覧で表示されています。「状態」列が「実行中」となっている場合はジョブが実行中であることを意味しています:
2023112603


この値が「OK」になっているとジョブの実行が完了、つまりクロールが完了して、検索可能な状態になっていることを意味しています。状態が「OK」になっていない場合は「OK」になるまで待ちます:
2023112601


これを必要なノーツデータベースのぶんだけ繰り返します。今回の場合は「NSF2DXL2WEB サンプル」に加えて「サンプル DB」も Standard UI で用意しているので検索可能です。というわけでこちらのデータベースについても同様にインデックスを作成して検索ジョブを実行し、両方が完了している状態を作っておきました:
2023112602


なお、このサンプルのサイトの場合は(普通に公開されているので)不要ですが、検索対象先にベーシック認証がかかっている場合はハンバーガーメニューから 「クローラー」-「ウェブ認証」 を選択して、ウェブ認証情報を追加することも可能です:
2023112601


では検索インデックスが準備できたので、実際に検索してみます。Fess のトップページに戻り、適当なキーワード(下図では「タブ」)を入力後に Enter キーで検索してみます:
2023112601


検索結果の一覧が表示されます。ちゃんと全文検索できているので、ビューも文書も検索結果に含まれています:
2023112602


試しに検索結果のある文書をクリックすると、その文書が正しく表示されます:
2023112603


この例では複数のノーツデータベースの検索インデックスを有効にしていたので、複数のデータベースにまたがる検索が可能です。複数のデータベース内に含まれる検索ワード(下の例では「テスト」)を指定して検索した検索結果は異なるデータベースのものが含まれるはずです。ノーツデータベースでいうところの「串刺し検索」が可能になっていることを確認できます:
2023112604



以上、ノーツデータベースの参照ウェブ化ツールである nsf2dxl2web の使い方を、カスタマイズや検索機能まで含めて5回にわたって紹介してきました。ノーツデータベースを参照目的に絞ってウェブ化するツールですが、XSL を採用することでノーツの設計思想に近い形のままウェブ化でき、そのためカスタマイズ時にもフォーム単位でのカスタマイズが可能になっていたり、nginx やクラウド/コンテナ化を併用することで抜群のパフォーマンスが期待できたり、参照用途には必須の全文検索まで含めて実現できることが確認できています。

ノーツをほぼ参照目的だけで使い続けているケースではこういうウェブ化もアリなんじゃないかと思いながら作ってみた nsf2dxl2web がどこかで誰かの役に立つ日が来ることを願っています。


(過去記事はこちらです)
nsf2dxl2web の挑戦(1)
nsf2dxl2web の挑戦(2)
nsf2dxl2web の挑戦(3)
nsf2dxl2web の挑戦(4)
nsf2dxl2web の挑戦(5)




これらの記事の続きです:
nsf2dxl2web の挑戦(1)
nsf2dxl2web の挑戦(2)
nsf2dxl2web の挑戦(3)


ノーツデータベースのウェブ化ツールである nsf2dxl2web を紹介しています。前回は基本処理となる nsf2dxl と dxl2web 、そして簡易ウェブサーバーを使ってウェブ化されたコンテンツを確認する所までを紹介しました。

4回目となる今回はカスタマイズ編として、オプション機能として提供している2種類のカスタマイズ処理について紹介します。カスタマイズ不要で運用する場合は無視していただいてもいいのですが、「カスタマイズするとこんなことができるようになる」という程度でも知っておくと、思い通りの結果にならなかった場合の対応が楽になることもあるのでは・・と思っています。


前回、基本処理である(1)、(2)と(5)を紹介しているので、順番がおかしいように見えるかもしれませんが続きの(3)から紹介します。

【(3)customxsl.js】
この処理の説明をする前にこちらをご覧ください(特に画面の下半分):
2023111701


これ↑はノーツの標準テンプレートである「ディスカッション」から作ったデータベースを nsf2dxl2web を使ってウェブ化した結果から「すべての文書」ビュー内のある文書を開いた時の様子です。この文書が参照している MainTopic というフォームがうまく XSL に変換しきれていないため、UI が乱れてしまっています。ちなみに同文書をノーツクライアントで見ると下のように見えます:
2023111702


このように UI が乱れてしまう原因はいくつかあります。nsf2dxl2web のツール側でも可能な限り対応していくつもりではありますが、残念ながら 100% 再現できるようにするのは難しいと判断しています。その最大の原因は@式です。

@式はノーツが持つマクロ機能の1つです。このマクロがあることで柔軟な処理が実現できていることは事実だと思いますが、nsf2dxl2web のような変換ツールからすると酷な機能となっています。例えば nsf2dxl2web はノーツのフォーム内にサブフォームや共有フィールドが含まれていても(XSL との相性の良さもあって)UI を再現できるようになっています。しかし問題は例えば「サブフォームの参照先が@式の計算結果になっているようなケース」です。nsf2dxl2web は@式を無視するので、その計算結果がどのサブフォームを参照するべきなのかがわかりません。他にも@式の計算結果が含まれる設計要素を自動で正しく再現することはまだ 100% ではありません。それらの理由があり、上述のような UI の乱れが発生してしまうことがあります(いわゆる「ノーツの標準テンプレート」の類は設計要素内で@式が使われていることが多く、このような UI の乱れが発生しやすいと思っています)。

今回紹介する customxsl.js は、このように「自動処理だけでは再現できない UI をカスタマイズすることで修正する処理」を行う機能です。

nsf2dxl2web は標準で以下3つのノーツ標準テンプレート・カスタマイズ用の XSL セットを提供しています:
・メール
・ディスカッション
・ドミノディレクトリ(names.nsf)

nsf2dxl2web を展開したフォルダには customs というフォルダがあり、その中には
・mail
・disc
・names

という3つのサブフォルダがあるはずです。これらが上記3つの標準テンプレート・カスタマイズ用 XSL セットをそれぞれ含んでいます:
2023111703


ちなみにディスカッションテンプレート用のサブフォルダ(disc)の中には MainTopic.xsl と Response.xsl という2つの XSL ファイルが存在しています:
2023111704


これらのファイルの内容はそれぞれ以下のようになっています:
(MainTopic.xsl)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html" encoding="UTF-8"/> <xsl:template match="/"> <html> <head> <title><xsl:value-of select="document/item[@name='Subject']" /></title> <link href="../resources/nsf2dxl2web.css" rel="stylesheet"/> <script src="../resources/nsf2dxl2web.js"></script> </head> <body> <h1><xsl:value-of select="document/item[@name='Subject']" /></h1> <br /> <table border="1"> <thead> <tr> <th>Subject:</th> <th><xsl:value-of select="document/item[@name='Subject']" /></th> </tr> </thead> <tbody> <tr> <td>Categories:</td> <td><xsl:value-of select="document/item[@name='Categories']" /></td> </tr> <tr> <td>From:</td> <td><xsl:value-of select="document/item[@name='From']" /></td> </tr> </tbody> </table> <hr/> <p style="text-align:right;">(<xsl:value-of select="document/noteinfo/created" />)</p> <p><xsl:copy-of select="document/item[@name='Body']" /></p> </body> </html> </xsl:template> </xsl:stylesheet>
(Response.xsl)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="UTF-8"/>
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="document/item[@name='Subject']" /></title>
<link href="../resources/nsf2dxl2web.css" rel="stylesheet"/>
<script src="../resources/nsf2dxl2web.js"></script>
</head>
<body>
<h1><xsl:value-of select="document/item[@name='Subject']" /></h1>

<br />

<table border="1">
<thead>
 <tr>
  <th>Subject:</th>
  <th><xsl:value-of select="document/item[@name='Subject']" /></th>
 </tr>
</thead>
<tbody>
 <tr>
  <td>Categories:</td>
  <td><xsl:value-of select="document/item[@name='Categories']" /></td>
 </tr>
 <tr>
  <td>From:</td>
  <td><xsl:value-of select="document/item[@name='From']" /></td>
 </tr>
</tbody>
</table>

<hr/>

<p style="text-align:right;">(<xsl:value-of select="document/noteinfo/created" />)</p>

<p><xsl:copy-of select="document/item[@name='Body']" /></p>
</body>
</html>
</xsl:template>

</xsl:stylesheet>

詳しい説明は省略しますが、それぞれディスカッションテンプレートの MainTopic フォームと Response フォームを表示するための(シンプルな)XSL となっています。


ではディスカッションテンプレートから作られたノーツデータベースを例に実際に UI をカスタマイズする手順を紹介します。といっても作業はごくシンプルで、上述のように適用したいフォームの UI 定義が記載された XSL ファイルを必要なフォームの分だけ(フォーム名).xsl というファイル名で用意し、一つのサブフォルダ(この例だと disc)内に格納しておきます。なお(フォーム名)部分は大文字小文字も正しく指定する必要があります。

その上で以下のコマンドを customxsl.js ファイルが存在しているフォルダ上で実行します:
$ node customxsl (対象の DXL が出力されているフォルダ) (カスタム XSL ファイルが格納されているフォルダ)

2023111705


すると上図のように指定した DXL フォルダ内の全文書に対して、その文書が参照しているフォーム定義を見つけ、そのフォーム定義を指定したカスタム定義用フォルダ内の XSL を適用して置き換えます。これによって dxl2web.js で作ったフォームの XSL ではなく、あらかじめ用意したフォームの XSL が使われるようになります。なお、この処理を実行後に再度同じデータベース内文書をウェブブラウザで見ると、以下のように(シンプルな見栄えではありますが)UI が乱れることなく表示することができるようになります(MainTopic フォームだけでなく Response フォームも書き換わっています):
2023111706


なお、この3つの標準テンプレートのカスタマイズサンプルに限って MIT ライセンスでのオープンソースとします(ビジネス利用含めて改変可)。また提供されている3つ以外のデータベースに対しても同様に(そのデータベース内に含まれるフォームの XSL を用意すれば)この customxsl.js を使ってカスタマイズ可能です。


【(4)viewhtml.js】
もう1つのカスタマイズツールが viewhtml.js です。上述の customxsl.js は文書の UI をカスタマイズするツールでしたが、こちらはビュー/フォルダの UI をカスタマイズします。ただ customxsl.js では独自の XSL を用意して文書の UI をフルカスタマイズすることができましたが、ビュー/フォルダの UI については以下の2種類用意していて、そのどちらを使うかを切り替えるツールという位置づけです:

・Simple UI(デフォルトはこちら)
・Standard UI

デフォルトでもある Simple UI はビューに含まれる文書の一覧を簡易的な検索機能とページネーションによって表示する機能を持っています。この検索やページネーションには jQuery を併用した JavaScript で動的に行っています(そのためビュー描画の処理が軽くなっています)。大きな制約事項として別途検索エンジンを使って検索機能を実装しようとした際に(JavaScript で動的に文書リストを取得しているので)HTML 自体には文書へのリンクが含まれないため、各文書がクロール対象にならない(検索対象にならない)、という制約があります。

一方の Standard UI は全文書を一枚の HTML 内で静的に表示します。DataTables も有効になるため、簡易検索に加えてビューの列を指定したソートなど、Simple UI にはない便利な機能が含まれます。この構成の場合、HTML 内に全文書へのリンクも含まれるので検索エンジンのクローラーが文書レベルでのクロールもしてくれます(つまり各文書が検索対象になります)。一方、数万個レベルの文書が含まれるようなビュー/フォルダの場合、HTML 内で対象となる文書数が非常に大きくなるため、描画が非常に重くなります(場合によってはブラウザが out of memory エラーとなります)。「デフォルトで Standard UI がいい」と思う人もいらっしゃると思いますが、このような影響の大きい制約事項があるため、デフォルトの挙動としては Standard UI を採用せずに Simple UI を採用しています。


この Simple UI と Standard UI を切り替えて表示したい場合に viewhtml.js を使います。切り替えを行うには viewhtml.js のあるフォルダで以下のコマンドを実行します:
$ node viewhtml (対象の DXL が出力されているフォルダ) (standard または simple)

前回ウェブ化したデータベースを Standard UI に変換してみます:
2023111801


この状態で(Standard UI で)ビューを参照すると以下のようになります。DataTables が有効なページネーションやフィルタリング(簡易検索)、テーブル列毎のソート機能が有効になった状態で全文書(つまりビュー/フォルダに含まれる全文書)へのリンクが含まれています:
2023112601


変換前の同じビューも比較のために載せておきます。デフォルトの Simple UI の場合はこちらでした(Standard UI よりも少しシンプルになっているのがわかると思います):
2023111803


詳しくは次回の記事で説明する予定ですが、クローラー型の検索エンジンを併用してウェブ化されたコンテンツを運用する場合、Standard UI の状態でないと(HTML 内に各文書への静的なリンクが含まれた状態でないと)文書が検索対象になりません。一方で Standard UI は文書数が数万レベルになると(ノーツデータベースの場合は結構ありえると思ってます)ビュー参照時にブラウザが out of memory エラーを起こしてビューが表示できない(したがって文書にもアクセスできない)ことが起こりえます。

というわけで、検索エンジン併用運用の場合は、
・いったん Simple UI から Standard UI に変更して、
・Standard UI の状態で検索エンジンのクローラーでクローリングして、
・クローリングが完了したら(必要に応じて) Simple UI に戻す
という処理をすることをお勧めします。


nsf2dxl2web の機能に関してはここまでで概ね紹介できたと思っています。次回は nsf2dxl2web からは少し離れますが、ここで少し紹介したようなウェブ化した複数データベースによるコンテンツを検索エンジンで全文検索する際の例を紹介するつもりです。



(過去記事や続きはこちらです)
nsf2web2dxl の挑戦(4)



これらの記事の続きです:
nsf2dxl2web の挑戦(1)
nsf2dxl2web の挑戦(2)


三回目となる今回は使い方編と位置づけ、 nsf2dxl2web の使い方を紹介します。2023-11-26 の現時点ではまだツールは(招待制のみでの)非公開ですが、一部の人から徐々に使っていただくことを想定していて、その時に使い方を知ってもらうための紹介ページのつもりで作ります。

なお nsf2dxl2web は今後段階的に公開していく予定ではありますが、オープンソース化の予定は今のところありません。ツールの改変も原則認める予定はありません(次回紹介予定のカスタマイズツールで提供しているサンプルのみ改変しての利用を認めます)。

また将来的に今後の改善や変更によって UI 含めて、ここで紹介している内容と異なる部分がでてくるかもしれない、という点をご了承願います。


【前提条件】
nsf2dxl2web は以下のツール類がインストール/セットアップされている条件の下で動作します:
・HCL ノーツ(バージョン8以降であれば動くと思いますが、バージョン 10 で動作確認しています)
Node.js(バージョン 16 で動作確認しています)

また nsf2dxl2web が変換対象とするノーツデータベースのサイズによっては動作中にメモリ不足が発生する可能性があります。当方では 16GB のメモリを搭載した Windows 11 PC で動作確認しており、この環境下でファイルサイズが約 12 GB のノーツデータベースの変換に成功した実績はあります。なおその際は notes.ini に以下の1行を追加して(ノーツ実行時の Java ヒープサイズを 512MB に増やして)実行しています:
JavaMaxHeapSize=512MB

ちなみに nsf2dxl2web を動作させるだけであればドミノサーバーは不要です(ノーツのセットアップ時に必要になるはずです)。

また後述の(1)および(2)の処理を実行するためには実行するマシンがインターネットに接続している必要がある点に注意してください。


【nsf2dxl2web ツールの取得】
いずれ GitHub リポジトリを公開して URL をここに記載する予定ですが、現時点ではプライベートリポジトリで運用しています。お手数をおかけしますが、しばらくの間は個別にリポジトリのアクセス権を与えられた後に該当 URL から git clone するか、zip でダウンロード/展開してください。


【nsf2dxl2web ツールに同梱されているもの】
ツール一式には nsf2dxl2web 本体を含めた数多くのファイルが含まれています。その中で利用者が明示的に使うことになる(可能性がある)ファイルは以下の6つです:
(1)nsf2dxl2web.nsf
(2)dxl2web.js
(3)customxsl.js
(4)viewhtml.js
(5)web.js
(6)README.md


(1)の nsf2dxl2web.nsf はデフォルトで参照権限のついたノーツデータベースで、この中に nsf2dxl エージェントが含まれています。利用者はこのデータベースをノーツで開き、アクションメニューから nsf2dxl エージェントを実行後に対象データベースを指定して nsf2dxl 処理を行います(詳しくは後述):
2023111601

なお、このデータベースを起動した時に開く「アプリケーションについて」文書の内容は(6)の README.md の内容と同等です。

(2)の dxl2web.js は dxl2web 処理を行う Node.js アプリケーションです。(1)の nsf2dxl と、(2)の dxl2web の2つの処理によって nsf2dxl2web を実現します。

(3)の customxsl.js は(2)の結果として生成された静的コンテンツの文書の見た目をカスタマイズする処理で、これも Node.js アプリケーションです。文書データの UI カスタマイズが必要な場合に使います。

(4)の viewhtml.js は(2)や(3)の結果として生成されたビューやフォルダの UI をカスタマイズする処理で、これも Node.js アプリケーションです。ビューやフォルダの UI カスタマイズが必要な場合に使います。

(5)の web.js は(2)や(3)、(4)の結果生成された静的コンテンツを表示するウェブアプリケーションで、これも Node.js アプリケーションです。これを使って運用してもよいのですが、どちらかというと出来上がった静的コンテンツの見た目を一時的に確認するテスト用ウェブサーバーというつもりで同梱しています(実際の運用ではウェブサーバーとして nginx などを使うことを想定しています)。

(6)は一通りの説明(英語)を含めた README.md です。使い方も記述していますが、英語が苦手な人もいると思うので、今回このブログエントリを書いています。


【nsf2dxl2web の各ツールの使い方】
以下、上述(1)~(5)の各ツールの使い方を紹介します。

【(1)nsf2dxl2web.nsf】
ノーツデータベース(nsf)を XML データ(dxl)として出力します。厳密には単に nsf を dxl 化するだけではなく、ビューデータの CSV 化なども含んでいますが、ここではすべて含めて「nsf2dxl 処理」と呼ぶことにします。

(1)の nsf2dxl2web.nsf をノーツクライアントで開きます:
2023111713


以下のようなセキュリティ警告ダイアログが表示された場合は「署名者を信頼する」を選択して実行してください:
ノーツ_実行セキュリティ警告


ちなみにこのデータベースにはフォームやビュー、文書は登録されていません。エージェントと、そのエージェントが参照するスクリプトライブラリが登録されているだけです。

起動オプションによって、このような「アプリケーションについて」文書が表示されます:
2023111602


この状態から nsf2dxl エージェントを実行するのですが、実行ログを表示できるように Java デバッグコンソールを表示しておきます。メニューから「ツール」-「Java デバッグコンソールの表示」を選択します:
2023111603


下図のようなウィンドウが表示されます。この後に実行する nsf2dxl エージェントの実行ログはこのウィンドウ内に表示されるので、途中で(out of memory などの)エラーが発生した場合はこのウィンドウ内に出力されるので、思っていたような結果にならない場合はこのウィンドウ内に表示されるメッセージを参照してみてください:
2023111604


では nsf2dxl エージェントを実行します。メニューから「アクション」-「nsf2dxl」を実行します:
2023111601


以下のようなデータベースを選択するダイアログ(タイトルは「開く」)が表示されます。ここでウェブ化したいデータベースを選択します:
2023111605


ちなみにここで指定しているデータベースはワークスペース上ではこのように表示されているものを使っています。後でウェブ上でどこまで再現されているかを確認してください:
2023111706


データベースファイルを選択すると、そのファイルをエクスポートする先のフォルダを指定する別のダイアログ(タイトルは「保存」)が表示されます。nsf2dxl2web の処理が完了すると、ここで指定したフォルダがウェブのコンテンツルートになるフォルダなので、初めて nsf2dxl を実行した場合は中身が空のフォルダ(2回目以降は初回に指定した時と同じフォルダ)を指定します。フォルダを指定したら(下図では C:\tmp\tmp)保存ボタンをクリックします:
2023111606


すると指定したデータベースファイルに対して nsf2dxl エージェントが実行され、その結果が指定したフォルダ(上の例だと C:\tmp\tmp)内にエクスポートされます。同時に実行ログが Java デバッグコンソールに表示されます:
2023111607


実行結果は指定したフォルダ内に「指定したデータベースのレプリカID」のサブフォルダが作られ、その中に(上の例だと C:\tmp\tmp\49258A000002200b\ フォルダ内に)出力されていきます。この出力先フォルダ名はログの3行目にも表示されています。 また最後の行に "Processing Step.2 done." と表示されていますが、この行が表示されていれば nsf2dxl 処理が正しく実行できたことを意味しています。

この時点で出力先フォルダの様子を見ると、中には "(指定したデータベースのレプリカID)_designs.xml" というファイル(この中にフォームやイメージリソースなどの設計要素の情報が含まれています)と、"(ビュー/フォルダの UNID).csv" というファイル名でデータベース内の全ビュー/フォルダの情報が CSV 形式でエクスポートされている様子が分かります:
2023111608

また "documents" というサブフォルダが作られていて、このフォルダ内にはデータベース内の全ての文書が "(文書の UNID).xml" というファイル名で出力されている様子が確認できます:
2023111609


nsf2dxl 処理が成功するとこのような結果になります。ビュー/フォルダの数や、含まれる文書数によって実行にかかる時間や出力結果のファイル数や各ファイルのサイズが異なりますが、"Processing Step.2 done." というログが最後に出力されていれば成功です。逆に途中で "Out of memory" などのエラーが表示されている場合は(上述の方法でヒープメモリを確保するなどの対処をして)再度実行する必要があります。

これで nsf2dxl の処理は完了ですが、まだ dxl2web の処理ができていないため、まだウェブでの参照はできません。ただここまででノーツクライアントを使った処理は完了です。これ以降の処理はすべて Node.js がインストールされた環境下で行うことになります。


【(2)dxl2web.js】
前述の nsf2dxl でエクスポートしたデータをウェブ化します。ここでの「ウェブ化」の意味は「静的サイト化」ですが、動的な XSLT 処理で HTML を生成するため、いわゆる HTML ファイルはあまり多く作られません(文書データはすべて XML データとなります)。

まずはシェルやコマンドプロンプトなどのターミナルを起動し、cd コマンドを使って nsf2dxl2web を展開したフォルダ(dxl2web.js があるフォルダ)に移動します:
2023111701


最初の一回だけは nsf2dxl2web を利用する上で必要な依存ライブラリをインストールする必要があります。依存ライブラリのインストールは dxl2web.js のあるフォルダで "npm install" を実行します:
2023111702


依存ライブラリがインストールできれいれば dxl2web.js を実行することができます。カレントディレクトリを dxl2web.js があるフォルダに変更した後に以下のコマンドを入力します:
$ node dxl2web (1)の処理で DXL を出力した先のフォルダ名

上記例では最後のフォルダ名が C:\tmp\tmp\49258A000002200B だったのでこのフォルダ名をフルパスで指定します。dxl2web.js が実行され、最後に "done" と表示されていれば処理は成功しています(対象データベース内の文書数が数百件程度であれば一瞬で終わりますが、数万レベルだと、この処理は結構時間がかかります):
2023111703


あっけない感じですが、これでデータベースのウェブコンテンツ化が(一応)完了しました。


【(5)web.js】
ウェブコンテンツ化された内容に対してカスタマイズを行うこともできるのですが、それは次回に説明するとして、まずはウェブコンテンツ化された内容をブラウザで表示してみましょう。そのためのツールが web.js です。

web.js を実行前に環境変数を指定します。まず環境変数 CONTENTS_ROOT に nsf2dxl 実行時に指定した結果出力先フォルダ名(レプリカ ID を含まないもの)を、Windows の場合は "\" マークを "/" にしたものを(今回の場合だと "/tmp/tmp" を)指定します。またこれはオプションですが、起動する HTTP サーバーのポート番号(無指定時のデフォルト値は 8080)を環境変数 PORT でそれぞれ指定します:
2023111704


この状態で 
$ node web
を実行します。指定したポート(上の例だと 8000 )で HTTP サーバーが待ち受ける状態になります:
2023111705


この HTTP サーバーにアクセスしてみましょう。ウェブブラウザで(この例の場合であれば) "http://localhost:8000" にアクセスしてみます:
2023111707


(1)の処理で指定したノーツデータベース名がアイコンと共に表示されているはずです。ではこのアイコンをクリックします:
2023111708


新しいタブが開き、その中で↑のような画面になります。画面は3分割されていて、それぞれ以下が表示されるフレームになっています(最初は左上のフレームだけが表示されていて、ここにデータベースの全ビュー/フォルダ、および「アプリケーションについて」「アプリケーションの使い方」へのリンクが表示されています):
2023111709


左上のフレームでいずれかのビュー/フォルダを選択すると、右上のフレームでそのビュー/フォルダが表示されます:
2023111710


そして右上のフレームでいずれかの文書を選択すると、下のフレームにその文書が表示されます:
2023111711


ちなみに同じデータベースの同じビューと同じ文書をノーツクライアントで選択するとこのようになります。画像やフォントなどが再現されている様子が確認できると思います:
2023111712


前回のブログエントリでも紹介しましたが、この文書データが表示される際に XSLT 処理が実行されています。文書データはあくまで XML データ(UI を持たないデータ)としてエクスポートされていますが、表示時にフォームの XSL が適用されることで、このように元のノーツ文書に近い UI が再現できています。


【他のデータベースにも適用】
上述した(1)の nsf2dxl 処理と(2)の dxl2web 処理を他のデータベースに対しても実行すると、対象になったデータベースすべてをウェブ化することができます。仮に5つのデータベースに同様の処理を行った後に HTTP サーバーにアクセスすると、以下のように5つのデータベースのアイコンと名前が(ノーツのワークスペースのような感じで)表示されるようになります:
2023111714


各アイコンをクリックすると新しいタブが開いて同様にウェブ化されたコンテンツを表示することができます:
2023111715


このシリーズの初回でも触れましたが、データベース間のリンクも再現できるようになっています。あるデータベースA内の文書の中で、別のデータベースB内のビューや文書へのリンクが作られていた場合、データベースAとB両方がこの nsf2dxl2web ツールによってウェブ化されていれば、ビューリンクや文書リンクもウェブ上で再現できます(わかりにくいと思いますが、↑の例で最初にウェブ化したデータベース内の文書からもう1つのデータベース内の文書にリンクが張られていて、そのリンクをクリックすると文書フレームの内容だけ別データベースの文書になっています):
2023111716


長くなってしまったのでいったんここまでにします。次回はカスタマイズ機能について紹介する予定です。



(過去記事や続きはこちらです)
nsf2web2dxl の挑戦(3)




このページのトップヘ