As imagens BLOB são exibidas apenas na atualização de uma página após uma atualização via p: dataTable ser feita no PrimeFaces
Estou exibindo imagens armazenadas na forma de BLOB no MySQL em um<p:graphicImage>
do seguinte modo.
<p:dataTable var="row" value="#{testManagedBean}" lazy="true" editable="true" rows="10">
<p:column headerText="id">
<h:outputText value="#{row.brandId}"/>
</p:column>
<p:column headerText="Image">
<p:cellEditor>
<f:facet name="output">
<p:graphicImage value="#{brandBean.image}" height="100" width="100">
<f:param name="id" value="#{row.brandId}"/>
</p:graphicImage>
</f:facet>
<f:facet name="input">
<p:graphicImage id="image" value="#{brandBean.image}" height="100" width="100">
<f:param name="id" value="#{row.brandId}"/>
</p:graphicImage>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit" width="50">
<p:rowEditor/>
</p:column>
</p:dataTable>
Durante a edição de uma linha, um<p:fileUpload>
é exibido em um<p:overlayPanel>
. Isso e muitas outras coisas são omitidas neste exemplo por uma questão de simplicidade, pois não estão relacionadas ao problema concreto.
O bean gerenciado JSF associado:
@ManagedBean
@ViewScoped
public final class TestManagedBean extends LazyDataModel<Brand> implements Serializable
{
@EJB
private final TestBeanLocal service=null;
private static final long serialVersionUID = 1L;
@Override
public List<Brand> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
setRowCount(3);
return service.getList();
}
}
O bean que recupera imagens do banco de dados com base em um identificador de linha exclusivo -BrandBean
.
@ManagedBean
@ApplicationScoped
public final class BrandBean
{
@EJB
private final BrandBeanLocal service=null;
public BrandBean() {}
public StreamedContent getImage() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
else {
String id = context.getExternalContext().getRequestParameterMap().get("id");
System.out.println("id = "+id);
byte[] bytes = service.findImageById(Long.parseLong(id));
return bytes==null? new DefaultStreamedContent(new ByteArrayInputStream(new byte[0])):new DefaultStreamedContent(new ByteArrayInputStream(bytes));
}
}
}
Quando uma linha é atualizada (depois de editada), clique em um visto localizado (indicado por<p:rowEditor>
) na última coluna da tabela de dados, ogetImage()
método noBrandBean
é invocado como deveria.
Isso acontece corretamente em um aplicativo em execução no servidor GlassFish 4.0 usando o PrimeFaces 5.0 e o JSF 2.2.6.
Uma nova imagem será exibida na tabela de dados imediatamente após a atualização de uma linha na tabela de dados (e consequentemente no banco de dados).
Há outro aplicativo em execução no servidor Tomcat 8.0.5 usando o Spring 4.0.0 GA no qualagetImage()
método não é chamado depois que uma linha mantida pela tabela de dados é atualizada, resultando na exibição doimagem antiga (não a recém-atualizada) na tabela de dados (mesmo que as alterações sejam propagadas corretamente no banco de dados).
A imagem recém-atualizada é exibida apenas quando a página é atualizada pressionandoF5 (na maioria dos navegadores). Ele ainda não é exibido no carregamento da página (insira um URL na barra de endereços e pressione o botãoentrar chave).
Em outras palavras, quando uma linha de uma tabela de dados é atualizada, clique no visto indicado por<p:rowEditor>
, agetImage()
O método não é chamado (portanto, a nova imagem não é buscada no banco de dados para ser exibida no<p:graphicImage>
) Esse método é chamado apenas quando a página é atualizada / recarregada pressionando o botãoF5 tecla de atalho.
Por que isso acontece? Como mostrar uma imagem recém-atualizada imediatamente após a atualização de uma linha?
Superficialmente, isso não deve estar relacionado ao Spring nem ao JPA (a operação de atualização é propagada corretamente no banco de dados após clicar no tique). Isso deve estar relacionado ao servidor Tomcat.