The aim of this post is to give an overview of the purpose of build tools in the context of Java and Scala applications. It is useful to look at the commonalities of several tools which should draw out the main reasons they exist.
There are probably many posts and blog entries explaining why build tool A is better than build tool B but in essence they all do a similar job. The build tools we will cover are Scala Build Tool (SBT), Ant, Maven and Gradle. These will be the build tools that will be covered by this and any related future posts. Javascript has build tools as well, one of which is NPM https://docs.npmjs.com/cli/build.
However as Javascript is an interpreted rather than compiled language we will not be covering its build tools as part of these posts. There are other compiled languages and build tools but to keep this focused we will stick to looking at the four Java / Scala tools mentioned above.
Some History
In 2004 I was working on a large-scale enterprise application and Ant was used to compile and package the application into jar files. This was the first time I had any exposure to build tools. Then I moved onto Maven, then Gradle and more recently as I have been working with Scala & SBT (Scala Build Tool).
Most modern build tools have build phases / lifecycles which are the stages /cycles a build tool goes through when you run them. Modern build tools use the software design paradigm “Convention over Configuration”. Meaning they are slightly less flexible than Ant but don’t require every detail of the build to be configured. This saves time and effort as most if not all code bases can live in identical folder structures. This has the added benefit of allowing helping when moving between code bases as it is easy to find where source code, tests and properties files will be located.
Ant
Ant was one of the first “modern” build tools (Make, Gnu Make were probably first). It is a command line tool and the “builds” are configured by build.xml files at the root of the code base.
In Ant you have to define targets which you can chain together in a specific order. The paths/locations for the code, resources, test code, build destination have to be defined manually.
See for an example of an ant project being defined and set up.
https://www.mkyong.com/ant/ant-how-to-create-a-java-project/
Ant is quite old and in rarely used these days due to the advent of more powerful build tools that have rich features and good community support. Most can be extended / enhanced by the introduction of Plugins.
Maven?
“Maven allows a project to build using its project object model (POM) and a set of plugins that are shared by all projects using Maven, providing a uniform build system. Once you familiarise yourself with how one Maven project builds you automatically know how all Maven projects build saving you immense amounts of time when trying to navigate many projects.”
The Pom.xml is placed at the root directory of the project.
http://www.baeldung.com/maven-directory-structure
- maven-project/src/main – contains source code and resources that become part of the artifact
- maven-project/src/test – holds all the test code and resources
An artifact is a file, usually a JAR, that gets deployed to a Maven repository.
Each artifact has a group ID (usually a reversed domain name, like com.example.foo), an artifact ID (just a name), and a version string. The three together uniquely identify the artifact.
Build Phases / Lifecycles
The standard tools have lifecycles, things they
http://maven.apache.org/ref/3.5.0/maven-core/lifecycles.html
https://docs.gradle.org/current/userguide/build_lifecycle.html
https://www.scala-sbt.org/1.x/docs/Command-Line-Reference.html
Phases Common Between Build Tools
The build tools have commonalities, they achieve similar goals and do similar things. They all work against the Java Virtual Machine and use a compiled language i.e. Java or Scala.
Compile
This is the phase where the source code is compiled as the name suggests. Ant also has the ability to compile code, this is one of the first steps to run and will stop if there are any compilation errors. Source code and test source code are usually compiled separately with the main source code being compiled first.
Packaging
Once the code has been compiled it needs to be packaged i.e. zipped up into a jar / war / ear file.
Packaging
Once the code has been compiled in order that it is can be deployed to an application server or servlet container the code is usually bundled into a War file. With frameworks like Spring boot for building lightweight Micro services we tend to build “Fat” executable Jar files. Since the advent of Microservices, large Enterprise Application servers like Weblogic, Ibm WebSphere are not needed to deliver funtionality.
What’s a JAR, WAR and EAR file:-
Taken from here http://stackoverflow.com/questions/1594667/war-vs-ear-file
A WAR (Web Archive) is a module that gets loaded into a Web container of a Java Application Server. A Java Application Server has two containers (runtime environments) – one is a Web container and the other is a EJB container. The Web container hosts Web applications based on JSP or the Servlets API – designed specifically for web request handling – so more of a request/response style of distributed computing. A Web container requires the Web module to be packaged as a WAR file – that is a special JAR file with a Enterprise applications may consist of one or more modules that can either be Web modules (packaged as a WAR file) or EJB modules (packaged as a JAR file) or both of them. Enterprise applications are packaged as EAR files – these are special JAR files containing an Basically EAR files are a superset containing WAR files and JAR files. Java Application Servers allow deployment of standalone web modules in a WAR file, though internally they create EAR files as a wrapper around WAR files. |
An Jar, War or Ear file are essentially a type of zip file packaged in a certain way i.e. WAR files (Java Web Application Archives) are based on ZIP, but have a defined folder structure and requirements to some of the files in there (e.g., some stuff needs to be in a WEB-INF
directory).
You can rename a .war file to .zip to view its contents or unzip it using a tool that doesn’t know about this relationship between the file format.
Testing
With Maven & Gradle as long as you put your test files inside <project root>/src/test/java they will be executed when “mvn install” / “gradle build” commands. Any failures will be displayed on the command line , more detailed reports are usually generated and placed in the build folders.
For Scala and SBT the files need to be located inside src/test/scala/ and they will be executed using the “sbt test” command.
You can override the test locations if needed.
Plugins
All the above tools have plugins, they fall out side the scope of this discussion but they allow us to enhance our build tools for different tasks. Here are some examples:-
1). create a docker image of the application based on a docker file
2). show code coverage once the tests have completed
3). allow integration tests with a tool like wiremock.
4). run browser tests of a web frontend using selenium.
5). check defined dependencies against owasp list.
Summary
These build tools have meant that developers can jump in and out of each others codebases. Assuming common conventions are followed, i.e. file naming, folder location etc. It is very easy to jump directly in to any code and run and build ANY code project. All that is needed is a basic understanding of the build tool and how to run it. Library dependencies needed for compilation are managed and retrieved automatically and tests can be run to ensure code is working.