[
https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12527379
]
Peter Ertl commented on WICKET-964:
-----------------------------------
I did some tests and it works great.
Thanks a lot! :-)
> provide direct access on output stream in resources
> ---------------------------------------------------
>
> Key: WICKET-964
> URL: https://issues.apache.org/jira/browse/WICKET-964
> Project: Wicket
> Issue Type: Improvement
> Components: wicket
> Reporter: Peter Ertl
> Assignee: Johan Compagner
> Fix For: 1.3.0-beta4
>
> Attachments: resource.patch, ResponseWriterResource.java
>
>
> I run into the following problem recently:
> In order to create ad-hoc PDF documents I decided on using the iText library
> (http://www.lowagie.com/iText).
> iText is capable of producing easily a 10000 pages PDF document on the fly
> without getting a scary OutOfMemoryException on the web server. This is
> because it's not buffering the result of creating a PDF but instantly writing
> the PDF data stream _while_ you build your PDF.
> Code looks something like this:
> Document doc = new Document();
> PdfWriter.getInstance(doc, outputStream);
> doc.addAuthor("Mr. Foobar");
> doc.open();
> doc.add(...); // some stuff -> will write directly to stream
> doc.add(...); // even more stuff -> will again write directly to stream
> doc.close();
> Of course I wanted to use org.apache.wicket.Resource to deliver the content
> to the browser in the very wicket way. However, Resource and all it's
> children have one similar problem:
> You need to implement
> IResourceStream getResourceStream()
>
> which in turn demands you to implement
> InputStream getInputStream() throws ResourceStreamNotFoundException
> So, whatever resource you would like to implement, you need an
> java.io.InputStream !
> However, as iText immediately writes to an java.io.OutputStream you would
> have to do one of these to successfully implement a Resource:
> (1) iText -> ByteArrayOutputStream -> byte[] -> ByteArrayInputStream ->
> Resource::getInputStream
> (2) iText -> FileOutputStream -> temp file -> FileInputStream ->
> Resource::getInputStream
> (3) iText -> PipedOutputStream (thread #1) -> PipedInputStream (thread #2)
> -> Resource::getInputStream
> However I don't like any of these (1)-(3) because this requirement is purely
> caused by the current design but technically you could just write direcly to
> the ServletOutputStream
> (4) PdfWriter.getInstance(doc,
> getWebResponse().getOutputStream(outputStream)));
> this would be the best performing and low memory solution, but Resource
> stream will no cooperate and still wants an InputStream.
> I wrote a simple proof-of-concept class called ResponseWriterResource (which
> currently will not work unless the issue gets resolved):
> public abstract class ResponseWriterResource extends Resource
> {
> @Override
> public void onResourceRequested()
> {
> RequestCycle.get().setRequestTarget(new IRequestTarget()
> {
> public void respond(RequestCycle requestCycle)
> {
> write(requestCycle.getResponse());
> }
> public void detach(RequestCycle requestCycle)
> {
> }
> });
> }
> @Override
> public IResourceStream getResourceStream()
> {
> // ignore
> return null;
> }
> protected abstract void write(Response response);
> }
> in the case of creating a pdf the code would look like this:
> Resource resource = new ResponseWriterResource()
> {
> write(Response response)
> {
> Document doc = new Document();
> PdfWriter.getInstance(doc, response.getOutputStream());
> //
> // ... create the pdf here
> // ... (and write it directly! to the servlet output stream)
> }
> }
> So the resource could immediately be rendered to the client without the need
> of buffering the response first.
> There's only one tiny change that I would need inside wicket:
> In order to override
> @Override
> public void onResourceRequested()
> I would need the removal of the final keyword from onResourceRequested()
> class Resource
> {
> // ...
> public final(*) void onResourceRequested() // (*) please remove
> the final keyword
> // ...
> }
> The benefit of this would be that any kind of very large resource could be
> created in the web application without the need of ugly solutions like
> (1)-(3).
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.