0

I'm relatively new to JSF and Primefaces.
I'm trying to build a document viewer that would display tiff, jpeg and pdf.
My UI has a left and a right layout. Left layout contains a vertical grid of thumbnails of the docs. User clicks on a thumbnail, and the right layout displays the doc (either via a p:graphicImage or via a p:documentViewer, depending on the thumbnail clicked).
For tiffs, I'm converting the image into PNG and then displaying (both, for the thumbnail and the main display).
For multi-page tiff files, I show only the first page as the left side thumbnail...and for the main display, I give Next and Previous buttons to navigate through the pages. The UI is something like this: enter image description here

The problem:
When I click on the thumbnails, the backing method gets invoked twice as expected (the second call returning the StreamedContent with the actual data). However, when I click the Prev and Next buttons, the same backing method is getting called only once -- just for phaseid=RENDER_RESPONSE. (eventually, this causes the bean method to return only an empty StreamedContent and not one carrying the actual image data...so I don't get to see the other pages of the tiff)

The form:

<h:form id="mainform">
        <p:layout fullPage="true" style="width:100%;height:100%">
            <p:layoutUnit position="west" style="width:15%;overflow:scroll;" resizable="true">
                <p:panelGrid header="Thumbnails" columns="1" class="thumbcell" >

                    <p:repeat value="#{viewerController.docIds}" var="docId">


                                <p:panelGrid style="padding:0px !important;" columns="1" rendered="#{docId.contains('img')}" >

                                    <p:commandLink update=":mainform:renderpanel" action="#{viewerController.setSelectedDocId(docId)}">
                                        <p:graphicImage value="#{viewerController.imageDocumentStream}" style="height: 100px; width: 90px; border: none !important; padding:0px;background: lightgrey;" 
                                        alt="#{viewerController.getDocumentName(docId)}">
                                            <f:param name="id" value="#{docId}" />
                                        </p:graphicImage>
                                    </p:commandLink>
                                    <p:outputLabel value="#{viewerController.getDocumentName(docId)}"/>

                                </p:panelGrid>


                                <p:panelGrid style="padding:0px !important;" columns="1" rendered="#{docId.contains('tif')}">

                                    <p:commandLink update=":mainform:renderpanel" action="#{viewerController.setSelectedDocId(docId)}">
                                        <p:graphicImage value="#{viewerController.tifDocumentStream}" style="height: 100px; width: 90px; border: none !important; padding:0px;background: lightgrey;" 
                                        alt="#{viewerController.getDocumentName(docId)}">
                                            <f:param name="id" value="#{docId}" />
                                            <f:param name="forThumbnail" value="true" />
                                        </p:graphicImage>
                                    </p:commandLink>
                                    <p:outputLabel value="#{viewerController.getDocumentName(docId)}"/>

                                </p:panelGrid>


                                 <p:panelGrid style="padding:0px !important;" columns="1" rendered="#{docId.contains('pdf')}">

                                    <p:commandLink update=":mainform:renderpanel" action="#{viewerController.setSelectedDocId(docId)}">
                                        <p:graphicImage value="#{viewerController.pdfFirstPageDocumentStream}" style="height: 100px; width: 90px; border: none !important; padding:0px;background: lightgrey;" 
                                        alt="#{viewerController.getDocumentName(docId)}">
                                            <f:param name="id" value="#{docId}" />
                                        </p:graphicImage>
                                    </p:commandLink>
                                    <p:outputLabel value="#{viewerController.getDocumentName(docId)}"/>


                                </p:panelGrid>



                    </p:repeat>


                </p:panelGrid>
            </p:layoutUnit>

            <p:layoutUnit position="center" style="width:85%;">

                <p:panel id="renderpanel">


                    <p:panelGrid style="padding:0px !important;" columns="1" rendered="#{viewerController.currentDocId.contains('tif')}">
                        <p:outputLabel value="#{viewerController.getDocumentName(viewerController.currentDocId)}"/> 
                        <p:panelGrid style="padding:0px !important;" columns="3" id="tifPanelGrid">

                            <p:commandButton update=":mainform:renderpanel" action="#{viewerController.navigateTif('prev', viewerController.currentDocId)}" 
                            id="prevButton" value="Prev" title="Previous page" disabled="#{viewerController.prevButtonDisable}"/>

                                <p:graphicImage rendered="#{viewerController.render}" id="tifPanel" value="#{viewerController.tifDocumentStream}" style="height: 600px; width: 800px; border: none !important; padding:0px;background: lightgrey;" 
                                alt="#{viewerController.getDocumentName(viewerController.currentDocId)}">
                                    <f:param name="id" value="#{viewerController.currentDocId}" />
                                    <f:param name="forThumbnail" value="false" />
                                </p:graphicImage>

                            <p:commandButton update=":mainform:renderpanel" action="#{viewerController.navigateTif('next', viewerController.currentDocId)}" 
                            id="nextButton" value="Next" title="Next page" disabled="#{viewerController.nextButtonDisable}"/>

                        </p:panelGrid>  
                    </p:panelGrid>


                    <p:panelGrid style="padding:0px !important;" columns="1" rendered="#{viewerController.currentDocId.contains('img')}">  
                        <p:outputLabel value="#{viewerController.getDocumentName(viewerController.currentDocId)}"/>
                        <p:graphicImage value="#{viewerController.imageDocumentStream}" style="height: 600px; width: 800px; border: none !important; padding:0px;background: lightgrey;" 
                                            alt="#{viewerController.getDocumentName(viewerController.currentDocId)}">
                            <f:param name="id" value="#{viewerController.currentDocId}" />
                        </p:graphicImage>
                   </p:panelGrid>

                   <p:panelGrid style="padding:0px !important;" columns="1" rendered="#{viewerController.currentDocId.contains('pdf')}">  
                        <p:outputLabel value="#{viewerController.getDocumentName(viewerController.currentDocId)}"/>
                        <pe:documentViewer height="600" width="800" value="#{viewerController.pdfDocumentStream}" > 
                            <f:param name="id" value="#{viewerController.currentDocId}" /> 
                         </pe:documentViewer>

                   </p:panelGrid>

               </p:panel>

            </p:layoutUnit>
        </p:layout>

    </h:form>

The controller class is annotated with these two:

javax.annotation.ManagedBean
javax.enterprise.context.SessionScoped

The backing method in the controller class, that is not getting invoked twice:

public StreamedContent getTifDocumentStream() throws IOException {
    FacesContext context = FacesContext.getCurrentInstance();

    if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE ) {
        return new DefaultStreamedContent();
    } else {
        String id = context.getExternalContext().getRequestParameterMap().get("id");
        String forThumbnail = context.getExternalContext().getRequestParameterMap().get("forThumbnail");

        Doc doc = tifDocMap.get(id);

        InputStream is = this.convertTiffToPng(doc, forThumbnail);
        return new DefaultStreamedContent(is);

    }
}

I'm on this combination: SpringBoot + JoinFaces + PF 6.2

Can any body please advise what I'm doing wrong?

An alternate way I'm considering, to achieve the purpose: May be, turn the pages of the tiff to individual PNGs beforehand, and then use galleria ...but it would be nice if I could get galleria to work with StreamedContent of each page dynamically.

Tatha
  • 101
  • 8
  • 1
    Where did you read that `javax.annotation.ManagedBean` is the correct one? Where did you read that `javax.enterprise.context.SessionScoped` can be used with it? Be careful when there are multiple options in the IDE-suggested autocomplete list. Make sure to use the example exactly as seen and explained in abovelinked duplicate. – BalusC Apr 15 '20 at 21:52
  • @BalusC Hi Balus. I tried annotating with `javax.inject.Named` instead, but it didn't make a difference to the issue. I think I've written the method for returning the StreamedContent correctly. It gets correctly invoked twice from the left side commandlinks, but not from the commandbuttons for navigation. I suspect, either there is something wrong in the XHTML or I'm annotating the controller class wrongly. If the method itself doesn't get called twice, I don't have any other options to try :( – Tatha Apr 16 '20 at 15:22
  • Tried annotating with `javax.faces.bean.ManagedBean` too. Didn't make a difference to the issue. – Tatha Apr 16 '20 at 15:24
  • No. In the abovelinked duplicate, `@Named @ApplicationScoped` is being used. Both from the CDI package. If you really want to use the deprecated `@ManagedBean`, then ensure that you use `@ApplicationScoped` from the same JSF package. The problem of managed beans not being found or invoked has got completely nothing to do with the job the bean is doing. You would have had exactly the same problem when just printing an empty bean class itself in an empty XHTML page like so `#{bean}`. – BalusC Apr 16 '20 at 15:55
  • @BalusC I got the scoping of the bean corrected, but that still didn't solve the issue of the Prev and Next commandbuttons within the right-side layout, as we see in the attached image. Clicking on those, weren't invoking the content serving method twice, as was expected. The issue was exactly ditto as somebody else was trying to solve here this [link](https://stackoverflow.com/questions/11014362/unable-to-display-image-in-pgraphicimage) . I now think, making those commandbuttons as `ajax='false'` would have solved it. – Tatha Apr 21 '20 at 15:11
  • Anyway, for the purpose of displaying and navigating through multipage tiffs, I then shifted to using the Galleria component from PrimeFaces. The purpose got solved. Thanks a lot for all your advise @BalusC . (Off-topic: I also used your awesome `Faces.sendFile()` method to get a file download feature) – Tatha Apr 21 '20 at 15:19

0 Answers0