Thread: NullPointerException in TypeInfoCache.getSQLType
Hello,
I am running into a NullPointerException in the Postgres JDBC driver. I am running driver version postgresql-9.4.1208.jre7-SNAPSHOT.jar. I am running against Postgres server version "PostgreSQL 9.4.5 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit". The error occurs when I am starting up my Spring Boot application. Typically this is concurrent with the startup of several dozen other Spring Boot apps, all which use the same Postgres server, but each in an entirely different JVM. These concurrent startups all are typically creating new schemas (then tables and other things in those schemas). If the error occurs, restarting the Spring Boot app resolves it. I have searched google and the mailing list but didn't see any obvious hits (other than the mention of this revert from the 9.4-1205 changelog: https://github.com/pgjdbc/pgjdbc/pull/406). The relevant part of the stack trace is at the end of the email. One possible cause I can imagine is that org.postgresql.jdbc.TypeInfoCache.getPGType(int) returns null (because oid == Oid.UNSPECIFIED)(https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java#L387) and then org.postgresql.jdbc.TypeInfoCache.getSQLType(String) doesn't correctly handle this null (https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java#L182).
Has anyone seen this before? Thanks in advance for any help.
Caused by: java.lang.NullPointerException
at org.postgresql.jdbc.TypeInfoCache.getSQLType(TypeInfoCache.java:182)
at org.postgresql.jdbc.TypeInfoCache.getSQLType(TypeInfoCache.java:178)
at org.postgresql.jdbc.TypeInfoCache.requiresQuoting(TypeInfoCache.java:851)
at org.postgresql.jdbc.PgDatabaseMetaData.getTypeInfo(PgDatabaseMetaData.java:2785)
at org.hibernate.engine.jdbc.spi.TypeInfo.extractTypeInfo(TypeInfo.java:101)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:163)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1887)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1845)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 22 more
Do you have a reproducer? Can you check if you have types with typname of null? select * from pg_catalog.pg_type t where t.typname is null > all are typically creating new schemas Can it be like: 1) org.postgresql.jdbc.PgDatabaseMetaData#getTypeInfo loads all the type ids 2) as it reaches org.postgresql.jdbc.TypeInfoCache#getPGType(int), the type is no longer in the DB (e.g. dropped) ? Can you add logging to TypeInfoCache#getPGType & rebuild & test to log the actual oid in question? Vladimir
>It will be hard to supply a reproducer since it seems to require lots of concurrent startups Blind guess would be: a two-threaded test. Thread 1: create & drop table in a loop Thread 2: PgDatabaseMetaData.getTypeInfo & clear cache in a loop >Your explanation seems plausible. I will add the suggested logging That would be awesome. Vladimir
It will be hard to supply a reproducer since it seems to require lots of concurrent startups, but I will see if I can simplifythe reproducible case. Your explanation seems plausible. I will add the suggested logging and rebuild and test to log the oid and other information.It will probably be a few days before I have those results. Thanks for your suggestions and time, Zach Marshall -----Original Message----- From: Vladimir Sitnikov [mailto:sitnikov.vladimir@gmail.com] Sent: Wednesday, February 17, 2016 9:20 AM To: Zachary Marshall <Zachary.Marshall@sas.com> Cc: pgsql-jdbc@postgresql.org Subject: Re: [JDBC] NullPointerException in TypeInfoCache.getSQLType Do you have a reproducer? Can you check if you have types with typname of null? select * from pg_catalog.pg_type t where t.typname is null > all are typically creating new schemas Can it be like: 1) org.postgresql.jdbc.PgDatabaseMetaData#getTypeInfo loads all the type ids 2) as it reaches org.postgresql.jdbc.TypeInfoCache#getPGType(int), the type is no longer in the DB (e.g. dropped) ? Can you add logging to TypeInfoCache#getPGType & rebuild & test to log the actual oid in question? Vladimir
It will be hard to supply a reproducer since it seems to require lots of concurrent startups, but I will see if I can simplifythe reproducible case. Your explanation seems plausible. I will add the suggested logging and rebuild and test to log the oid and other information.It will probably be a few days before I have those results. Thanks for your suggestions and time, Zach Marshall -----Original Message----- From: Vladimir Sitnikov [mailto:sitnikov.vladimir@gmail.com] Sent: Wednesday, February 17, 2016 9:20 AM To: Zachary Marshall <Zachary.Marshall@sas.com> Cc: pgsql-jdbc@postgresql.org Subject: Re: [JDBC] NullPointerException in TypeInfoCache.getSQLType Do you have a reproducer? Can you check if you have types with typname of null? select * from pg_catalog.pg_type t where t.typname is null > all are typically creating new schemas Can it be like: 1) org.postgresql.jdbc.PgDatabaseMetaData#getTypeInfo loads all the type ids 2) as it reaches org.postgresql.jdbc.TypeInfoCache#getPGType(int), the type is no longer in the DB (e.g. dropped) ? Can you add logging to TypeInfoCache#getPGType & rebuild & test to log the actual oid in question? Vladimir
Vladimir I am able to reproduce the NullPointerException with a standalone test. I have created the following repository with the test case, https://github.com/stephraleigh/postgres-jdbc-npe-rep Please let me know if you are able to clone and reproduce the NPE. Thanks Steph -----Original Message----- From: Vladimir Sitnikov [mailto:sitnikov.vladimir@gmail.com] Sent: Wednesday, February 17, 2016 9:50 AM To: Zachary Marshall <Zachary.Marshall@sas.com> Cc: pgsql-jdbc@postgresql.org Subject: Re: [JDBC] NullPointerException in TypeInfoCache.getSQLType >It will be hard to supply a reproducer since it seems to require lots of concurrent startups Blind guess would be: a two-threaded test. Thread 1: create & drop table in a loop Thread 2: PgDatabaseMetaData.getTypeInfo & clear cache in a loop >Your explanation seems plausible. I will add the suggested logging That would be awesome. Vladimir
Thanks for the reproducer. I've implemented a fix here: https://github.com/pgjdbc/pgjdbc/pull/530 There are other similar places when type information is loaded by using several queries. For example: getProcedureColumns, however it is likely to be used with some reasonable schema/procedure patterns, thus it is less likely to fail. Vladimir
Vladimir I am able to reproduce the NullPointerException with a standalone test. I have created the following repository with the test case, https://github.com/stephraleigh/postgres-jdbc-npe-rep Please let me know if you are able to clone and reproduce the NPE. Thanks Steph -----Original Message----- From: Vladimir Sitnikov [mailto:sitnikov.vladimir@gmail.com] Sent: Wednesday, February 17, 2016 9:50 AM To: Zachary Marshall <Zachary.Marshall@sas.com> Cc: pgsql-jdbc@postgresql.org Subject: Re: [JDBC] NullPointerException in TypeInfoCache.getSQLType >It will be hard to supply a reproducer since it seems to require lots of concurrent startups Blind guess would be: a two-threaded test. Thread 1: create & drop table in a loop Thread 2: PgDatabaseMetaData.getTypeInfo & clear cache in a loop >Your explanation seems plausible. I will add the suggested logging That would be awesome. Vladimir
Thanks for the reproducer. I've implemented a fix here: https://github.com/pgjdbc/pgjdbc/pull/530 There are other similar places when type information is loaded by using several queries. For example: getProcedureColumns, however it is likely to be used with some reasonable schema/procedure patterns, thus it is less likely to fail. Vladimir