StreamingResolution, temporary files, and Exceptions

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

StreamingResolution, temporary files, and Exceptions

krick
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users
Reply | Threaded
Open this post in threaded view
|

Re: StreamingResolution, temporary files, and Exceptions

Matthijs Laan

The most obvious way would be to call this.setFilename("export.csv") after your call to getCsvData().

Matthijs

On 2014-06-23 23:33, William Krick wrote:
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?




------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft


_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users


------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users
Reply | Threaded
Open this post in threaded view
|

Re: StreamingResolution, temporary files, and Exceptions

Ben Gunter
In reply to this post by krick
Yes, sort of a hybrid of your two approaches.

    public Resolution exportCsv() throws IOException {
        final File tempFile[] = { null };
        final InputStream is;
        try {
            tempFile[0] = File.createTempFile(UUID.randomUUID().toString(), null);
            getCsvData(tempFile[0]);
            is = new FileInputStream(tempFile[0]);
        } catch (IOException e) {
            logger.error("Unable to export to csv file: " + e);
            throw new IOException();
        } finally {
            FileUtils.deleteQuietly(tempFile[0]);
        }

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        }.setFilename("export.csv");
    }



On Mon, Jun 23, 2014 at 5:33 PM, William Krick <[hidden email]> wrote:
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users
Reply | Threaded
Open this post in threaded view
|

Re: StreamingResolution, temporary files, and Exceptions

krick
Sorry to dig up an old thread but I was working on another project for a while and now I'm coming back to the original project and the StreamingResolution issue.

The hybrid solution posted by Ben Gunter seems to work well.  Thank you.

I have two questions/concerns.

1) I see why tempFile needs to be declared final (to access it inside of the StreamingResolution), and I also see why it needs to be an array where we reference item 0 (to get around it being final for the method that populates the temp file and creates the InputStream), but it really looks and feels like a hack.  Isn't there a better way to do this that isn't so hacky?

2) I'm doing this same thing (populating a temp file, streaming it to the user, deleting the temp file) in a lot of places in a multi-page web application.  Is there a clean way to encapsulate these 20-something lines of code into a class so that I'm not copy/pasting boilerplate code over and over again?

Thanks


On Tue, Jun 24, 2014 at 8:25 AM, Ben Gunter <[hidden email]> wrote:
Yes, sort of a hybrid of your two approaches.

    public Resolution exportCsv() throws IOException {
        final File tempFile[] = { null };
        final InputStream is;
        try {
            tempFile[0] = File.createTempFile(UUID.randomUUID().toString(), null);
            getCsvData(tempFile[0]);
            is = new FileInputStream(tempFile[0]);
        } catch (IOException e) {
            logger.error("Unable to export to csv file: " + e);
            throw new IOException();
        } finally {
            FileUtils.deleteQuietly(tempFile[0]);
        }

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        }.setFilename("export.csv");
    }



On Mon, Jun 23, 2014 at 5:33 PM, William Krick <[hidden email]> wrote:
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users
Reply | Threaded
Open this post in threaded view
|

Re: StreamingResolution, temporary files, and Exceptions

Nestor Hernandez

Well, I think that that could be much better like this. Just write to the response outpustream.

return new StreamingResolution() {
    public void stream(request, response){
         getExportCsv(response.getOutputstream());
    }
}

El 9/7/2015 17:48, "William Krick" <[hidden email]> escribió:
Sorry to dig up an old thread but I was working on another project for a while and now I'm coming back to the original project and the StreamingResolution issue.

The hybrid solution posted by Ben Gunter seems to work well.  Thank you.

I have two questions/concerns.

1) I see why tempFile needs to be declared final (to access it inside of the StreamingResolution), and I also see why it needs to be an array where we reference item 0 (to get around it being final for the method that populates the temp file and creates the InputStream), but it really looks and feels like a hack.  Isn't there a better way to do this that isn't so hacky?

2) I'm doing this same thing (populating a temp file, streaming it to the user, deleting the temp file) in a lot of places in a multi-page web application.  Is there a clean way to encapsulate these 20-something lines of code into a class so that I'm not copy/pasting boilerplate code over and over again?

Thanks


On Tue, Jun 24, 2014 at 8:25 AM, Ben Gunter <[hidden email]> wrote:
Yes, sort of a hybrid of your two approaches.

    public Resolution exportCsv() throws IOException {
        final File tempFile[] = { null };
        final InputStream is;
        try {
            tempFile[0] = File.createTempFile(UUID.randomUUID().toString(), null);
            getCsvData(tempFile[0]);
            is = new FileInputStream(tempFile[0]);
        } catch (IOException e) {
            logger.error("Unable to export to csv file: " + e);
            throw new IOException();
        } finally {
            FileUtils.deleteQuietly(tempFile[0]);
        }

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        }.setFilename("export.csv");
    }



On Mon, Jun 23, 2014 at 5:33 PM, William Krick <[hidden email]> wrote:
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users
Reply | Threaded
Open this post in threaded view
|

Re: StreamingResolution, temporary files, and Exceptions

Nestor Hernandez

Your method getExportCsv could be like this:

getExportCsv (outpustream){
   //Write to the outpustream
}

And there is no need of temp files !
Cheers

El 9/7/2015 18:07, "Nestor Hernandez" <[hidden email]> escribió:

Well, I think that that could be much better like this. Just write to the response outpustream.

return new StreamingResolution() {
    public void stream(request, response){
         getExportCsv(response.getOutputstream());
    }
}

El 9/7/2015 17:48, "William Krick" <[hidden email]> escribió:
Sorry to dig up an old thread but I was working on another project for a while and now I'm coming back to the original project and the StreamingResolution issue.

The hybrid solution posted by Ben Gunter seems to work well.  Thank you.

I have two questions/concerns.

1) I see why tempFile needs to be declared final (to access it inside of the StreamingResolution), and I also see why it needs to be an array where we reference item 0 (to get around it being final for the method that populates the temp file and creates the InputStream), but it really looks and feels like a hack.  Isn't there a better way to do this that isn't so hacky?

2) I'm doing this same thing (populating a temp file, streaming it to the user, deleting the temp file) in a lot of places in a multi-page web application.  Is there a clean way to encapsulate these 20-something lines of code into a class so that I'm not copy/pasting boilerplate code over and over again?

Thanks


On Tue, Jun 24, 2014 at 8:25 AM, Ben Gunter <[hidden email]> wrote:
Yes, sort of a hybrid of your two approaches.

    public Resolution exportCsv() throws IOException {
        final File tempFile[] = { null };
        final InputStream is;
        try {
            tempFile[0] = File.createTempFile(UUID.randomUUID().toString(), null);
            getCsvData(tempFile[0]);
            is = new FileInputStream(tempFile[0]);
        } catch (IOException e) {
            logger.error("Unable to export to csv file: " + e);
            throw new IOException();
        } finally {
            FileUtils.deleteQuietly(tempFile[0]);
        }

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        }.setFilename("export.csv");
    }



On Mon, Jun 23, 2014 at 5:33 PM, William Krick <[hidden email]> wrote:
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users
Reply | Threaded
Open this post in threaded view
|

Re: StreamingResolution, temporary files, and Exceptions

Rick Grashel
I could be wrong, but it sounded to me like he was generating the CSV file on the filesystem based on user-input.  So it could be a file being created out of the database.  If the CSV file can be very large, he definitely should keep it on the file system and use buffered streams to send it back to the client.  Otherwise, he stands to consume a lot of memory on the server which is bad.

It's very easy to delete the temporary file in a finally block with a high confidence that the deletion won't fail.

-- Rick


On Thu, Jul 9, 2015 at 6:27 PM, Nestor Hernandez <[hidden email]> wrote:

Your method getExportCsv could be like this:

getExportCsv (outpustream){
   //Write to the outpustream
}

And there is no need of temp files !
Cheers

El 9/7/2015 18:07, "Nestor Hernandez" <[hidden email]> escribió:

Well, I think that that could be much better like this. Just write to the response outpustream.

return new StreamingResolution() {
    public void stream(request, response){
         getExportCsv(response.getOutputstream());
    }
}

El 9/7/2015 17:48, "William Krick" <[hidden email]> escribió:
Sorry to dig up an old thread but I was working on another project for a while and now I'm coming back to the original project and the StreamingResolution issue.

The hybrid solution posted by Ben Gunter seems to work well.  Thank you.

I have two questions/concerns.

1) I see why tempFile needs to be declared final (to access it inside of the StreamingResolution), and I also see why it needs to be an array where we reference item 0 (to get around it being final for the method that populates the temp file and creates the InputStream), but it really looks and feels like a hack.  Isn't there a better way to do this that isn't so hacky?

2) I'm doing this same thing (populating a temp file, streaming it to the user, deleting the temp file) in a lot of places in a multi-page web application.  Is there a clean way to encapsulate these 20-something lines of code into a class so that I'm not copy/pasting boilerplate code over and over again?

Thanks


On Tue, Jun 24, 2014 at 8:25 AM, Ben Gunter <[hidden email]> wrote:
Yes, sort of a hybrid of your two approaches.

    public Resolution exportCsv() throws IOException {
        final File tempFile[] = { null };
        final InputStream is;
        try {
            tempFile[0] = File.createTempFile(UUID.randomUUID().toString(), null);
            getCsvData(tempFile[0]);
            is = new FileInputStream(tempFile[0]);
        } catch (IOException e) {
            logger.error("Unable to export to csv file: " + e);
            throw new IOException();
        } finally {
            FileUtils.deleteQuietly(tempFile[0]);
        }

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        }.setFilename("export.csv");
    }



On Mon, Jun 23, 2014 at 5:33 PM, William Krick <[hidden email]> wrote:
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users
Reply | Threaded
Open this post in threaded view
|

Re: StreamingResolution, temporary files, and Exceptions

Nestor Hernandez

In any case the solution I posted works

1. Existing file

getExportCsv(outpustream) {
File file =  ...
Inputstream in = null;
try{
in = new FileInpustream(file);
IOUtils.copy(in, outpustream)
} finally{
  IOUtils.closeQuietly(in);
}
}

2. Just write to the outpustream

El 9/7/2015 18:34, "Rick Grashel" <[hidden email]> escribió:
I could be wrong, but it sounded to me like he was generating the CSV file on the filesystem based on user-input.  So it could be a file being created out of the database.  If the CSV file can be very large, he definitely should keep it on the file system and use buffered streams to send it back to the client.  Otherwise, he stands to consume a lot of memory on the server which is bad.

It's very easy to delete the temporary file in a finally block with a high confidence that the deletion won't fail.

-- Rick


On Thu, Jul 9, 2015 at 6:27 PM, Nestor Hernandez <[hidden email]> wrote:

Your method getExportCsv could be like this:

getExportCsv (outpustream){
   //Write to the outpustream
}

And there is no need of temp files !
Cheers

El 9/7/2015 18:07, "Nestor Hernandez" <[hidden email]> escribió:

Well, I think that that could be much better like this. Just write to the response outpustream.

return new StreamingResolution() {
    public void stream(request, response){
         getExportCsv(response.getOutputstream());
    }
}

El 9/7/2015 17:48, "William Krick" <[hidden email]> escribió:
Sorry to dig up an old thread but I was working on another project for a while and now I'm coming back to the original project and the StreamingResolution issue.

The hybrid solution posted by Ben Gunter seems to work well.  Thank you.

I have two questions/concerns.

1) I see why tempFile needs to be declared final (to access it inside of the StreamingResolution), and I also see why it needs to be an array where we reference item 0 (to get around it being final for the method that populates the temp file and creates the InputStream), but it really looks and feels like a hack.  Isn't there a better way to do this that isn't so hacky?

2) I'm doing this same thing (populating a temp file, streaming it to the user, deleting the temp file) in a lot of places in a multi-page web application.  Is there a clean way to encapsulate these 20-something lines of code into a class so that I'm not copy/pasting boilerplate code over and over again?

Thanks


On Tue, Jun 24, 2014 at 8:25 AM, Ben Gunter <[hidden email]> wrote:
Yes, sort of a hybrid of your two approaches.

    public Resolution exportCsv() throws IOException {
        final File tempFile[] = { null };
        final InputStream is;
        try {
            tempFile[0] = File.createTempFile(UUID.randomUUID().toString(), null);
            getCsvData(tempFile[0]);
            is = new FileInputStream(tempFile[0]);
        } catch (IOException e) {
            logger.error("Unable to export to csv file: " + e);
            throw new IOException();
        } finally {
            FileUtils.deleteQuietly(tempFile[0]);
        }

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        }.setFilename("export.csv");
    }



On Mon, Jun 23, 2014 at 5:33 PM, William Krick <[hidden email]> wrote:
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users
Reply | Threaded
Open this post in threaded view
|

Re: StreamingResolution, temporary files, and Exceptions

krick
I noticed something odd.  I'm not sure if it's a bug or user error.

When I set the filename OUTSIDE, it works as expected...

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        }.setFilename("export.csv");


But if I set the filename INSIDE like this, the ".csv" gets cut off the end of the filename on the download...

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
            this.setFilename("export.csv");
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        };



On Thu, Jul 9, 2015 at 7:50 PM, Nestor Hernandez <[hidden email]> wrote:

In any case the solution I posted works

1. Existing file

getExportCsv(outpustream) {
File file =  ...
Inputstream in = null;
try{
in = new FileInpustream(file);
IOUtils.copy(in, outpustream)
} finally{
  IOUtils.closeQuietly(in);
}
}

2. Just write to the outpustream

El 9/7/2015 18:34, "Rick Grashel" <[hidden email]> escribió:
I could be wrong, but it sounded to me like he was generating the CSV file on the filesystem based on user-input.  So it could be a file being created out of the database.  If the CSV file can be very large, he definitely should keep it on the file system and use buffered streams to send it back to the client.  Otherwise, he stands to consume a lot of memory on the server which is bad.

It's very easy to delete the temporary file in a finally block with a high confidence that the deletion won't fail.

-- Rick


On Thu, Jul 9, 2015 at 6:27 PM, Nestor Hernandez <[hidden email]> wrote:

Your method getExportCsv could be like this:

getExportCsv (outpustream){
   //Write to the outpustream
}

And there is no need of temp files !
Cheers

El 9/7/2015 18:07, "Nestor Hernandez" <[hidden email]> escribió:

Well, I think that that could be much better like this. Just write to the response outpustream.

return new StreamingResolution() {
    public void stream(request, response){
         getExportCsv(response.getOutputstream());
    }
}

El 9/7/2015 17:48, "William Krick" <[hidden email]> escribió:
Sorry to dig up an old thread but I was working on another project for a while and now I'm coming back to the original project and the StreamingResolution issue.

The hybrid solution posted by Ben Gunter seems to work well.  Thank you.

I have two questions/concerns.

1) I see why tempFile needs to be declared final (to access it inside of the StreamingResolution), and I also see why it needs to be an array where we reference item 0 (to get around it being final for the method that populates the temp file and creates the InputStream), but it really looks and feels like a hack.  Isn't there a better way to do this that isn't so hacky?

2) I'm doing this same thing (populating a temp file, streaming it to the user, deleting the temp file) in a lot of places in a multi-page web application.  Is there a clean way to encapsulate these 20-something lines of code into a class so that I'm not copy/pasting boilerplate code over and over again?

Thanks


On Tue, Jun 24, 2014 at 8:25 AM, Ben Gunter <[hidden email]> wrote:
Yes, sort of a hybrid of your two approaches.

    public Resolution exportCsv() throws IOException {
        final File tempFile[] = { null };
        final InputStream is;
        try {
            tempFile[0] = File.createTempFile(UUID.randomUUID().toString(), null);
            getCsvData(tempFile[0]);
            is = new FileInputStream(tempFile[0]);
        } catch (IOException e) {
            logger.error("Unable to export to csv file: " + e);
            throw new IOException();
        } finally {
            FileUtils.deleteQuietly(tempFile[0]);
        }

        return new StreamingResolution(Constants.CONTENT_TYPE_CSV, is) {
            public void stream(HttpServletResponse response) throws Exception {
                try {
                    super.stream(response);
                } finally {
                    FileUtils.deleteQuietly(tempFile[0]);
                }
            }
        }.setFilename("export.csv");
    }



On Mon, Jun 23, 2014 at 5:33 PM, William Krick <[hidden email]> wrote:
In my web application, I have code that generates a temporary file (based on user input) and streams it back to the user using a StreamingResolution.

The initial implementation had a utility method that generated the file and passed back an InputStream...

public Resolution exportCsv() throws IOException {
  InputStream is = getCsvData();
  StreamingResolution sr = new StreamingResolution(Constants.CONTENT_TYPE_CSV, is);
  sr.setFilename("export.csv");
  return sr;
}

However, I want to be able to clean up the temporary file after it has been streamed to the user.
I thought that I could use the anonymous inner class method described in the stripes javadocs...

public Resolution exportCsv() throws IOException {
  return new StreamingResolution(Constants.CONTENT_TYPE_CSV) {
    public void stream(HttpServletResponse response) throws Exception {
      File tempFile = null;
      InputStream is = null;
      try {
        tempFile = File.createTempFile(UUID.randomUUID().toString(), null);
        getCsvData(tempFile);
        is = new FileInputStream(tempFile);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
      }
      catch(IOException e) {
        logger.error("Unable to export to csv file: " + e);
        throw new IOException();
      }
      finally {
        IOUtils.closeQuietly(is);
        FileUtils.deleteQuietly(tempFile);
      }
    }
  }.setFilename("export.csv");
}


I'm finding that if there's an exception, whatever error page my application generates gets streamed back to the user in a file called "export.csv".  So this method isn't really viable, at least the way I'm using it.

Is there a pattern for this sort of thing in Stripes?



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users



------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Stripes-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/stripes-users