Mapping images from MySQL database to JSF datatable

I have a MySQL database that stores images in a blob column. I would like to show them in PrimeFaces <p:dataTable> . How can I achieve this?

+4
source share
2 answers

You can use <p:graphicImage> to display images stored in byte[] , regardless of the source byte[] (DB, disk file system, network, etc.). The simplest example:

 <p:graphicImage value="#{bean.streamedContent}" /> 

which refers to the StreamedContent property.

However, this does occur, especially when used in an iterable component, such as a data table: the getter method will be called twice; for the first time, JSF itself generates the URL for <img src> , and the second time for the web browser when it needs to load image content based on the URL in <img src> . To be effective, you should not beat the database the first time getter is called. In addition, to parameterize the getter method call, so that you can use a common method in which you pass a specific image identifier, you must use <f:param> (note that the EL 2.2 function to pass method arguments will not work at all like this does not end with the URL <img src> !).

To summarize, this should do:

 <p:dataTable value="#{bean.items}" var="item"> <p:column> <p:graphicImage value="#{imageStreamer.image}"> <f:param name="id" value="#{item.imageId}" /> </p:graphicImage> </p:column> </p:dataTable> 

#{item.imageId} , obviously, returns the unique idenfitier of the image in the database (primary key) and therefore not the contents of byte[] . #{imageStreamer} is a bean application area that looks like this:

 @ManagedBean @ApplicationScoped public class ImageStreamer { @EJB private ImageService service; public StreamedContent getImage() throws IOException { FacesContext context = FacesContext.getCurrentInstance(); if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) { // So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL. return new DefaultStreamedContent(); } else { // So, browser is requesting the image. Return a real StreamedContent with the image bytes. String imageId = context.getExternalContext().getRequestParameterMap().get("imageId"); Image image = imageService.find(Long.valueOf(imageId)); return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes())); } } } 

The Image class is in this particular example with only @Entity with @Lob on the bytes property (since you are using JSF, I assume you are using JPA to interact with the database).

 @Entity public class Image { @Id @GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course. private Long id; @Lob private byte[] bytes; // ... } 

ImageService is the standard @Stateless EJB, nothing much to see here:

 @Stateless public class ImageService { @PersistenceContext private EntityManager em; public Image find(Long id) { return em.find(Image.class, id); } } 

See also:

+11
source

If you use Richfaces, you can use the a4j: mediaOutput component for the blob stream from the bean.

If this is not the case, I am afraid that I am not familiar with Primefaces. If it does not provide any component for this, you need a way to create a URL that points to the servlet that blob returns. That way you can use h:graphicImage with this automatically generated url.

-1
source

Source: https://habr.com/ru/post/1484581/


All Articles