How to use p:graphicImage with StreamedContent within p:dataTable? [duplicate]

The <p:graphicImage> will call the getter method twice. First time is when the <img> element is to be rendered to HTML and thus requires an URL in the src attribute. If you just return new DefaultStreamedContent(), then it will autogenerate the right URL in src attribute. Second time is when the browser really requests the image, this is the moment when you should return the actual image.

So, the getter method should basically look like this:

public StreamedContent getStreamedImageById() {
    FacesContext context = FacesContext.getCurrentInstance();

    if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
        // So, we're rendering the view. Return a stub StreamedContent so that it will generate right URL.
        return new DefaultStreamedContent();
    }
    else {
        // So, browser is requesting the image. Get ID value from actual request param.
        String id = context.getExternalContext().getRequestParameterMap().get("id");
        Image image = service.find(Long.valueOf(id));
        return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
    }
}

images are saved in the database as byte[] if we save them through hibernate. I uploaded the images with <p:fileUpload... tag then I save the image alongwith other data values using hibernate.

On second page, I'm displaying the whole table data (of course with images) using

<p:dataTable  var="data" value="#{three.all}" ....

and dynamic Images using

<p:graphicImage   alt="image"  value="#{three.getImage(data)}" cache="false"  >
                <f:param id="image_id" name="image_id" value="#{data.number}" />
</p:graphicImage></p:dataTable>

Here "three" is the name of Backing Bean. In method getAll(), I'm retrieving data from table through hibernate and in the same method, I've created a HashMap<Integer, byte[]>. HashMap is an instance variable of the bean and The Bean is SessionScoped. I'm putting the images (which are in byte[] form) alongwith an integer image_id.

code:

    for (int i=0; i<utlst.size(); i++ ){
             images.put(utlst.get(i).getNumber(), utlst.get(i).getImage());}
//utlst is the object retrieved from database. number is user-id.

In the view getImage.xhtml, <p:graphicImage alt="image" value="#{three.getImage(data)}" cache="false" > it calls the method getImage(data /*I am passing current object of the list which is being iterated by*/ )

code of getImage:

public StreamedContent getImage(Util ut) throws IOException {
       //Util is the pojo

          String image_id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("image_id");
          System.out.println("image_id: " + image_id);

          if (image_id == null) {

                defaultImage=new DefaultStreamedContent(FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/Capture.PNG"), "image/png");

            return defaultImage; 
        }


         image= new DefaultStreamedContent(new ByteArrayInputStream(images.get(Integer.valueOf(image_id))), "image/png");

        return image;
    }

just keep your dynamic Images with ids in A HashMap in the session then they will be correctly streamed.

Thanks & regards, Zeeshan


In PrimeFaces 3.2 the bug is still present. I do the workaround with

<p:graphicImage value="#{company.charting}">
    <f:param id="a" name="a" value="#{cc.attrs.a}" />
    <f:param id="b" name="b" value="#{cc.attrs.b}" />
</p:graphicImage>

and

ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
String a= externalContext.getRequestParameterMap().get("a");
String b= externalContext.getRequestParameterMap().get("b");

But even with this the bean is called 2 times. But in the second call variable a + b is filled ;-)

Damn bug