長文を変数に入れたい場合、#defineを使う。

Velocityで長文を作って変数に入れたい場合、#defineを使いましょう。
#macroだと、Velocityにキャッシュされ、同じ結果が出てしまいます。

次の例を見ましょう。

import java.io.IOException;
import java.io.StringWriter;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;

public class TestMacro {

    public static void main(String[] args) {
        String src =
            "#macro(content) \n" +
            "長文コンテンツです1。 \n" +
            "長文コンテンツです2。 \n" +
            "長文コンテンツです3。 \n" +
            "長文コンテンツです4。 \n" +
            "長文コンテンツです5。 \n" +
            "#end \n" +
            "#content \n" +
            "#macro(content) \n" +
            "変更-長文コンテンツです1。 \n" +
            "変更-長文コンテンツです2。 \n" +
            "変更-長文コンテンツです3。 \n" +
            "変更-長文コンテンツです4。 \n" +
            "変更-長文コンテンツです5。 \n" +
            "#end \n" +
            "#content \n";
        Context vc = new VelocityContext();
        try (StringWriter sw = new StringWriter()) {
            Velocity.evaluate(vc, sw, "test", src);
            System.out.println("=== START ===");
            System.out.println(sw.toString());
            System.out.println("=== END ===");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 結果
     * === START ===
     * 長文コンテンツです1。
     * 長文コンテンツです2。
     * 長文コンテンツです3。
     * 長文コンテンツです4。
     * 長文コンテンツです5。
     *
     * 長文コンテンツです1。
     * 長文コンテンツです2。
     * 長文コンテンツです3。
     * 長文コンテンツです4。
     * 長文コンテンツです5。
     *
     *
     * === END ===
     */
}

結果を見ると、「長文コンテンツですX。」が五つ、「変更-長文コンテンツですX。」が五つを期待しましたが、

「長文コンテンツですX。」のみ、十回表示されます。

後で同じ名前の#macroを定義しても最初の#macroの結果を使うようです。
おそらくパフォーマンス上の理由でキャッシュしているでしょう。
ですので、#macroは長文を変数化する用途には使わないようにしましょう。

では、どうすれば長文を変数に入れられるかということ、次のように#defineを使えばいいです。

import java.io.IOException;
import java.io.StringWriter;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;

public class TestDefine {

    public static void main(String[] args) {
        String src =
            "#define($content) \n" +
            "長文コンテンツです1。 \n" +
            "長文コンテンツです2。 \n" +
            "長文コンテンツです3。 \n" +
            "長文コンテンツです4。 \n" +
            "長文コンテンツです5。 \n" +
            "#end \n" +
            "$content \n" +
            "#define($content) \n" +
            "変更-長文コンテンツです1。 \n" +
            "変更-長文コンテンツです2。 \n" +
            "変更-長文コンテンツです3。 \n" +
            "変更-長文コンテンツです4。 \n" +
            "変更-長文コンテンツです5。 \n" +
            "#end \n" +
            "$content \n";
        Context vc = new VelocityContext();
        try (StringWriter sw = new StringWriter()) {
            Velocity.evaluate(vc, sw, "test", src);
            System.out.println("=== START ===");
            System.out.println(sw.toString());
            System.out.println("=== END ===");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 結果
     * === START ===
     * 長文コンテンツです1。
     * 長文コンテンツです2。
     * 長文コンテンツです3。
     * 長文コンテンツです4。
     * 長文コンテンツです5。
     *
     * 変更-長文コンテンツです1。
     * 変更-長文コンテンツです2。
     * 変更-長文コンテンツです3。
     * 変更-長文コンテンツです4。
     * 変更-長文コンテンツです5。
     *
     *
     * === END ===
     */

}

#macroと似ていますが、表記が下記のように違います。

  • #macroの代わりに#defineを使う
  • #defineの変数名の前に$を付ける(例: #define($content))。
  • 変数出力時、#でなく、$を使う(例: $content)。