Charlie Martin
Charlie Martin

Reputation: 112366

Grails/Hibernate: Null Pointer Exception on versioning

Working with a legacy codebase in Grails. Under some conditions (we're unclear exactly what) we get a mysterious NPE, stack trace as below, while doing a findBy.

So far we're sort of stymied; this appears in several fora for Hibernate but the responses seem to come down to "something is wrong with your schema." It would be wonderful to find some additional detail to help us track the issue down.

Update

Thanks for the answer. Yes, it's clear that at the point this NPE happens, version is null. The trouble is that when we look at it in the code, it's not null.

We've begun to suspect there's a threading issue.

Caused by: java.lang.NullPointerException
    at org.hibernate.type.LongType.next(LongType.java:79)
    at org.hibernate.engine.Versioning.increment(Versioning.java:131)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.getNextVersion(DefaultFlushEntityEventListener.java:387)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:279)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:151)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
    at org.codehaus.groovy.grails.plugins.quartz.listeners.SessionBinderJobListener.jobWasExecuted(SessionBinderJobListener.java:58)
    at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1910)

Upvotes: 20

Views: 10249

Answers (4)

qiulvelu
qiulvelu

Reputation: 1

@Version
@Column(name = "xxx")
private Integer xxx;

find @Version annotation in your VO and set this column a default value in database;

Upvotes: 1

BlueLettuce16
BlueLettuce16

Reputation: 2093

I had the same problem. This is the problem with old database records. You have added version column in your database table and @Version annotation in your VO and it works fine for the new objects, that were created after that chagne, however it fails for old objects - value in this column is null. The solution is to update all old object - their version column with 0 (or some different value depending on datatype). I hope it helps.

Upvotes: 12

Ravi Parekh
Ravi Parekh

Reputation: 5594

<version name="versionID" type="java.lang.Long" unsaved-value="null">
  <column name="version" precision="10" scale="0"/>
</version>

try removing unsaved-value="null" or adding unsved-value="null"

Upvotes: 0

Pascal Thivent
Pascal Thivent

Reputation: 570365

Here is my understanding of the trace:

  • you or something do a findBy
  • this triggers a flush
  • the session contains a dirty object with a version field (of type Long) that needs to get updated
  • Hibernate tries to get the next value for the version field for the update
  • and that's where you get a NPE

The body of org.hibernate.engine.Versioning.increment(Versioning.java:131) is:

public static Object increment(Object version, VersionType versionType, SessionImplementor session) {
    Object next = versionType.next( version, session ); // line 131
    if ( log.isTraceEnabled() ) {
        log.trace(
                "Incrementing: " +
                versionType.toLoggableString( version, session.getFactory() ) +
                " to " +
                versionType.toLoggableString( next, session.getFactory() )
        );
    }
    return next;
}

And the body of org.hibernate.type.LongType.next(LongType.java:79) (which provides the implementation of the above versionType.next):

public Object next(Object current, SessionImplementor session) {
    return new Long( ( (Long) current ).longValue() + 1 ); // line 79
}

It seems clear that the version passed to increment is null.

I would thus look in the database for a record with a NULL value in its version column. Activating SQL logging might help to narrow down the search.

Upvotes: 24

Related Questions