6 Replies Latest reply on Feb 10, 2010 11:05 AM by ajk52

    NPE in audit queries

      Hello,

       

      I get the following NPE whenever I try to query my audit entities with reader.find or reader.createQuery().forEntitiesAtRevision:

       

      processRequests    got exception while processing    [java.lang.NullPointerException
          at org.hibernate.tuple.entity.AbstractEntityTuplizer.createProxy(AbstractEntityTuplizer.java:394)
          at org.hibernate.persister.entity.AbstractEntityPersister.createProxy(AbstractEntityPersister.java:3469)
          at org.hibernate.envers.entities.mapper.relation.ToOneIdMapper.mapToEntityFromMap(ToOneIdMapper.java:90)
          at org.hibernate.envers.entities.mapper.MultiPropertyMapper.mapToEntityFromMap(MultiPropertyMapper.java:118)
          at org.hibernate.envers.entities.EntityInstantiator.createInstanceFromVersionsEntity(EntityInstantiator.java:93)
          at org.hibernate.envers.entities.EntityInstantiator.addInstancesFromVersionsEntities(EntityInstantiator.java:103)
          at org.hibernate.envers.query.impl.EntitiesAtRevisionQuery.list(EntitiesAtRevisionQuery.java:90)
          at org.hibernate.envers.query.impl.AbstractAuditQuery.getSingleResult(AbstractAuditQuery.java:104)
          at org.hibernate.envers.reader.AuditReaderImpl.find(AuditReaderImpl.java:104)
          at com.loanworkbench.trust.ua.collection.ui.LegalActionsArchiveGrid$Adapter.getObjects(LegalActionsArchiveGrid.java:66)
          at com.softgenic.basis.comp.ObjectGridTemplate.<init>(ObjectGridTemplate.java:35)

       

      Envers tries to create proxy for the instances (not audited) that are referenced by audited entities but inside hibernate proxyFactory is null for this entity. Maybe it is caused by one of this:

      - the entity has default-proxy set to false (as all other entities in my case and I cannot change it)

      - this particular entity is immutable (mutable="false") and cached in the 2nd level cache (cache usage="read-only")

       

      Could this be a problem in envers? Are there any workarounds?

       

      Thank you.

        • 1. Re: NPE in audit queries
          adamw

          I must say I didn't know about default-proxy setting, what does it do?

          I would bet that it's also the culprit. Could you create a jira issue with a testcase? Or at least a description on how to reproduce?

           

          Adam

          • 2. Re: NPE in audit queries

            Hello, Adam,

             

            Sorry, "default-proxy" is a typo. I mean "default-lazy"

            • 3. Re: NPE in audit queries

              Adam,

               

              It looks like it really has to do with default-lazy = false (xml config) or its annotation alternative @Proxy(lazy=false).

              It iterates over audited class properties and executes the following code for referenced entities:

               

                              value = versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName).
                                      createProxy((Serializable)entityId, new ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision, verCfg));

               

              When i comment @Proxy(lazy=false) out on the referenced entity class (referencedEntityName) it goes through to the next property. If I uncomment it I get NPE in hibernate coding .

              • 4. Re: NPE in audit queries
                • 5. Re: NPE in audit queries
                  adamw

                  Ah, yes, probably the proxies aren't available at all then. Unfortunately I don't have any ideas on how to fix this without some debugging right now.

                   

                  Adam

                  • 6. Re: NPE in audit queries

                    I've been having the same problem with lazy=false entities. As a quick hack to see if I could get this working. I added the following in ToOneIdMapper, in the mapToEntityFromMap method:

                     

                      ToOneDelegateSessionImplementor sessionImplementor = new ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision, verCfg);

                     

                                  try {
                                    value = versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName).
                                            createProxy((Serializable)entityId, sessionImplementor);
                                  }
                                  catch (NullPointerException e) {
                                    // Tryied to proxy a non lazy object, need to load now
                                    value = sessionImplementor.doImmediateLoad(referencedEntityName);
                                  }

                     

                    Catching the NPE is not a nice way of doing it obv, but there wasn't an obvious way to check if an type is proxyable. This code will force the referenced object to be loaded immediately instead of proxying it (much like it would in the normal hibernate usage).

                     

                    I haven't really tested this much or with many situations, but it seems to work for what I'm doing. Perhaps it'll be of some help to someone to work out a proper fix.