Skip to content

Grails 3.0.1 - save() causes NullPointerException under a certain JDK version when there is a validation error #698

@nobeans

Description

@nobeans

Reproducible example: https://github.com/nobeans/grails-report-grails301-domain-save-npe

In my environment (Mac OS X 10.10.3), when running the BookSpec:

  • Java 8u45: PASSED
  • Java 7u80: FAILED with NPE like this.
java.lang.NullPointerException
    at org.hibernate.engine.spi.BatchFetchQueue.removeBatchLoadableEntityKey(BatchFetchQueue.java:163)
    at org.hibernate.engine.internal.StatefulPersistenceContext.addEntity(StatefulPersistenceContext.java:388)
    at org.hibernate.engine.internal.StatefulPersistenceContext.addEntity(StatefulPersistenceContext.java:461)
    at org.hibernate.action.internal.AbstractEntityInsertAction.makeEntityManaged(AbstractEntityInsertAction.java:143)
    at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:203)
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:181)
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:216)
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:324)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:209)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:194)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:114)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:684)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:676)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:671)
    at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.performSave_closure3(AbstractHibernateGormInstanceApi.groovy:254)
    at groovy.lang.Closure.call(Closure.java:423)
    at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:198)
    at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:142)
    at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:112)
    at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.performSave(AbstractHibernateGormInstanceApi.groovy:253)
    at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.save(AbstractHibernateGormInstanceApi.groovy:179)
    at org.grails.datastore.gorm.GormInstanceApi.save(GormInstanceApi.groovy:101)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:112)
    at grails301.domain.save.npe.BookSpecSpec.$tt__$spock_feature_0_1(BookSpecSpec.groovy:28)
    at grails301.domain.save.npe.BookSpecSpec.It works well if there is a validate error: maxSize_closure2(BookSpecSpec.groovy)
    at groovy.lang.Closure.call(Closure.java:423)
    at groovy.lang.Closure.call(Closure.java:439)
    at grails.transaction.GrailsTransactionTemplate$1.doInTransaction(GrailsTransactionTemplate.groovy:67)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at grails.transaction.GrailsTransactionTemplate.executeAndRollback(GrailsTransactionTemplate.groovy:64)
    at grails301.domain.save.npe.BookSpecSpec.It works well if there is a validate error: maxSize(BookSpecSpec.groovy)

It depends on JVM version (and/or more something environmental).

When I tried to show DEBUG log of org.grails.spring.beans.factory.OptimizedAutowireCapableBeanFactory for analysis, I realized that the order of initializing beans was different between in Java 7 and 8.

And when the NPE occurred, org.grails.gorm.hibernate.internal.POST_INIT_BEAN-DEFAULT bean was initialized before the domain class' validator bean. I think it has to be initialized after all user's domain validator beans. Does it have to do with this issue?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions