Alfresco Share JAR ModulesによるDashletの作成方法

前回のエントリでは、Alfresco Share JAR Modulesで作成されたSite Tags Dashletを紹介しました。今回はこのDashletの作成方法について書いていきます。

前提

  • Maven2 or 3がインストールされていること

Alfresco Share JAR Modulesを作成するための、Maven用のテンプレートが用意されているのでこれを利用します。

プロジェクトの作成

  • コマンドプロンプトから下記のコマンドを実行します。コマンド中の、groupId、artifactId、versionは好みの値に変えてください。
mvn archetype:generate -DarchetypeGroupId=org.alfresco.maven -DarchetypeArtifactId=maven-alfresco-share-module-archetype -DarchetypeVersion=1.0.0-SNAPSHOT -DgroupId=com.mycompany -DartifactId=my-custom-share-module -Dversion=1.0-SNAPSHOT -DarchetypeRepository=http://maven.alfresco.com/nexus/content/repositories/snapshots -DinteractiveMode=false
  • これでAlfresco Share JAR Modulesのプロジェクトひな形が自動生成されます。下記の構成となっていて、実は、Site Tags Dashletのソースがサンプルとして含まれている。
my-custom-share-module
├─pom.xml
└─src
    └─main
        └─resources
            ├─alfresco
            │  └─site-webscripts
            │      └─org
            │          └─alfresco
            │              └─components
            │                  └─dashlets
            │                      ├─site-tags.get.config.xml
            │                      ├─site-tags.get.desc.xml
            │                      ├─site-tags.get.head.ftl
            │                      ├─site-tags.get.html.ftl
            │                      ├─site-tags.get.js
            │                      ├─site-tags.get.properties
            │                      └─site-tags.get_cy.properties
            └─META-INF
                └─components
                    └─dashlets
                        ├─images
                        │  └─refresh.png
                        ├─site-tags-min.js
                        ├─site-tags.css
                        └─site-tags.js

上記ファイルについて簡単に説明します。

src/main/resources/alfresco/site-webscripts 以下のファイル

サーバサイドで動作するコンポーネントです。

  • site-tags.get.config.xml
    • 設定ファイル。ここで設定した値をftlファイルから参照できる。Site Tags Dashletでは、タグの最大表示数を設定している。
  • site-tags.get.desc.xml
    • Dashletのエントリポイントとなるファイル。下記の内容となっていますが、重要なのはの値です。ここをsite-dashletとすることで、サイト単位のDashletになります。もし、user-dashletとすると、ユーザごとのダッシュボードに配置可能なDashletになります。dashletとすると両方に配置可能になります。は、この後で説明するsrc/main/resources/META-INF以下のディレクトリ構造と一致させます。
<webscript>
   <shortname>Tag Cloud</shortname>
   <description>Displays a cloud of all the tags defined in this site</description>
   <family>site-dashlet</family>
   <url>/components/dashlets/site-tags</url>
</webscript>
  • site-tags.get.head.ftl
    • このDashletの画面をレスポンスとして出力するFreeMakerのテンプレートです。headがファイル名についていますが、HTMLので返したい内容を定義すると埋め込んでくれます。なので、CSSJavaScriptの読み込みなどで使います。
  • site-tags.get.html.ftl
    • 同様にFreeMakerのテンプレートですが、こちらはHTMLの本文を定義します。つまり、Dashletで返したい内容を記述します。
  • site-tags.get.js
    • JavaScriptですが、ブラウザで動作する物ではありません。こちらはサーバサイドで動作する物。ここに、Dashletの画面表示の前に処理したいことを記述することになります。
    • Alfresco内での一般的な書き方としては、下記のようにmain関数を定義し、そのmain関数を実行するような形になっています。
const PREFERENCES_ROOT = "org.alfresco.share.dashlet";

function main()
{
   var s = new XML(config.script);
   model.maxItems = parseInt(s.maxitems, 10);

   …(省略)…

   model.preferences = preferences;
}

main();
    • 重要なポイントはmodel.preferences = preferences;の部分。model変数の任意のプロパティに値を設定することで、レスポンスを生成するテンプレートファイルに値を渡すことができます。
  • site-tags.get.properties、site-tags.get_cy.properties
    • メッセージファイルです。多言語対応には必要。日本語リソースが必要な場合は、site-tags.get_ja.propertiesというファイルで作成すればOK。
src/main/resources/META-INF 以下のファイル

ここに配置したファイルは、クライアントからアクセスされる静的なリソースファイル(JavaScriptCSS、画像ファイルなど)になる。

  • site-tags.css
    • CSSファイル。site-tags.get.head.ftlによりで読み込まれている。
  • site-tags.js/site-tags-min.js
    • JavaScriptのファイル。*-min.jsファイルは、YUI Compressorで圧縮したもの。
    • これもsite-tags.get.head.ftlによりで読み込まれているのですが、FreeMakerのマクロ機能でデバッグモード時は*-min.jsを自動的に読むようになっています。site-tags.get.head.ftlの中身を見ると分かりますが、scriptタグを使用せずに@scriptタグを使用しています。
<#include "../component.head.inc">
<!-- Tag cloud -->
<@link rel="stylesheet" type="text/css" href="${page.url.context}/res/components/dashlets/site-tags.css" />
<@script type="text/javascript" src="${page.url.context}/res/components/dashlets/site-tags.js"></@script>
    • この@付きがFreeMakerのマクロで、実体は<#include>でインクルードしているcomponent.head.incに定義されている。これはAlfrescoの本体に格納されている共通部品なので注意。下記のように、DEBUG変数の値で-min.jsに置換している。
<#--
   JavaScript minimisation via YUI Compressor
-->
<#macro script type src>
   <script type="${type}" src="${DEBUG?string(src, src?replace(".js", "-min.js"))}"></script>
</#macro>
    • 肝心のタグクラウドとしての処理、タグの一覧を取得するのはどこに実装されているかですが、実はこのsite-tags.jsで実装されている。つまり、Site Tags DashletはほぼクライアントサイドのJavaScriptで実装されています。タグの一覧はAlfrescoのREST APIを叩いて取得していて、それを画面に表示しているだけです。下記のコードでタグ一覧をJSONで取得し、画面に描画しています。
         // Make an AJAX request to the Tag Service REST API
         Alfresco.util.Ajax.jsonGet(
         {
            url: Alfresco.constants.PROXY_URI + "api/tagscopes/site/" + $combine(this.options.siteId, this.containerId, "tags"),
            successCallback:
            {
               fn: this.onTagsSuccess,
               scope: this
            },
            failureCallback:
            {
               fn: this.onTagsFailed,
               scope: this
            },
            scope: this,
            noReloadOnAuthFailure: true
         });

日本語タグに対応してみる

前回のエントリでちょっと書いたとおり、日本語のタグを作ってしまうと、Site Tags Dashletからのリンク遷移で失敗してしまうという問題があります。これを修正してみます。

原因は何か?

日本語のタグを作ると、Site Tags Dashletからのリンク遷移を行うとタグ名が文字化けしています。タグ名はURLパラメータとして渡しているので、URLエンコードに問題がありそうです。

site-tags.js:325を見ると、タグ名はencodeURIComponentを使用してエンコードしています。

            case "documentLibrary":
               uri += '/documentlibrary#filter=tag|' + encodeURIComponent(tag.name);
               break;

一方、タグに対応したドキュメント一覧の表示画面では、share.war/components/documentlibrary/documentlist.jsで処理されています。これをみると、タグ名をDL_fnDecodeBookmarkedFilter関数でデコードしているのですが、window.unescapeを使って元にもどしている。encodeURIComponentとunescapeでは文字コードが異なるので、ここで化けてしまっていました*1

         var fnDecodeBookmarkedFilter = function DL_fnDecodeBookmarkedFilter(strFilter)
         {
            var filters = strFilter.split("|"),
               filterObj =
               {
                  filterId: window.unescape(filters[0] || ""),
                  filterData: window.unescape(filters[1] || "")
               };
            
            filterObj.filterOwner = Alfresco.util.FilterManager.getOwner(filterObj.filterId);
            return filterObj;
         };

なので、修正方法としては、site-tags.js:326のエンコード方式を変えてあげればよい。下記のように、encodeURIComponent関数をwindow.escape関数に変えてあげる。

            case "documentLibrary":
               uri += '/documentlibrary#filter=tag|' + window.escape(tag.name);
               break;

作成したDashletをビルドする

作成されたプロジェクトをビルドするには、Mavenの下記コマンドを実行します。ビルドが成功すると、target/my-custom-share-module-1.0-SNAPSHOT.jarができています。

mvn install

作成したDashletをデプロイする

前回のエントリと同様に、ビルドしたJARをAlfrescoの下記に配置します。また、catalina.propertiesのshared.loaderの設定も忘れずに!

/opt/alfresco-3.4.b/tomcat/shared/lib

Alfrescoを起動している場合は、再起動します。これでDashletが使えるようになる。

まとめ

  • Dashletの開発では、Mavenを使えば簡単にプロジェクトの作成→ビルドが行える環境が整います。
  • Dashletの開発において、Java言語は必要ありません。HTML、CSSJavaScript、FreeMakerによるテンプレートファイルがメインです。ShareはWeb2.0スタイルと言っているだけあって、クライアントサイドのJavaScriptでごりごり開発するのが基本的な形のようです。その時標準で使えるライブラリとしてはYUIとなります。
  • また、AlfrescoではREST APIが豊富に用意されています。JSONを返してくれるので、クライアントサイド(またはサーバサイド)のJavaScriptからアクセスし、結果を加工して画面表示するようなアーキテクチャになります。

*1:documentlist.jsではwindow.unescapeをなぜ利用しているかというと、YUIのHistoryManagerをこいつは使っていて、HistoryManager自身もwindow.escape/unescapeで利用しているためと思われる。