0

BIRTによって生成されたレポートファイルを提供するユーティリティを呼び出すWicketLink内のどこかで、IllegalStateExceptionが発生しています。

Wicketページから:

Link<Void> downloadLink = new Link<Void>("download") {
    private static final long serialVersionUID = 1L;

    @Override
    public void onClick() {

        HttpServletResponse response =
                (HttpServletResponse)((WebResponse)getResponse()).getContainerResponse();
        ReportUtility.getInstance().serveFile("myFileName.rptdesign", "pdf", response, null);

    }

};
add (downloadLink);

ReportUtility.javaから:

public void serveFile(String reportDesignFile, String extType,
        HttpServletResponse response, Map<String, Object> paramMap) {

    InputStream is = null;
    ServletOutputStream os = null;
    try {
        is = ReportUtility.class.getResourceAsStream(reportDesignFile);
        os = response.getOutputStream();

        IReportRunnable irr = engine.openReportDesign(is);
        IRunAndRenderTask task = engine.createRunAndRenderTask(irr);

        HTMLRenderOption options = new HTMLRenderOption();
        options.setOutputFormat(extType);
        options.closeOutputStreamOnExit(true);
        options.setOutputStream(os);

        // to force open/save/cancel with our specified filename
        String outputFileName = createReportFileName(reportDesignFile, extType);
        response.addHeader("Content-Disposition", "attachment;filename=" + outputFileName);

        if (paramMap != null) {
            task.setParameterValues(paramMap);
        }
        task.setRenderOption(options);      
        task.run();

    }
    catch (EngineException ex) {
        logger.error("Engine Exception while serving file", ex);
        throw new RuntimeException(ex);
    }
    catch (IOException ioex) {
        logger.error("IO Exception while openning response output stream", ioex);
        throw new RuntimeException(ioex);
    }

    finally {
        try {
            if (os != null)
                os.close();
            if (is != null)
                is.close();
        } catch (IOException e) {
            // ignore
        }
    }
}

重要な場合、createReportFileNameメソッドは、今日の日付と適切なファイル拡張子をレポートデザインファイルのベース名に追加します。つまり、「myFileName.rptdesign」は「myFileName_04_24_2012.pdf」になります。

statckトレースは次のとおりです。

Apr 24, 2012 9:35:04 AM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet default threw exception
    java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:435)
at org.apache.wicket.protocol.http.servlet.ServletWebResponse.sendRedirect(ServletWebResponse.java:230)
at org.apache.wicket.protocol.http.BufferedWebResponse$SendRedirectAction.invoke(BufferedWebResponse.java:392)
at org.apache.wicket.protocol.http.BufferedWebResponse.writeTo(BufferedWebResponse.java:580)
at org.apache.wicket.protocol.http.HeaderBufferingWebResponse.flush(HeaderBufferingWebResponse.java:89)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:195)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:241)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)

これは操作に影響を与えないことを述べることが重要です。ユーザーがクリックすると、開く/保存/キャンセルが表示され、ファイルが表示され、非常にきれいに見えます。ただし、ワード後、ユーザーが次に何をしようとしても、StalePageExceptionを使用してエラーページに送信します。その後、すべてが再び正常に戻ります。

これにはHttpServletResponseが関係しているのではないか、あるいはWicketから取得する方法が関係しているのではないかと思います。ただし、ヘッダー付きの応答にファイルを追加するコードのその部分は、BIRTのチュートリアルからほぼ正確にコピーされます。(たぶん、BIRTとWicketはお互いが好きではありません。)

私自身のコードはどれもスタックトレースに表示されないことに注意してください。また、onClick、serveFile、さらにはWicketアプリケーションなど、いくつかの場所でIllegalStateExceptionを「キャッチ」しようとしましたが、すべて成功しませんでした。もちろん、捕まえられたとしても、そもそも引き起こしたことがない方がいいと思います。

4

1 に答える 1

0

レポートを配信するためのより良い方法は、独自のResourceStreamを実装することです(...implements IResourceStream)。ユーザーがクリックすると、実装は生成されたレポートを返します。

レポートをクライアントにストリーミングする改札リンクを追加する方法の例を次に示します。

add(new Link("reportAsPdfButton") {
    @Override
    public void onClick() {
        BirtReportResourceStream brrs = new BirtReportResourceStream();
        getRequestCycle().scheduleRequestHandlerAfterCurrent(new ResourceStreamRequestHandler(brrs, "your_report_name.pdf"));
    }
});

IResourceStreamを実装するためのホットな短いサンプルを次に示します。

public class BirtReportResourceStream implements IResourceStream {
    private byte[] content = null;

    ...

    public BirtReportResourceStream() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        EngineConfig config = new EngineConfig();
        config.setEngineHome(basePath + "/WEB-INF/ext_lib/");

        try {
            Platform.startup(config);
            IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
            IReportEngine engine = factory.createReportEngine(config);
            IReportRunnable report = engine.openReportDesign("path/to/your/report-definiton.rpt");
            IRunAndRenderTask task = engine.createRunAndRenderTask(report);

            if (null != getParameter()) {
                task.setParameterValues(getParameter());
            }  

            PDFRenderOption options = new PDFRenderOption();
            options.setOutputFormat(format.toString().toLowerCase());
            options.setOutputStream(baos);
            task.setRenderOption(options);
            task.run();
            task.close();
        } catch (BirtException e) {
            // handle the exception...
        }

        content = baos.toByteArray();
    }

    public InputStream getInputStream() throws ResourceStreamNotFoundException {
        return new ByteArrayInputStream(content);
    }

    ...
}

実装するメソッドは他にもいくつかありますが、それらは単純です。最も複雑な部分は、レポートを作成してバイト配列にストリーミングする方法と、レポートをクライアントにストリーミングする方法を見つけることでした。これらの2つの方法は上に示されています。

それが役に立てば幸い。

于 2012-04-24T14:46:37.453 に答える