Liquibase R2DBC Spring Boot starter

Overview

Liquibase R2DBC Spring Boot starter tests pages

This repository demonstrates how 2 implement Liquibase R2DBC Spring Boot starter to be used in reactive projects with MySQL, MariaDB, PostgreSQL, MS SQL Server, r2dbc-pool, r2dbc-proxy or H2 database. It's not pure reactive liquibase implementation as you might think, we are simply transforming R2DBC URL into liquibase compatible in a little spring-boot starter to apply liquibase migrations update automatically within application runner bean

Maven Central

Getting started

<dependency>
  <groupId>io.github.daggerokgroupId>
  <artifactId>liquibase-r2dbc-spring-boot-starterartifactId>
  <version>2.0.5version>
dependency>

or

dependency("io.github.daggerok:liquibase-r2dbc-spring-boot-starter:2.0.5")

If you want to use *-SNAPSHOT version, please make sure you have added snapshot maven repository like so

<repositories>
    <repository>
        <id>sonatype-nexus-snapshotsid>
        <name>Sonatype OSS Snapshot Repositoryname>
        <url>https://s01.oss.sonatype.org/content/repositories/snapshotsurl>
        <snapshots><enabled>trueenabled>snapshots>
        <releases><enabled>falseenabled>releases>
    repository>
repositories>

or

repositories {
    maven {
        url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots")
    }
}

See: https://s01.oss.sonatype.org/content/repositories/snapshots/io/github/daggerok/

Otherwise, use only released version. See: https://repo1.maven.org/maven2/io/github/daggerok/liquibase-r2dbc-spring-boot-starter/

Technology Stack

  • Liquibase
  • R2DBC
  • Spring Boot
  • Kotlin
  • Junit Jupiter 5
  • H2 (file, mem)
  • MySQL
  • MariaDB
  • Postgresql
  • MS SQL Server
  • R2DBC (pool, proxy)
  • Testcontainers
  • Maven

Reference documentation

Checkout documentation for details

Developer guide for contributors

Feel free to contribute! Create a fork or report bug to improve this project

Build and test

./mvnw clean ; ./mvnw verify

Integration test (MySQL)

if [[ "" != `docker ps -aq` ]] ; then docker rm -f -v `docker ps -aq` ; fi

docker run -d --rm --name mysql --platform=linux/x86_64 \
  --health-cmd='mysqladmin ping -h 127.0.0.1 -u $MYSQL_USER --password=$MYSQL_PASSWORD || exit 1' \
  --health-start-period=1s --health-retries=1111 --health-interval=1s --health-timeout=5s \
  -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=database \
  -e MYSQL_USER=user -e MYSQL_PASSWORD=password \
  -p 3306:3306 \
  mysql:8.0.24

while [[ $(docker ps -n 1 -q -f health=healthy -f status=running | wc -l) -lt 1 ]] ; do
  sleep 3 ; echo -n '.'
done

sleep 15; echo 'MySQL is ready.'

rm -rf ~/.m2/repository/daggerok/liquibase/r2dbc* 
./mvnw clean install -DskipTests

./mvnw -f examples/mysql spring-boot:start

http :8001
http :8001/api
http :8001/api/messages
http :8001/api/messages body=hey
http :8001/api/messages

./mvnw -f examples/mysql spring-boot:stop
docker stop mysql

Integration test (Postgresql)

if [[ "" != `docker ps -aq` ]] ; then docker rm -f -v `docker ps -aq` ; fi

docker run -d --rm --name postgres -p 5432:5432 --platform=linux/x86_64 \
  -e POSTGRES_PASSWORD=password -e POSTGRES_DB=database -e POSTGRES_USER=user \
  --health-start-period=1s --health-retries=1111 --health-interval=1s --health-timeout=5s \
  --health-cmd='pg_isready -h 127.0.0.1 -p 5432 -d $POSTGRES_DB -U $POSTGRES_USER || exit 1' \
  postgres:14.3-alpine3.16

while [[ $(docker ps -n 1 -q -f health=healthy -f status=running | wc -l) -lt 1 ]] ; do
  sleep 3 ; echo -n '.'
done

rm -rf ~/.m2/repository/daggerok/liquibase/r2dbc* 
./mvnw clean install -DskipTests

./mvnw -f examples/postgresql spring-boot:start

http :8002
http :8002/api
http :8002/api/messages
http :8002/api/messages body=hey
http :8002/api/messages

./mvnw -f examples/postgresql spring-boot:stop
docker stop postgres

Integration test (H2 file)

rm -rf ~/.m2/repository/daggerok/liquibase/r2dbc* 
./mvnw clean install -DskipTests

./mvnw -f examples/h2/file spring-boot:start

http :8003
http :8003/api
http :8003/api/messages
http :8003/api/messages body=hey
http :8003/api/messages

./mvnw -f examples/h2/file spring-boot:stop

Integration test (H2 mem)

rm -rf ~/.m2/repository/daggerok/liquibase/r2dbc* 
./mvnw clean install -DskipTests

./mvnw -f examples/h2/mem spring-boot:start

http :8004
http :8004/api
http :8004/api/messages
http :8004/api/messages body=hey
http :8004/api/messages

./mvnw -f examples/h2/mem spring-boot:stop

Integration test (H2 tcp file)

if [[ "" != `docker ps -aq` ]] ; then docker rm -f -v `docker ps -aq` ; fi

docker run -p 3306:3306 -d --rm --name mariadb --platform=linux/x86_64 \
  --env MARIADB_USER=user --env MARIADB_PASSWORD=password --env MARIADB_ROOT_PASSWORD=password --env MARIADB_DATABASE=database \
  --health-cmd='mysqladmin ping -h 127.0.0.1 -u $MARIADB_USER --password=$MARIADB_PASSWORD || exit 1' \
  --health-start-period=1s --health-retries=1111 --health-interval=1s --health-timeout=5s \
  mariadb:10.7.4

while [[ $(docker ps -n 1 -q -f health=healthy -f status=running | wc -l) -lt 1 ]] ; do
  sleep 3 ; echo -n '.'
done
echo 'MariaDB is ready.'

rm -rf ~/.m2/repository/daggerok/liquibase/r2dbc* 
./mvnw clean install -DskipTests

./mvnw -f examples/mariadb spring-boot:start

http :8005
http :8005/api
http :8005/api/messages
http :8005/api/messages body=hey
http :8005/api/messages

./mvnw -f examples/mariadb spring-boot:stop

Integration test (MariaDB)

if [[ "" != `docker ps -aq` ]] ; then docker rm -f -v `docker ps -aq` ; fi

docker run -p 3306:3306 -d --rm --name mariadb --platform=linux/x86_64 \
  --env MARIADB_USER=user --env MARIADB_PASSWORD=password --env MARIADB_ROOT_PASSWORD=password --env MARIADB_DATABASE=database \
  --health-cmd='mysqladmin ping -h 127.0.0.1 -u $MARIADB_USER --password=$MARIADB_PASSWORD || exit 1' \
  --health-start-period=1s --health-retries=1111 --health-interval=1s --health-timeout=5s \
  mariadb:10.7.4

while [[ $(docker ps -n 1 -q -f health=healthy -f status=running | wc -l) -lt 1 ]] ; do
  sleep 3 ; echo -n '.'
done
echo 'MariaDB is ready.'

rm -rf ~/.m2/repository/daggerok/liquibase/r2dbc* 
./mvnw clean install -DskipTests

./mvnw -f examples/mariadb spring-boot:start

http :8005
http :8005/api
http :8005/api/messages
http :8005/api/messages body=hey
http :8005/api/messages

./mvnw -f examples/mariadb spring-boot:stop
You might also like...
Sample Social Login Project of Spring Boot and Kotlin

Sample-Spring-Boot-Social-Kotlin Sample Social Login Project of Spring Boot and Kotlin dependencies dependencies { implementation("org.springframewor

This repository demonstrates how Kotlin can simplify Spring Boot configuration properties file mapping

Kotlin spring-boot nested config props This repository demonstrates how Kotlin can simplify Spring Boot configuration properties file mapping @Constru

My personal template for a Spring Boot REST reactive webapp

My personal spring boot kotlin reactive template Features Spring Security implementation with JWT access and refresh token MongoDB database Project Co

The Okila server project uses the Spring boot framework and uses the Kotlin language

Okila-Server The Okila server project uses the Spring boot framework and uses the Kotlin language Format Response //The response successfully format

An application that simulate the Swedish Transport Agency, implemented with Spring Boot, Kotlin and GraphQL

graphql-kotlin-spring-server An application that simulate the Swedish Transport Agency, implemented with Spring Boot, Kotlin and GraphQL Running the s

API for a library using Kotlin, Spring-boot and covered by test

Library API This API is to create Books and be able to borrow from them I'm using: Spring Boot version 2.5.6 Kotlin 1.5.31 Java 11 I'm implementing us

Push notification application using One Signal + Spring Boot + Kotlin

Spring Boot push notification system using One Signal This project was created to demonstrate a simple application built with Kotlin + Spring Boot inc

Kotlin Based Spring Boot ETL project
Kotlin Based Spring Boot ETL project

Adverity ETL REST API (AERA) A simple ETL Spring Boot application with H2. This API provides the following basics functionalities: Endpoint that retur

Spring Boot Webflux RDBMS Sample App

R2DBC Spring Boot Webflux Sample Project generate schema (DDL script) h2-console (Web based database management console) WebFlux and r2dbc is not supp

Comments
  • liquibase loading twice when schema is not public

    liquibase loading twice when schema is not public

    I have the following configuration

    spring:
      r2dbc:
        url: 'r2dbc:h2:mem:///h2database'
        username: 'h2user'
        password: 'h2password'
        initialization-mode: always
        properties:
          Mode: PostgreSQL
          MULTI_THREADED: TRUE
          DB_CLOSE_ON_EXIT: FALSE
      liquibase:
        change-log: classpath:/db/changelog/db.changelog-master.yaml
        liquibase-schema: LIQUIBASE
        default-schema: EXAMPLE
    

    NOTE: the liquibase-schema is LIQUIBASE and default-schema is EXAMPLE

    When I try to boot the same I notice the following in the console

    2022-11-19 18:48:07.570  INFO 15851 --- [           main] p.respository.ExampleR2dbcTest           : Starting ExampleR2dbcTest using Java 17.0.5 on Pauls-MacBook-Pro.local with PID 15851 (started by paulwilliams in /Users/paulwilliams/Desktop/WORKSPACE/GIT/hexagonal-spring-boot-kotlin/r2dbc-adapter)
    2022-11-19 18:48:07.571  INFO 15851 --- [           main] p.respository.ExampleR2dbcTest           : The following 1 profile is active: "test"
    2022-11-19 18:48:07.744  INFO 15851 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
    2022-11-19 18:48:07.810  INFO 15851 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 64 ms. Found 1 R2DBC repository interfaces.
    2022-11-19 18:48:08.582  INFO 15851 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
    2022-11-19 18:48:08.596  INFO 15851 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
    2022-11-19 18:48:08.815  INFO 15851 --- [           main] liquibase.lockservice                    : Successfully acquired change log lock
    2022-11-19 18:48:08.899  INFO 15851 --- [           main] liquibase.changelog                      : Creating database history table with name: LIQUIBASE.DATABASECHANGELOG
    2022-11-19 18:48:08.902  INFO 15851 --- [           main] liquibase.changelog                      : Reading from LIQUIBASE.DATABASECHANGELOG
    Running Changeset: db/changelog/includes/201220202080010-create-example.yaml::create-table-t_example::Paul WILLIAMS
    2022-11-19 18:48:08.935  INFO 15851 --- [           main] liquibase.changelog                      : Table T_EXAMPLE created
    2022-11-19 18:48:08.936  INFO 15851 --- [           main] liquibase.changelog                      : ChangeSet db/changelog/includes/201220202080010-create-example.yaml::create-table-t_example::Paul WILLIAMS ran successfully in 4ms
    2022-11-19 18:48:08.945  INFO 15851 --- [           main] liquibase.lockservice                    : Successfully released change log lock
    2022-11-19 18:48:08.997  INFO 15851 --- [           main] p.respository.ExampleR2dbcTest           : Started ExampleR2dbcTest in 1.594 seconds (JVM running for 2.078)
    2022-11-19 18:48:08.999  INFO 15851 --- [           main] liquibase.database                       : Set default schema name to PUBLIC
    2022-11-19 18:48:09.005  INFO 15851 --- [           main] liquibase.lockservice                    : Successfully acquired change log lock
    2022-11-19 18:48:09.009  INFO 15851 --- [           main] liquibase.changelog                      : Creating database history table with name: PUBLIC.DATABASECHANGELOG
    2022-11-19 18:48:09.011  INFO 15851 --- [           main] liquibase.changelog                      : Reading from PUBLIC.DATABASECHANGELOG
    Running Changeset: db/changelog/includes/201220202080010-create-example.yaml::create-table-t_example::Paul WILLIAMS
    2022-11-19 18:48:09.017  INFO 15851 --- [           main] liquibase.changelog                      : Table T_EXAMPLE created
    2022-11-19 18:48:09.018  INFO 15851 --- [           main] liquibase.changelog                      : ChangeSet db/changelog/includes/201220202080010-create-example.yaml::create-table-t_example::Paul WILLIAMS ran successfully in 1ms
    2022-11-19 18:48:09.019  INFO 15851 --- [           main] liquibase.lockservice                    : Successfully released change log lock
    2022-11-19 18:48:09.021  INFO 15851 --- [           main] .g.d.l.r.LiquibaseR2dbcAutoConfiguration : R2DBC liquibase update classpath:/db/changelog/db.changelog-master.yaml completed
    2022-11-19 18:48:09.335  WARN 15851 --- [ionShutdownHook] o.s.b.f.support.DisposableBeanAdapter    : Custom destroy method 'close' on bean with name 'liquibaseR2dbcDatabase' threw an exception: liquibase.exception.DatabaseException: java.sql.SQLException: Connection is closed
    2022-11-19 18:48:09.335  WARN 15851 --- [ionShutdownHook] o.s.b.f.support.DisposableBeanAdapter    : Custom destroy method 'close' on bean with name 'liquibaseR2dbcJdbcConnection' threw an exception: liquibase.exception.DatabaseException: java.sql.SQLException: Connection is closed
    2022-11-19 18:48:09.335  INFO 15851 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
    2022-11-19 18:48:09.337  INFO 15851 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
    

    From the logs you may notice that the the tables are created twice once for schema EXAMPLE and again for schema PUBLIC.

    Is there any mis-configuration ?

    How to re-produce ?

    opened by paul58914080 0
  • Use SpringResourceAccessor instead of ClassLoaderResourceAccessor

    Use SpringResourceAccessor instead of ClassLoaderResourceAccessor

    When running a JAR produced by the Spring Boot Gradle Plugin. The JAR that is produced will not run correctly due to the autoconfiguration using the ClassLoaderResourceAccessor. In the Spring Boot JDBC version of the autoconfiguration SpringResourceAccessor is used, which is aware of the structure of the Spring Boot produced JAR so is able to find the liquibase changelogs.

    opened by surecloud-slloyd 1
  • why do u use R2DBC

    why do u use R2DBC

    Hi, i am reading your project and i am interested in this, but i have a question, why do you use R2DBC instead of other non blocking IO like Hibernate Reactive or others... can you tell me your purpose, the pros and cons of R2DBC, thank you so much

    opened by fizz12344321 0
Owner
Maksim Kostromin
Fullstack Senior Software Engineer, Team Lead in Software Company. I do cloud native Java, JS. Spring fan, Kotlin lover and Scala admirer. All we need is JVM
Maksim Kostromin
Reactive setup with Spring WebFlux , Kotlin, Postgres and Spring Data R2DBC

Reactive Spring with Kotlin and Pg Spring WebFlux with Netty instead of Spring Web with Tomcat Mono and Flux in all layers (controller, service, repo)

Bimal Raj Gyawali 7 Dec 9, 2022
Demo Spting REST Service on Kotlin. Works with PostgreSQL via Spring Data. Data initialization provided by liquibase

Spring Boot REST API with Kotlin Spring Boot REST API service. Spring Data with PostgreSQL. Data initialization with Liquibase. Swagger UI Reference D

null 0 Jun 10, 2022
This repository demonstrates Spring GraphQL + RSocket + WebFlux + R2DBC + H2

Reactive GraphQL with Spring This repository demonstrates Spring GraphQL + RSocket + WebFlux + R2DBC + H2 O__ +-----------+

Maksim Kostromin 1 Nov 27, 2021
Generated with spring boot kotlin starter kit

Kotlin backend Generated with spring boot kotlin starter kit The idea is to: Get a microservice written in kotlin for managing users and roles. To be

Oriol Subirana 1 Oct 19, 2021
This repository contains RabbitMQ Protobuf starters with its usage samples for spring-rabbit and spring-cloud-starter-stream-rabbit modules

This repository contains RabbitMQ Protobuf starters with its usage samples for spring-rabbit and spring-cloud-starter-stream-rabbit modules

Maksim Kostromin 2 Nov 29, 2021
Spring-with-maven - Spring Boot App with Postgresql and maven

Spring Boot Api Aplikasi ini dibuat menggunakan bahasa kotlin dan untuk database

Aldi Aulia Rosyad 1 Jan 12, 2022
Spring-graphql-getting-started - Spring for GraphQL provides support for Spring applications built on GraphQL Java

Getting Started with GraphQL and Spring Boot Spring for GraphQL provides support

Shinya 0 Feb 2, 2022
R2DBC Sharding Example with Kotlin Coroutine

R2DBC Sharding Example with Kotlin Coroutine A minimal sharding example with R2DBC and coroutine, where user table is divided into 2 different shards.

K.S. Yim 0 Oct 4, 2021
Spring Boot Example with Kotlin and Domain Driven Design

Spring Boot Kotlin Domain Driven Design Example Just an example project where ddd is implemented with some other great patterns and architecture from

Fernando Guevara Sanchez 16 Jun 29, 2022
A sample skeleton backend app built using Spring Boot kotlin, Expedia Kotlin Graphql, Reactive Web that can be deployed to Google App Engine Flexible environmennt

spring-kotlin-gql-gae This is a sample skeleton of a backend app that was built using: Spring Boot(Kotlin) Reactive Web Sprinng Data R2DBC with MYSQL

Dario Mungoi 7 Sep 17, 2022