ListViewの拡張をやってみた(失敗)

Hudsonの売りの1つにプラグインによる機能の拡張がありますが、ちょっと前から拡張ポイントが増えています。
今回はListViewColumnを使用して、ジョブの一覧に項目を追加してみます。ちょうど1.282?から、ジョブを起動した原因(ビルドトリガ)を表示する機能が追加されているので、ジョブの一覧に表示してみます。



あらかじめ、結論から言うと失敗しました。ちょっと、Hudsonに修正が必要のようです。

まずは、お決まりのPluginを継承したクラスを作ります。

public class CauseColumnPlugin extends Plugin {
    @Override
    public void start() throws Exception {
        ListViewColumn.LIST.add(CauseListViewColumn.DESCRIPTOR);
    }
}


次に、ListViewColumnを継承したクラスを作ります。ここでは、まず適当に一覧のタイトルをして"Cause"と表示します。

public class CauseListViewColumn extends ListViewColumn {

    public static final CauseListViewColumnDescriptor DESCRIPTOR = new CauseListViewColumnDescriptor();

  // タイトルを表示 
    @Override
    public String getColumnCaption() {
        return "Cause";
    }

    public Descriptor<ListViewColumn> getDescriptor() {
        return DESCRIPTOR;
    }

    public static class CauseListViewColumnDescriptor extends Descriptor<ListViewColumn> {

        public CauseListViewColumnDescriptor() {
            super(CauseListViewColumn.class);
            load();
        }

        @Override
        public String getDisplayName() {
            return "Cause ListViewColumn";
        }

        @Override
        public ListViewColumn newInstance(StaplerRequest req, JSONObject formData) throws FormException {
            return req.bindJSON(CauseListViewColumn.class, formData);
        }
    }
}


最後に、ジョブ毎に表示するcell.jellyを作成します。cell.jellyと言うのは、ListViewColumnのJavadocに記述されています。
今のところ、固定で"TEST"と表示します。

<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">

  <td>TEST</td>

</j:jelly>


これでとりあえず、プロトタイプとしてできたはずなので、mvn hpi:runで起動してみます。とりあえずは、ジョブを1つ作ってみます。

何にも変化なしです... Hudsonのソースを見てみると、"すべて"のタブを表示するAllView.javaには何もプラグイン絡みの記述はありませんが、ListView.javaにはあります。どうも、"すべて"タブには対応していないようです。ということで、タブを1つ作ってみます...

HTTP ERROR: 500

INTERNAL_SERVER_ERROR

RequestURI=/createView
Caused by:

java.lang.NullPointerException
at hudson.plugins.causecolumn.CauseListViewColumn$CauseListViewColumnDescriptor.newInstance(CauseListViewColumn.java:45)
at hudson.plugins.causecolumn.CauseListViewColumn$CauseListViewColumnDescriptor.newInstance(CauseListViewColumn.java:27)
at hudson.model.ListView.initColumns(ListView.java:87)

む...

        @Override
        public ListViewColumn newInstance(StaplerRequest req, JSONObject formData) throws FormException {
            return req.bindJSON(CauseListViewColumn.class, formData);
        }

ここの、req.bindJSONでぬるぽが出たようです。確かに、hudson.model.ListView.javaで、newInstanceにnullを渡しているのでたぶんここが問題のようです。

    private void initColumns() {
        // create all instances
        ArrayList<ListViewColumn> r = new ArrayList<ListViewColumn>();
        for (Descriptor<ListViewColumn> d : ListViewColumn.LIST)
            try {
                r.add(d.newInstance(null,null));
            } catch (FormException e) {
                // so far impossible. TODO: report
            }
        columns = Collections.unmodifiableList(r);
    }

でも、DescriptorのnewInstance()には、第一引数requestはAlways non-nullとあるけど。別のnewInstanceか何かを追加するか、NullObjectみたいなものが必要かもしれません。とりあえず、プラグインのnewInstanceを修正します。

        public ListViewColumn newInstance(StaplerRequest req, JSONObject formData) throws FormException {
            return new CauseListViewColumn();
        }

再度、mvn hpi:runで起動して、作成したタブを表示。

2009-02-17 23:22:59.401::WARN: /view/%E3%83%86%E3%82%B9%E3%83%88/:
org.apache.commons.jelly.JellyTagException: jar:file:/home/sogabe/src/hudson/plugins/causecolumn/target/work/webapp/WEB-INF/lib/hudson-core-1.283.jar!/lib/hudson/projectViewRow.jelly:45:57: No page found 'column.jelly' for class hudson.plugins.causecolumn.CauseListViewColumn
at org.kohsuke.stapler.jelly.IncludeTag.doTag(IncludeTag.java:92)

うぐぅ... column.jellyがないですか。作った覚えありません。とりあえず、projectViewRow.jellyを見てみる。

      <j:forEach var="col" items="${columnExtensions}">
          <st:include page="column.jelly" it="${col}" />
      </j:forEach>

cell.jellyではなくてcolumn.jellyですね。直して起動。


できた...プロトタイプが。


ということで、とりあえずプロトタイプができました。今度は、ジョブからビルドのトリガを取得してcolumn.jellyで表示するようにしたいところですが、hudsonを修正するのが先のようです。