Backlog4Jの仕様ないし不具合の話。
Problem
Backlog API(v2)を利用してBacklog上のプロジェクトの課題の情報を抽出したい。
よく手に馴染んだ言語、そして公式サポートのライブラリを利用したい。
そこでBacklog4Jを利用して課題の情報を抽出することにしたが、課題に設定されているカスタム属性の値を取得する方法 がわからない。
APIクライアントのgetIssue()
ないしgetIssues()
メソッドはIssue
オブジェクト(ないしそのリスト)を返す。Issue.getCustomFields()
はCustomField
オブジェクトのリストを返す。そしてCustomField
オブジェクトは・・・getValue()
やgetValues()
メソッドを提供 していない。
Solution
Backlog4Jでは課題に設定されたカスタム属性の値を抽出することは できない(Backlog4J v2.6.0現在)。
このため次の中からいずれかを選択しなくてはならない:
- 諦める
- 何らかの方法で迂回(ライブラリを介さず独自コードで直接HTTP要求するなど)
- 別の言語向けのライブラリを利用
- Backlog4JのGitリポジトリをクローンして修正
Backlog APIのリファレンスに含まれているGet Issueの解説ページを見ると、サンプルの応答のJSONが呈示されており、応答に customFields
プロパティが含まれていることがわかる:
リファレンスではこのcustomFields
プロパティがどのようなオブジェクトの配列であるか示されていない。
しかしCurlなどでコマンドラインでAPIを実行して応答のJSONを確認してみると、Backlog4JのCustomFieldインターフェースに相当するオブジェクトであることがわかる。
そして応答のJSONではこのCustomFieldインターフェースにvalue
というプロパティが存在しており、CustomFieldListItemインターフェースにおおよそ相当するオブジェクトもしくはその配列が設定されていることがわかる。
{
"id": 72619110,
"projectId": 106780,
"issueKey": "XXX-1",
"keyId": 1,
...
"customFields": [
{
"id": 321088,
"fieldTypeId": 6,
"name": "カスタム属性名AAA",
"value": [
{
"id": 1,
"name": "カスタム属性値aaa",
"displayOrder": 0
}
]
}
],
...
}
一方であらためてCustomFieldインターフェースを確認すると、getValue()
やgetValues()
メソッドが存在 しない(Problemで述べた通り)。
つまりBacklog APIとしてはカスタム属性の値value
プロパティを提供しているのだが、Backlog4Jとしてそれに対応するJavaのオブジェクトを提供していない。
package com.nulabinc.backlog4j;
/**
* @author nulab-inc
*/
public interface CustomFieldListItem {
long getId();
String getName();
int getDisplayOrder();
}
カスタム属性は単一値をとるケースと複数値をとるケースとがあって、これはカスタム属性の設定次第で変わる。
厄介なのは設定がいずれであっても、APIの応答のJSON上はカスタム属性値は同じvalue
というプロパティ名。単一値のときは value
で複数値のときはvalues
─というふうになっていればよいのだが、残念ながらそうではない。
Java言語的には「単一値でもあり複数値でもある」という曖昧なオブジェクトは表現できない。これがCustomField
インターフェースにはgetValue()
メソッドが存在しない理由らしい(←推測!)。
単一値ないし複数値のカスタム属性値のコンテナになるオブジェクトがあれば CustomField.getValue()
メソッドを実装できるはず。しかしJavaオブジェクト-JSON間のシリアライズ/デシリアライズのロジックを考えるとその実装は意外と面倒そう。そしてBacklog4Jユーザーとしてもインターフェースの変更に追随して既存ロジックにコードを追加しなくてはならない箇所が出てくるかもしれない:
public interface CustomFieldListItem {
long getId();
String getName();
int getDisplayOrder();
CustomFieldValue getValue(); // ←プロパティを追加
}
public interface CustomFieldValue {
boolean isMultiple();
CustomFieldListItem get();
List<CustomFieldListItem> getItems();
}
ということで、Backlog4Jでは課題に設定されたカスタム属性値を取得 できない。
(今度時間をみつけてBacklog4JのFIXバージョンを作成したい)