Spring Boot version is 3.1.4.
Reproducer (ignore the README title, the initial scope of the reproducer is unrelated to this issue)
git clone git@github.com:fbiville/liquibase-neo4j-issue-479.git -b liquibase-only-props
docker run --rm \
--env NEO4J_AUTH='neo4j/letmein!' \
--env NEO4J_ACCEPT_LICENSE_AGREEMENT=yes \
--publish=7687:7687 \
--health-cmd "cypher-shell -u neo4j -p 'letmein!' 'RETURN 1'" \
--health-interval 5s \
--health-timeout 5s \
--health-retries 5 \
neo4j:5-enterprise
mvn spring-boot:run --file liquibase-neo4j-issue-479/pom.xml
Description
I believed (maybe wrongly so) that:
- having
spring-boot-starter,liquibase-core(andliquibase-neo4j) on the classpath - defining the configuration below
would theoretically be enough to run Liquibase:
spring:
liquibase:
driver-class-name: liquibase.ext.neo4j.database.jdbc.Neo4jDriver
change-log: classpath:changeLog.xml
url: jdbc:neo4j:neo4j://example.com
user: neo4j
password: *********
That is however not the case in practice.
First, I have to add spring-jdbc to the classpath, as org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseConfiguration requires it (via @ConditionalOnClass(ConnectionCallback.class)).
But when I do that, here is what I get:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
The quick fix would be move most of the properties under the spring.datasource namespace.
However, this is a bad idea, at the very least in the case of the Neo4j extension.
Indeed, liquibase.ext.neo4j.database.jdbc.Neo4jDriver is a JDBC implementation specifically created for Liquibase purposes: only the required subset of all the JDBC APIs are implemented, and Liquibase only uses a single connection per execution - which eliminates a lot of complexity that would arise in generic JDBC implementations.
In other words, the extension does NOT provide a generic JDBC implementation .
Configuring a Datasource with spring.datasource could lead to that data source being used outside Liquibase, thus exercising the aforementioned implementation that is not designed for general use.
I believe some other Liquibase extensions provide their own limited JDBC implementation as well (at least Mongo iirc), so it is very likely they would suffer from the same issue.
Is there a way to make the above configuration sufficient for executing Liquibase? It looks like it should be.
Comment From: wilkinsona
Spring Boot's support for Liquibase is intended for initializing an SQL database. Given this, it's to be expected that it may not work for initialization of a NoSQL database.
We can look at expanding the scope of our Liquibase integration to support Neo4j, Mongo, and the like, but that would be an enhancement in 3.3 or later rather than a bug fix in an existing version. In the meantime, to use Liquibase with Neo4j in a Spring Boot application you should define the SpringLiquibase bean yourself.
Comment From: rursprung
note: this is also relevant for liquibase-opensearch. i'll now probably build a bare minimum spring integration there for the time being.
i don't know if this can be handled purely on the Spring side or if SpringLiquibase (which is in liquibase-standard itself, not in spring boot) needs some modifications (to do it cleanly it most likely needs some as liquibase in general is tightly interwoven with java.sql. see also liquibase/liquibase#4236 for further details.
Comment From: wilkinsona
https://github.com/spring-projects/spring-boot/issues/47863 is a similar request for Flyway.