Gradle Multi-Project WAR Build Featuring Instant Code Reload

Get the code at, then “cd GradleWarMultiProject”.



I like Java programming.  For all its warts and the faint smell of old-guy cologne, it’s still a fine general-purpose language, and there are plenty of companies that’ll pay you to code in it. What’s not to like?

Well, OK, if it’s not a rhetorical question, thanks for asking: configuration of new projects could be a bit simpler. But in fairness, Maven goes a long way toward solving that — and in the end our dependency management is a lot easier to work with on a day to day basis than Python, for example.  Gradle takes that simplicity of Maven and Ivy even further with a host of new features that make it my new go-to tool for new projects.  For an overview, check out this feature comparison.

But what I really like about Gradle even more than all those whiz-bang features I haven’t used yet is the simplicity of the tool. In a couple of hours on a Saturday I was able to go from not much experience to a multi-module build where the dependencies got built correctly and ready to deploy, running inside an embedded Jetty or Tomcat web server. Or how about the fact that I didn’t have to explicitly configure Jetty or Tomcat, and in either case changes to the code I made were reloaded into the server as soon as I saved it. (OK you Python and Ruby folks, I hear you snickering, but what arguments do I pass to those methods of yours again?  Oh, yeah, right, you need documentation for that, don’t you?)

In this tutorial I’ll walk you step by step through the process of setting this up.  You can download the code for the tutorial on Github at, then “cd GradleWarMultiProject”. Now if you do that and poke around you can pretty much figure out what I did, but what kind of tutorial would this be if we just left you poking around in someone else’s repository?

No, sir, for the rest of this tutorial we’ll assume you need to walk through some of the steps from scratch. So let’s start by making sure Gradle 3.0 and Java are installed on your system, then let’s start out by creating a clean directory and going there. Got a clean directory? Let the adventure begin.


First Steps and File Structure

In your new directory, start by typing “gradle init”. This sets up a couple of basic starter files and installs the gradle wrapper, which is the recommended way to start your project off right in case my tutorial becomes the basis for your awesome startup, HyperGlobalMeganet or what have you.

Next you’ll need to set up a directory consisting of a jar_dependency directory underneath which you’ll need the standard Maven/Gradle JAR file layout, plus the Maven/Gradle standard layout for a war file in the current directory.

[Later edit: Note — the following section about batch files and shell scripts has been make quaint an obsolete by some new information about “gradle init”. This command takes a “–type” argument, and even though gradle init is in incubator status, some of these types are working. So the right way to start your directory structure for java (minus the packages we set up) is with “gradle init –type java-library”. For more information on what’s available, use “gradle -q help –task init”.]

There are two files for this checked in to the repo, and makedirs.bat. Here they are.

For Linux and Mac:

For Windows:


Something To Build – Let’s Add Code

Next we’ll need a smattering of Java Code and JSPs, since we’ll want something to test. Our index.jsp file allows up to test a JSP link, as well as the Code Reload feature across the JSP itself, the code in our WAR, and the code in the JAR. However, in this project all the code merely exists to test that the build does what we want. Since it’s not too interesting in itself, I’ll leave you to review it, but let’s briefly summarize what’s there.

  • ./jar_dependency/src/main/java/com/example/ – This is a simple class with a getMessage method, built to test automatic reload of java code inside a dependent jar.
  • ./src/main/java/com/example2/ – Another class with a getMessage method, this time to test automatic reload of java code in the war itself.
  • ./src/main/webapp/WEB-INF/web.xml – A boilerplate web.xml file that the WAR should have.
  • ./src/main/webapp/jsp/testrelative.jsp – A simple JSP file to test a relative link within the war file.
  • ./src/main/webapp/index.jsp – This JSP loads the messages in Message and LocalMessage and displays them. Editing this file also allows us to test automatic reload of the JSP files.


Set up the Build

Now that we have some code to test, let’s set up the Gradle build itself. First let’s set up our jar build in the jar_dependency directory, since this is the simplest biuld we’ll be dealing with:


The built-in java plugin includes support for compiling and building a jar. Setting jcenter as the repository is the current Gradle default. The SLF4J dependency for the code build and the test dependency on JUnit are for illustration only at this point, we’re not using them yet.

Now let’s move on and take a look at settings.gradle and build.gradle in the root of the project. These need to contain a bit more configuration to support building the jar as a dependency and automatic reload. Here’s the settings.gradle file first, removing the comments in the file for brevity:


Here we simply include the project we depend on, jar_dependency, as a sub-project for Gradle purposes. This allows our whole build to work together seamlessly. Next, we override the default project name for the root project (which would otherwise match the directory), to give the project the name war_starter. This name will be the name for the JAR and will also appear in our main URL, which we’ll see in a minute. But first, here’s our main build.gradle file. The comments in the code should tell you how the magic works.



Run It!

And now, here’s the payoff. Let’s run our server.

gradle -t -q jettyRunWar

This should start a jetty server with a message that the URL to go to is:


Go there and see that it worked. Now without restarting the server, edit some of the code or the JSP itself. Wait a second or two and watch the code reload.

Now I know you want to edit those message classes to say “Hello World!”, don’t you? Of course!


Leave a Reply