Please note: Although the two primary techs in this question are Spring Boot and Gradle, I really think this is a Linux/command-line question at heart, involving fore- and background processes!
I’m trying to get my Spring Boot app to run in hot swap (“dev”) mode via Gradle. After reading this interesting DZone article, all it takes is a few easy steps:
- Make some minor tweaks to your
build.gradle
- Open a terminal and run
./gradlew build --continuous
; wait for it to finish/start up - Open a second terminal and run
./gradlew bootRun
- Voila! Now you can make code changes to your JVM classes and they will be hot-recompiled on the fly and picked up by your Spring Boot app. Hooray fast dev cycles!
However I’m trying to improve upon this just a wee bit. I’d like to just run a single shell script (e.g. runDevMode.sh
) and have both these processes spun up for me in the correct order. So I tried:
./gradlew build --continuous & ./gradlew bootRun && fg
I put that inside runDevMode.sh
and then ran sh runDevMode.sh
. I could see both tasks starting without any errors, but now when I make code changes to my Java classes, I don’t see the changes picked up. Any ideas as to where I’m going awry?
Advertisement
Answer
The successful runs were run in separate terminals, so perhaps the unsuccessful runs were fighting over the same resources, (whatever those might be). Try using separate subshells:
- launch 1st instance of program in background subshell.
- sleep 30 seconds
- launch 2nd instance of program in background subshell.
foreground ‘3’. (It didn’t need to be in the background.)
( ./gradlew build --continuous & ) ; sleep 30s && ( ./gradlew bootRun & ) ; fg
Commands in parenthesis are launched in a subshell. In an open terminal, suppose we run sh
or bash
or another shell and then assign a variable, then type exit
, and try to use that variable:
$ PS1='~> ' dash # assign a temporary prompt, run subshell ~> foo=bar ~> echo :$foo: :bar: ~> exit $ echo :$foo: ::
Above ‘$‘ is the main shell prompt, (don’t type that), and ‘-> ‘ is the subshell’s prompt, (don’t type that either). The colons (‘::‘) aren’t commands, they help show when *$foo*
is unset or empty. Variable assignments cannot leave a subshell, (nor can they cross over to a concurrent subshell).
See also “Compound Commands” in man bash
.