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

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.

Related

Can you replace a Spring Boot jar while the application is running?

In our Linux environment applications are restarted periodically (the reasons aren't important here). It would be convenient for us to deploy new versions of an application by copying the application Spring Boot jar on top of the existing (old) jar thereby overwriting it and then simply wait for the application to restart (that is, the JVM running the application to restart).
However, this seems to not work. We get different kinds of errors - sometimes the app just hangs, sometimes we get a ClassNotFoundException. It's as if Spring Boot (or something inside Spring Boot) reopens the jar and expects it to be the same one it was when the application was originally started.
We had a look through Spring's common application properties, but didn't see anything appropriate. Is there a way to make this work? When we were using WAR files we configured the servlet container to unpack the WAR file and run from the unpacked version. Can we do something similar with Spring Boot?
First of all the errors you are experiencing can come from multiple sources. Usually replacing the file from a process is not a big problem as the whole file is loaded into memory before execution. Java is a little bit different, because the actual process that is running is the JVM and it only loads the jar file from disk. The JVM loads classes only on demand, this means if there was any class that was not loaded before it will try to load it and most likely fail, if the jar file is different. In the case of spring boot there are also other resources (such as HTML files) inside the jar file that are dynamically loaded.
You mentioned you are using a linux environment. If you can just replace your startup with a script you can just copy the jar and start it from the copied location:
#!/bin/bash
JAR_NAME="spring-boot.jar"
NEW_JAR_NAME=".$JAR_NAME" # Use an appropriate name here
cp $JAR_NAME $NEW_JAR_NAME
java -jar $NEW_JAR_NAME
rm $NEW_JAR_NAME
Now every time you start the application a copy is being made and started from there. You can replace the original jar and on the next restart the new application will load.
You coud also use rsync instead of cp to avoid copying the same jar twice, if the application is restarted multiple times without changing the jar.
It would be convenient for us to deploy new versions of an application
by copying the Spring Boot jar on top of the existing (old) jar and
then simply wait for the application to restart
Why would you do such a thing to yourself? You are trying solve a usecase that's against best practices, sound like asking for trouble just to avoid an app restart. When you are doing a deployment, you need to make sure the deployment went through, otherwise how will you troubleshoot if something goes wrong in your application, you will have one more variable in hand when you troubleshoot, i,e the uncertainty of current version of the code.
If you are having downtime while deploying (I am assuming thats why you want to limit the restarts), why don't you bring up another instance with the newer version of code and once its healthy shutdown the old one

can spring auto reload changes like grails?

One of the main benefits of grails, which is based on Spring, is that you dont need to rebuild and re-run the entire application (which takes minutes) each time you change a line of code, it just recopiles that one file and auto-loads the changes.
Following this tutorial:
https://spring.io/guides/gs/spring-boot/
To run the app, you have to use the command line and do this outside of intellij:
./gradlew build && java -jar build/libs/gs-spring-boot-0.1.0.jar
If you change a line of code, e.g. in a controller, you have to kill the application, rebuild it and restart it, which takes a while.
I came across something called automatic restart in dev tools. Is this something to do with auto-reloading of changes, and if so, how is it used?
If a class is changed , I am sorry that Spring boot devtools will not just reload that changed classes but it will restart the whole application automatically . But this restart should be faster than the normal cold start based on what the docs said :
The restart technology provided by Spring Boot works by using two
classloaders. Classes that do not change (for example, those from
third-party jars) are loaded into a base classloader. Classes that you
are actively developing are loaded into a restart classloader. When
the application is restarted, the restart classloader is thrown away
and a new one is created. This approach means that application
restarts are typically much faster than “cold starts”, since the base
classloader is already available and populated.
If you need to just reload the changed classes , you may consider to use JRebel which is not free.
To use spring boot devtools , just includes its dependency and then start the application as usual using IDE.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
It will the monitor the classpath folders and then restart the application if there are any changes in these folders.
In case of Eclipse , what you need is to ensure Project ➡️ Build Automatically is selected. Once the source codes are changed , Eclipse will then just compiled that changed sources codes to the classes in the classpath folders automatically which trigger devtools to restart the application.
Based on the #Ken Chan answer but very briefly
For Eclipse - click in the menu "Project" -> select "Build Automatically"
In my case I was running some spring boot server - I had to stop the server, enable "Build Automatically" like on the picture, then start the server again and on every change - the code recompiled.

How to configure Eclipse-RCP with Spring-Boot

I have an Eclipse RCP(E4) application, which I can start without any problem. Now I decide to connect it to my Spring-Boot embedded Tomcat-server. The Spring-Boot-container runs an H2 as an in memory DB. Running Spring-Boot as "Java Application", I access the data in the DB via a rest-service over the browser.
The problem is, I actually want to embed the Spring-Boot part in my RCP-application. So once I start the application it will start my embedded Sring-Boot tomcat and I can run my CRUD-operations directly from the RCP-UI.
Has anyone got experience dealing with Eclipse-RCP running with Spring-Boot?
P.S: I chose explicitly to not put any code hier, because I don't have any code problem yet. The applications run separately well. I just haven't no clue how to relate them.

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.

Bootstrapping and re-initializing application with Java-based configuration

I've been looking for someone else doing this same thing, but haven't seen a scenario that's quite like this so I thought I'd see if anyone here has any good ideas on how to accomplish this.
My group builds and maintains an open-source neuroimaging data archive tool called XNAT. Previous versions of our application have always required users to run a builder application that took in a build.properties file and used that to initialize the database server configuration, among other things. We're really trying to get down to a single installable war file that we can make available on the NeuroDebian repository. In order to do this, we need to be able to start the application WITHOUT any database configuration information, run through a configuration wizard a la Wordpress or Drupal installations that includes the user inputting the database configuration, and finally setting this configuration information SOMEWHERE and re-starting or re-initializing the application context so that it gets its data source started up, Hibernate entity scans run, all auto-wired or injected dependencies that require the data source or Hibernate transaction manager resolved, and services scanned for #Transactional annotations, and so on.
I can easily see how we can use the new Spring Framework WebApplicationInitializer to detect whether the user has already set up the database configuration and initialize the app properly based on that:
If database has not been configured, create an servlet that just supports the UI for the initialization wizard
If database has been configured, create the regular application context
The problem in the first case is what happens once the user has completed the initialization wizard? We can store the database configuration somewhere and now we're ready to go but... how do we get the regular application context working? Can we just take the code that we'd call in the already initialized scenario and call that? Will that initialize the application properly then, with component scans and so on all being handled or...?
The only solution we have currently is to have the user restart the server manually (it's usually Tomcat) or use the server manager application to restart just our application. That's not very aesthetically pleasing though.
My end goal here will be to write a simple test app that takes in the database credentials and then tries to initialize everything else afterwards, but I'm hoping to see if anyone's thought about this particular issue and/or tried it and has any advice on how to handle it. Any help would be greatly appreciated!

Resources