Chapter 3. Building a Gradle project by example

 

This chapter covers

  • Building a full-stack Java project with Gradle
  • Practicing efficient web application development
  • Customizing default conventions to adapt to custom requirements
  • Using the Gradle wrapper

Chapter 2 introduced Gradle’s feature set and showed how it compared to other JVM build tools. Some simple examples gave you a first impression of the tool’s expressive build language. By running your first build script, you saw how easy it is to become productive on the command line. Now it’s time to strengthen this newly acquired knowledge by building a real-world Java project.

When starting a brand-new application, Java doesn’t guide you toward a standardized project structure. You may ask yourself where to put source, configuration, and library files. What if you want to separate your application code from your test source files? Gradle provides a build-by-convention approach for certain domains like Java projects by introducing predefined project layouts with sensible defaults. Stuck with a legacy application that has a different directory structure? No problem! Gradle allows for adapting its conventions to your needs.

3.1. Introducing the case study

This section introduces a simple application to illustrate the use of Gradle: a To Do application. Throughout the book, we’ll apply the content to demonstrate Gradle’s features in each phase of the build pipeline. The use case starts out as a plain Java application without a GUI, simply controlled through console input. Over the course of this chapter, you’ll extend this application by adding components to learn more advanced concepts.

The To Do application will act as a vehicle to help you gain a broad knowledge of Gradle’s capabilities. You’ll learn how to apply Gradle’s standard plugins to bootstrap, configure, and run your application. By the end of this chapter, you’ll have a basic understanding of how Gradle works that you can apply to building your own web-based Java projects with Gradle.

3.2. Building a Java project

In the last section, we identified the Java classes required to write a standalone To Do application. To assemble an executable program, the source code needs to be compiled and the classes need to be packaged into a JAR file. The Java Development Kit (JDK) provides development tools like javac and jar that help with implementing these tasks. Unless you’re a masochist, you don’t want to run these tasks manually each and every time your source code changes.

Gradle plugins act as enablers to automate these tasks. A plugin extends your project by introducing domain-specific conventions and tasks with sensible defaults. One of the plugins that Gradle ships with is the Java plugin. The Java plugin goes far beyond the basic functionality of source code compilation and packaging. It establishes a standard layout for your project and makes sure that tasks are executed in the correct order so they make sense in the context of a Java project. It’s time to create a build script for your application and apply the Java plugin.

3.3. Web development with Gradle

In Java, server-side web components of the Enterprise Edition (Java EE) provide the dynamic extension capabilities for running your application within a web container or application server. As the name Servlet may already indicate, it serves a client request and constructs the response. It acts as the controller component in a Model-View-Controller (MVC) architecture. The response of a Servlet is rendered by the view component—the Java Server Page (JSP). Figure 3.4 illustrates the MVC architecture pattern in the context of a Java web application.

A WAR (web application archive) file is used to bundle web components, compiled classes, and other resource files like deployment descriptors, HTML, JavaScript, and CSS files. Together they form a web application. To run a Java web application, the WAR file needs to be deployed to the server environment, a web container.

You implemented your web application with the help of classes that aren’t part of the Java Standard Edition, such javax.servlet.HttpServlet. Before you run the build, you’ll need to make sure that you declare those external dependencies. The War plugin introduces two new dependency configurations. The configuration you’ll use for the Servlet dependency is providedCompile. It’s used for dependencies that are required for compilation but provided by the runtime environment. The runtime environment in this case is Jetty. As a consequence, dependencies marked provided aren’t going to be packaged with the WAR file. Runtime dependencies like the JSTL library aren’t needed for the compilation process, but are needed at runtime. They’ll become part of the WAR file. The following dependencies closure declares the external libraries you need for your application:

The War plugin makes sure that the assembled WAR file adheres to the standard structure defined by the Java EE specification. The war task copies the contents of the default web application source directory src/main/webapp to the root of the WAR file without modifying the structure. Compiled classes end up in the directory WEB-INF/classes, and runtime libraries, defined through the dependencies closure, get put in WEB-INF/lib. The following directory structure shows the contents of the assembled WAR file after running jar tf todo-webapp-0.1.war:

3.4. Gradle wrapper

Gradle provides a very convenient and practical solution to this problem: the Gradle wrapper. The wrapper is a core feature and enables a machine to run a Gradle build script without having to install the runtime. It also ensures that the build script is run with a specific version of Gradle. It does so by automatically downloading the Gradle runtime from a central location, unpacking it to your local file system, and using it for the build. The ultimate goal is to create reliable and reproducible builds independent of the operating system, system setup, or installed Gradle version.

Using the wrapper is considered best practice and should be mandatory for every Gradle project. Gradle scripts backed by the wrapper are perfectly prepared to run as part of automated release processes like continuous integration and delivery.

3.5. Summary

In chapter 2, you learned how to express and execute simple logic by adding tasks to your project. In this chapter we’ve gone much further. You implemented a full-stack Java application and used Gradle to build it. Many Java projects are similar in nature. They need to compile Java source code, run tests, and bundle a JAR file containing the classes. Luckily, you didn’t have to write these tasks yourself to make this happen in your project. Through the use of Gradle plugins, you merely had to write code in your build script.

After a short recap of the fundamentals of Java web application development, we discussed how to extend the example project by Java EE–compatible web components. Gradle helps you with simplifying web development through the War and Jetty plugins. The War plugin assists in assembling a WAR file, and the Jetty plugin provides efficient deployment to a lightweight Servlet container. You saw that the convention-over-configuration paradigm was applied to this dynamic duo as well. You also learned that using the wrapper is a best practice for every Gradle project. Not only does it allow you to run the project on a machine that doesn’t have Gradle installed, it also prevents version compatibility issues.

sitemap