hypersistence-utils: Cannot read the array length because "" thrown by Hibernate 6 when using the PostgreSQLEnumType with Audited

In combination with Envers, Hibernate throws error

java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

	at org.hibernate.type.EnumType.getAnnotation(EnumType.java:228)
	at org.hibernate.type.EnumType.getEnumType(EnumType.java:219)
	at org.hibernate.type.EnumType.setParameterValues(EnumType.java:126)
	at com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType.setParameterValues(PostgreSQLEnumType.java:46)
	at org.hibernate.mapping.MappingHelper.injectParameters(MappingHelper.java:70)

when I mark up an enum with the @Type(PostgreSQLEnumType.class) annotation. The problem can be reproduced very easily by changing the test as follows:

    @Audited
    @Entity(name = "Post")
    @Table(name = "post")
    public static class Post {

        ...
        
        @Enumerated(EnumType.STRING)
        @Column(columnDefinition = "post_status_info")
        @Type(PostgreSQLEnumType.class)
        private PostStatus status;

       ...
    }

The expected behavior would be that also for the processing of the audit log table the annotations are recognized.

Setup

+- org.springframework.boot:spring-boot-starter-web:jar:3.0.0:compile
+- org.springframework.boot:spring-boot-starter-data-jpa:jar:3.0.0:compile
|  +- org.hibernate.orm:hibernate-core:jar:6.1.5.Final:compile
|  |  +- jakarta.persistence:jakarta.persistence-api:jar:3.1.0:compile
|  |  \- ...
+- org.hibernate.orm:hibernate-envers:jar:6.1.5.Final:compile
+- com.vladmihalcea:hibernate-types-60:jar:2.20.0:compile

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 34 (14 by maintainers)

Commits related to this issue

Most upvoted comments

I’m sure that I could get used to it, but Java has been evolveing beautifully over the past years, so I’ll stick to it.

If 6.1.7 has the fix for HHH-15970, and you can still replicate this issue mentioned here, then HHH-15970 is not related to HHH-15806.

@skromberg The issue no longer replicates in HIbernate 6.2, and the project provides the hypersistence-utils-hibernate-62 for Hibernate 6.2.

I created this test case to prove that the problem was solved in Hibernate.

@vladmihalcea - I have now invested three hours to understand the problem. The second call (by @Audited annotation) of the method setParameterValues is executed without the property

org.hibernate.type.ParameterType.xproperty -> {JavaXProperty@7552} "status" with the related annotations

annotationsMethod = {Annotation[3]@7740} 
 0 = {$Proxy46@7746} "@jakarta.persistence.Enumerated(STRING)"
 1 = {$Proxy47@7747} "@jakarta.persistence.Column(nullable=true, precision=0, unique=false, name="", length=255, scale=0, updatable=true, columnDefinition="post_status_info", table="", insertable=true)"
 2 = {$Proxy48@7748} "@org.hibernate.annotations.Type(parameters={}, value=com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType.class)"

Hibernate should pass this correctly. Maybe my ticket is wrong here - and should be created in Hibernate.

@vladmihalcea Thanks, but even with the latest library, the problem persits.

you still use hypersistence-utils-hibernate-60 but there is a hypersistence-utils-hibernate-62

For boot user, I’ve tried it with spring boot 3.0.5, but it doesn’t work. probably we need to wait till 6.2.x version support from boot.

  implementation("org.springframework.boot:spring-boot-starter-data-jpa") {
    exclude(module = "hibernate-core")
  }
  implementation("org.hibernate:hibernate-core:6.2.0.Final")
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: org/hibernate/type/descriptor/converter/spi/EnumValueConverter
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) ~[spring-beans-6.0.7.jar:6.0.7]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.7.jar:6.0.7]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.7.jar:6.0.7]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.7.jar:6.0.7]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.7.jar:6.0.7]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.7.jar:6.0.7]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.7.jar:6.0.7]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1132) ~[spring-context-6.0.7.jar:6.0.7]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:907) ~[spring-context-6.0.7.jar:6.0.7]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[spring-context-6.0.7.jar:6.0.7]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.0.5.jar:3.0.5]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-3.0.5.jar:3.0.5]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-3.0.5.jar:3.0.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[spring-boot-3.0.5.jar:3.0.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1304) ~[spring-boot-3.0.5.jar:3.0.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1293) ~[spring-boot-3.0.5.jar:3.0.5]
	at co.sprintapp.api.ApplicationKt.main(Application.kt:32) ~[main/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-3.0.5.jar:3.0.5]
Caused by: java.lang.NoClassDefFoundError: org/hibernate/type/descriptor/converter/spi/EnumValueConverter
	at io.hypersistence.utils.hibernate.type.HibernateTypesContributor.contribute(HibernateTypesContributor.java:61) ~[hypersistence-utils-hibernate-62-3.3.1.jar:na]
	at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:390) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
	at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:143) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1348) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1419) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) ~[spring-orm-6.0.7.jar:6.0.7]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[spring-orm-6.0.7.jar:6.0.7]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.0.7.jar:6.0.7]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.0.7.jar:6.0.7]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) ~[spring-orm-6.0.7.jar:6.0.7]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1816) ~[spring-beans-6.0.7.jar:6.0.7]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) ~[spring-beans-6.0.7.jar:6.0.7]
	... 21 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.hibernate.type.descriptor.converter.spi.EnumValueConverter
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na]
	... 33 common frames omitted

@dmitry-weirdo Here’s a list of 250 Major issues from 2004 onward that are all assigned.

I think you are missing the fact that the Hibernate ORM project has a very small team that has to work on:

When I was working on Hibernate, we were 4-5 people working on the project. I bet most of you are working on teams that have more devs than the Hibernate core team.

So, you can follow my advice and provide a fix, or you can leave it to chance and see how it goes. It’s up to you.

@skromberg As an ex-Hibernate developer, if the ticket was not assigned, it’s unlikely that it will be resolved.

So, from my experience, the best way to make sure that a ticket is resolved is if you provide a Pull Request with a fix proposal for it. Otherwise, it may take years if the issue is not critical to the core team. For instance, there will always be issues that will still be unresolved after 10 or 15 years.

@skromberg- That’s sad. It is the last puzzle for migration 😦

The only way I could make enum type work for postgres is to use below

@Enumerated(EnumType.STRING)
@Column(columnDefinition = "<name of enum on DB>")

and add specify stringtype=unspecified in jdbc url.