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.
The problem
I've a multi module project which comprises different web apps that should run together.
I noticed that executing
gradle :application_A:bootRun
and, once application_A is built and running,
gradle :application_B:bootRun
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:
gradle --status
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.
Why does that happen?
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.
What can we do?
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 🙄.
So?
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 --parallel
flag.
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 --max-workers
flag:
gradle :application_A:bootRun :application_B:bootRun --parallel --max-workers=4
Top comments (0)