バッチ処理(Dropwizard の Command) でメール送信処理を書く必要があり、
テンプレートエンジンを何かしら使おうとして、
Wicket の PackageTextTemplate を使用した結果を記載します。
正直かなり無理矢理感はありますが、TemplateEngine として使うことはできました。
前提
- Wicket version 7.6.0 を使用して動作確認は実施しました。
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-core</artifactId>
<version>7.6.0</version>
</dependency>
参考記事
Wicket を TemplateEngine として使う
Wicket の Example Page に、Mail Templates の項があります。
Wicket Examples - Render mail templates
Example では Page、Panel、もしくは、PackageTextTemplate を使用して、
Template の取得、パラメータ設定を行っています。
以下、Example のざっくり抜粋になります。
Page を Template として使う
PageProvider、ComponentRenderer#renderPage() を使って、 テンプレート取得、パラメータ設定をします。
PageProvider pageProvider = new PageProvider(TemplateBasedOnPage.class, parameters);
CharSequence pageHtml = ComponentRenderer.renderPage(pageProvider);
Panel を Template として使う
ComponentRenderer.renderComponent() を使って、 テンプレート取得、パラメータ設定をします。
CharSequence panelHtml = ComponentRenderer.renderComponent(new MailTemplatePanel("someId",
new PropertyModel<String>(MailTemplate.this, "name")));
txt ファイルを Template として使う
PackageTextTemplate を使って、 テンプレート取得、パラメータ設定をします。
PackageTextTemplate template = new PackageTextTemplate(MailTemplate.class, "mail-template.tmpl");
CharSequence templateHtml = template.asString(variables);
バッチ処理内で、PackageTextTemplate を使用する
Batch 処理 (WARアプリケーションではない。Wicket Filter や、 Wicket Servlet が起動されない処理) では、
以下の実装で、 PackageTextTemplate
を動作させることができました。
- createMessageメソッド
private String createMessage(ContactMailTaskManage entity) throws IOException {
String message = null;
MockApplication mock = new MockApplication();
ThreadContext.setApplication(mock);
mock.setName("BATCH");
mock.setServletContext(new MockServletContext(mock, ""));
mock.initApplication();
try (TextTemplate textTemplate = new PackageTextTemplate(this.getClass(), "inqueryMailTmpl.txt")) {
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("name", entity.getName());
vars.put("emailAddress", entity.getEmail());
vars.put("subject", entity.getSubject());
vars.put("message", entity.getMessage());
message = textTemplate.asString(vars);
} catch (IOException e) {
throw e;
}
return message;
}
- 説明
以下の記述で、MockApplication を生成して、
ThreadContextに設定しています。
上記を実行しないと、ThreadContextに、紐づくApplicationが存在しない状態になり、MockApplication mock = new MockApplication(); ThreadContext.setApplication(mock); mock.setName("BATCH"); mock.setServletContext(new MockServletContext(mock, "")); mock.initApplication();
リソース取得時に以下のエラーが発生します。これではまっていたのですが、Wicket のテストクラスで、MockApplicationの設定記述があったので、! org.apache.wicket.WicketRuntimeException: There is no application attached to current thread main ! at org.apache.wicket.Application.get(Application.java:235) ! at org.apache.wicket.util.template.PackageTextTemplate.load(PackageTextTemplate.java:195) ! at org.apache.wicket.util.template.PackageTextTemplate.getString(PackageTextTemplate.java:255) ! at org.apache.wicket.util.template.TextTemplate.asString(TextTemplate.java:72)
そちら参考に実装して上手く動かすことができました。
無理矢理なので、TextTemplate を継承実装して、無理矢理感をなくす。
記事を記載していて、あまりに無理矢理なので、
別の方式にしたほうがいい気がしてきました。PackageTextTemplate の親クラスで、TextTemplate を継承して実装すると、
Application に依存する処理をスキップすることができるので、そちらを試してみました。
以下、変更した createMessageメソッド になります。
- createMessageメソッド
private String createMessage(ContactMailTaskManage entity) throws IOException {
String message = null;
try (TextTemplate textTemplate = new TextTemplate("text") {
private InputStream is;
private BufferedReader br;
private InputStreamReader isr;
@Override
public String getString() {
is = this.getClass().getResourceAsStream("inqueryMailTmpl.txt");
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
StrBuilder sb = new StrBuilder();
br.lines().forEach(line -> {
sb.appendln(line);
});
return sb.toString();
}
@Override
public TextTemplate interpolate(Map<String, ?> map) {
throw new UnsupportedOperationException("Not support..");
}
@Override
public void close() {
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(isr);
IOUtils.closeQuietly(br);
}
}) {
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("name", entity.getName());
vars.put("emailAddress", entity.getEmail());
vars.put("subject", entity.getSubject());
vars.put("message", entity.getMessage());
message = textTemplate.asString(vars);
}
return message;
}
-
説明1 TextTemplate のgetString メソッド、interpolate メソッドを実装したインナークラスを作成しました。
interpolate
は、TextTemplate#asString() を使う限りは、呼び出されないので、例外をスローする実装にしました。 -
説明2 TextTemplateは、
Closeable
をimplementsしているので、closeメソッドを実装する必要があります。 -
説明3 getString() の呼び出し毎に、ファイルを取得しにいく必要はないので、パフォーマンスとしては改善の余地はあるように思います。
Application クラスに依存しない形でTextTemplateの実装はできました。
Panelなども、Application クラスに依存しない形で、純粋な TemplateEngine として使うこともできるかもしれません。
他にもTemplateEngine のライブラリは存在するので、無理に使う必要はないですが。。
以上です。
コメント