Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraphicImageManager leaking files of 0 bytes on page refresh #2

Open
99sono opened this issue Jun 1, 2015 · 2 comments
Open

GraphicImageManager leaking files of 0 bytes on page refresh #2

99sono opened this issue Jun 1, 2015 · 2 comments

Comments

@99sono
Copy link

99sono commented Jun 1, 2015

The GraphicImageManager leaks files upon refresh of a page with <p:graphicImage>.

Essentially the problem seems to be that on the first page rendering, where the functionality works properly, the StreamContent of the view access scoped bean gets closed and its contets saved on a temp file.

On a susequent request to the page (e.g. refresh of the labrador page) the the uniqueId of the page stay the same and the code would just ask for the operating system to go ahead and create a new temp file. The new temp file would be a leakage since it corresponded to an already existing unique id and in addition it would be empty because the original StreamedContent input stream had already been closed on the first rendereing.

I refactored the register method to be as follows:

/** \* During the rendering phase of p:graphic image for which the avanced graphic image feature is enabled the \* StreamedContent gets writtent to a temporary file in the OS tmp file folder. Finally, the uniqueId will be used \* to do a lookup of path to the temporary file to render the iamge requested. * \* @param content \* the primefaces streamed content for an image which should be written out to an OS temporary file. \* @param uniqueId \* a unique id for the current user session and image access, used to create a new unique temp file * */ public void registerImage(StreamedContent content, String uniqueId) {
    // (1) Trivial scenario - there is nothing to be done here because
    // the user is most likely doing a page refresh and the image already exists in a temp file location
    if (storedContent.containsKey(uniqueId)) {
        LOGGER.log(Level.FINEST,
                "The streamed content for uniqueId will not be saved to a new file since it already exists in the cache. UiqueId: "
                        + uniqueId);
        return;
    }

    // (2) The uniqueId is brand new one so the streamed cotent streamed has not yet been closed
    // and we can save the data to a temporary file.
    ReadableByteChannel inputChannel = null;
    WritableByteChannel outputChannel = null;
    try {
        File tempFile = File.createTempFile(uniqueId, "primefaces");
        storedContent.put(uniqueId, tempFile.getAbsolutePath());
        // get a channel from the stream
        inputChannel = Channels.newChannel(content.getStream());
        outputChannel = Channels.newChannel(new FileOutputStream(tempFile));
        // copy the channels
        fastChannelCopy(inputChannel, outputChannel);
    } catch (IOException e) {
        LOGGER.log(
                Level.SEVERE,
                "Unexpected error took place while attempting to save primefaces streamed content image to the temporary fold",
                e);
    } finally {
        // closing the channels
        try {
            if (inputChannel != null) {
                inputChannel.close();
            }
        } catch (Exception e) {
            LOGGER.log(
                    Level.SEVERE,
                    "Unexpected error took place while attempting to close the input stream of the image to be saved into a temporary location",
                    e);
        }
        try {
            if (outputChannel != null) {
                outputChannel.close();
            }
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE,
                    "Unexpected error took place while attempting to close the output stream of the temp file", e);
        }
    }
}

Thanks

@rdebusscher
Copy link
Owner

I can't see how this method can be called more then once with the same uniqueId parameter value.

Since this value is made unique by the call to the method org.primefaces.component.graphicimage.GraphicImageRenderer#createUniqueContentId which generates this uniqueId.

@rdebusscher
Copy link
Owner

As mentioned in issue #4, there is an issue with ViewScoped beans and refreshing the page with AJAX.

When uniqueId generation is only based on clientId and expressionString, the registerImage can be called with the same uniqueId multiple times.

In that case, the check must be performed.

rdebusscher pushed a commit that referenced this issue Jun 27, 2015
…s issue with ViewScoped bean and AJAX update.) solves #2 and #4.
@rdebusscher rdebusscher mentioned this issue Jun 27, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants