Do a dependency REST service check before liquibase scripts run in a Sprint Boot application - spring-boot

I'd like to do a simple GET call before Liquibase runs it's db scripts in my project (for a dependency check). I have the GET call encapsulated in a method in one of my service implementations that I'd like to use.
I could call the method in main before
SpringApplication.run(RESTApplication.class, args);
But the problem there is that Spring boot has yet to boot. If I use ApplicationRunner, liquibase has already ran its scripts. I'm looking for a good pick off point of when Spring starts up but before Liquibase does it's script sequence that I can hook in to.
Any suggestions are appreciated!

How about customPrecondition? You can call a Java class in them and do whatever you need to do.
<customPrecondition className="com.example.CustomTableCheck">
<param name="tableName" value="our_table"/>
<param name="count" value="42"/>
</customPrecondition>
Check out customPrecondition section preconditions article.

Related

Can we invoke a method in spring in case the application start fails

I have situation where I need to perform certain tasks in case my springboot applications fails to start. Basically I want to release various resources. I tried using #PreDestroy annotation but it did not work as application was not started yet. Is there any way out by which we can perform few actions in case springboot application fails to start
Spring app heavily using threadpool context when start the program , so when the main program fail spring can not manage the standard beans related to spring. you can only start new thread using implements Runnable in main class and no access to spring resources as well , just simple getclassloader().getresourceasstream is available there .
However you can write independence java Agent using -javaagent to do some operation on release resource ,see java.lang.instrument.Instrumentation;

How to debug when Flyway doesn't work on Spring Boot?

I am using Maven and Spring Boot. I run the application using mvn spring-boot:run.
https://flywaydb.org/documentation/plugins/springboot says Flyway should be called on Spring Boot start.
So my pom.xml contains the dependency to Flyway.
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>4.1.2</version>
</dependency>
The first time I ran the Maven command above it downloaded Flyway stuff, so I think the dependency is working.
I have the following files:
./src/main/resources/db/migration/V123__foo.sql
./src/main/resources/application.properties
The above article implied it should "just work", but I don't understand where it would find the JDBC URL to the database. So I added the following to the application.properties file:
flyway.url=jdbc:postgresql://localhost:5432/services?user=postgres&password=postgres
flyway.enabled=true
When Spring Boot starts up (and loads and makes available my web application) there are no logs from Flyway. I think Flyway is ignored.
What can I do? Or, more generally, how would I go about debugging this problem myself?
Nobody has posted an answer so I'll post what I found out.
M. Deinum was indeed correct in their comments to the question, the problem was a lack of a data source.
My original question was what the approach should be to debugging this kind of issue. Obviously one option is to post to stackoverflow :) But I wanted to know how to do it myself.
Spring Boot has a number of classes which look at your code and classpath, and act appropriately. For example, there are classes providing implementations to the rules like "if Flyway is on the path, and there is a data source, then execute Flyway". That rule wasn't getting triggered in my case, because I had no data source.
It's not the case that the code you write calls Spring Boot, it's the other way around, Spring Boot (external to your code) inspects your code and decides what to do based on rules. This architecture is known as action at a distance. The main problem with action at a distance is it's very difficult to debug.
The only real way to find the solution, and it was the way I went about confirming M. Deinum's diagnostic, is to read the Spring Boot source code and understand the annotations which are used to create Spring Boot code.
From the source code to Spring Boot's Flyway integration we see
#ConditionalOnClass(Flyway.class)
#ConditionalOnBean(DataSource.class)
This means "this code will get executed if Flyway is on the classpath, and if there is a DataSource bean available; otherwise it silently won't get executed".
So the answer to the question "how to debug this problem" is that there is no mechanism other than to read the source code of Spring Boot and find out how it works.
If you want to avoid this sort of problem, you have to avoid frameworks which work via "action at a distance", and that includes Spring Boot.

Spring Integration Invoking Spring Batch

Just looking for some information if others have solved this pattern. I want to use Spring Integration and Spring Batch together. Both of these are SpringBoot applications and ideally I'd like to keep them and their respective configuration separated, so they are both their own executable jar. I'm having problems executing them in their own process space and I believe I want, unless someone can convince me otherwise, each to run like they are their own Spring Boot app and initialize themselves with their own profiles and properties. What I'm having trouble with though is the invocation of the job in my SpringBatch project from my SpringIntegration project. At first I couldn't get the properties loaded from the batch project, so I realized I need to pass the spring.active.profiles as a Job Parameter and that seemed to solve that. But there are other things in the Spring Boot Batch application that aren't loading correctly like the schema-platform.sql file and the database isn't getting initialized, etc.
On this initial launch of the job I might want the response to go back to Spring Integration for some messaging on Job Status. There might be times when I want to run a job without Spring Integration kicking off the job, but still take advantage of sending statuses back to the Spring Integration project providing its listening on a channel or something.
I've reviewed quite a few Spring samples and have yet to find my exact scenario, most are with the two dependencies in the same project, so maybe I'm doing something that's not possible, but I'm sure I'm just missing a little something in the Spring configuration.
My questions/issues are:
I don't want the Spring Integration project to know anything about the SpringBatch configuration other than the job its kicking off. I have found a good way to do that reference to the Job Bean without getting my entire batch configuration loading.
Should I keep these two projects separated or would it be better to combine them since I have two-way communication between both.
How should the Job be launch from the integration project. We're using the spring-batch-integration project with JobLaunchRequest and JobLauncher. This seems to run it in the same process as the Spring Integration project and I'm missing a lot of my SpringBootBatch projects initialization
Should I be using a CommandLineRunner instead to force it to another process.
Is SpringApplication.run(BatchConfiguration.class) the answer?
Looking for some general project configuration setup to meet these requirements.
Spring Cloud Data Flow in combination with Spring Cloud Task does exactly what you're asking. It launches Spring Cloud Task applications (which can contain batch jobs) as new processes on the platform you choose. I'd encourage you to check out that project here: http://cloud.spring.io/spring-cloud-dataflow/

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).

Spring Batch Quick Start not working

I'm trying Spring Batch Quick Start from Spring site (Spring Boot Quick Start) but I can't get it to work:
end() method in SimpleJobBuilder (see job method in BatchConfiguration class) is missing
When I run the main class (removing the reference to end method), Spring Boot starts up (I see the logs in the console) but the job it's not getting executed; from docs around the web I saw that the job should start as soon as the SpringApplication is run
There is something terribly wrong in Spring Batch Quick Start or there's something terribly wrong in what I'm doing?
I think it's useless to publish my code: it's copied from Spring Batch Quick Start...
Thanks for your help!
I think that little sample might be incomplete. For instance you would need #Enable AutoConfiguration in order to get a job to run on start up. There's a more extensive example here, if it helps: https://spring.io/guides/gs/batch-processing/.
In step one of the Spring Batch quick started, the guide asked to add this(the dependency below) into the pom.xml but it errored when there's no version provided. Reason being is that the guide didn't include the parent dependency. So the annotations and the java objects do not know where to look.
I got the quick guide to work by directly including the spring-boot-starter dependency. Then the app ran.. A lot of the spring framework guides seem to assume a strong knowledge in project management and comprehension tool.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>

Resources