You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by "Peter Ertl (JIRA)" <ji...@apache.org> on 2007/09/13 16:37:33 UTC
[jira] Updated: (WICKET-964) provide direct access on output stream
in resources
[ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Peter Ertl updated WICKET-964:
------------------------------
Summary: provide direct access on output stream in resources (was: enable direct access to output stream in resources)
> 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
> 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.