Does Spring boot Support Fast fail on Liquibase - spring-boot

From Spring DB Initialization docs, Spring boot DB initialization using Spring JDBC supports
feature Fast fail - that means if there are any issues in DB init script or migration scripts then Spring boot Context initialization failed. as result Spring boot server won't start.
now can we have this functionality when we use Advanced DB Migration tool like liquibase?
Spring Docs Doesn't say anything about this in liquibase section. Does this feature only works in Spring JDBC initialization?

whenever there is an issue in your liquibase script, application won't start because datasource is not properly initialised.

You can specify the desired behaviour using 'Preconditions'.
On default, it actually will fail fast, but you can overwrite it (example using SQL syntax):
-- preconditions onFail:WARN onError:WARN
Available parameters:
HALT: Immediately halt the execution of the entire changelog. [DEFAULT]
CONTINUE: Skip over the changeset. Execution of the change set will be
attempted again on the next update. Continue with the changelog.
MARK_RAN: Skip over the changeset, but mark it as executed. Continue
with the changelog. WARN Output a warning and continue executing the
changeset / changelog as normal.
see https://docs.liquibase.com/concepts/advanced/preconditions.html

Related

Spring Boot migration to 2.5/2.6 from 2.1 - Issue with SQL Script DataSource Initialization order

I'm migrating my existing Spring Boot 2.1.x application to 2.6.x. I want the following behavior (for integration tests which uses embedded H2 database), which is working fine in 2.1.x (obviously) but I'm struggling to achieve the same behavior in 2.6.x.
Create DDL automatically (without any custom SQL script)
Execute custom DML (data.sql)
Initialize beans which implements InitializingBean and use data populated in step #2. Eg. Cache database table records for application to use later
Problem #1 (Solved)
2.6.x was no longer created DDL automatically by default. So adding below properties explicit seemed to be the solution.
spring.jpa.generate-ddl = true
spring.jpa.hibernate.ddl-auto = create-drop
This solves Step #1 with 2.6.x.
Problem #2 (Solved)
Starting from 2.5, Boot was running scripts in data.sql before Hibernate is initialized. Hence, data.sql was failing. To make Boot wait for DDL creation to complete, adding below property seemed to be the solution.
spring.jpa.defer-datasource-initialization = true
This solves *Step #2 with 2.6.x.
Problem #3 (Need solution)
Seemingly because of setting spring.jpa.defer-datasource-initialization to true, Step #3 is happening before Step #2 i.e. in 2.6.x. This cause beans to initialize with empty database tables e.g. Cache is populated with no entries. These are causing my tests to fail.
I played with properties like spring.jpa.defer-datasource-initialization, spring.data.jpa.repositories.bootstrap-mode and spring.sql.init.mode to workaround this without any luck.

Flyway with spring boot overwrites whole DB every time I switch run mode between WAR and IDE run

I'm facing very weird issue while integrating flyway DB migration with spring boot application.
When I run the application from executable WAR using command line, it creates new DB at the start-up of application.
Now, If I switch the application run mode to IDE (i.e. run from STS), it again fires all the script from my db/migration folder. I can see the installed_on column time changes every-time I switch between these 2 run modes. I have tried enabling baselineOnMigrate property, but didn't get any effect of it.
Do you think its something related to spring boot embedded tomcat ? because at both run it creates individual tomcat which is embedded.
Please find my spring boot application.properties below:
mssql.dbname=issueDB
mssql.password=password
mssql.dbserver=localhost
mssql.port=1501
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.url=jdbc:sqlserver://${mssql.dbserver}:${mssql.port};databaseName=${mssql.dbname}
spring.datasource.username=user
spring.datasource.password=${mssql.password}
spring.flyway.baselineOnMigrate=true
spring.flyway.locations=classpath:db/migration/testissue
spring.flyway.out-of-order=true
spring.flyway.baseline-version=1.3
spring.flyway.placeholder-prefix=$
spring.flyway.placeholder-suffix=$
spring.flyway.mixed=true
spring.flyway.cleanOnValidationError=true
I suppose, it could be caused by this property spring.flyway.cleanOnValidationError=true. According to the docs:
Whether to automatically call clean or not when a validation error occurs.
This is exclusively intended as a convenience for development. Even tough we strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a way of dealing with this case in a smooth manner. The database will be wiped clean automatically, ensuring that the next migration will bring you back to the state checked into SCM.
May be that you got some validation problems if you are running your application in different ways on the same database and flyway just clean your database and overwrite it with the current scripts state.

Disable hibernate hbm2ddl

I have a spring boot project that uses flyway to insert the database structure and it works perfectly except when testing. When I run my tests I can see that the flyway sql files are executed so that works however for some reason hibernate drops and creates the database structure. This only happens when in testing so it seams as if Spring is telling Hibernate to drop-create the schema when testing.
How can I completly disable the hbm2dll?
I can understand that this is the default behaviour however it this the right thing to do? Spring should never assume that someone wants hbm2dll eneabled when testing, that should be indicated by the user not spring.

Using Liquibase and Spring Boot

I have a Spring Boot application and want to use Liquibase to generate the changelogs for my JPA entities. However, I encounter different issues, depending on my approach.
My first approach is to use the diff goal of the maven plugin. The url is my H2 development database with the H2 driver and the reference URL is something like "hibernate:spring:myBasePackage.myEntityPackage?dialect=org.hibernate.dialect.H2Dialect" with the driver "liquibase.ext.hibernate.database.connection.HibernateDriver". In that case Liquibase seems to recognize my entities, but prints the differences to the console. Also the differences do not have the form of a changelog file.
My second approach would be to use the generateChangeLog goal of the maven plugin. In this case my url is "hibernate:spring:myBasePackage.myEntityPackage?dialect=org.hibernate.dialect.H2Dialect" with the driver "liquibase.ext.hibernate.database.connection.HibernateDriver. In this case I am getting an error "Unable to resolve persistence unit root URL: class path resource [] cannot be resolved to URL because it does not exist". This error can be found in both the Spring an the Liquibase issue trackers, but it seems like it is always said that this error is already fixed.
My third approach is basically like the second, but in this case I am using a "hibernate:classic" url with an implementation of "CustomClassicConfigurationFactory", which registers my annotated classes explicitly. This does work. However, in this case I have to do this in my application-jar. I have to add my application-jar as a dependency for the maven-plugin. Thus I have to build my application-jar (and install it to the local Maven repository), before I can generate the changelogs. This seems to be cumbersome.
My questions are:
Is there an easier way to generate the changelogs for JPA entities in a Spring boot based application?
Why are the first two approaches not working?
Is there a way to simplify the third approach?
I am using:
Spring Boot 1.5.4.RELEASE
Liquibase-Hibernate4 3.6
Liquibase 3.5.3
Many thanks in advance.
In the first approach using liquibase:diff , the change set for the entities (create table change set) will not be generated since liquibase do not assume new jpa entity as change.
In the second approach generateChangeLog, it generates the change log from the given data base.It won't look into your jpa entities.
In order to generate the ddl scripts for your jpa entities , just submit the following to your jpa properties
<property key="javax.persistence.schema-generation.scripts.action">drop-and-create</property>
<property key="javax.persistence.schema-generation.scripts.create-target">./ddl/create.sql</property>
<property key="javax.persistence.schema-generation.scripts.drop-target">./ddl/drop.sql</property>
The above will generate the scripts the ddl folder under the root folder.
You can check the other properties here https://thoughts-on-java.org/standardized-schema-generation-data-loading-jpa-2-1/

Spring Boot Batch - execluding JobLauncherCommandLineRunner

i have a simple Spring Batch job configured in Spring Boot (something similar to the spring guides). at startup, it auto-detects and invokes JobLauncherCommandLineRunner and i want to stop that behavior. I want the job to only be fired by a defined trigger elsewhere in the app, not on startup.
i've tried the #ComponentScan(excludeFilters... approach but it still gets invoked.
any way to switch off this 'helper' class?
You can set spring.batch.job.enabled=false or you can set spring.batch.job.names=none (see source code for details).

Resources