4

I'm having issues to show an image in the Primefaces component graphicImage.

When my MB is SessionScoped, all works fine. But when it´s ViewScoped, the images doesn´t show.

I could keep SessionScoped, but my page do upload/delete in images, and those are stored in a PostgreSQL (please, my software architecture forced me to do this). The problem is when I insert a new image or delete one, the page still show the last values (un-refreshed ones) until I close my browser and open again. I hope with ViewScoped I can reload the page and my problem is solved.

Here is the snap of the page:

                    <p:panel id="panelListFotoProduto" header="Fotos do Produto" toggleable="true" collapsed="false" closable="false"
                             toggleSpeed="500" widgetVar="panelListFotoProduto" visible="true" >
                        <p:dataTable id="listFotoProduto" paginatorPosition="bottom" value="#{produtoMB.listProdutoFoto}" 
                                     lazy="true" var="pf" selectionMode="single" paginator="true" rows="1"
                                     rowKey="#{pf.id}">
                            <p:column style="width: 100%" >
                                <h:panelGrid columns="1" cellpadding="4"> 
                                    <p:graphicImage id="imageProduto" value="#{produtoMB.getFoto(pf)}" onclick="dialogFotoProduto.show()"/>
                                    <p:commandButton value="Excluir" style="width: 100%;" update=":growl :formProduto:panelListFotoProduto" actionListener="#{produtoMB.removeFoto(pf)}"/>
                                </h:panelGrid>     
                            </p:column>
                            <f:facet name="footer">
                                <h:panelGrid columns="1" cellpadding="4"> 
                                    <p:commandButton value="Adicionar" style="width: 100%;" update=":growl :formProduto:panelListFotoProduto" actionListener="#{produtoMB.adicionarFoto()}"/>
                                    <h:outputText id="totalProdutos" style="font-weight:bold" value="Total de Fotos Cadastrados: #{produtoMB.listProdutoFoto.size() }"/>
                                </h:panelGrid>                                      
                            </f:facet>
                        </p:dataTable>
                    </p:panel>

Here are my MB:

@ManagedBean
@SessionScoped
public class ProdutoMB {

    private Produto       produto_atual      = new Produto();
    private Produto_Foto  produto_foto_atual = new Produto_Foto();

    private List<Produto>      listProduto         = null;    
    private List<Produto_Foto> listProdutoFoto     = null;
    private List<Produto_Foto> listProdutoFoto_all = null;

    private boolean adicionarFoto = false;
    private StreamedContent last;

    public Produto getProduto_atual(){
        return produto_atual;
    }    

    public void setProduto_atual(Produto produto) throws SQLException, IOException{        
        if(produto != null && produto_atual != null 
        && produto.getCd_produto().equals(produto_atual.getCd_produto())){
            return ;
        }
        produto_atual = produto;
        produto_foto_atual = null;        
        listProdutoFoto    = new ArrayList<>();

        int index = 0;
        System.out.println("List >> " + getListProdutoFoto_all());
        for(Produto_Foto p_f : getListProdutoFoto_all()){
            if(produto_atual.getCd_produto().equals(p_f.getCd_produto())){
                p_f.setId(index++);
                p_f.setContent(getFoto_b(produto_atual.getCd_empresa(), p_f.getCd_imagem()));
                listProdutoFoto.add(p_f);
            } 
        }

        if(listProdutoFoto.isEmpty()){
            Produto_Foto p_f = new Produto_Foto();
            p_f.setId(-1);
            p_f.setCd_produto(produto_atual.getCd_produto());
            p_f.setCd_empresa(produto_atual.getCd_empresa());
            p_f.setCd_imagem(-1);
            p_f.setContent(getFoto_b(produto_atual.getCd_empresa(), p_f.getCd_imagem()));
            listProdutoFoto.add(p_f);
        }       
    }

    public void setProduto_foto_atual(Produto_Foto produto_foto) {
        if(produto_foto != null && produto_foto_atual != null 
        && produto_foto.getCd_produto().equals(produto_foto_atual.getCd_produto())){
            return ;
        }
        produto_foto_atual = produto_foto;
    }

    public ProdutoMB(){
    }

    public void handleFileUpload(FileUploadEvent event) throws SQLException, IOException{
        if(event != null){            
            UploadedFile imagem_upload = event.getFile();

            byte[] buf = imagem_upload.getContents();
            BufferedImage image = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(buf)));            

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write( image, "jpg", baos );
            baos.flush();
            buf = baos.toByteArray();
            baos.close();            

            BufferedImage scaledImage = Scalr.resize(image, 250);

            if(scaledImage != null){
                baos = new ByteArrayOutputStream();
                ImageIO.write( scaledImage, "jpg", baos );
                baos.flush();
                byte[] imageInByte = baos.toByteArray();
                baos.close();

                buf = imageInByte;
            }

            if(adicionarFoto){
                adicionarFoto = false;

                Produto_Foto p_f = new Produto_Foto();
                p_f.setId(listProdutoFoto.size());
                p_f.setCd_produto(produto_atual.getCd_produto());
                p_f.setCd_empresa(produto_atual.getCd_empresa());
                p_f.setCd_imagem(-1);
                p_f.setContent(buf);

                if(listProdutoFoto.size() == 1){
                    Produto_Foto p_f_aux = listProdutoFoto.get(0);
                    if(p_f_aux.getId() == -1){
                        p_f.setId(0);
                        listProdutoFoto.set(0, p_f);
                    } else {
                        listProdutoFoto.add(p_f);
                    }
                } else {
                    listProdutoFoto.add(p_f);
                }
                return;
            }

            if(produto_foto_atual != null){
                int index = produto_foto_atual.getId();
                if(index >= 0){
                    produto_foto_atual.setContent(buf);
                    listProdutoFoto.set(index, produto_foto_atual);
                } else if(index == -1){
                    produto_foto_atual.setContent(buf);
                    produto_foto_atual.setId(++index);
                    listProdutoFoto.set(index, produto_foto_atual);
                }
            }
        } 
    }

    public void adicionarFoto(){
        adicionarFoto = true;
        RequestContext.getCurrentInstance().execute("dialogFotoProduto.show()");
    }

    public void removeFoto(Produto_Foto produto_foto) throws SQLException, IOException{
        if(produto_foto == null){
            return ;
        }
        int index = produto_foto.getId();
        if(index >= 0){
            listProdutoFoto.remove(index);

            for(int i = 0; i < listProdutoFoto.size(); i++){
                Produto_Foto p_f = listProdutoFoto.get(i);
                if(p_f.getId() > index){
                    p_f.setId(p_f.getId() - 1);
                }
            }
        }
        if(listProdutoFoto.isEmpty()){
            Produto_Foto p_f = new Produto_Foto();
            p_f.setId(-1);
            p_f.setCd_produto(produto_atual.getCd_produto());
            p_f.setCd_empresa(produto_atual.getCd_empresa());
            p_f.setCd_imagem(-1);
            p_f.setContent(getFoto_b(produto_atual.getCd_empresa(), p_f.getCd_imagem()));
            listProdutoFoto.add(p_f);
        }    
    }

    public void removeFotoAtual(){
        if(produto_foto_atual == null){
            return ;
        }
        int index = produto_foto_atual.getId();
        if(index >= 0){
            listProdutoFoto.remove(index);

            for(int i = 0; i < listProdutoFoto.size(); i++){
                Produto_Foto p_f = listProdutoFoto.get(i);
                if(p_f.getId() > index){
                    p_f.setId(p_f.getId() + 1);
                }
            }
        }
    }

    public void removeFotoBanco(Produto_Foto pf_aux) throws SQLException{
        if(produto_atual == null){
            return ;
        }

        if(pf_aux == null){
            return ;
        }

        Integer cd_empresa = produto_atual.getCd_empresa();

        if(cd_empresa == null){
            return ;
        }

        Connection conn = null;
        Connection conn_p = null;
        PreparedStatement ps = null;
        ResultSet rs         = null;
        try {
            conn   = conectorImagemPostgreSQL.getConnection(); 
            conn_p = conectorPostgreSQL.getConnection();
            conn.setAutoCommit(false);

            ps = conn_p.prepareStatement(" DELETE FROM produto_foto WHERE cd_empresa = ? AND cd_produto = ? AND nm_foto = ? AND cd_imagem = ?;");                        
            ps.setInt(1, cd_empresa);
            ps.setString(2, produto_atual.getCd_produto());
            ps.setString(3, pf_aux.getNm_foto());
            ps.setInt(4, pf_aux.getCd_imagem());
            ps.executeUpdate();
            ps.close();
        } catch(Exception e){
            e.printStackTrace();
        } finally{
            if (rs != null) {
                rs.close();
            }
            if (ps != null) {
                ps.close();
            }
            conn.commit();
        }
    }

    public void salvaFotoBanco() throws SQLException{
        if(produto_atual == null){
            return ;
        }

        if(listProdutoFoto == null || listProdutoFoto.isEmpty()){
            return ;
        }

        Integer cd_empresa = produto_atual.getCd_empresa();

        if(cd_empresa == null){
            return ;
        }

        Connection conn = null;
        Connection conn_p = null;
        PreparedStatement ps = null;
        ResultSet rs         = null;

        conn   = conectorImagemPostgreSQL.getConnection(); 
        conn_p = conectorPostgreSQL.getConnection();  

        ps = conn_p.prepareStatement(" DELETE FROM produto_foto WHERE cd_empresa = ? AND cd_produto = ?;");

        ps.setInt(1, cd_empresa);
        ps.setString(2, produto_atual.getCd_produto());
        ps.executeUpdate();
        ps.close();

        conn_p.commit();

        for(Produto_Foto p_f : listProdutoFoto){                       
            try {
                conn.setAutoCommit(false);
                if(p_f.getId() >= 0 && p_f.getCd_imagem() < 0){

                    ps = conn.prepareStatement("SELECT f_sequencial('IMAGEMLO', ?) as cd_imagem");
                    ps.setInt(1, cd_empresa);
                    rs = ps.executeQuery();
                    if (rs != null) {
                        while(rs.next()) {
                            p_f.setCd_empresa(produto_atual.getCd_empresa());
                            p_f.setCd_produto(produto_atual.getCd_produto());
                            p_f.setCd_imagem(rs.getInt(1));
                        }
                    }
                    byte[] b = p_f.getContentBytes();

                    BufferedImage image = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(b)));            

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImageIO.write( image, "jpg", baos );
                    baos.flush();
                    b = baos.toByteArray();
                    baos.close();            

                    BufferedImage scaledImage = Scalr.resize(image, 250);

                    if(scaledImage != null){
                        baos = new ByteArrayOutputStream();
                        ImageIO.write( scaledImage, "jpg", baos );
                        baos.flush();
                        byte[] imageInByte = baos.toByteArray();
                        baos.close();

                        b = imageInByte;
                    }
                    LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();
                    int oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE);
                    LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);
                    obj.write(b);
                    obj.close();
                    ps = conn.prepareStatement(" INSERT INTO imagemlo(cd_empresa, cd_imagem, ds_imagem, by_imagem) "
                                                        + "VALUES (?, ?, ?, ?);");

                    String file_name = p_f.getCd_empresa() + "_" + 
                                p_f.getCd_produto() + "_" + 
                                p_f.getCd_imagem() + ".jpg";

                    ps.setInt(1, cd_empresa);
                    ps.setInt(2, p_f.getCd_imagem());
                    ps.setString(3, file_name);
                    ps.setLong(4, oid);
                    ps.executeUpdate();
                    ps.close();
                }
                ps = conn_p.prepareStatement(" INSERT INTO produto_foto(cd_empresa, cd_produto, nm_foto, cd_imagem) "
                                                    + "VALUES (?, ?, ?, ?);");

                String file_name = p_f.getCd_empresa() + "_" + 
                                p_f.getCd_produto() + "_" + 
                                p_f.getCd_imagem() + ".jpg";

                ps.setInt(1, cd_empresa);
                ps.setString(2, produto_atual.getCd_produto());
                ps.setString(3, file_name);
                ps.setInt(4, p_f.getCd_imagem());
                ps.executeUpdate();
                ps.close();
            } catch(Exception e){
                e.printStackTrace();
            } finally{
                if (rs != null) {
                    rs.close();
                }
                if (ps != null) {
                    ps.close();
                }
                conn.commit();
            }
        }
        FacesMessage msg = new FacesMessage("Alterações salvas com sucesso.", "");  
        FacesContext.getCurrentInstance().addMessage(null, msg); 
    }

    public void editaFoto(Produto_Foto produto_foto){
        if(produto_foto != null){
            produto_foto_atual = produto_foto;
        }
    }

    public StreamedContent getFotoAtual() throws SQLException, IOException{
        if(produto_foto_atual != null){
            int index = produto_foto_atual.getId();
            if(index >= 0){
                last = listProdutoFoto.get(index).getContent();
            }
        }
        return last;
    }

    public StreamedContent getFoto(Produto_Foto produto_foto) throws SQLException, IOException{
        if(produto_foto != null){
            produto_foto_atual = produto_foto;

            int index = produto_foto.getId();
            if(index >= 0){
                last = listProdutoFoto.get(index).getContent();
            }

            if(index == -1){
                last = listProdutoFoto.get(0).getContent();
            }
        }

        if(last == null){
            last = (new DefaultStreamedContent(new ByteArrayInputStream(getFoto_b(produto_atual.getCd_empresa(), -1)), "image/jpeg", "img_padrao"));
        }
        return last;
    }

    public StreamedContent getFoto(Integer cd_empresa, Integer cd_imagem) throws SQLException, IOException{
        Usuario u = (Usuario)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("LoggedUser");

        if(u == null){
            System.out.println("Usuário é nulo");
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));
            return (new DefaultStreamedContent(fis, "image/jpeg", "img_padrao"));
        }

        if(produto_atual == null){
            System.out.println("Produto Atual é nulo");
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));
            return (new DefaultStreamedContent(fis, "image/jpeg", "img_padrao"));
        }

        if(cd_empresa == null){
            System.out.println("cd_empresa é nulo");
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));
            return (new DefaultStreamedContent(fis, "image/jpeg", "img_padrao"));
        }

        if(cd_imagem == null || cd_imagem < 0){
            System.out.println("cd_imagem é nulo ou menor que zero");
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));
            return (new DefaultStreamedContent(fis, "image/jpeg", "img_padrao"));
        }

        Connection        conn = null;
        PreparedStatement   ps = null;
        ResultSet           rs = null;

        try {        
            conn = conectorImagemPostgreSQL.getConnection();  
            conn.setAutoCommit(false);
            LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();

            ps = conn.prepareStatement("SELECT ds_imagem, by_imagem FROM imagemlo WHERE cd_empresa = ? AND cd_imagem = ?");
            ps.setInt(1, cd_empresa);
            ps.setInt(2, cd_imagem);

            rs = ps.executeQuery();
            if (rs != null) {
                while(rs.next()) {

                    String ds_imagem = rs.getString("ds_imagem");   
                    int oid = rs.getInt("by_imagem");

                    LargeObject obj = lobj.open(oid, LargeObjectManager.READ);

                    //read the data
                    byte buf[] = new byte[obj.size()];
                    obj.read(buf, 0, obj.size());
                    obj.close();

                    BufferedImage image = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(buf)));            

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImageIO.write( image, "jpg", baos );
                    baos.flush();
                    buf = baos.toByteArray();
                    baos.close();            

                    BufferedImage scaledImage = Scalr.resize(image, 250);

                    if(scaledImage != null){
                        baos = new ByteArrayOutputStream();
                        ImageIO.write( scaledImage, "jpg", baos );
                        baos.flush();
                        byte[] imageInByte = baos.toByteArray();
                        baos.close();

                        buf = imageInByte;
                    }
                    return (new DefaultStreamedContent(new ByteArrayInputStream(buf), "image/jpeg", ds_imagem));
                }
            }
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));

            return (new DefaultStreamedContent(fis, "image/jpeg", "img_padrao"));
        } finally{
            if (rs != null) {
                rs.close();
            }
            if (ps != null) {
                ps.close();
            }
            conn.commit();
        }
    }    

    public byte[] getFoto_b(Integer cd_empresa, Integer cd_imagem) throws SQLException, IOException{
        Usuario u = (Usuario)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("LoggedUser");

        if(u == null){
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));

            ByteArrayOutputStream out = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024]; 
            while (fis.read(buffer) != -1) out.write(buffer); 

            return out.toByteArray();
        }

        if(produto_atual == null){
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));

            ByteArrayOutputStream out = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024];
            while (fis.read(buffer) != -1) out.write(buffer); 

            return out.toByteArray();
        }

        if(cd_empresa == null){
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));

            ByteArrayOutputStream out = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024]; 
            while (fis.read(buffer) != -1) out.write(buffer); 

            return out.toByteArray();
        }

        if(cd_imagem == null || cd_imagem < 0){
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));

            ByteArrayOutputStream out = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024]; 
            while (fis.read(buffer) != -1) out.write(buffer); 

            return out.toByteArray();
        }

        Connection        conn = null;
        PreparedStatement   ps = null;
        ResultSet           rs = null;

        try {        
            conn = conectorImagemPostgreSQL.getConnection();  
            conn.setAutoCommit(false);
            LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();

            ps = conn.prepareStatement("SELECT ds_imagem, by_imagem FROM imagemlo WHERE cd_empresa = ? AND cd_imagem = ?");
            ps.setInt(1, cd_empresa);
            ps.setInt(2, cd_imagem);

            rs = ps.executeQuery();
            if (rs != null) {
                while(rs.next()) {

                    String ds_imagem = rs.getString("ds_imagem");   
                    int oid = rs.getInt("by_imagem");

                    LargeObject obj = lobj.open(oid, LargeObjectManager.READ);

                    //read the data
                    byte buf[] = new byte[obj.size()];
                    obj.read(buf, 0, obj.size());
                    obj.close();
                    BufferedImage image = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(buf)));            

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImageIO.write( image, "jpg", baos );
                    baos.flush();
                    buf = baos.toByteArray();
                    baos.close();            

                    BufferedImage scaledImage = Scalr.resize(image, 250);

                    if(scaledImage != null){
                        baos = new ByteArrayOutputStream();
                        ImageIO.write( scaledImage, "jpg", baos );
                        baos.flush();
                        byte[] imageInByte = baos.toByteArray();
                        baos.close();

                        buf = imageInByte;
                    }
                    return buf;
                }
            }
            FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getRealPath("image_not_found.png"));

            ByteArrayOutputStream out = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024]; 
            while (fis.read(buffer) != -1) out.write(buffer); 

            return out.toByteArray();
        } finally{
            if (rs != null) {
                rs.close();
            }
            if (ps != null) {
                ps.close();
            }
            conn.commit();
        }
    }    

    public void save() throws SQLException{
        salvaFotoBanco();
    }

    public List<Produto> getListProduto() {

        Usuario u = (Usuario)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("LoggedUser");

        if(u == null){
            return null;
        }        

        Integer cd_empresa = u.getCd_empresa();

        if(cd_empresa == null){
            return null;
        }

        if(listProduto == null){
            listProduto = getProduto(cd_empresa);
        }

        return listProduto;
    }

    public List<Produto_Foto> getListProdutoFoto_all() {
        if(listProdutoFoto_all == null){
            listProdutoFoto_all = getProduto_Foto(produto_atual.getCd_empresa());
        }
        return listProdutoFoto_all;
    }

    /**
     * Methods to get/set data in the DB...
     */
}

If I can reload the contents with SessionScoped, better.

Thanks for the help.

I´m using JBOSS 7, Primefaces 3.4.2

[]s William Bertan

William Da Silva
  • 563
  • 6
  • 18

2 Answers2

16

It's important to understand how <p:graphicImage> with StreamedContent works. The property behind the <p:graphicImage value> will for every single image basically be consulted in two completely separate HTTP requests.

The first HTTP request (the one which does all the JSF works and is thus responsible for generating the bunch of HTML code including <img> tags) will basically consult the property in order to determine what type of image it returns (e.g. a String or a StreamedContent) so that the proper URL could be inlined/autogenerated. Note that in case of StreamedContent the image's content is not been read. HTML images does namely not work that way: it's not the webserver who inlines them in the very same HTTP request, but it's the webbrowser who downloads it separately in another HTTP request.

When StreamedContent is used, then the second HTTP request (the one which is fired by the webbrowser when it needs to download the concrete image file based on the URL of <img> element in order to show it at the desired location in the HTML document) will basically consult the property once again in order to download the image content.

A view scoped bean is tied to a specific JSF view by a hidden input field javax.faces.ViewState. If this is absent in the HTTP request (or has a different value), then there's basically means of a completely different view. So the very same view scoped bean instance won't be reused for those image requests. Every image request get a brand new view scoped bean instance with all properties set to default. The session scoped bean lives basically as long as the currently established HTTP session between the client and the server, so the very same bean instance would be reused for those image requests, so it just works that way.

To solve your concrete problem, best is to create an application or maybe request scoped bean which obtains the image by its ID as request parameter. This way you also don't need to pollute the session with tens or hundreds of images together at once (which would only waste server memory in case of multiple concurrent users who are viewing the same images). You just need to have a list of image identifiers for the datatable and serve the images by a separate application scoped bean.

See also:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • based on the discussion about `` on the site, tried your proposed solution with `@ConversationScoped` bean without luck. Getting the error "SEVERE: Error in streaming dynamic resource. WELD-001303 No active contexts for scope type javax.enterprise.context.ConversationScoped" even with attached `cid ` as `f:param`. The error seems to occur due to the Primeface's servlet doesn't know about conversation. Can you improve your answer with suggestion on ConversationScoped? – Uluk Biy Sep 12 '13 at 13:22
  • @Uluk: Using a conversation scoped bean for `StreamedContent` is not making any sense as the image identifier is request scoped anyway. Just put bean in request scope. Or, if the bean doesn't hold any state, just put bean in application scope. See also 1st "See also" link for a concrete example of such a bean. – BalusC Sep 12 '13 at 13:29
0

I had a "similar" problem to the OP, and I landed here (and in many other answers by BalusC).

BalusC explanation is perfect as usual, but how do you solve the problem if, like me and the OP, you are in tight constraints? In my case: the bean had to be ViewScope, the image bytes where stored in the bean, upon upload the bytes are refreshed immediately "ajaxely", you cannot retrieve the image again based on an attribute (like an ID, and get it out of the DB). In general, any time you have a one-time generated image (captcha?) or images coming in ajaxely (uploaded image? User-modified image?).

I know, for this kind of ajax-rich applications JSF/PrimeFaces is not the best framework, but the application is written entirely in PrimeFaces, so... maybe you want to stick with PF and see if a solution is possible.

You can do it using a combination of ajax components and creativity, namely remoteCommand, a bit of JS, and a bunch of StackOverflow answers I am going to link.

First, you need to invoke the remoteCommand. I am doing it in the "onupload" event of fileUploader (similarly to this answer), as well as at document ready time (for the generated image):

<p:fileUpload fileUploadListener="#{bean.handleFileUpload}"
              oncomplete="displayImageBegin();"

displayImageBegin just calls into the remoteCommand:

function displayImageBegin() {
    if (typeof(getImage) == "function")
        getImage();
}

And

<p:remoteCommand name="getImage" action="#{bean.getImage()}"
                 oncomplete="displayImageEnd(xhr, status, args);"
                 style="display: none;" />

On the bean side, the getImage function just returns the image bytes. You have two options here: either use inline, base64 encoding for img src (see this answer, and this one), or just return and octect stream and put it into a canvas. The second option is more flexible, and works with larger images (mine are small and size is controlled, so the base64 encoding was fine):

You need to control completely the format of the XHR answer, like in this answer (BTW, I agree this is abusing JSF as a REST service; treat this code as an interesting experiment):

public void getImage() throws IOException {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    externalContext.setResponseContentType("application/text");
    externalContext.setResponseCharacterEncoding("UTF-8");

    if (getCurrentImagePresent()) {
        String base64Image = Base64.getEncoder().encodeToString(yourByteArray);
        externalContext.getResponseOutputWriter().write(base64Image);
    }
    else {
        externalContext.setResponseStatus(404);
    }
    facesContext.responseComplete();
}

The remoteCommand oncomplete event wires the data returned from this bean function to our JS, like in this answer:

function displayImageEnd(xhr, status, args) {
    if (xhr.status == 200) {
        $('#previewCurrentImage').attr("src", "data:image/png;base64," + xhr.responseText);
    }
}

(of course, you need the correct img tag in your xhtml)

Why does this work? The answer is here:

A @ViewScoped bean lives exactly as long as a JSF view. [...]

A @ViewScoped bean is thus particularly more useful in rich Ajax-enabled views which needs to remember the (changed) view state across Ajax requests.

The byte array for the image is generated as part of the bean creation, and/or as a response to an ajax action on the page; it is then retrievable by any other ajax action on the page, as it will hit the same ViewScoped bean.

It is a solution that worked in my case; I do not recommend it in general, but if your constraints are very similar, you can do something.. similar! :)

I just wanted to share it as it may be a good fit for the OP question (or people coming in searching for a similar problem), and it is a good collage of good SO answers.

Community
  • 1
  • 1
Lorenzo Dematté
  • 6,161
  • 2
  • 33
  • 71