How to use <p:graphicImage> with DefaultStreamedContent in an ui:repeat?

19,029

It is not possible to use <p:graphicImage> this way. You should rather iterate over a collection of unique image identifiers, not over a collection of StreamedContent. Those unique image identifiers have then to be passed as a <f:param> to <p:graphicImage> which in turn will generate the right URLs for the browser.

<ui:repeat value="#{data.imageIds}" var="imageId">
    <p:graphicImage value="#{imageStreamer.image}">
        <f:param name="id" value="#{imageId}" />
    </p:graphicImage>
</ui:repeat>

Your #{data} managed bean must just have a:

private List<Long> imageIds; // +getter

The #{imageStreamer} should be a separate application scoped managed bean which look basically like this:

@ManagedBean
@ApplicationScoped
public class ImageStreamer {

    @EJB
    private ImageService service;

    public StreamedContent getImage() throws IOException {
        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()));
        }
    }

}
Share:
19,029

Related videos on Youtube

user1433804
Author by

user1433804

Updated on September 10, 2022

Comments

  • user1433804
    user1433804 over 1 year

    I was trying to display a panel where user can see a list of items category(displayed as images) and on clicking they can view products within the category(images will be displayed)

    For displaying the item category, i used the ui:repeat nad the supporting bean calss Below is my xhtml code

    <ui:repeat id="repeat" value="#{getData.images}" var="img" varStatus="loop">
    <h:panelGroup>
    <p:graphicImage id="img1" value="#{img}" alt="image not available" >
    </p:graphicImage>
    </h:panelGroup>
    </ui:repeat>
    

    And the Managed Bean Code parts

    private ByteArrayOutputStream baos = new ByteArrayOutputStream();
    private List<StreamedContent> imageList = new ArrayList<StreamedContent>();
    
    public List<StreamedContent> getImages(){
      for (int i = 0; i < sdh.getNumOfImages(); i++) {
        imageID = imageIDArray.get(i);
        ImageService imgSer = new ImageService();
        imgList.add(imageID);
        imgSer.setData(imageID);
        baos = imgSer.getImage();
        try {
          imageList.add(new DefaultStreamedContent(new 
                ByteArrayInputStream(baos.toByteArray())));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
      }
      imageNum = 0;
      return imageList;
    }
    
    public StreamedContent getData() {
        baos = imageList.get(imageNum);
        //imageList.add(baos);
        imageNum++;
        return new DefaultStreamedContent(new ByteArrayInputStream(baos.toByteArray()));
    }
    

    Now my problem if i don't uncomment the 'imageList.add(baos)' in 'getData', the images are not displayed. Now i really wants to know how the 'ui:repeat' works, since the 'imageList' contains the images and i can save the same if required in either of the method. If i specify a fixed number (ex:'imageList.get(0)') in the 'getData' method then the same image is show multiple times. Where as if i put the 'imageNum' without the 'imageList.add(baos)' it throw error 'Error in streaming dynamic resource'

    I tired Bjorn Pollex's suggestion and made the necessary changes but now images don't appear

    • Björn Pollex
      Björn Pollex almost 12 years
      You are not referencing the loop-variable (img in your case) inside your <ui:repeat>. Your getImages should return a List<StreamedContent>, and your <p:graphicImage> should have value="#{img}".