Develop with pleasure!

福岡でCloudとかBlockchainとか。

FreeMarker内でTilesのタグを利用する。

Struts2でViewの構成をTiles+FreeMarkerにするときの構成。

まず、クラスパスに以下のjarを追加する。
tiles-core.jar
tiles-jsp.jar
tiles-api
struts2-tiles-plugin.jar

続いて、web.xmlにTilesのリスナーとtilesのtaglib定義する。tiles-jsp.tldは、tiles-jsp.jarのMETA-INF\tldフォルダ直下にある。

<listener>
    <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>

<jsp-config>
    <taglib>
        <taglib-uri>http://tiles.apache.org/tags-tiles</taglib-uri>
        <taglib-location>/WEB-INF/tld/tiles-jsp.tld</taglib-location>
    </taglib>
</jsp-config>

お次は、WEB-INF直下にtiles.xmlを配置し、レイアウトの定義を行う。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
    <definition name="/mockLayout" template="/default.ftl">
        <put-attribute name="title" value="default title"/>
        <put-attribute name="body" value="mock.ftl"/>
    </definition>
</tiles-definitions>

テンプレートとなるdefault.ftlは

<#assign tiles=JspTaglibs["http://tiles.apache.org/tags-tiles"] />
<@tiles.importAttribute name="title" scope="request"/>
<html>
    <head><title><@tiles.getAsString name="title"/></title></head>
<body>
    <p id="body">
        <@tiles.insertAttribute name="body"/>
    </p>
    <p>Notice that this is a layout made in FreeMarker</p>
</body>
</html>

な感じ。

これで動作するだろうと思ったら、

Caused by: java.io.IOException: Error invoking Freemarker template.Expression JspTaglibs is undefined on line 1, column 16 in default.ftl.

とJspTaglibsが解釈できずエラーになる。原因不明で対処方法に悩んでいたが、Struts2のサイトにちゃんとJSPのtaglibを利用する際の方法がきちんと書かれてた。
http://struts.apache.org/2.x/docs/freemarker.html
web.xmlにJspSupportServletの定義を追加する必要があったと…。なので、web.xml

<servlet>
    <servlet-name>JspSupportServlet</servlet-name>
    <servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

と追加するとJspTaglibsが解釈可能になり、無事FreeMarker+Tiles連携ができる。