ICEfacesを使うと、CSVを出力するのにストリームは使えないのかな?getWrite()は既に呼ばれています、というExceptionが出てしまう。
ゆっくり調べている時間もなく、とにかくCSVで出せればいいから、とのことだったので、一旦サーバ上にCSVファイルとして作成し、それに動的にリンクを貼ってダウンロードする方法にしてみた。
何となく動いたので、とりあえず動くものをメモメモ。まだファイル名が動的ではないけど、その辺はすぐに改修できるので(笑)
まずはJSP側でCSV作成ボタンを用意。せっかくICEfacesを使っているので、ボタンをクリックしたら「しばらくお待ちください」と表示させ、CSVファイルが準備できたらダウンロードを促すメッセージとリンクを表示するようにしてみる。
<ice:outputConnectionStatus
activeLabel="CSVファイルを準備しています。しばらくお待ちください。"
rendered="#{!page$Test.isDownloadReady}"/>
<ice:outputText value="CSVファイルの準備ができました。"
rendered="#{page$Test.isDownloadReady}"/>
<br />
<ice:outputText
value="下のリンクを右クリックしてファイルに保存してください。"
rendered="#{page$Test.isDownloadReady}"/>
<br />
<br />
<ice:commandButton id="csvout1"
action="#{page$Test.btnCsvOut}"
value="CSVファイル出力"
rendered="#{!page$Test.isDownloadReady}"/>
<ice:outputLink value="#{page$Test.downloadPath}"
rendered="#{page$Test.isDownloadReady}">
<ice:outputText value="CSVファイルをダウンロードする"
rendered="#{page$Test.isDownloadReady}"/>
</ice:outputLink><br />
ManagedBean側は、以下のメソッドを用意してみる。
private static final String LOCAL_PATH =
"../applications/j2ee-apps/Test-ear/Test-war_war";
private static final String FILE_NAME = "/page/csv_test.csv";
private boolean isDownloadReady = false;
private String downloadPath = "";
public boolean getIsDownloadReady() {
return this.isDownloadReady;
}
public String getDownloadPath() {
return this.downloadPath;
}
public void btnCsvOut() {
FacesContext fcon = FacesContext.getCurrentInstance();
ExternalContext excon = fcon.getExternalContext();
try {
List<Map> mapList = new ArrayList<Map>();
Map m = new HashMap();
m.put("AAA", "あいうえお");
m.put("BBB", "かきくけこ");
m.put("CCC", "さしすせそ");
mapList.add(m);
InputStream stream = excon.getResourceAsStream(
"/WEB-INF/reports/Test.jasper");
JRDataSource ds = new JRBeanArrayDataSource(mapList.toArray());
JasperPrint jasperPrint =
JasperFillManager.fillReport(stream, null, ds);
JRExporter exporter = new JRCsvExporter();
exporter.setParameter(
JRExporterParameter.CHARACTER_ENCODING,
"Windows-31J");
exporter.setParameter(
JRExporterParameter.JASPER_PRINT,
jasperPrint);
exporter.setParameter(
JRExporterParameter.OUTPUT_FILE_NAME,
LOCAL_PATH + FILE_NAME);
exporter.exportReport();
} catch (Exception e) {
throw new FacesException(e);
}
this.downloadPath = excon.getRequestContextPath() + FILE_NAME;
isDownloadReady = true;
}
お粗末だけど、とりあえず機能としてはこれでよさそう。
ちなみに、LOCAL_PATH が変な指定になっているけど、これはなぜかカレントフォルダが glassfish\domain\domain1\config になってしまっていたので、そこからの相対パスでデプロイされたフォルダの中のCSVファイル仮置き場を指定しています。
なんでconfigフォルダなんだろう…そこまで調べている時間もないので、そういうものと割り切って、とりあえず汎用性のない作りで(笑)
時間が無いと言いつつ、これを書いてるのは…そう、いつかまたこういった処理を使うことがあるかもしれないから。たぶんきっと…。
コメント