1 2 Previous Next 16 Replies Latest reply on Aug 5, 2013 9:20 AM by daxxy

    display byte array as image from database using richfaces and JPA

    rlemerson

      Hi,

       

      I'm new to Richfaces and JPA. I'm currently working on an image cover flow where all images will be coming from a mysql database where they are stored as mediumblob. I was curious if someone can easily display a persisted byte array retrieved from the database as an image using Richfaces and JPA? I've been spinning my wheels trying to come up with a workable solution without having to do this an archaic way.

       

      Currently, I have a persistent "Screenshot" class:


      @Entity
      @XmlRootElement
      @Table(name="Jun2012", uniqueConstraints = @UniqueConstraint(columnNames = "id"))
      public class Screenshot implements Serializable {
          private static final long serialVersionUID = 1L;
      
          @Id
          @GeneratedValue
          private Long id;
      
          private String user;
      
          private Timestamp time;
      
          private String mode;
      
          @Lob
          private byte[] png;
      
          **** Getters/Setters,,,,,,, ****
      }
      


      Also, in another class I'm producing a list of screenshots:

       

      @RequestScoped
      public class ScreenshotListProducer {
         @Inject
         private EntityManager em;
      
         private List<Screenshot> screenshots;
         @Produces
         @Named
         public List<Screenshot> getScreenshots() {
            return screenshots;
         }
      
         public void onScreenshotListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final Screenshot screenshot) throws FileNotFoundException {
                   retrieveAllScreenshotsOrderedByTime();
         }
      
         @PostConstruct
         public void retrieveAllScreenshotsOrderedByTime() throws FileNotFoundException {
            CriteriaBuilder cb = em.getCriteriaBuilder();
            CriteriaQuery<Screenshot> criteria = cb.createQuery(Screenshot.class);
            Root<Screenshot> screenshot = criteria.from(Screenshot.class);
            criteria.select(screenshot).orderBy(cb.asc(screenshot.get("time")));
            screenshots = em.createQuery(criteria).getResultList();
         }
      }
      

       

      My current usage in my xhtml is as follows:

       

      ........
      ........
         <!-- Load .png images from the database -->
         <div class="ContentFlow">
             <div class="loadIndicator"><div class="indicator"></div></div>
                  <div class="flow">
                    <ui:repeat var="img" value="#{screenshots}">
                      <img class="item" src="#{img.png}" title="#{img.mode}"/>
                    </ui:repeat>
                  </div>
            <div class="globalCaption"></div>
            <div class="scrollbar"><div class="slider"><div class="position"></div></div></div>
         </div>
      ..........
      ..........
      

       

      My image cover flow successfully shows my mode within title, but obviously doesn't show my png image since it hasn't been converted. Is there an easy way to convert the byte array to an image in this context?

       

      Any help is very much appreciated.


        • 1. Re: display byte array as image from database using richfaces and JPA
          healeyb

          Hi, firstly the conclusion I eventually reached was that it was best to just store images in the file system. Prior to that I

          was using this solution which was heavily based on a solution published by the prolific and ever helpful BalusC. The

          idea behind this is that if you have a class Membership, then by passing the id of the row it will pass the photo attribute

          back as a stream which can be displayed by h:graphicImage. The idea behind photoInterface is that it is simply an

          interface which has a "photo" attribute.

           

          Regards,

          Brendan.

           

          package uk.co.sportquest.jsfbeans.helper;

           

           

          /*

          * @author Brendan Healey

          *

          * Originates from BalusC. Used like this:

          *

          * <h:graphicImage value="/ImageServlet/?class=Membership&amp;id=#{tm.id}"

          *

          * where Membership implements PhotoInterface...

          *

          */

           

           

          import java.io.Closeable;

          import java.io.IOException;

          import javax.inject.Inject;

          import javax.servlet.ServletException;

          import javax.servlet.ServletOutputStream;

          import javax.servlet.annotation.WebServlet;

          import javax.servlet.http.HttpServlet;

          import javax.servlet.http.HttpServletRequest;

          import javax.servlet.http.HttpServletResponse;

          import uk.co.sportquest.ejb.MembershipEJB;

          import uk.co.sportquest.general.Log;

           

           

          @WebServlet(name = "ImageServlet", urlPatterns = {"/ImageServlet/*"})

          public class ImageServlet extends HttpServlet {

           

           

              @Inject

              private MembershipEJB ejb;

           

           

              protected void processRequest(HttpServletRequest request, HttpServletResponse response)

                      throws ServletException, IOException {

           

           

                  String classString = request.getParameter("class");

                  String idString = request.getParameter("id");

           

           

                  if (classString == null || classString.isEmpty() || idString == null || idString.isEmpty()) {

                      response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.

                      return;

                  }

           

           

                  Long id = Long.parseLong(idString.trim());

           

           

                  PhotoInterface entry = null;

           

                  Class<?> c = null;

           

           

                  try {

                      c = Class.forName("uk.co.sportquest.entities." + classString.trim());

                  } catch (Exception ex) {

                      Log.log("Unknown class name: " + classString);

                  }

           

           

                  try {

                      entry = (PhotoInterface) ejb.find(c, id);

                  } catch (Exception ex) {

                      Log.log(ex.getMessage());

                  }

           

           

                  if (entry == null) {

                      response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.

                      return;

                  }

           

           

                  ServletOutputStream out = null;

           

           

                  try {

                      response.reset();

           

           

                      // It works ok without setting any of these...

                      //response.setContentType(image.getContentType());

                      //response.setHeader("Content-Length", String.valueOf(image.getLength()));

                      //response.setHeader("Content-Disposition", "inline; filename=\"" + image.getName() + "\"");

                      //response.setContentType("image/bmp");

                      //response.setContentType("image/x-jpeg");

           

           

                      out = response.getOutputStream();

           

           

                      if (entry.getPhoto() != null && entry.getPhoto().length != 0) {

                          out.write(entry.getPhoto());

                      }

                  } catch (IOException e) {

                      Log.log(e.getMessage());

                  } finally {

                      close(out);

                  }

           

           

              }

           

           

              @Override

              protected void doGet(HttpServletRequest request, HttpServletResponse response)

                      throws ServletException, IOException {

                  processRequest(request, response);

              }

           

           

              @Override

              protected void doPost(HttpServletRequest request, HttpServletResponse response)

                      throws ServletException, IOException {

                  processRequest(request, response);

              }

           

           

              // Helpers (can be refactored to public utility class) ----------------------------------------

              private static void close(Closeable resource) {

                  if (resource != null) {

                      try {

                          resource.close();

                      } catch (IOException e) {

                          // Do your thing with the exception. Print it, log it or mail it.

                          Log.log(e.getMessage());

                      }

                  }

              }

          }

          1 of 1 people found this helpful
          • 2. Re: display byte array as image from database using richfaces and JPA
            rlemerson

            Thanks for the quick reply Brendan! I had been looking over the original BalusC post and am still a bit confused with the DAO versus using my JPA and a jta datasource. I've tried adding an Image element to my Screenshot class along with a byte[] to Image conversion attempt on the fly within the getImage, but with no luck.

            • 3. Re: display byte array as image from database using richfaces and JPA
              healeyb

              Well try using the above code, you should be able to get it working. Here are a few extra snippets:

               

              <h:graphicImage value="/ImageServlet/?class=Membership&amp;id=#{tm.id}"/>

               

              PhotoInterface.java

              ----------------------------

              public interface PhotoInterface {

                  byte[] getPhoto();

              }

               

              Membership.java

              -------------------------

              @Entity

              public class Membership implements Serializable, PhotoInterface {

                  ...

                 @Basic(fetch = FetchType.LAZY)

                 @Column(name = "photo")

                 @Lob

                 private byte[] photo;

                 ...

                  // getters & setters required

                  ...

              }

              • 4. Re: display byte array as image from database using richfaces and JPA
                rlemerson

                Thanks for the code. I've used this with a few modifications, but am still having trouble displaying my images. I can see all of the rows returning and placeholders representing an image, but no image. Following is my setup:

                 

                ____________________________________________________________________________________________________________

                @Entity
                @XmlRootElement
                @Table(name="Jun2012", uniqueConstraints = @UniqueConstraint(columnNames = "id"))
                public class Screenshot implements Serializable, PhotoInterface {
                    private static final long serialVersionUID = 1L;

                    @Id
                    @GeneratedValue
                    private Long id;

                    private String user;

                    private Timestamp time;

                    private String mode;

                    @Lob
                    private byte[] png;

                    **** Getters/Setters,,,,,,, ****
                ___________________________________________________________________________________________________________

                 

                PhotoInferface......

                public interface PhotoInterface {

                          byte[] getPng();

                }

                ___________________________________________________________________________________________________________

                 

                /**

                * Servlet implementation class ImgServlet

                */

                @WebServlet(name = "ImgServlet", urlPatterns = {"/ImgServlet/*"})

                public class ImgServlet extends HttpServlet {

                          private static final long serialVersionUID = 1L;

                 

                    @Inject

                    Screenshot model;

                    private EntityManagerFactory emf;

                 

                    protected void processRequest(HttpServletRequest request, HttpServletResponse response)

                            throws ServletException, IOException {

                 

                        String classString = request.getParameter("class");

                        String idString = request.getParameter("id");

                 

                        if (classString == null || classString.isEmpty() || idString == null || idString.isEmpty()) {

                            response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.

                            return;

                        }

                 

                        Long id = Long.parseLong(idString.trim());

                        PhotoInterface entry = null;

                        EntityManager em = emf.createEntityManager();

                 

                        try {

                            entry = em.find(Screenshot.class, id);

                        } catch (Exception ex) {

                            //write to log

                        }

                 

                        if (entry == null) {

                            response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.

                            return;

                        }

                 

                        ServletOutputStream out = null;

                 

                        try {

                            response.reset();

                             // It works ok without setting any of these...

                            //response.setContentType(image.getContentType());

                            //response.setHeader("Content-Length", String.valueOf(image.getLength()));

                            //response.setHeader("Content-Disposition", "inline; filename=\"" + image.getName() + "\"");

                            //response.setContentType("image/bmp");

                            //response.setContentType("image/x-jpeg");

                 

                            out = response.getOutputStream();

                 

                            if (entry.getPng() != null && entry.getPng().length != 0) {

                                out.write(entry.getPng());

                            }

                        } catch (IOException e) {

                            //write to log

                        } finally {

                            close(out);

                        }

                    }

                 

                    public ImgServlet() {

                        super();

                        // TODO Auto-generated constructor stub

                    }

                 

                          /**

                           * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

                           */

                          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

                                    // TODO Auto-generated method stub

                          }

                 

                          /**

                           * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

                           */

                          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

                                    // TODO Auto-generated method stub

                          }

                 

                    // Helpers (can be refactored to public utility class) ----------------------------------------

                    private static void close(Closeable resource) {

                        if (resource != null) {

                            try {

                                resource.close();

                            } catch (IOException e) {

                                // Do your thing with the exception. Print it, log it or mail it.

                                //write to log

                            }

                        }

                    }

                }

                ___________________________________________________________________________________________________________

                 

                web.xml...........

                  <servlet>

                    <servlet-name>ImgServlet</servlet-name>

                    <servlet-class>org.jboss.tools.example.richfaces.servlets.ImgServlet</servlet-class>

                  </servlet>

                  <servlet-mapping>

                    <servlet-name>ImgServlet</servlet-name>

                    <url-pattern>/ImgServlet/*</url-pattern>

                  </servlet-mapping>

                ___________________________________________________________________________________________________________

                 

                xhtml.............

                <div class="ContentFlow">

                            <div class="loadIndicator"><div class="indicator"></div></div>

                            <div class="flow">

                              <ui:repeat var="img" value="#{screenshots}">

                                <img class="item" src="/ImgServlet/?class=Screenshot&amp;id=#{img.id}"/>

                              </ui:repeat>

                            </div>

                            <div class="globalCaption"></div>

                            <div class="scrollbar"><div class="slider"><div class="position"></div></div></div>

                          </div>

                ___________________________________________________________________________________________________________

                 

                I'm not sure what the problem may be. It could be something very simple that I've overlooked. If you have any other thoughts and suggestions just let me know. I really appreciate the help!!


                • 5. Re: display byte array as image from database using richfaces and JPA
                  healeyb

                  Is getPng() actually getting called? I know I had urlPatterns = {"/ImageServlet/*"}) without */ImageServlet. It would help to

                  load the page with something like chrome developer tools network tab to see what response the server is sending. Also

                  make sure that you've got a good image in the png attribute.

                   

                  Do you know which servlet container you're using (see web.xml <web-app version="3.0") - if you're using V3 you don't

                  need the web.xml entry because the @WebServlet annotation takes care of everything.

                   

                  I'm sure it's only a case of getting everything lined up correctly before it works ok.

                   

                  Regards,

                  Brendan.

                  • 6. Re: display byte array as image from database using richfaces and JPA
                    rlemerson

                    I've made a few tweaks, but still no images. I do have V3. So, I removed my new entries in web.xml. Also, my @WebServlet annotation appears to be the same. I've been looking at the network tab on chrome developer tools and see that I'm getting a 404 error on the images. It's telling me that they are of text/html, but that may be the default with the 404. I set the type to "image/png" by uncommenting the line: response.setContentType("image/png"); This didn't change anything though. At this point I think it may be something minor. I'm not 100% sure that I have a good image in the png attribute just yet, but plan to check that. Any other suggestions is appreciated! Thanks again for the input!

                    • 7. Re: display byte array as image from database using richfaces and JPA
                      healeyb

                      There are a couple of places in the code where it sends a 404 response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.

                      so probably best to put some logging in there.

                      • 8. Re: display byte array as image from database using richfaces and JPA
                        iabughosh

                        Hello Randy,

                        try using a4j:mediaOutput, i think it will help you to get over your problem.

                         

                        regards.

                        • 9. Re: display byte array as image from database using richfaces and JPA
                          rlemerson

                          Thanks for the info Ibrahim. I've researched a4j:mediaOutput a little in the past, but wasn't quite sure how easy it would be. Have you used this to display byte arrays from a database?

                          • 10. Re: display byte array as image from database using richfaces and JPA
                            rlemerson

                            I've been trying to verify that my ImgServlet is functioning properly by adding debug messages throughout ImgServlet.java. I've used PrintWriter, ServletContext, and even System.out.println, but haven't been seeing my log messages in the console or the log file in the AS7->standalone->log directory. Not sure if my ImgServlet just isn't working correctly or if I need to use another way of logging. Any suggestions?

                            • 11. Re: display byte array as image from database using richfaces and JPA
                              healeyb

                              I suspect that the servlet isn't being called rather than multiple logging issues. @WebServlet can be a dangerous annotation,

                              make sure that you don't have testing code with the same urlPattern sitting in the classpath. If you do then comment out the

                              @WebServlet line. This blew me to bits for ages at the time, having tried numerous different implementations (look at anything

                              with @WebServlet).

                               

                              Very importantly don't forget to clean & build.

                              • 12. Re: display byte array as image from database using richfaces and JPA
                                rlemerson

                                I made some progress on that issue. I changed the graphicImage call in the xhtml to this:

                                 

                                <h:graphicImage value="ImgServlet?id=#{img.id}"/>

                                 

                                and now it appears to be going into the servlet code. Although, I did move my code from processRequest to doGet.

                                 

                                Now I'm fighting with NullPointerExceptions and some other issues with creating an EntityManagerFactory to use with my "find" in doGet. It appears that there is an issue with using "primary" that is defined in my persistence.xml. I'm tracking down those issues as we speak. Any suggestions is appreciated. Thanks!!

                                • 13. Re: display byte array as image from database using richfaces and JPA
                                  iabughosh

                                  yes randy, here is the code :

                                   

                                  .xhtml :

                                            <h:dataTable value="#{imagesBacking.images}" var="image">

                                                      <h:column>

                                                                <f:facet name="header">ID</f:facet>

                                                                #{image.id}

                                                      </h:column>

                                                      <h:column>

                                                                <f:facet name="header">Image</f:facet>

                                                                <a4j:mediaOutput cacheable="false"                                                                       

                                                                                                         createContent="#{imagesBacking.paint}"

                                                                                                         element="img"

                                                                                                         mimeType="#{image.mime}"

                                                                                                         value="#{image}"/>

                                                      </h:column>

                                            </h:dataTable>

                                   

                                  kindly find the attached Java code.

                                   

                                  regards.

                                  • 14. Re: display byte array as image from database using richfaces and JPA
                                    rlemerson

                                    Thanks for the code example Ibrahim!

                                     

                                    After working through a few errors and getting my EntityManager defined correct it finally works!!

                                     

                                    Thanks for the help Brendan and Ibraham!

                                    1 2 Previous Next