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:56:32 UTC

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

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


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.


[jira] Updated: (WICKET-964) provide direct access on output stream in resources

Posted by "Peter Ertl (JIRA)" <ji...@apache.org>.
     [ 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.


[jira] Commented: (WICKET-964) provide direct access on output stream in resources

Posted by "Peter Ertl (JIRA)" <ji...@apache.org>.
    [ 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.


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

Posted by "Peter Ertl (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

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

    Attachment: resource.patch

Johan,

this patch is based on your comment at 12/Sep/07.

Maybe you like it :-)

> 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: 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.


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

Posted by "Peter Ertl (JIRA)" <ji...@apache.org>.
     [ 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.


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

Posted by "Peter Ertl (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12527114 ] 

Peter Ertl commented on WICKET-964:
-----------------------------------

+1 for -- IResourceStreamWriter extends IResourceStream --

would be awesome to get that functionality, can't wait to get it :-)

> 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: 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.


[jira] Closed: (WICKET-964) provide direct access on output stream in resources

Posted by "Johan Compagner (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Johan Compagner closed WICKET-964.
----------------------------------

       Resolution: Fixed
    Fix Version/s: 1.3.0-beta4

applied the patch.
Not everything in wicket (like thumbnail generated) will work right when using IResourceStreamWriter instead of IResourceStream.. 

> 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.


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

Posted by "Peter Ertl (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12527064 ] 

Peter Ertl commented on WICKET-964:
-----------------------------------

Johan,

you are absolutely right and I don't like InputStream being null either.

I think the best design decision would be to not use an InputStream for generating resource data

   InputStream getInputStream() throws ResourceStreamNotFoundException 

but instead something like

  ResourceData getResourceData() throws ResourceStreamNotFoundException 

// suggestion //

public interface ResourceData extends IClusterable
{
  write(OutputStream);
}

public class InputStreamResourceData implements ResourceData
{
  private final InputStream input;

  public class InputStreamResourceData(InputStream input)
  {
    this.input = input:
  }
  
  public void write(OutputStream output) 
  {
     Streams.copy(this.input, output);
  }
}

ResourceData would care about putting the data into the response stream, whereever it comes from (input stream, byte array, builder, database result set, ...(

ResourceStreamRequestTarget would need only little change to make this work.

However changing that one interface method will cause quite some changes of code that depend on this method. Maybe you guys think of a better solution that is more backward compatible.

However *imho* it's quite essential being able to access the response stream directly to produce unbuffered response data because:

- when resource data is really, really large (like 10-100 MB) memory could exhaust easily
- the overall memory requirements of the server could be lowered significantly
- zillions of clients access your resources and again memory could exhaust just to easy
- it's faster!


> 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.


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

Posted by "Johan Compagner (JIRA)" <ji...@apache.org>.
    [ 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.


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

Posted by "Johan Compagner (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12527088 ] 

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

yes thats much better, doesn't break anything and is a nice addition to the api/functionality
except that i think i let this: IResourceWriter extends IClusterable
be this: IResourceStreamWriter extends IResourceStream 
because else IResourceWriter is such a lonely interface that has no relation to what it really does and where it really belongs to
Also a IResourceWriter has to be a IResourceStream anyway..

now i only need to check our code base if we call IResourceStream.getInputStream() on other places to also make sure that we now
support null of it and/or that it handles it as a IResourceStreamWriter


> 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: 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.


[jira] Updated: (WICKET-964) enable direct access to output stream in resources

Posted by "Peter Ertl (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

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

    Summary: enable direct access to output stream in resources  (was: enhance remove 'final' keyword from org.apache.wicket.Resource to support builder style content generation)

> enable direct access to 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.


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

Posted by "Johan Compagner (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/WICKET-964?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Johan Compagner reassigned WICKET-964:
--------------------------------------

    Assignee: Johan Compagner

> 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.