Delayed loading of graphic images from servlet

UI Components for JSF
Post Reply
Edgewise
Posts: 4
Joined: 09 Apr 2013, 00:05

09 Apr 2013, 00:55

Hi all,

My situation is a little unusual; I'll explain and then provide some code. We have an application that has multiple tabbed views of a document, and one of the tabs is meant to display the raw page images (jpg) of that document. In the case of all the tabs, content should be loaded after the document is explicitly loaded from a dropdown list. The problems we're having are with this particular tab.

For these raw page images, we opted to provide them from a servlet instead of as dynamic content. The reason is so we can take advantage of caching. I've tried this with dynamic content, and it was actually even more problematic (using f:param and DefaultStreamedContent). So for that reason and for caching purposes, we changed to this approach.

What we're seeing is strange. Network traffic shows that the images are indeed being loaded. However, the carousel is initially blank and empty. However, upon reloading the page, the carousel and its images now appear. As far as I can tell, I am properly updating components. When I turn off Ajax for the load button, this problem goes away.

However, there is yet another problem, even when the carousel appears. If the carousel tab itself was being displayed when the images are loaded, then its forward and back navigation buttons don't work. The first page shows fine, but clicking on the page link "circles" will only show the second and third page (we're only loading three test pages as of now), and the third slot for a page is completely blank.

I've tested this out simply by putting the graphicImage on its own, outside the carousel. We still encounter the issue that we need to refresh to display the image, even in such cases.

Anyway, here's code for the relevant parts:

Image servlet -

Code: Select all

private Pattern pageUrlPattern = Pattern.compile(".*-(\\d+)\\.jpg$");

@Inject
BackingBean backingBean;

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String requestedUri = request.getRequestURI();
    Matcher pageUrlMatcher = pageUrlPattern.matcher(requestedUri);
        
    if (pageUrlMatcher.find()) {
        // get page image object
        String pageNumberText = pageUrlMatcher.group(1);
        int pageNumber = Integer.parseInt(pageNumberText);
        PageImage pageImage = backingBean.getPageNumberToImage().get(pageNumber);
            
        // set content type
        response.setContentType("image/jpeg");
            
        // stuff page image bits into response
        try (OutputStream outStream = response.getOutputStream(); InputStream inStream = pageImage.getPageStream()) {
            int dataSize = inStream.available();
            byte[] data = new byte [dataSize];
            inStream.read(data);
            outStream.write(data);
        }
    }
}
PageImage.getPageStream() -

Code: Select all

public InputStream getPageStream() {
    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
    ImageIO.write(pageImage, "image/jpeg", byteOut);
    return new ByteArrayInputStream(byteOut.toByteArray());
}
page.xhtml -

Code: Select all


<p:commandButton value="Load" 
                 id="loadSpecificationButton"
                 actionListener="#{backingBean.loadSelectedSpecification()}" 
                 update=":form:documentTabView:rawDocumentScrollPanel :form:documentTabView:rawPageImageCarousel :form:documentTabView:rawPageImageMissingMessage :form:documentTabView:pageImageTab  :form:documentTabView:rawPageImageCarousel:pageImageDisplay"
                 disabled="#{! backingBean.isSpecificationSelected()}"
                 oncomplete="openSpecMenuDialog.hide();"
>

...

<p:tab id="pageImageTab" title="Raw Document">
    <p:scrollPanel mode="native" style="height:292px;width:auto;overflow:auto" id="rawDocumentScrollPanel" rendered="#{backingBean.areTherePages()}">
        <p:carousel id="rawPageImageCarousel" value="#{mbssMapper.pageImages}" var="pageImage" rows="1" rendered="#{mbssMapper.areTherePages()}">
            <p:panelGrid columns="1" style="border:0px white none !important">
                <h:outputText value="Page #{pageImage.pageNumber} of #{backingBean.pageImages.size()}"/>
                <p:graphicImage id="pageImageDisplay" value="#{pageImage.url}" style="height:850px;min-width:1280px;">
                    <f:param name="pageNumber" value="#{pageImage.pageNumber}"/>
                </p:graphicImage>
            </p:panelGrid>
        </p:carousel>
    </p:scrollPanel>

    <p:panel id="rawPageImageMissingMessage" style="border:0px white none" rendered="#{! backingBean.areTherePages()}">
        <b>No document is loaded</b>
    </p:panel>
</p:tab>
Primefaces 3.4, JSF 2.1, Glassfish 3.1.2.2, Mojarra 2.1.6

User avatar
andyba
Expert Member
Posts: 2473
Joined: 31 Mar 2011, 16:27
Location: Steinfeld, near Bremen/Osnabrück, DE
Contact:

09 Apr 2013, 11:15

One the things I noticed here is that you are not closing (or flushing) the Servlet output stream. You really need to set the content length of the response as well.
If you don't do these things then the browser will be waiting for the image stream to deliver more content which isn't coming.

I am a little puzzled as to why this was regarded as a question in a PrimeFaces forum, this is Servlet 101.
PF 4.x (Elite versions), PF 5, Pf 5.1, PF 6.0
Glassfish 4.1, Mojarra 2.x, Java 8, Payara 4.1.1.
If you haven't read the forum rules read them now

Edgewise
Posts: 4
Joined: 09 Apr 2013, 00:05

09 Apr 2013, 17:13

andyba, thanks for your advice, but I think you may be unfamiliar with try-with-resources (http://docs.oracle.com/javase/tutorial/ ... Close.html). You're right that there was no flush, but I just added that and it's not the issue. So this is not servlet 101, though it may be a java7 101 for you :)
Primefaces 3.4, JSF 2.1, Glassfish 3.1.2.2, Mojarra 2.1.6

Edgewise
Posts: 4
Joined: 09 Apr 2013, 00:05

09 Apr 2013, 17:20

Just to be clear, I also tried setting the response content length, to no avail. I was having this problem back when I was using DefaultStreamedContent, so it really has nothing to do with servlet issues. If anything, moving to a servlet solution for the images has improved things slightly.
Primefaces 3.4, JSF 2.1, Glassfish 3.1.2.2, Mojarra 2.1.6

Edgewise
Posts: 4
Joined: 09 Apr 2013, 00:05

10 Apr 2013, 23:34

I found a solution, but it's a bit disappointing. I turned off ajax for the button, and had it redirect to the first tab. However, it's disappointing that I had to workaround these issues instead of solving them in the context of ajax requests. If you come to this page because you're having a similar issue, all I can tell you is that I wasn't able to find any help and you may have to employ a similar workaround or very different solution, perhaps without Primefaces.
Primefaces 3.4, JSF 2.1, Glassfish 3.1.2.2, Mojarra 2.1.6

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 23 guests