You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by "Johan Compagner (JIRA)" <ji...@apache.org> on 2007/09/12 23:59:32 UTC

[jira] Commented: (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:comment-tabpanel#action_12526916 ] 

Johan Compagner commented on WICKET-964:
----------------------------------------

i dont like removing the final keyword from that
and i really don't like being able to return null for the IResourceStream because that is being used on more then once place (lastmodified date)
also support for setting the size and content type where is that happening now?
setting the size is i guess not really doable in your scenario?

i like to have a solution that we can integrate in to IResourceStream somehow
for example have another interface that extends IResourceSTream with the method write(Response)
and that is then tested in the Resource and then write is called instead of getInputStream.

> 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
>            Assignee: Johan Compagner
>         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.