tohokuaikiのチラシの裏

技術的ネタとか。

ORMとしてActiveObjectsを使用する

Atlassianのデータを保存する場所といえば、BandanaでありContentPropertyManagerである。

tohokuaiki.hateblo.jp

が、JIRA4.4からConfluence4.3からは特に意識しなくてもActiveObjectsが使えるようになった。こちらの方が早くて軽くて大容量でそのプラグイン固有のデータを保存して利用することができるということだ。

以下の記事をベースに使い方を見てみる。
Getting Started with Active Objects - Atlassian Developers

使えるようにするには

まず、pom.xmlDependencyを記述

<dependency>
  <groupId>com.atlassian.activeobjects</groupId>
  <artifactId>activeobjects-plugin</artifactId>
  <version>${ao.version}</version>
  <scope>provided</scope>
</dependency>

で、${ao.version}というのはこのURLから自由に選んでくれっていうことらしい。チュートリアルでは1.2.3を使っている。Confluence用っぽい0.24-m5-confluenceっていうのがあってこれを使うといいのだろうか・・・・。 https://maven.atlassian.com/content/repositories/atlassian-public/com/atlassian/activeobjects/activeobjects-plugin/

あと、なぜかGoogle.collectionsも入れておいてって言われた。

<!-- Google Collections, useful utilities for manipulating collections -->
<dependency>
  <groupId>com.google.collections</groupId>
  <artifactId>google-collections</artifactId>
  <version>1.0</version>
  <scope>provided</scope>
</dependency>

ActiveObjectsとして使用されるClassを指定

atlasian-plugin.xml

<ao key="ao-module">
  <description>The module configuring the Active Objects service used by this plugin</description>
  <entity>com.atlassian.tutorial.ao.todo.Todo</entity>
</ao>

というように、使用するActive Objects Classを記述する。上記の場合、com.atlassian.tutorial.ao.todo.TodoクラスがActiveObjectとなって使用されるようになる。

前述のClassを実装

atlassian-plugin.xmlで記述した com.atlassian.tutorial.ao.todo.Todo をinterfaceで実装する。

setter/getterでエンティティを定義。この時「ID」は net.java.ao.Entityが使っているのでよっぽどでない限りOverwriteはしない。

package com.atlassian.tutorial.ao.todo;

import net.java.ao.Entity;

public interface Todo extends Entity
{
    String getDescription();

    void setDescription(String description);

    boolean isComplete();

    void setComplete(boolean complete);
}

ServletXWorkで使用する場合の準備

Servletの場合

public final class TodoServlet extends HttpServlet
{

    private final ActiveObjects ao;


    public TodoServlet(ActiveObjects ao)
    {
        this.ao = checkNotNull(ao);
    }

という感じでいつものようにConstructorでInjectionする。このaoを使って先ほどのEntity化されたObjectをCRUDする。

XWorkの場合

XWorkの場合はConstructorによるInjectionが無いのでsetter/getterを使うかと思いきや、このActiveObjectsにはそれが使えないっぽい。なので一旦ActiveObjectsを使うClassをComponentとして登録する。

一旦Componentを作成する。

まずatlassian-plugin.xmlでcomponentとして登録する

<component key="foo-service" name="Foo-Service" class="jp.example.com.FooServiceImpl" public="true">
    <interface>jp.example.com.FooService</interface>
</component>

jp.example.com.Fooのinterfaceを作成し、jp.example.com.FooImplを実装する。public=trueでないならinterfaceは不要なわけだと思うけど。

で、こいつのConstructorにてActiveObjectsをInjectionしてもらう。

import static com.google.common.base.Preconditions.checkNotNull;


public class FooServiceImpl implements FooService {

    private final ActiveObjects ao;

    public FooServiceImpl(ActiveObjects ao) {
    this.ao = checkNotNull(ao);
    }

で、XWorkの方でこのComponentを読み込む

XWorkでsetter/getterを定義してComponentを使えるようにする。

import static com.google.common.base.Preconditions.checkNotNull;

    private FooService fooService;
    
    public FooService getFooService() {
        return fooService;
    }
    public void setFooService(FooService fooService) {
        this.fooService = checkNotNull(fooService);
    }