Neste exemplo temos uma alternativa para usar o GraphicImage no PrimeFaces com JSF 2 para mostrar uma imagem gravada no banco de dados.
O GraphicImage é um componente prático porque elimina a necessidade de servlets ou outros artifícios para carregar a imagem.
Um ponto importante é que o GraphicImage não funciona com @ViewScope, que é muito usado nas aplicações com JSF 2. Ele funciona apenas com @SessionScope e @RequestScope. Para resolver esse problema, criei o ImagemProdutoBean, um managed bean com @RequestScope.
Código-fonte
O projeto completo está disponível no GitHub. Além do GraphicImage, o projeto mostra exemplos de outros componentes PrimeFaces, além de soluções simples para problemas comuns de aplicações web.
Persistência
No nosso exemplo vamos criar a classe Produto com o atributo byte[] foto, que deve ter a anotação @Lob. Em alguns bancos de dados temos que definir um tamanho desse arquivo, como é o caso do HSQLDB, que é usado no exemplo. No MySQL não é necessário.
public class Produto {
{...}
@Lob
@Column(length = 1024 * 1024 * 5)
private byte[] especificacaoFabricante;
@Lob
@Column(length = 1024 * 1024 * 5)
private byte[] foto;
{...}
}
JSF
A página produto.xhtml vai mostrar a imagem através do managed bean imagemProdutoBean.
{…}
id=”uploadfotoProduto” /> id=”uploadfotoProduto” /> actionListener=”#{produtoBean.salvar}” icon=”ui-icon-disk”
update=”messages” />
{…}
Managed bean
Precisamos de 2 managed beans. O primeiro, ProdutoBean, é para a página XHTML e tem escopo @ViewScoped. O segundo, ImagemProdutoBean é somente para a imagem e pode ser @RequestScoped ou @SessionScoped. Eu prefiro o @RequestScoped, mas fica a critério de cada um.
Observe o método salvar(), que deve ter uma condição para não apagar a imagem já gravada, no caso em que o usuário está fazendo a edição do registro.
Para esse exemplo, o ajax do upload está desabilitado. Para habilitar o ajax, você pode usar essa dica.
@ViewScoped
@ManagedBean
public class ProdutoBean {
{…}
private UploadedFile foto;
private Produto produto;
public void setFoto(UploadedFile foto) {
this.foto = foto;
}
public UploadedFile getFoto() {
return foto;
}
public boolean isExisteFoto() {
try {
return getProduto().getFoto().length > 0;
} catch (Exception e) {
return false;
}
}
public void salvar() {
try {
//
if (getEspecificacaoFabricante() != null
&& getEspecificacaoFabricante().getSize() > 0) {
byte[] dados = IOUtils.toByteArray(getEspecificacaoFabricante()
.getInputstream());
getProduto().setEspecificacaoFabricante(dados);
}
//
if (getFoto() != null && getFoto().getSize() > 0) {
byte[] dados = IOUtils.toByteArray(getFoto().getInputstream());
getProduto().setFoto(dados);
}
//
getProdutoService().salvar(getProduto());
infoMsg(MENSAGEM_SUCESSO_GRAVACAO);
} catch (Exception e) {
errorMsg(e);
}
}
}
GraphicImage no Primefaces
Essa é a abordagem mais simples para mostrar uma imagem no PrimeFaces. E pode ser usada no sistema todo.
Um detalhe é que o PrimeFaces executa duas vezes o método getConteudoImagem() e somente da segunda vez é que a imagem deve ser carregada.
package net.marcoreis.ecommerce.controlador;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import net.marcoreis.ecommerce.entidades.Produto;
import net.marcoreis.ecommerce.negocio.GenericService;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
@ManagedBean
@RequestScoped
public class ImagemProdutoBean extends BaseBean {
private static final long serialVersionUID = -7524476303834771432L;
private Produto produto;
@PostConstruct
public void init() {
produto = new Produto();
}
public StreamedContent getConteudoImagem() {
try {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
String idS = getParametro(“id”);
Long id = Long.parseLong(idS);
produto = (Produto) new GenericService()
.findById(Produto.class, id);
InputStream is = new ByteArrayInputStream(produto.getFoto());
DefaultStreamedContent dsc = new DefaultStreamedContent(is);
return dsc;
} catch (Exception e) {
return new DefaultStreamedContent();
}
}
}