Friday, July 31, 2015

Introduction to .war Packaging and Maven

The .war (Web application ARchive) is a packaging mechanism for putting together the application code of a web application to be deployed to a Servlet container. It is nothing complex and can be considered similar to ZIP files, the only difference being that it contains java related meta files that distinguishes it from regular ZIP files.

And just like ZIP files package up directory structures and their contents, .war files also do the same, the only difference being that the directory structures has to be laid out in a particular format.

This post is the second in a series of posts on Servlet based web application development in Java. It will thus introduce .war files, their structure and how to create one using Maven.

If building an application using Ruby on Rails, the framework specifies a required directory structure that needs to be adhered to; with source code going under different directories based on their functions. This is similar to how the .war packaging articulates a directory structure for web application to be deployed to a Servlet container. 

The directory structure that makes up a .war file is as follows:
  -> Meta related files
       -> this directory contains all the 3rd party libraries needed by your app
       -> this directory contains the code you write
web.xml -> The web descriptor. Could be left out as from Servlet 3.0

So if this is the required layout, then you may ask: why not get down straight to business and create the above directory structure? download and put all jar files the application will need in the /WEB-INF/lib directory and start putting the .java files within the /WEB-INF/classes directory since it is the directory that holds the application code...right? Wrong!

Thing is, Java is not an interpreted language in the same way as say Ruby is. It needs to be compiled; which is a process that takes the source code and transforms it into a state in which it can then be executed by a computer. With languages like Ruby or JavaScript, this transformation and execution is done at runtime, but with Java, the transformation (compilation) needs to happen before an attempt to execute the code, meaning that the application code that resides in /META-INF/classes needs to be the .class files and not the raw source code that resides in .java files.

What then is the most practical war of creating a .war file?

This is where a tool like Maven comes in. Maven is a build tool (maybe more than a build tool...) which can be used to create .war files with the required directory layout needed for a Servlet application. 

Maven takes the Java source code, compile it, put it in the WEB-INF/classes while taking care that all the dependencies that your code needs are downloaded and put into the /WEB-INF/lib folder.  

So even though, theoretically you can manually create the directory structure specified above, manually put dependencies in /META-WEB/lib, manually compile your .java files and move them to /META-WEB/classes, that won’t be the practical approach. The practical approach would be to use a build tool.

It is worth mentioning though, that Maven isn’t the only tool in the java ecosystem for such a task: Gradle, or Ant, or Sbt are some examples of other tools that can also be used to build .war files.

A full coverage of Maven capabilities is not something that can be achieved in a single blogpost, (it is a topic on which books have been written), what I do instead is to show how to use Maven to produce .war files that can be successfully deployed to a Web Server and in the next post in this series, Quick overview of basic maven concepts, I cover some of the foundational concepts in Maven. You should also consult the list of links included under the Additional resources section in this post to get more information on Maven

So let us see how to use Maven to create .war files.

Creating .war file with Maven

Maven also demands that a specific directory structure be followed. This structure contains the application’s source code and is usually referred to as a Maven project. What Maven then do is to take the contents of the Maven project and create whatever output required (technically this output is referred to as artifacts). In our case, the output required is a .war file.
The layout required for a Maven project is as follows:

src/main/java Application/Library sources
src/main/resources Application/Library resources
src/main/filters Resource filter files
src/main/config Configuration files
src/main/scripts Application/Library scripts
src/main/webapp Web application sources
src/test/java Test sources
src/test/resources Test resources
src/test/filters Test resource filter files
src/it Integration Tests (primarily for plugins)
src/assembly Assembly descriptors
src/site Site
LICENSE.txt Project's license
NOTICE.txt Notices and attributions required by libraries that the project depends on
README.txt Project's readme

And you will have the a file called pom.xml in the root directory...As I slightly hinted above, Maven is not only a build tool, it also a dependency management tool. The pom.xml file is where we specify the dependencies needed by an application, amongst other things.

The src/main/java will contain the .java files, src/main/resources would contain non .java files needed by the application e.g. configurations, static files etc, and src/main/webapp would contain web application resource like web.xml

To generate a .war from the layout above is as simple as going into the root directory: the directory where the pom.xml file resides and execute the following command from the terminal:

mvn package

And that is it. This is what is needed to take the contents of the Maven project and generate the necessary .war file from it

It is possible to also manually create the directory structure outlined above, but that would be repetitive, boring and error prone. You would want to use a Java IDE for this, or employ Maven archetypes. These alternatives are better, especially when you not only need to create the required project structure, but also package and deploy the .war file to a web server.

Next couple of posts in the series would provide more details on how to create a Maven project directory and package a .war file and deploy it to a web server using Maven Archetypes or the IntelliJ IDE...but before then, we quickly cover some high level concepts we have in Maven.

Next Post: Quick Overview of Basic Maven Concepts
Previous Post: Introduction to the Servlet API, Web Server and Servlet Container

Additional Resources

No comments: