0 Replies Latest reply on Jan 12, 2011 12:14 PM by nathan dennis

    Entity Manager Returning Wrong DB Blob In a Servlet

    nathan dennis Expert

      jboss 5.1
      seam 2.2 GA


      Ive been fighting a problem one and off for about 4 months now. I followed the examples and wrote a servlet that servers up images from the DB. The issue is, the seams example provided periodically fails when there are multiple images on the page. i had previously used JAI for on the fly scaling and thought it was the source of the trouble. but after removing the code entirely and going with shane's 2Dgraphics example managed to get it working for one site. moved to a different site... and running the same servlet code saw the bug once again. so i debugged more and found that in fact the entityManager was returning the incorrect record. Im not sure if its a configuration problem or a serious bug in seams (something to do with caching maybe)..


      so i moved the servlet to a usermanaged transaction... and it worked.. mostly. the incorrect results query results stopped.. but then i started having trouble with the context not being active.. but not being able to join the transaction. end result is periodically the servlet will fail to return anything at all... i know i cant be the only person seeing this problem... here is some code...


      public class ContentServlet extends HttpServlet {
           private static final long serialVersionUID = -8461940507242022217L;
      
           private static final String IMAGES_PATH= "/image";
      
           private static final String MERCHANT_IMAGES_PATH = "/mimages";
           
           /**
            * The maximum width allowed for image rescaling
            */
           private static final int MAX_IMAGE_WIDTH = 800;
      
           private byte[] noImage;
      
           public ContentServlet() {
                InputStream in = getClass().getResourceAsStream("/img/seamlogo.png");
                if (in != null) {
                     ByteArrayOutputStream out = new ByteArrayOutputStream();
                     byte[] buffer = new byte[512];
                     try {
                          int read = in.read(buffer);
                          while (read != -1) {
                               out.write(buffer, 0, read);
                               read = in.read(buffer);
                          }
      
                          noImage = out.toByteArray();
                     } catch (IOException e) {
                     }
                }
      
           }
      
           @Override
           protected void doGet(HttpServletRequest request,
                     HttpServletResponse response) throws ServletException, IOException {
                String r = request.getPathInfo();
                String [] rarray = r.split("\\.");
                String [] nr = rarray;
                if (nr.length > 0){
                     nr = rarray[0].split("\\_");
                }
                if (IMAGES_PATH.equals(nr[0])) {
      //**************************************************
      //************THIS IS THE PROBLEM WITH THE EXAMPLE**
      //**************************************************
      
      
                     ContentAction contentAction = (ContentAction) Component
                               .getInstance(ContentAction.class);
      
                     String id = request.getParameter("id");
                     Picture mi = (id != null && !"".equals(id)) ? contentAction
                               .getProductImage(Long.parseLong(id)) : null;
      
                     String contentType = null;
                     byte[] data = null;
      
                     if (mi != null && mi.getImage() != null && mi.getImage().length > 0) {
                          contentType = mi.getContenttype();
                          data = mi.getImage();
                     } else if (noImage != null) {
                          contentType = "image/png";
                          data = noImage;
                     }
      
                     if (data != null) {
                          boolean ratiocrop = false;
                          boolean rescale = false;
                          int width = 0;
                          ImageIcon icon = null;
      
                          // Check if the image needs to be rescaled
                          if (request.getParameter("width") != null) {
                               width = Math.min(MAX_IMAGE_WIDTH, Integer.parseInt(request
                                         .getParameter("width")));
                               icon = new ImageIcon(data);
                               if (width > 0 && width != icon.getIconWidth())
                                    rescale = true;
                          }
      
                          // Rescale the image if required
                          if (rescale) {
                               String formatName = "";
                               if (contentType != null && contentType.indexOf("png") != -1)
                                    formatName = "png";
                               else if (contentType != null
                                         && (contentType.indexOf("jpg") != -1)
                                         || contentType.indexOf("jpeg") != -1)
                                    formatName = "jpeg";
                               else if (contentType != null
                                         && (contentType.indexOf("gif") != -1)
                                         || contentType.indexOf("gif") != -1)
                                    formatName = "gif";
                               else if (contentType != null
                                         && (contentType.indexOf("bmp") != -1)
                                         || contentType.indexOf("bmp") != -1)
                                    formatName = "bmp";
      
                               double ratio = (double) width / icon.getIconWidth();
                               int height = (int) (icon.getIconHeight() * ratio);
                               if (request.getParameter("ratiocrop") != null) {
                                    if (request.getParameter("ratiocrop").equals("true"))
                                         ratiocrop = true;
                               }
      
                               PictureUtilAction picaction = new PictureUtilAction();
                               picaction.loadPicture(data);
      
                               LayerUtilAction lu = new LayerUtilAction();
      
                               //picaction.loadRenderedImage(lu.createLayeredImage(picaction.writeRenderedImage()));
                               int cropxoff = 0;
                               int cropyoff = 0;
                               int cropwidth = picaction.writeRenderedImage().getWidth();
                               int cropheight = picaction.writeRenderedImage().getHeight();
                               if (ratiocrop) {
                                    if (cropwidth >= cropheight) {
                                         picaction.cropImage((int) (Math
                                                   .floor((cropwidth - cropheight) / 2)),
                                                   (int) 0, cropheight, cropheight);
                                         System.out.println("inside crop 1");
                                    } else if (cropwidth < cropheight) {
                                         picaction.cropImage((int) 0, (int) Math
                                                   .floor((cropheight - cropwidth) / 2),
                                                   cropwidth, cropwidth);
                                         System.out.println("inside crop 2");
                                    }
      
                                    picaction.loadBuffered(picaction
                                              .writeResult(formatName));
                               }
      
                               System.out.println("width:"
                                         + picaction.writeRenderedImage().getWidth()
                                         + " height: "
                                         + picaction.writeRenderedImage().getHeight());
                               picaction.loadRenderedImage(lu.createLayeredImage(picaction
                                         .writeRenderedImage()));
      
                               picaction.scaleImageBicubic((float) width);
      
                               response.getOutputStream().write(
                                         picaction.imageToByteArray(formatName, 1f));
      
                               //response.getOutputStream().write(picaction.bufferedToByteArray(picaction.writeResult("jpeg"), "jpeg"));
                          } else {
                               String formatName = "";
                               if (contentType != null && contentType.indexOf("png") != -1)
                                    formatName = "png";
                               else if (contentType != null
                                         && (contentType.indexOf("jpg") != -1)
                                         || contentType.indexOf("jpeg") != -1)
                                    formatName = "jpeg";
                               else if (contentType != null
                                         && (contentType.indexOf("gif") != -1)
                                         || contentType.indexOf("gif") != -1)
                                    formatName = "gif";
                               else if (contentType != null
                                         && (contentType.indexOf("bmp") != -1)
                                         || contentType.indexOf("bmp") != -1)
                                    formatName = "bmp";
                               PictureUtilAction picaction = new PictureUtilAction();
                               picaction.loadPicture(data);
      
                               LayerUtilAction lu = new LayerUtilAction();
                               //picaction.loadRenderedImage(lu.createLayeredImage(picaction.writeRenderedImage()));
                               //picaction.loadBuffered(picaction.writeResult(formatName));
                               //response.getOutputStream().write(picaction.bufferedToByteArray(picaction.writeResult(formatName), formatName));
                               response.getOutputStream().write(data);
                          }
                     }
      
                     response.getOutputStream().flush();
                } else if (IMAGES_PATH.equals(request.getPathInfo())){
                     /**TODO
                      * add the merchant image query and write response
                      */
                }
           } 
      }
      
      
      


      ContentAction.java -- seen this somewhere before?


      @Scope(STATELESS)
      @Name("contentAction")
      public class ContentAction {
           @In
           EntityManager entityManager;
      
           public Picture getProductImage(long pictureId) {
                Picture img = entityManager.find(Picture.class, pictureId);
      
                //if (img == null || !Identity.instance().hasPermission(img, "view"))
                // return null;
                // else
                return img;
           }
      
      



      so as i said before, first i changed my code to completely mirror the seams example... rendering included... and i still see the mess...
      then i did this..


      public class ContentServlet extends HttpServlet implements Serializable {
      
           /**
            * 
            */
           private static final long serialVersionUID = 7824843230114725939L;
      
           private static final String IMAGES_PATH= "/i";
      
           private String contentType = null;
           private byte[] data = null;
           private boolean watermark = true;
      
           private static final int MAX_IMAGE_WIDTH = 800;
      
           private byte[] noImage;
      
           public ContentServlet() {
                InputStream in = getClass().getResourceAsStream("/img/TruckLineArt.jpg");
                if (in != null) {
                     ByteArrayOutputStream out = new ByteArrayOutputStream();
                     byte[] buffer = new byte[512];
                     try {
                          int read = in.read(buffer);
                          while (read != -1) {
                               out.write(buffer, 0, read);
                               read = in.read(buffer);
                          }
      
                          noImage = out.toByteArray();
                     } catch (IOException e) {
                     }
                }
      
           }
      
           
           @Override
           protected void doGet(HttpServletRequest request,
                     HttpServletResponse response) throws ServletException, IOException {
              final HttpServletRequest req = request;
              final HttpServletResponse res = response;
               
              
              // Getting an EntityManager 
      
              EntityManager em = (EntityManager) Component
                      .getInstance("entityManager");
      
      ///Transactions the WRONG WAY.. i know this has to be all wrong
              UserTransaction utx = null;
              boolean txStarted = false;
              Picture picture = new Picture();
              Merchantpicture mi = new Merchantpicture();
              String query = null;
                try{                  
                data=null;            
                             
                String r = req.getPathInfo();
                String [] rarray = r.split("\\.");
                String [] nr = rarray;
                if (nr.length > 0){
                     nr = rarray[0].split("\\_");
                }
                //hack to handle adobe "_" problem
           //     if(nr.length < 2){
           //          nr = rarray[0].split("Z");
           //     }
                
      
                if (nr.length >1){
                     utx = (UserTransaction) Component
                  .getInstance("org.jboss.seam.transaction.transaction");
                          System.out.println(utx.getStatus());
                          if (utx.getStatus() == Status.STATUS_NO_TRANSACTION) {
                             utx.begin();
                             txStarted = true;
                         }
                         em.joinTransaction();
                         
      
                     String path = nr[0];
                     if (IMAGES_PATH.equals(path)){
                          query = "from Picture p where pid = :pid";
                           picture = (Picture) em.createQuery(query).setParameter("pid",
                                        Long.parseLong(nr[1])).getSingleResult();
                             
                           if (txStarted)
                                utx.commit(); 
                              contentType = picture.getContentType();
      
                     } else if (MERCHANT_IMAGES_PATH.equals(path)){
                          query = "from Merchantpicture p where mpid = :mpid";
                           mi = (Merchantpicture) em.createQuery(query).setParameter("mpid",
                                        Long.parseLong(nr[1])).getSingleResult();
                             
                           if (txStarted)
                                utx.commit(); 
                              contentType = mi.getContenttype();
                     }
                } else if (req.getParameter("id") != null) {
                     switchEntity(nr[0], req.getParameter("id"));     
                }
                //if (data != null) {
                if (picture.getImage() != null || mi.getImage() !=null) {
                          boolean rescale = false;
                          int width = 0;
                          ImageIcon icon = null;
                          if(picture.getImage() != null){
                               icon =  new ImageIcon(picture.getImage());//new ImageIcon(data);;
                          } else if (mi.getImage() != null){
                               icon = new ImageIcon(mi.getImage());
                          }
      
                          // Check if the image needs to be rescaled
                          if (req.getParameter("width") != null) {
                               width = Math.min(MAX_IMAGE_WIDTH, Integer.parseInt(req
                                         .getParameter("width")));
                               icon = new ImageIcon(data);
                               if (width > 0 && width != icon.getIconWidth())
                                    rescale = true;
                          } else {
                               if (nr.length >2 ){
                                    if(nr.length > 3)
                                    try{     
                                    width = Math.min(MAX_IMAGE_WIDTH, Integer.parseInt(nr[2]));
                                    
                                    if (width > 0 && width < icon.getIconWidth())
                                         rescale = true;
                                    } catch(Exception e){ e.printStackTrace();}
                               }
                          }
      
                          
      
                            response.setContentType(contentType);
                   
       
        
                            // Rescale the image if required
                            if (rescale)
                            {
                               double ratio = (double) width / icon.getIconWidth();
                               int height = (int) (icon.getIconHeight() * ratio);
                               
                               int imageType = "image/png".equals(contentType) ? 
                                     BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;                  
                               BufferedImage bImg = new BufferedImage(width, height, imageType);
                               Graphics2D g2d = bImg.createGraphics();
                               g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                                     RenderingHints.VALUE_INTERPOLATION_BICUBIC);
                               g2d.drawImage(icon.getImage(), 0, 0, width, height, null);
                               g2d.dispose();
                   
                               String formatName = "";
                               if (contentType != null && contentType.indexOf("png") != -1)
                                  formatName = "png";
                               else if (contentType != null && (contentType.indexOf("jpg") != -1) ||
                                     contentType.indexOf("jpeg") != -1)
                                  formatName = "jpeg";
                   
                               ImageIO.write(bImg, formatName, response.getOutputStream());
                            }
                            else
                            {
                              if(picture.getImage() != null){
                                   response.getOutputStream().write(picture.getImage());//.write(data);
                              } else if (mi.getImage() != null){
                                   response.getOutputStream().write(mi.getImage());
                              }
                            }
                         }
      
                         response.getOutputStream().flush();
                         response.getOutputStream().close();
                      
                } catch(Exception e) {
                     try {
                          utx.rollback();
                     } catch (IllegalStateException e1) {
                          // TODO Auto-generated catch block
                          e1.printStackTrace();
                     } catch (SecurityException e1) {
                          // TODO Auto-generated catch block
                          e1.printStackTrace();
                     } catch (SystemException e1) {
                          // TODO Auto-generated catch block
                          e1.printStackTrace();
                     }
                     e.printStackTrace();
                     
                     
                }
           }
      }
      
      



      seriously ive been on this for 4 months. every time i think it is fixed.. give it a week and back again. can someone please direct me was to what might be going on here? i have debugged countless times and i know for a fact the parameters enter the servlet correctly in the seams example but the entityManager periodically returns the WRONG RECORD ,,, WHEN there are numerous servlet request on the same page.
      im getting desperate here and doubting my abilities started 3 months ago. PLEASE,, how do i make the problem just go away and work like the code i wrote???