ManagedBean returns null in graphicImage in Primefaces

I'm having problems displaying the image in the Primefaces graphic.

When my MB SessionScoped, everything works fine. But when it is ViewScoped, images are not displayed.

I could save SessionScoped, but my page loads / removes images and they are stored in PostgreSQL (please, my software architecture made me do this). The problem is that when I insert a new image or delete it, the page still displays the latest values ​​(not updated) until I close the browser and open it again. I hope that with ViewScoped I can reload the page and my problem is resolved.

Here is the link to 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 is 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 content using SessionScoped, better.

Thanks for the help.

I am using JBOSS 7, Primfaces 3.4.2

[] s William Bertan

+4
source share
2 answers

It's important to understand how <p:graphicImage> StreamedContent with StreamedContent . The property behind <p:graphicImage value> will be used for each individual image in two completely separate HTTP requests.

The first HTTP request (the one that runs all the JSF works and, thus, is responsible for creating a bunch of HTML code, including <img> tags) will basically consult with this property to determine what type of image it returns (e.g. , a String or StreamedContent ) so that the correct URL can be embedded / auto-generated. Please note that in the case of StreamedContent the image content was not read. HTML images do not work that way: this is not a web server that builds them in the same HTTP request, but it is a web browser that loads it separately in another HTTP request.

When using StreamedContent , then the second HTTP request (the one that the web browser launches when it needs to load a specific image file based on the URL of the <img> element to display it at the desired location in the HTML document) will basically check the property again to load the contents of the image.

An object of type bean is bound to a specific JSF view by a hidden input field javax.faces.ViewState . If this is not present in the HTTP request (or has a different meaning), then basically it means a completely different view. Thus, the same bean will not be reused for these image requests. Each image request receives a new bean instance with full coverage of all objects set by default. The bean session area lives mostly until the currently established HTTP session between the client and server, so the same bean instance will be reused for these image requests, so it just works that way.

To solve your specific problem, it is best to create an application, or perhaps request a bean scope that receives the image by its identifier as a request parameter. Thus, you also do not need to pollute the session with several tens or hundreds of images at the same time (which will only discard the server’s memory if it is simultaneously viewed by several identical images at the same time). You just need to have a list of image identifiers for the data and serve the images using a special bean application.

See also:

+16
source

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

The BalusC explanation is perfect, as usual, but how do you solve the problem if, like me and the OP, you are in tight limits? In my case: the bean was supposed to be ViewScope, the bytes of the images stored in the bean are immediately updated with "ajaxely" after loading the bytes, you cannot get the image again based on an attribute (for example, identifier, and get it from the database). In general, every time you have a one-time generated image (captcha?) Or images included in ajaxely (uploaded image? Custom image?).

I know that for such ajax-rich applications, JSF / PrimeFaces is not the best structure, but the application is completely written in PrimeFaces, so ... maybe you want to stick with PF and see if a solution is possible.

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

First, you need to call remoteCommand. I do this in the onupload event of the fileUploader file (similar to this answer ), and also when the document is ready (for the generated image):

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

displayImageBegin just calls in 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 simply returns the bytes of the image. You have two options: either use inline, base64 for img src (see this answer , and this one ), or just return and blow the stream and put it in canvas . The second option is more flexible and works with large images (mine are small and the size is controlled, so base64 encoding was great):

You need to completely control the format of the XHR response, as in this answer (BTW, I agree that this is an abuse of 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 passes the data returned from this bean function to our JS, as 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 xhtml)

Why does it work? The answer is here :

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

A @ViewScoped bean is therefore particularly useful in rich Ajax-enabled views, which should remember the state of a (modified) view through Ajax requests.

An byte array for the image is generated as part of the creation of the bean and / or as a response to the ajax action on the page; it is then retrieved by any other ajax action on the page, as it falls into the same ViewScoped bean.

This is the solution that worked in my case; I do not recommend it at all, but if your limitations are very similar, you can do something .. it seems! :)

I just wanted to share it, as this may be well suited to the OP question (or people looking for a similar problem), and this is a good collage of good SO answers.

0
source

All Articles