🏠Spring BootHow to convert Spring Boot JAR to WAR?

How to convert Spring Boot JAR to WAR?

Spring Boot

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 at unavoidable situations, you may need a WAR file.

  • 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.
    • First, you need to run ps -ef | grep java
    • And then identify and execute kill -9 <PID>.
    • There is an easier way though.
  • 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 Example.

<?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 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.

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)

Maven will ignore dependencies if the scope is provided. Application server Runtime will supply these dependencies.

Initializing spring in the web application context

Every executable JAR files will have a Main-Class entry in META-INF\MANIFEST.MF file. Spring-boot takes advantage of this behaviour for JAR files. But when we convert JAR to WAR files, the Main-Class entry won’t cut it. Here, you would need web.xml or servlet-3.0 annotations.

Thanks to spring-web, we can configure SpringBootServletInitializer to initialize our servlet context. That is exactly what we have done below.

@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)

Now you can run mvn package and see the war file under target/ directory. You can deploy this file on any application server like tomcatWildFly,GlassFish etc.

For Spring Boot 1.x, the SpringBootServletInitializer is under org.springframework.boot.web.support.

Similar Posts

Leave a Reply

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