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/12 22:58:32 UTC

[jira] Updated: (WICKET-964) enhance remove 'final' keyword from org.apache.wicket.Resource to support builder style content generation

     [ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Peter Ertl updated WICKET-964:
------------------------------

    Attachment: ResponseWriterResource.java

> enhance remove 'final' keyword from org.apache.wicket.Resource to support builder style content generation
> ----------------------------------------------------------------------------------------------------------
>
>                 Key: WICKET-964
>                 URL: https://issues.apache.org/jira/browse/WICKET-964
>             Project: Wicket
>          Issue Type: Improvement
>          Components: wicket
>            Reporter: Peter Ertl
>         Attachments: 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.