JFreeChartで生成したグラフを一時ファイルに保存してServletで出してみる(JFreechart 0.9.16)
JFreeChartでグラフを生成するのは非常に高価である.同じグラフを表示するのであれば,何度もJFreeChartオブジェクトを生成して画像データに変換して出力するということはしたくない.JFreeChartではこういった問題に対処するためのユーティリティクラスなどがあるようなので試してみた.
同じJFreeChartを何度も生成して画像データに変換して出力したくはない場合,画像データを一時ファイルとして保存し,それを出力するという方針が考えられる.JFreeChartで提供されている部品をこの方針にそって(私なりに)解釈すると,以下の三つの機能が含まれていることがわかる.
二つのサーブレットがあり,matsu.sample.TmpFileChartServletはJFreeChartを生成,グラフ画像を一時ファイルとして保存する.org.jfree.chart.servlet.DisplayChartはJFreeChartで用意されているサーブレットで,そのJavaDocにあるとおり,web.xmlを記述するだけで一時画像ファイルを読み出してクライアントに返す.
- 一時ファイルを読み出してクライアントに返す.
- グラフを一時ファイルとして保存する.
- 一時ファイルの管理(アクセス権管理と削除).
DisplayChartはJFreeChartで用意されているサーブレットで,web.xmlを記述だけで一時画像ファイルを読み出してクライアントに返してくれるが,JavaDocには説明がないので,仕様がよくわからない.ソースに目を通した所,大体以下のような機能がある.
- 一時画像ファイルの読みだし
- 読み出す一時画像ファイルは以下で特定される
- request.getParameter("filename")で取得した値を一時ファイルファイル名とする.
- 一時ファイルのあるパスはSystem.getProperty("java.io.tmpdir")で返る文字列(※)であらわされる.
ServletUtilities.sendTempFile(file, response);
- 一時画像ファイルのアクセス権確認
- 一時ファイルにアクセスするには,以下のいずれかを満たす必要がある.
- 同じセッション上で以下の方法で保存した画像である.
ServletUtilities.saveChartAsPNG(chart, width, height, session)
- 一時ファイル名が"public"で始まる.
- 同じセッション上で以下の方法で保存した画像である.
※ 私はDebian GNU/Linux WoodyでTomcat4をapt-getしたのだが,System.getProperty("java.io.tmpdir")の値は
/usr/share/tomcat4/tempで,
# ls -l /usr/share/tomcat4/temp lrwxrwxrwx ...... /usr/share/tomcat4/temp -> /var/cache/tomcat4/_tempだった.
DisplayChartで一時ファイルに保存されたグラフを読み出すには,まずグラフを一時ファイルに保存しておく必要がある.これを行う私が作成したサンプルを以下に示す.
サンプルのサーブレットはリクエスト(GET)のクエリ(任意)にpublicを取る.public=trueなら,一時ファイル名をpublicで始まるものにする.すなわちグラフを作成したセッションとは別のセッションからでも一時ファイル名が分かればDisplayChartで表示されるようになる.サンプルファイルのプレフィクスは以下で設定できる.
ServletUtilities.setTempFilePrefix(prefix);念のためにプレフィクスの取得も.
ServletUtilities.getTempFilePrefix();サンプルはセッション上にグラフの一時ファイル名の文字列がなければ,JFreeChartオブジェクトを生成してグラフ画像を保存し,一時ファイル名をセッションに格納する.
if (savedFileName == null) {
try {
// 棒グラフのJFreeChartを作成
JFreeChart chart = createChart();
... 省略 ...
// グラフをPNG形式でファイル保存
savedFileName = ServletUtilities.saveChartAsPNG(chart, width, height, session);
System.err.println("savedFileName = " + savedFileName);
session.setAttribute(CHART_FILENAME_KEY, savedFileName);
... 省略 ...
} catch (IOException e) {
e.printStackTrace();
}
}
サンプルでは一時ファイルのプレフィクスが切り替わった時には,セッションから一時ファイル名を削除するようにした.
session.removeAttribute(CHART_FILENAME_KEY);
今回のサンプルのポイントはorg.jfree.chart.servlet.ChartDeleterである.これはHttpSessionBindingListenerを実装しており,セッションに登録される際と削除された際にそれぞれ自分自身の持つvalueBound,valueUnboundが呼び出される.valueBoundは何もしない.valueUnboundは自分自身に登録されている一時ファイルを削除する.これを踏まえてServletUtilities.saveChartAsPNGの動きを追ってみる.
- 一時ファイル名を生成
- ChartUtilities.saveChartAsPNGでJFreeChartをPNGとして保存.
- session上にChartDeleterがキー"JFreeChart_Deleter"で登録されていなければ,作成してキー"JFreeChart_Deleter"登録
- chartDeleter.addChartでChartDeleterオブジェクトに先程作成したグラフの一時ファイルを登録(キーはファイル名).
chartDeleter.isChartAvailable(filename)でチェックしている.これにより同じセッション上で
ServletUtilities.saveChartAsPNG(chart, width, height, session)で保存した画像かどうかを確認している.
サンプルのソースを置いておく.これ.JFreeChartとJCommonのjarファイルを展開したディレクトリの下のlibの下に置いて
ant warなどとすれば作成できる.で,このサンプルはシステムプロパティやファイル作成などを行うので,セキュリティ関連の設定が必要である.catalina.policyで以下を追記した.
grant codeBase "file:/home/tomcat/webapps/tmp_file_servlet/WEB-INF/lib/-" {
permission java.util.PropertyPermission "java.io.tmpdir", "read";
permission java.io.FilePermission "/usr/share/tomcat4/temp", "read,write";
permission java.io.FilePermission "/usr/share/tomcat4/temp/*", "read,write,del
ete";
};
※ Debian GNU/Linux WoodyでTomcat4をapt-get installしたら,/etc/tomcat/catalina.policyは読み込み専用になっていて,/etc/policy.d/に4つに分解されていた.
$ ls /etc/tomcat4/policy.d/ 01system.policy 02debian.policy 03catalina.policy 04webapps.policyので,/etc/tomcat/catalina.policyではなく,/etc/policy.d/下のファイルを編集する必要がある./etc/init.d/tomcat4 startを実行すると,/etc/policy.d/下のファイルは以下で一つに結合される.
cat /etc/tomcat4/policy.d/*.policy >/var/lib/tomcat4/catalina.policy今回のサンプルで私が実際に編集したのは
/etc/tomcat4/policy.d/04webapps.policyである.

