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

2

9

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

Gratifying answered 8/6, 2012 at 7:26 Comment(1)
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}".Komsomol
M
17

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()));
        }
    }

}
Multivocal answered 8/6, 2012 at 14:53 Comment(4)
hankyou BalusC it worked but i had to comment @EJB, if i don't i get "com.sun.faces.mgbean.ManagedBeanCreationException: An error occurred performing resource injection on managed bean imageStreamer" I have One more questions > When i refresh the page the images disappear, why is it so. Once again ThankyouGratifying
You're welcome. Well, I just assumed that you were using EJBs for business/data services. It provides an easy and safe way of transparently handling DB transactions. If you aren't using it, then just do whatever way you normally do to obtain the service.Multivocal
One more Question, if i need to get a click event on the image then how do i do it. I can't put a Ajax inside the ui:repeat.Gratifying
@Multivocal how to return a 404 error if the image is not found?Mythify
K
0

You used wrong ui:repeat tag. You have var attribute but you can't use this in p:graphicImage tag value attribute.Please see sample usage,

       <ui:repeat value="#{yourBean.images}" var="img">
           <p:graphicImage value="/images/#{img}" />
        </ui:repeat>
Krysta answered 8/6, 2012 at 7:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.