tohokuaikiのチラシの裏

技術的ネタとか。

Confluenceのプラグインでフォームを含む管理画面を作ること(1)

フォームを扱う場合、一般的にはフレームワークを使うと楽なので生では使いたくないのですが、Confluenceのプラグインでもそのような方法があるみたい。
Creating an Admin Configuration Form - Documentation - Atlassian Developer Documentation
チュートリアルを見てみる。このチュートリアルの予備知識としては、JavaのプログラミングスキルとAtlassianプラグインの基本的な作り方を知っていること。

Atlassian RefApp

というのがあって、About the Atlassian RefApp - Documentation - Atlassian Developer Documentationによると、

使用するライブラリ

Shared Access Layer (SAL) API

ユーザー認証や、データの保存などに使うAPI

Atlassian Template Renderer (ATR)

Velocityテンプレートなどへのレンダラー

Atlassian User Interface (AUI)

Atlassianアプリケーションのルック&フィールを提供する

REST module

ブラウザとサーバの間の通信を制御するRESTモジュール

作るべきファイル

  1. Javaクラス。プラグインのロジックが(Framework2により)カプセル化されている。
  2. UIに関するリソース(JavaScriptとか画像とかCSS
  3. XMLによる設定ファイル

サンプル

Atlassianにより、サンプルが下記から取得できる。

git clone https://bitbucket.org/atlassian_tutorial/xproduct-admin-ui-plugin

ちなみに、このチュートリアルや上記のサンプルは、RefAppプラグインとして作っているが、Confluenceのプラグインとしても使用できるチュートリアルであると信じる。。。

とりあえず、サーブレットを設置する

チュートリアルのStep1~3までの部分を流し見。Add a credential checkというところは、昨日やったとおり。

Atlassian Template Rendererを使えるようにする

pomに

<dependency>
  <groupId>com.atlassian.templaterenderer</groupId>
  <artifactId>atlassian-template-renderer-api</artifactId>
  <version>1.5.4</version>
  <scope>provided</scope>
</dependency>

を追加する。バージョンは現時点での1系*2の最新。

atlassian-plugin.xmlを追加。

<component-import key="renderer" interface="com.atlassian.templaterenderer.velocity.one.six.VelocityTemplateRenderer" />

Javaにimportして、

import com.atlassian.templaterenderer.TemplateRenderer;

最初、NetBeans
com.atlassian.confluence.renderer.template.TemplateRenderer
を薦めてきたので、これかと思ったら違った*3

コンストラクタに引数追加。

    public MypostServlet(UserManager userManager, LoginUriProvider loginUriProvider, TemplateRenderer renderer) {

あるいは

    public MypostServlet(SpaceManager spaceManager, PageManager pageManager, ContentPropertyManager contentPropertyManager, UserManager userManager, LoginUriProvider loginUriProvider, BandanaManager bandanaManager, TemplateRenderer renderer) {

とか*4

そして、このレンダラーを使って出力。doGetメソッドの最後に

  renderer.render("admin.vm", response.getWriter());

というようにする。

Velocityテンプレート変数を入れたい場合は、

  renderer.render("admin.vm", map, response.getWriter());

その下にある、

$webResourceManager.requireResource("com.atlassian.auiplugin:ajs")

は、Velocityテンプレートに入れると各々のアプリケーションにあったヘッダーとかを出してくれる*5が、Confluenceプラグインで開発している限りは特に必要が無かった。

i18n

i18nは、I18N Architecture - Confluence Development - Atlassian Developer Documentationによると、

  1. /com/atlassian/confluence/core/ConfluenceActionSupport_.properties
  2. /com/atlassian/confluence/core/ConfluenceActionSupport_.properties
  3. /com/atlassian/confluence/core/ConfluenceActionSupport_.properties

の順番で認識するようだ。

COOKIEのconfluence-languageをいじることで、言語は変更できるので調査。
普通は、langまでかlang_countryまでの指定で済むと思う。

atlassian-plugin.xml
    <resource type="i18n" name="i18n" location="com.atlassian.tutorial.xproductadminui.i18n" />

と指定することで、テンプレートやJavaで使用できるようになる。

上記の指定の場合、
/src/main/resources/com/atlassian/tutorial/xproductadminui/i18n.properties
がメインのi18nプロパティファイルになる。

日本語だと、
/src/main/resources/com/atlassian/tutorial/xproductadminui/i18n_ja_JP.properties
を作ることになる。

ただし、マルチバイトの場合ちょっと厄介なのはUnicode参照文字形式でエンコードしたものを使わないとイケない点。

例えば、

my.plugin.name=なまえ

ではダメで、

my.plugin.name=\u306a\u307e\u3048

としなければいけない。

これ、結構大変なんだけど、どうもこことか読むと、Springの仕様なのでpropertyファイルでやるのは仕方がないような気がする。Language Packを作る方法でやれば回避できるのかしら・・・。

JavaScriptの為に、「今」の位置を把握する

applicationPropertiesというコンポーネントを利用する。

<component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties" /> 

これは、デフォルトで入っていると思う。keyが重なるとプラグインコンパイルに失敗するので注意。

更にこれをテンプレートから使えるようにするために、

<template-context-item key="applicationPropertiesContextItem" component-ref="applicationProperties" context-key="applicationProperties" name="Application Properties Context Item"/> 

というのも追加する。

すると、テンプレートファイルで$applicationPropertiesという変数が使えるようになる。

というのとは関係なく

Atlassianのチュートリアルには、

    <meta name="application-base-url" content="$applicationProperties.getBaseUrl()">

を入れると、jQuery

AJS.$("meta[name='application-base-url']").attr("content")

でConfluenceのパスが取れるってあるけど、これはRefAppとしてプラグインを作った場合の話。Confluenceのプラグインとして作っていれば

AJS.$("meta[name='confluence-base-url']").attr("content")

で最初から問題なく取得できる。

JavaScript/CSSをロードする時も、atlassian-plugin.jsにを書いておけばJavaScriptは自動的にタグ内に内蔵される。


次回、JavaScriptとRESTを使って更新する方法をあれこれ書く。

*1:って何かよく分かってないけど

*2:チュートリアルが1.1.1だったので

*3:renderメソッドが無いので気が付いた

*4:不思議なんだけどHTTPServletのサブクラスのコンストラクタって、どういう引数の順番でもいいんだろうか?実際に適当に順番変えてもちゃんと引数が収まってたのでいいんだろうけど

*5:正確にはCSSとかだと思う