I'd like to share the way I'm handling a multi module project in Spring. In particular, how to start multiple web applications at once taking advantage of the Gradle daemon.
I've a multi module project which comprises different web apps that should run together.
I noticed that executing
and, once application_A is built and running,
two different Gradle daemons are spawn even if the two executions are eligible for using the same daemon.
You can check it with the command:
You should see something similar to
PID STATUS INFO 23606 BUSY 3.5.1 24703 BUSY 3.5.1
(I know, that's and old version of Gradle...)
This has a huge performance impact, since a gradle daemon is quite eager in term of resources and having different instances defies its very purpose.
The reason why the second Spring application is not using the existing daemon is that the
bootRun task simply does not terminate: it remains in the running state until we explicitly kill the process. This behavior keeps the daemon in
BUSY state so application_B is obliged to spawn a new daemon.
Assuming we don't want to disable the Gradle daemon (that of course will solve the problem...) or simply we can't (e.g. the Tooling API used by IDEs always starts a daemon), the first solution that comes to mind is to execute the two tasks as a single Gradle command, like that:
gradle :application_A:bootRun :application_B:bootRun
Unfortunately, this does not solve our problem... Gradle will gladly run application_A but once again will stop on that task until we don't terminate it. So, this time we have one single daemon, but also one single app started 🙄.
Turns out that the latter is indeed the correct approach but we have to enable parallel execution, which will allow Gradle to run multiple task in parallel, without waiting for the previous task to end. In particular, it will try so execute
:application_B:bootRun even if
:application_A:bootRun is not terminated (our original problem).
This is as simple as adding the
gradle :application_A:bootRun :application_B:bootRun --parallel
Now you should see both the apps up and running waiting for requests 😊.
In older versions of Gradle (like mine) this is not sufficient. We should also tell Gradle the number of workers it is allowed to use. Apparently, it otherwise sticks to 1 so that, even with
--parallel flag, the execution is sequential.
We can easily solve this with the
gradle :application_A:bootRun :application_B:bootRun --parallel --max-workers=4