I'm trying to make Spring Boot application with Flyway (and Hikari pool) to start the server even when the DB is not available at that time.
I need to support cases when:
1. DB is not available when applicaition starts (it should run Flyway after DB starts, it can be up to 30 mins).
2. DB goes offline during the application lifetime and then goes back up.
I got a problem with the first case, Flyway always tries to do migrations even when DB is not available and application stops.
I tried adding spring.datasource.continue-on-error: true but Flyway ignores that, and I couldn't find any flyway configuration that would allow such operation.
Is it possible or should I wrap Flyway and do it myself?
Spring boot 2.1.4
A couple of points to consider
What is the desired behavior of the application when the DB is really not available when the instance of java application? Ok, so flyway won't start, but how the application will be able to handle requests that will have to reach the database?
Flyway itself relies on DataSource bean, maybe on hibernate if you use it, and these are much more complicated infrastructures than flyway itself?
Maybe if the database is not available the application won't need to start at all?
Instead it worth to rely on orchestrators (like kubernetes, ECS or whatever that will recognize that the application didn't start and will try to retrigger the start again, again, and again till the database will be ready)?
This is my recommendation in general.
Now, assuming find answers to all these questions and still, want to proceed with this path:
Spring Boot by itself works like this when it comes to flyway integration:
If the relevant classes (Flyway class) exist on classpath and spring.flyway.enabled=true then the bean of flyway starts and spring boot does its magic.
Technically the relevant auto configuration can be found in class org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration (org.springframework.boot:spring-boot-autoconfigure module)
I think the way to go is to disable flyway, and given that fact that beans like DataSource are available (somehow) - create a Flyway Bean by yourself and trigger the migration in some kind of loop in the background that will exit only if the migration actually succeeds (or already applied)
Related
I'm making an application for a school project, but I'm running into the issue that when I try to run the unit tests that it tries to connect to the database while starting up the application, which isn't required for the tests (because it will be mocked), and is not available in the CI/CD pipeline.
jdbc connection error
I'm building my project in Java Maven Springboot and would like to know how I can prevent it from trying to connect to the database when running my test.
here is a link to my repository: https://gitlab.com/kwetter_jack/Kwetter_posts/-/tree/ci_cd_setup
Your test classes have #SpringBootTest annotation which will start a Spring application context - as your application uses a database the tests will also try to setup and use a database connection.
The simplest solution is to remove the annotation so the tests no longer try to connect to a database. You'll probably need to mock some more dependencies as a result as Spring is no longer creating these for you. You could also have a look at https://www.baeldung.com/spring-boot-testing for some other ideas how you could alter your tests.
Alternatively if you do want / need the application context to run you can add a application.yaml for the tests that defines and uses a in memory DB so the tests have something to connect to - see https://www.baeldung.com/spring-boot-h2-database for details how to do this.
Just change value under spring.datasource to H2 database to prevent
The application connect the real database.
Test application.yml
FYI, You no need to copy all config from original application.yml, just only some config that you need to override.
while I was investigating the spring boot H2 in-memory database (as suggested by Chris Olive and Paranaaan) I also came across the option of using a test container. after looking into this I saw that this enables the project to create a temp docker container with a MySQL image that I can use during the testing of my project, considering I was planning on using docker anyway for the integration testing of my microservices project I attempted this and it worked as I had hoped it would.
if anyone is interested in the test container solution that I used, the information can be found here:
https://www.testcontainers.org/modules/databases/mysql/
I have a SpringBoot application that will fail to start up when the database it is using is not up since the datasource bean will fail to initialize. I want for my application to not start before my db is up in order to avoid this failure.
To mention that this app is running in Kubernetes so one option would be to use an init-container. I would want though to have that logic inside the application itself.
First of all, is that a bad idea and I should stick with init-containers?
If it is not a bad idea what is usually the best approach for this. I was looking at Spring Retry and one possible solution seems to be to have retry logic in the #Bean datasource initialization method. Does that have any possible drawbacks? Is there a better way?
Not sure if this works for you but in case you have Data source beans declared.
You can you #Lazy annotation to delay the bean initialization until required.
Your application startup shouldn't fail on startup as the Datasource bean would not be initialized until needed
You can have a startup probe to check DB connections at the start. If you want the DB connections to be constantly pooled for health, you can use other probles. Or in the pipeline which you use to deploy, after the check build unittest phases, you can add a step to check connections of external services/db which you use.
I need to understand, Is there anyway I can continuously look for change in Maria-DB table using Hibernate.
I have a spring boot application that is connected to Maria-DB. If some other application perform CURD on table, I want to catch that in spring.
If it's not possible using hibernate, suggest me alternative.
PS : This spring boot application is running is different Docker Container and Maria-DB is running is different Docker Container.
You can use Database Triggers, or better why don't you try enabling Hibernates 2nd level cache?
Solution to this specific problem is Spring Integration module as other ways not working here. I have create a sample application to demonstrate here you can find the source code
What this application does look database continuously.
Specification
Each tenant has their own database which handles users in greater detail, and there needs to exist a central database which handles:
Tokens (OAuth2)
Users (limited level of detail)
Mapping users to their database
Problem
I've found solutions for multi-tenancy which allows me to determine the datasource depending on the user. However, I'm not sure how I can also link certain crud repositories to this central datasource, and others to variable datasources.
Another solution involved updating the properties file, and using a configuration server (i.e. via git) to trigger #RefreshScope annotated configs. Though I'm not sure if this can work for Datasources, or if this could cause problems later on.
Extra Context
I'm using Spring Boot and Hibernate heavily in this project.
This blog gives a very good tutorial on how to do it.
After a lot of research it looks like hibernate just isn't built for doing that, but by manually writing the schema myself I can inject that into new tenant databases using native queries.
I also had a problem with MS Server DBs, as they don't allow simply appending ;createDatabaseIfNotExist to the JDBC URL, which meant even more native queries (Moving the project over to use MySQL anyway, so this is no longer a problem.)
I'm building a fairly simple Spring Boot application which needs some configuration to be set (and regularly updated as part of it's use). I'd like to create a simple admin interface and first-run wizard to set/update this configuration.
I'd like a way to easily read and write these configuration values within the application and have them persist. I would like to avoid the overhead of a database for 5-10 configuration strings. There is some good documentation on externalising configuration in Spring Boot but it doesn't talk about how this config could be updated and persisted by the app.
Options I have come up with:
There is a write option with Spring configuration that I'm not aware of (this would be awesome)
Don't use the Spring Boot configuration functionality, instead use apache commons configuration (or similar??) to read and write to a file which lives in a location specified by an environment variable
as per option 2 but use HSQL, H2 or Derby as a file-based database
Thanks for any suggestions as to how best to achieve this.