Differences between war and jar files

In fact , a jar library is just a zip archive, which directly follows from its name: Java Archive . Most often it contains just four things:

  • compiled classes;
  • resources: properties files and the like;
  • manifest MANIFEST.MF;
  • other jar libraries (rare).

The typical structure of such an archive looks like this:

  META-INF/
  	MANIFEST.MF
  com/
  	codegym/
	      MyApplication.class
  application.properties

Now let's look at a typical war file. By the way, war is not from the word war, but from W eb Ar chive . The structure of a war file is usually more complex. Most often it consists of two parts:

  • Java part
    • compiled classes
    • resources for java classes: properties files and the like
    • other jar libraries (often)
    • manifest MANIFEST.MF
  • web part
    • web-xml - web service deployment descriptor
    • jsp servlets
    • static web resources: HTML, CSS, JS files

An example of a typical war file:

META-INF/
    MANIFEST.MF
WEB-INF/
    web.xml
    jsp/
    	helloWorld.jsp
    classes/
    	static/
    	templates/
    	application.properties
    lib/
    	// *.jar files as libs

Important! jar file can be run by just a java machine, but to run a war file, it must be uploaded to a web server. It does not start on its own.

war file plugin with maven-war-plugin

Let's imagine that we have a simple web project. Let the project be given such a file structure, how do we assemble it?

|-- pom.xml
 `-- src
 	`-- main
     	|-- java
     	|   `-- com
     	|   	`-- example
     	|       	`-- projects
     	|           	`-- SampleAction.java
     	|-- resources
     	|   `-- images
     	|   	`-- sampleimage.jpg
     	`-- webapp
         	|-- WEB-INF
         	|   `-- web.xml
         	|-- index.jsp
         	`-- jsp
             	`-- websource.jsp

First, we need to tell Maven to build all this as a war file , there is a <package> tag for this , for example:

	<project>
  	...
      <groupId>com.example.projects</groupId>
      <artifactId>simple-war</artifactId>
  	<packaging>war</packaging>
      <version>1.0-SNAPSHOT</version>
  	<name>Simple War Project</name>
      <url>http://codegym.cc</url>
  	...
    </project>

Second, we need to include the maven-war-plugin plugin . Example:

  <build>
	<plugins>
  	<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
    	<version>3.3.2</version>
    	<configuration>
          <webappDirectory>/sample/servlet/container/deploy/directory</webappDirectory>
    	</configuration>
      </plugin>
    </plugins>
  </build>

Here we simply define a plugin that can be configured in the future. Also, using the webappDirectory tag , we redefine the directory into which the project will be deployed. Now I'll tell you more about what I'm talking about.

The plugin can be set to two build modes (two types of goal):

  • war:war
  • war:exploded

In the first case, the resulting war file is simply placed in the target folder and named <artifactId>-<version>.war .

But you can “ask” the plugin so that the contents of the war file are placed in the final folder in the state in which it will be unpacked by the web server inside. For this, goal war:exploded is used .

The second approach is often used if you are running or debugging a project directly from Intellij IDEA.

By the way, the webappDirectory tag in the example above allows you to redefine the directory where your war file will be unpacked when building in war:exploded mode.

You can learn about other plugin settings from its official page .

Building a web application based on SpringBoot

Well, I would like to disassemble some real assembly example. Let's not be trifles and consider this using an example application based on SpringBoot.

Step one. Create an empty Maven web project with IDEA.

Step two. Add Spring dependencies to its pom.xml.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

Step three. Create a class com.codegym.spring.MainController . It needs to be placed in the src/main/java folder :

@Controller
public class MainController {

	@GetMapping("/")
    public String viewIndexPage(Model model) {
        model.addAttribute("header", "Maven Generate War");
    	return "index";
	}
}

There are 3 things described here. First, the @Controller annotation tells the SpringBoot framework that this class will be used to serve incoming web requests.

Second, the @GetMapping annotation , indicates that our method will be called to service a GET request on the root URI - /

Third, the method returns the string "index" . This tells the SpringBoot framework to return the contents of the index.html file as a response .

Step four. You need to add an index.html file to the project with the following content:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
    <!-- Bootstrap core CSS -->
    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
</head>
<body>
    <nav class="navbar navbar-light bg-light">
    	<div class="container-fluid">
        	<a class="navbar-brand" href="#">
            	CodeGym Tutorial
        	</a>
    	</div>
    </nav>
    <div class="container">
    	<h1>[[${header}]]</h1>
    </div>
</body>
</html>

It's not just html. Before its content is given to the client, it will be modified on the server by the Thymeleaf framework . Special tags are embedded in this file, which allow the Thymeleaf library to process and modify the content of the page.

The tags in red are the tags that will be processed by the Thymeleaf library, the green ones are the styles of the Bootstrap CSS library.

Step five. Set the plugin in pom.xml:

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.3.1</version>
</plugin>

I overestimated my strength a bit. It takes a lot of time to fully parse a simple example. But you can download the full code of the project from GitHub and try to understand it yourself. By the way, 80% of your working time you will do just that :)

You can download the full code from the link in GitHub .