Image serving with StreamedContent fails in @ViewScoped but works in @SessionScoped

51 Views Asked by At

Ok, What am I doing wrong? I try to create simple image uploader with image preview. I have a product in my database with some name, description, etc. And image. My goal is to create edit (and later add) form for manager user. I created a bean:

package pl.jedenpies.sklep.beans;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.imageio.ImageIO;

import org.primefaces.event.FileUploadEvent;

import pl.jedenpies.sklep.dto.Image;
import pl.jedenpies.sklep.utils.ImageUtil;

@ViewScoped @ManagedBean(name = "editProductForm")
public class NewEditProductForm {

    private Image currentThumbnail;
    private Image uploadedImage;
    private Image uploadedThumbnail;

    public void save() {
        System.out.println("Saved");
    }

    public void handleFileUpload(FileUploadEvent event) throws IOException {

        BufferedImage originalImage = ImageIO.read(event.getFile().getInputstream());
        BufferedImage thumbnail = ImageUtil.makeThumbnail(originalImage);
        setUploadedImage(originalImage);
        setUploadedThumbnail(thumbnail);
    }


    public Image getCurrentThumbnail() {
        return currentThumbnail;
    }
    public void setCurrentThumbnail(BufferedImage currentThumbnail) {
        this.currentThumbnail = new Image(currentThumbnail);
    }
    public Image getUploadedImage() {
        return uploadedImage;
    }
    public void setUploadedImage(BufferedImage uploadedImage) {
        this.uploadedImage = new Image(uploadedImage);
    }
    public Image getUploadedThumbnail() {
        return uploadedThumbnail;
    }
    public void setUploadedThumbnail(BufferedImage uploadedThumbnail) {
        this.uploadedThumbnail = new Image(uploadedThumbnail);
    }
}

where Image is a class wrapping BufferedImage and allowing to create StreamedContent object:

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.primefaces.model.DefaultStreamedContent;

public class Image {

    private BufferedImage image;

    public Image() {}

    public Image(BufferedImage image) {
        this.image = image;
    }

    public DefaultStreamedContent stream() throws IOException { 

    if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
        return new DefaultStreamedContent();
    }    

    if (image == null) return null;
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(image, "png", os);
        ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray());
        return new DefaultStreamedContent(bais, "image/png");
    }
}

My xhtml page is:

<h:form id="editProductForm">
  <div class="form" style="width: 830px;">

    <p:panel id="imageUploader">
      <c:if test="#{editProductForm.currentThumbnail != null}">
        <p:graphicImage
          styleClass="thumbnail"
          id="currentThumbnail" value="#{editProductForm.currentThumbnail.stream()}" cache="false" />                
      </c:if>
      <c:if test="#{editProductForm.currentThumbnail == null}">
        <p:graphicImage 
          value="/resources/images/logo-plaskie-duze.png"
          styleClass="thumbnail" />
      </c:if>
      <c:if test="#{editProductForm.uploadedThumbnail != null}">
        <p:graphicImage
          styleClass="thumbnail"
          id="uploadedThumbnail" value="#{editProductForm.uploadedThumbnail.stream()}" cache="false" />
      </c:if>
      <c:if test="#{editProductForm.uploadedThumbnail == null}">
        <p:graphicImage
          styleClass="thumbnail empty"
          id="uploadedThumbnail" />
      </c:if>    
      <p:fileUpload 
        style="border: 1px solid green;"
        fileUploadListener="#{editProductForm.handleFileUpload}"        
        auto="true"
        update=":editProductForm:imageUploader"
        mode="advanced"
        dragDropSupport="true"

        sizeLimit="20000000" allowTypes="/(\.|\/)(gif|jpe?g|png)$/">
      </p:fileUpload>
    </p:panel>
  </div>
  </h:form>

When I try to use my new form, freshly uploaded image is not displaying. When I change the scope to @SessionScoped, it works. But I'm not interested in making this bean session scoped. Is it even going to work with view scope? Or maybe I just need to keep image in session this way or another?

As @BalusC suggested I tried "special getter method approach" (I tried it before too), but without a result. When I set the scope to View, method stream() is called once in PhaseId.RENDER_RESPONSE and I get 22:10:22,816 SEVERE [org.primefaces.application.resource.StreamedContentHandler] (default task-58) Error in streaming dynamic resource. null in my logs.

0

There are 0 best solutions below