struts2 / Freemarkerでpublicフィールドを参照できるようにする

Freemarkerでは通常getterを見るようになっていてpublicフィールドは参照しません。
ちなみにこれは

${hoge.hoge1}

みたいな場合で

<@s.property value="hoge.hoge1"/>

のようにすればpublicフィールドも参照可能です。(これはfreemarkerではなくstruts2のValueStackを使っているため)
なので、フィールドはprivateにしてgetter/setterを使うというのが正攻法だと思います。
ただ、好みの問題ではありますがpublicフィールドを使っているところもあります。
そのほうがコードとしてはシンプルです。
S2JDBCなんかもpublicフィールドにしています。
なので、publicフィールドも使えると便利です。


いくつか見つけた中では、
http://d.hatena.ne.jp/colun/20100102
これは一般論なので、そのままstruts2で使うわけにはいきません。
http://d.hatena.ne.jp/runfor/20090911
これはライブラリをそのまま書き換えてます。
stuts2のバージョンアップとかが面倒になるので、あまりやりたくないです。


提案したい方法は次のとおりです。
上のリンク先にあるように、やることとしては簡単に言うと

ObjectWrapper#setExposeFields(true);

とするだけです。

  • ライブラリ内のプログラムを継承して上書き
  • 設定で新しく作ったクラスを使うように変更
FreemarkerManagerを上書きする場合

クラス作成(MyFreemarkerManager)

package kamegu.common.freemarker;

import javax.servlet.ServletContext;

import org.apache.struts2.views.freemarker.FreemarkerManager;

import freemarker.ext.beans.BeansWrapper;
import freemarker.template.ObjectWrapper;

public class MyFreemarkerManager extends FreemarkerManager {
	protected ObjectWrapper createObjectWrapper(ServletContext servletContext) {
		ObjectWrapper wrapper = super.createObjectWrapper(servletContext);
		((BeansWrapper) wrapper).setExposeFields(true);
		return wrapper;
	}
}

設定(struts.xml)

(省略)
  <constant name="struts.freemarker.manager.classname" value="kamegu.common.freemarker.MyFreemarkerManager"/>
(省略)
FreemarkerResultを上書きする場合

クラス作成(MyFreemarkerResult)

package kamegu.common.freemarker;

import org.apache.struts2.views.freemarker.FreemarkerResult;

import freemarker.ext.beans.BeansWrapper;
import freemarker.template.ObjectWrapper;

public class MyFreemarkerResult extends FreemarkerResult {
	protected ObjectWrapper getObjectWrapper() {
		ObjectWrapper wrapper = super.getObjectWrapper();
		((BeansWrapper) wrapper).setExposeFields(true);
		return wrapper;
	}
}

設定(struts.xml)

(省略)
  <package ~~~~~>
    <result-types>
        <result-type name="freemarker" class="kamegu.common.freemarker.MyFreemarkerResult"/>
    </result-types>
(省略)