🏠Spring BootJAR to WAR: Deploy Spring Boot on App Servers like Tomcat

JAR to WAR: Deploy Spring Boot on App Servers like Tomcat

In this post, We will learn about converting Spring Boot JAR to WAR file. We know that Spring Boot produces a fat JAR That helps You to start the app by running java -jar <your jar file>. We can deploy these JARs with ease. But in unavoidable situations, you may need a WAR file.

Josh Long making a quote on JAR and WAR
  • Each application runs on a separate port. That means maintaining a list of free ports for all the services to execute.
  • It is annoying to stop the application.
  • Each application has a separate web container.
    • They will run Class-loading, Garbage Collection and other JVM activities.
    • That implies added CPU and memory overhead.
  • Grouping of applications in a single container.
    • That method is more comfortable for the operations team. After all, they just have to stop one server and call it a day.

Existing Setup

Let’s take our Hello World Spring Boot Example. We try to convert this project to create a WAR file from this JAR project.

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springhow.example</groupId> <artifactId>hello-world</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>hello-world</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Code language: HTML, XML (xml)

And your main Class for Spring boot resembles this.

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @SpringBootApplication public class HelloWorldApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(HelloWorldApplication.class); } public static void main(String[] args) { SpringApplication.run(HelloWorldApplication.class); } @RequestMapping("/") String helloWorld() { return "Hello World!"; } }
Code language: Java (java)

Step 1: Package type from JAR to WAR.

In pom.xml file, Change the line <packaging>jar</packaging> in to <packaging>war</packaging>. So your pom.xml can look like this.

<groupId>com.springhow.example</groupId> <artifactId>hello-world</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging>
Code language: HTML, XML (xml)

At this point, running mvn package would result in a WARfile in the target/ directory. But, we are not done yet.

Step 2 : Remove the extra dependencies

By default, Spring boot adds the spring-boot-starter-tomcat dependency to your web application. This starter brings in all jars for embedded tomcat. Their dependencies may clash with the server’s runtime and cause unpredictable outcomes. So to convert spring boot from JAR to WAR, you should eliminate the server dependencies.

To avoid this, you need to mark the starter in pom.xml as provided.

<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> <!-- This is important. --> </dependency>
Code language: HTML, XML (xml)

By marking the dependencies as provided, maven will ignore these dependencies.

Initializing spring in the web application context

One key difference between JAR and WAR files are how they both initialize the application. For instance, the JAR starts by calling the Main-Class entry in MANIFEST.MF file. However, This won’t work in WAR files. The WAR files usually have a WEB.xml file that tells the application server which path matches to which servlet etc. With the new Servlet 3.0, you can use annotations to bring the same behaviour.

But we don’t have to do all of that, thanks to spring-web. Spring Web module provides a SpringBootServletInitializer class for initializing the web context.

@RestController @SpringBootApplication public class HelloWorldApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(HelloWorldApplication.class); } public static void main(String[] args) { SpringApplication.run(HelloWorldApplication.class); } @RequestMapping("/") String helloWorld() { return "Hello World!"; } }
Code language: Java (java)

You are almost done at this point. Run the mvn package command and you have successfully converted your spring boot application from JAR into a WAR file. You can safely deploy these WAR files on application servers like Tomcat, GlassFish etc.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *