Schema drop fails after H2 upgrade to 2.1.212

Hi everyone,

we have a tricky error after upgrading our H2-dependency to version 2.1.212. Our Liquibase Version is 4.11.0.

We use H2 in our spring boot tests. After the upgrade we experience that every time the application test context is build up new (for example if a test uses a mockbean) the drop of the schema by liquibase fails.

Our application properties that are used in the tests are:

swagger.json.location=openapi/openapi.json swagger.json.location=openapi/openapi.json

test database

spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;CASE_INSENSITIVE_IDENTIFIERS=TRUE;DB_CLOSE_ON_EXIT=false;INIT=CREATE SCHEMA IF NOT EXISTS test\\;SET SCHEMA test;MODE=MySQL;DATABASE_TO_LOWER=TRUE
spring.datasource.username=sa
spring.datasource.password=

database dialect

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=validate

Liquibase

spring.liquibase.default-schema=test
spring.liquibase.liquibase-schema=test
spring.liquibase.user=sa
spring.liquibase.password=
spring.liquibase.drop-first=true
spring.liquibase.parameters.appDbUser=sa

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

We debugged a lot and we saw that the error is happening at the drop of the old schema at the "StandardLockService"

This leads to the following error:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.DatabaseException: liquibase.exception.CommandExecutionException: java.lang.NullPointerException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:144)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
	... 27 more
Caused by: liquibase.exception.DatabaseException: liquibase.exception.CommandExecutionException: java.lang.NullPointerException
	at liquibase.Liquibase.dropAll(Liquibase.java:1833)
	at liquibase.Liquibase.dropAll(Liquibase.java:1810)
	at liquibase.integration.spring.SpringLiquibase.createLiquibase(SpringLiquibase.java:330)
	at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:267)
	at org.springframework.boot.autoconfigure.liquibase.DataSourceClosingSpringLiquibase.afterPropertiesSet(DataSourceClosingSpringLiquibase.java:46)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800)
	... 44 more
Caused by: liquibase.exception.CommandExecutionException: java.lang.NullPointerException
	at liquibase.command.CommandScope.execute(CommandScope.java:163)
	at liquibase.Liquibase.dropAll(Liquibase.java:1831)
	... 50 more
Caused by: java.lang.NullPointerException
	at liquibase.diff.output.changelog.ChangeGeneratorFactory.fixUnexpected(ChangeGeneratorFactory.java:102)
	at liquibase.lockservice.StandardLockService.destroy(StandardLockService.java:489)
	at liquibase.command.core.InternalDropAllCommandStep.run(InternalDropAllCommandStep.java:118)
	at liquibase.command.CommandScope.execute(CommandScope.java:157)
	... 51 more

Did anyone experience this before?

I edited your post to format the code snippets. It’s much easier to help if you post the code or error text as plain text using the available formatting buttons rather than images, because then the folks in the community who want to help don’t have to type the text from the image out, we can just copy and paste it if we need to use it to search or to correct something.

I searched for the first line of the error message and found the same error in several postings on StackOverflow, including this one from December 2020: java - Error creating bean with name 'liquibase' in Spring Boot App - Stack Overflow

The accepted answer on that post reads:

you should add path to your changelog file in application.yml

for example:

spring:
  liquibase:
    change-log: classpath:db/changelog/db.changelog-master.xml

and you should create valid empty changelog:

<?xml version="1.0" encoding="UTF-8"?>

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">


</databaseChangeLog>

Hi Tabby,
Thank you for the formatting and your reply :smile:
tried the configuration of the change-log path you mentioned but the error persists. This makes sense in a way because “classpath:db/changelog/db.changelog-master.yaml” is the default value of this parameter. Additionaly: It did work before we upgraded the h2-database with the configuration mentioned in my post.

Kind Regards
Tobias

What version of H2 were you using before the upgrade? Forgive me if it was in your post, I only skimmed it when checking your reply. Have you looked at H2’s resources? I looked to see if the issue was resolved in the 214 update, but didn’t see anything that looked like it matched. They also have a GitHub repo where you can report this as a bug. Issues · h2database/h2database · GitHub

Hi Tabby, we are now currently using version 1.4.200 of the H2 database. Yes, I already consulted the Release Notes and other documentation on their website but without success so far :frowning:
Maybe my next stop will be the h2 github. Thanks for pointing that out!

I think the issue is DATABASE_TO_LOWER=TRUE (and likewise setting DATABASE_TO_UPPER=FALSE) because internally, Liquibase seems to have a case sensitive cache of database entities, and forcing to lowercase when Liquibase tries to find DATABASECHANGELOG it can’t be found in its snapshot.

Likewise, not forcing to uppercase creates a similar issue.

Leaving as default, and just setting CASE_INSENSITIVE_IDENTIFIERS=TRUE allows Liquibase to be case sensitive, but then allows JPA/Hibernate generated queries to not be thrown off kilter by quoted identifiers, which are forced to be case sensitive without CASE_INSENSITIVE_IDENTIFIERS=TRUE.