3 Replies Latest reply on Sep 21, 2006 11:58 AM by andygrav

    ERROR: invalid large-object descriptor: 0 with postgreql

    andygrav

      I have a problem reading Blob s in postgres
      ERROR: invalid large-object descriptor: 0 (in the log you see the spanish translation)

      I am not sure if it is to do with hibernate, postgres or seam.

      What I wanted to do is download a file thats in a Blob.

      I wrote a test using pure jdbc and the Blob in the database can be read correctly as long as autocomit is set to false.

      There are other pages that say the problem happens when not in a transaction
      http://jira.jboss.com/jira/browse/JBPORTAL-575
      http://archives.postgresql.org/pgsql-general/2004-09/msg00848.php
      http://archives.postgresql.org/pgsql-interfaces/2000-10/msg00004.php

      http://jdbc.postgresql.org/documentation/80/binary-data.html says
      You must access Large Objects within an SQL transaction block. You can start a transaction block by calling setAutoCommit(false).

      but I am using a stateful session bean with an extended persistent context
      also added em.joinTransaction(); just to make sure.

      In the log it shows that it is in a JTATransaction, does that mean that there is a JDBC Transaction to the database?

      Two related questions:
      Is what I am doing the best way to download a file?

      Another question I have is when writing the Blob I use
      Blob blob=Hibernate.createBlob(stream);
      but dont know if this requires that the whole file be in memory.
      If so how can I write it using an OutputStream

      thanks in advance

      Andy Bailey


      In the entity bean i have

      @Entity
      @Name("document")
      public class Document
      {
      private Blob content;
      @Lob @Basic(fetch = FetchType.EAGER)
      public Blob getContent()
      {
      return content;
      }

      public void setContent(Blob content)
      {
      this.content = content;
      }
      ...
      }



      @Stateful
      @Scope(SESSION)
      @Name("documents")
      public class DocumentsBean implements Serializable, Documents
      {
      @DataModel
      private List documentList;

      @DataModelSelection
      @In(required=false)
      @Out(required=false)
      private Document document;

      @PersistenceContext(type=EXTENDED)
      private EntityManager em;

      public void download()
      {
      //try to solve problem with blobs in postgres outside of transactions
      em.joinTransaction();

      FacesContext context = FacesContext.getCurrentInstance();

      HttpServletResponse response =
      ( HttpServletResponse ) context.getExternalContext().getResponse();

      String fileName=document.getFileName();
      String contentType=document.getContentType();
      int read = 0;
      byte[] bytes = new byte[1024];

      response.setContentType(contentType);

      response.setHeader("Content-Disposition", "attachment;filename=\"" +
      fileName + "\"");
      InputStream is = null;
      OutputStream os = null;

      try {

      Blob blob=document.getContent();
      is = blob.getBinaryStream();

      os = response.getOutputStream();
      while((read = is.read(bytes)) != -1){
      os.write(bytes,0,read);
      }

      os.flush();
      os.close();
      }
      catch (Exception e)
      {
      logger.error("download "+document,e);
      }

      FacesContext.getCurrentInstance().responseComplete();

      }


      Excerpt from the logs


      2006-09-15 09:04:17,730 DEBUG [org.jboss.seam.contexts.Contexts] found in session context: documents
      2006-09-15 09:04:17,730 DEBUG [org.jboss.seam.jsf.SeamVariableResolver] resolved name to seam component
      2006-09-15 09:04:17,730 DEBUG [org.jboss.ejb3.entity.ExtendedPersistenceContextPropagationInterceptor] ++++ LongLivedSessionPropagationInterceptor
      2006-09-15 09:04:17,730 DEBUG [org.hibernate.jdbc.JDBCContext] TransactionFactory reported no active transaction; Synchronization not
      registered
      2006-09-15 09:04:17,730 DEBUG [org.hibernate.ejb.AbstractEntityManagerImpl] Looking for a JTA transaction to join
      2006-09-15 09:04:17,730 DEBUG [org.hibernate.jdbc.JDBCContext] successfully registered Synchronization
      2006-09-15 09:04:17,731 DEBUG [org.jboss.seam.contexts.Contexts] found in event context: document
      2006-09-15 09:04:17,731 DEBUG [org.jboss.seam.Component] selected row: c cldc_mvm.pdf 130907 application/pdf
      2006-09-15 09:04:17,731 DEBUG [org.hibernate.ejb.AbstractEntityManagerImpl] Looking for a JTA transaction to join
      2006-09-15 09:04:17,731 DEBUG [org.hibernate.ejb.AbstractEntityManagerImpl] Transaction already joined
      2006-09-15 09:04:17,800 DEBUG [org.jboss.seam.Component] instantiating Seam component: interpolator
      2006-09-15 09:04:17,800 ERROR [com.hazlorealidad.sgi.control.DocumentsBean] download c cldc_mvm.pdf 130907 application/pdf
      java.io.IOException: java.sql.SQLException: ERROR: el descriptor de objeto grande no es válido: 0
      at org.postgresql.largeobject.BlobInputStream.read(BlobInputStream.java:97)
      at java.io.InputStream.read(InputStream.java:164)
      at java.io.InputStream.read(InputStream.java:89)
      at com.hazlorealidad.sgi.control.DocumentsBean.download(DocumentsBean.java:139)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
      at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
      at org.jboss.seam.interceptors.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
      at org.jboss.seam.interceptors.ValidationInterceptor.validateTargetComponent(ValidationInterceptor.java:64)
      at sun.reflect.GeneratedMethodAccessor444.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at org.jboss.seam.util.Reflections.invoke(Reflections.java:13)
      at org.jboss.seam.interceptors.Interceptor.aroundInvoke(Interceptor.java:90)
      at org.jboss.seam.interceptors.SeamInvocationContext.proceed(SeamInvocationContext.java:60)
      at org.jboss.seam.interceptors.OutcomeInterceptor.interceptOutcome(OutcomeInterceptor.java:21)
      at sun.reflect.GeneratedMethodAccessor443.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at org.jboss.seam.util.Reflections.invoke(Reflections.java:13)

      ...
      ] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
      2006-09-15 09:04:17,910 DEBUG [org.jboss.seam.jsf.SeamExtendedManagedPersistencePhaseListener] committing transaction after phase: INVOKE_APPLICATION(5)
      2006-09-15 09:04:17,910 DEBUG [org.jboss.seam.util.Naming] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
      2006-09-15 09:04:17,910 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] processing flush-time cascades
      2006-09-15 09:04:17,910 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] dirty checking collections
      2006-09-15 09:04:17,910 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
      2006-09-15 09:04:17,910 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 (re)creations, 0 updates, 0 removals
      to 0 collections
      2006-09-15 09:04:17,910 DEBUG [org.hibernate.pretty.Printer] listing entities:
      2006-09-15 09:04:17,911 DEBUG [org.hibernate.pretty.Printer] com.hazlorealidad.sgi.model.Document{digital=false, dateRegistered=2006-09-15 09:03:53, length=130907, content=org.hibernate.lob.SerializableBlob@e21cfc, controlled=true, contentType=application/pdf, external=false, id=23, version=1.0, fileName=cldc_mvm.pdf, dateModified=null, state=null, url=null, name=c}
      2006-09-15 09:04:17,911 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection
      2006-09-15 09:04:17,911 DEBUG [org.hibernate.jdbc.JDBCContext] TransactionFactory reported no active transaction; Synchronization not..

        • 1. Re: ERROR: invalid large-object descriptor: 0 with postgreql
          andygrav

          I added
          EntityTransaction tx1 = em.getTransaction();
          tx1.begin();
          just after em.joinTransaction();
          to see if I could force a jdbc transaction but got

          java.lang.IllegalStateException: JTA EntityManager cannot access a transactions
          at org.hibernate.ejb.AbstractEntityManagerImpl.getTransaction(AbstractEntityManagerImpl.java:278)
          at org.jboss.ejb3.entity.ExtendedEntityManager.getTransaction(ExtendedEntityManager.java:174)
          at com.hazlorealidad.sgi.control.DocumentsBean.download(DocumentsBean.java:97)
          ....

          • 2. Re: ERROR: invalid large-object descriptor: 0 with postgreql

            You cannot use an extended context with Blob. This is the reason you are getting the descriptor error. Make your persistence context type transactional.

            See this post, Part 2, for a more detailed description: http://forum.hibernate.org/viewtopic.php?t=963566

            Also, you might need to use the em.merge function to have the entity bean brought into the current EM context. You have to do this because the EM is injected each time the session bean is invoked.

            • 3. Re: ERROR: invalid large-object descriptor: 0 with postgreql
              andygrav

              Great that did the trick, thanks a lot.

              To sum up for anyone else with the same problem.

              The EntityBean has
              @Lob
              public Blob getContent()
              {
              return content;
              }
              In the Stateful session bean
              @DataModel
              private List documentList;

              @DataModelSelection
              @In(required=false)
              @Out(required=false)
              private Document document;

              @PersistenceContext
              private EntityManager em;

              //You do need to do the merge before accessing the BLOB

              em.merge(document);
              Blob blob=document.getContent();
              is = blob.getBinaryStream();
              ....