7 Replies Latest reply on Jul 11, 2005 2:31 PM by Jeff Schnitzer

    Storing Image and PDF files

    Murtuza Vohra Newbie

      Hello,

      How to store files such as image and pdf files using EJB3. What data type should be used when such files have data upto 2-3MB.

      One of the way i found people doing it through other forum is they use byte[] data type and may be they use some custom code to read and write image files at the client end. I want to know if this is good technique for large files upto 3MB. What other techniques can we use?

      Murtuza

        • 2. Re: Storing Image and PDF files
          Jon Åkerström Newbie

          Be aware though, if you are using MySQL to handle the blob limit issue.

          Se my earlier posts on this:

          http://www.jboss.org/index.html?module=bb&op=viewtopic&t=62137

          • 3. Re: Storing Image and PDF files
            Murtuza Vohra Newbie

            I get following errors when i try to insert the image in the database using blob datatype

            11:47:29,809 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: S1000
            11:47:29,809 ERROR [JDBCExceptionReporter] Packet for query is too large (1048592 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.
            11:47:29,809 INFO [STDOUT] javax.ejb.EJBException: null; CausedByException is:
             could not insert: [com.kt.order.entity.bean.ProductDetails]
            11:47:29,809 INFO [STDOUT] at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:46)
            11:47:29,809 INFO [STDOUT] at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:70)
            11:47:29,809 INFO [STDOUT] at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:134)
            11:47:29,809 INFO [STDOUT] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
            11:47:29,809 INFO [STDOUT] at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:72)
            11:47:29,809 INFO [STDOUT] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
            11:47:29,809 INFO [STDOUT] at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:39)
            11:47:29,809 INFO [STDOUT] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
            11:47:29,809 INFO [STDOUT] at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:63)
            11:47:29,809 INFO [STDOUT] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
            11:47:29,809 INFO [STDOUT] at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:93)
            11:47:29,819 INFO [STDOUT] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
            11:47:29,819 INFO [STDOUT] at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:183)
            11:47:29,819 INFO [STDOUT] at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:107)
            11:47:29,819 INFO [STDOUT] at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:69)
            11:47:29,819 INFO [STDOUT] at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:325)
            11:47:29,819 INFO [STDOUT] at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:201)
            11:47:29,819 INFO [STDOUT] at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:259)
            11:47:29,819 INFO [STDOUT] at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:313)
            11:47:29,819 INFO [STDOUT] at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:147)
            11:47:29,819 INFO [STDOUT] org.hibernate.exception.GenericJDBCException: could not insert: [com.kt.order.entity.bean.ProductDetails]
            


            Here is the code snippet of Entity bean

            @Column(name="imageBlob", columnDefinition="MEDIUMBLOB NOT NULL")
             public java.sql.Blob getImageBlob() {
             try {
             java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
             java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(baos);
             oos.writeObject(image);
             imageBlob = org.hibernate.Hibernate.createBlob(baos.toByteArray());
             System.out.println("getImageBlob: done");
             } catch (IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
             }
             return imageBlob;
             }
            


            For this test, the image size i used is not that big (28KB). It looks like it uses SQL statement to inset blob data??!!??

            Can anyone help me on how to store and retrieve blob data. As mentioned earlier, I will have files upto 3MB to store in the database.

            Murtuza

            • 4. Re: Storing Image and PDF files
              Murtuza Vohra Newbie

              Has anyone tried to insert huge files using EJB3.0 or is this a bug. Can you anyone help on this topic.

              Murtuza

              • 5. Re: Storing Image and PDF files
                Alain Penders Newbie

                Every BLOB/CLOB example I have seen uses the @Lob annotation, which is missing from the code example you gave. Adding that doesn't help?

                Personally I'd also write the getter to return a byte[], as it removes a dependancy on Hibernate (if, for example, you ever want to run the code on Oracle's EJB3 implementation).

                And yes, BLOBs getting inserted using SQL is normal.

                • 6. Re: Storing Image and PDF files
                  Jeff Schnitzer Newbie

                  You don't need to rely on Hibernate to use java.sql.Blob. The createBlob() method just creates a trivial object that implements the Blob by wrapping the InputStream or byte[] you pass it.

                  Just implement the wrapper yourself. Here's the code:

                  /*
                   * $Id$
                   * $URL$
                   *
                   * Similar to hibernate BlobImpl
                   */
                  
                  package com.similarity.sql;
                  
                  import java.io.ByteArrayInputStream;
                  import java.io.IOException;
                  import java.io.InputStream;
                  import java.io.OutputStream;
                  import java.sql.Blob;
                  import java.sql.SQLException;
                  
                  /**
                   * Trivial implementation of <code>java.sql.Blob</code>. Mostly borrowed
                   * from hibernate code.
                   *
                   * @author Gavin King
                   * @author Jeff Schnitzer
                   */
                  public class BlobImpl implements Blob
                  {
                   private InputStream stream;
                   private int length;
                   private boolean needsReset = false;
                  
                   public BlobImpl(byte[] bytes)
                   {
                   this.stream = new ByteArrayInputStream(bytes);
                   this.length = bytes.length;
                   }
                  
                   public BlobImpl(InputStream stream, int length)
                   {
                   this.stream = stream;
                   this.length = length;
                   }
                  
                   /**
                   * @see java.sql.Blob#length()
                   */
                   public long length() throws SQLException
                   {
                   return length;
                   }
                  
                   /**
                   * @see java.sql.Blob#getBinaryStream()
                   */
                   public InputStream getBinaryStream() throws SQLException
                   {
                   // First time through we don't need reset, all other times we do
                   if (needsReset)
                   {
                   try
                   {
                   stream.reset();
                   }
                   catch (IOException ex)
                   {
                   throw new SQLException("Could not reset stream");
                   }
                   }
                   else
                   needsReset = true;
                  
                   return stream;
                   }
                  
                   /**
                   * @see java.sql.Blob#truncate(long)
                   */
                   public void truncate(long pos) throws SQLException
                   {
                   throw new UnsupportedOperationException();
                   }
                  
                   /**
                   * @see java.sql.Blob#getBytes(long, int)
                   */
                   public byte[] getBytes(long pos, int len) throws SQLException
                   {
                   throw new UnsupportedOperationException();
                   }
                  
                   /**
                   * @see java.sql.Blob#setBytes(long, byte[])
                   */
                   public int setBytes(long pos, byte[] bytes) throws SQLException
                   {
                   throw new UnsupportedOperationException();
                   }
                  
                   /**
                   * @see java.sql.Blob#setBytes(long, byte[], int, int)
                   */
                   public int setBytes(long pos, byte[] bytes, int i, int j) throws SQLException
                   {
                   throw new UnsupportedOperationException();
                   }
                  
                   /**
                   * @see java.sql.Blob#position(byte[], long)
                   */
                   public long position(byte[] bytes, long pos) throws SQLException
                   {
                   throw new UnsupportedOperationException();
                   }
                  
                   /**
                   * @see java.sql.Blob#setBinaryStream(long)
                   */
                   public OutputStream setBinaryStream(long pos) throws SQLException
                   {
                   throw new UnsupportedOperationException();
                   }
                  
                   /**
                   * @see java.sql.Blob#position(Blob, long)
                   */
                   public long position(Blob blob, long pos) throws SQLException
                   {
                   throw new UnsupportedOperationException();
                   }
                  }
                  


                  • 7. Re: Storing Image and PDF files
                    Jeff Schnitzer Newbie

                    BTW I also found a problem fetching java.sql.Blob types. I'm using jboss-head from a couple days before the beta so I'm not sure if it has been fixed. Here's the JIRA entry (still open):

                    http://jira.jboss.org/jira/browse/EJBTHREE-194

                    My workaround was to fetch the Blob with JDBC.

                    Jeff