[Java] ICEfacesでCSV出力

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フォルダなんだろう…そこまで調べている時間もないので、そういうものと割り切って、とりあえず汎用性のない作りで(笑)

時間が無いと言いつつ、これを書いてるのは…そう、いつかまたこういった処理を使うことがあるかもしれないから。たぶんきっと…。

コメント

タイトルとURLをコピーしました