Heads up… this article is old! For an updated version of this article, see Deploy a Spring Boot Application into Tomcat on the Okta developer blog.

Spring Boot makes it easy to create stand-alone Java web applications. However in production environments, a web container often already exists. How do we deploy our apps in these situations and have them run side-by-side with other servlets? In this tutorial, we’ll walk through how to use WAR files to do just that.

Getting Started with With Spring Boot, Tomcat, and WAR Files

In a previous tutorial, we built a simple RESTful web app using Spring Boot. I’m going to use this as a base and show how to deploy it into a container. You can grab the code for this tutorial on GitHub.

To ensure an existing Spring Boot app is container-ready one needs do three things

– Renaming the embedded Tomcat libraries

– Repackage the output file as a WAR

– Wire the application up as a servlet

Tomcat Libraries

Building a Spring Boot application produces a runnable jar file by default. If your app includes server functionality, then Tomcat will be bundled with it. We need to ensure the Tomcat libraries don’t clash with an existing container (since the container will include the same libraries).

When we do a clean clone of our repo (grab the code on GitHub if you haven’t yet) and do an mvn clean package we end up with a target directory containing our runnable jar.

$ mvn clean package 1 2 $ mvn clean package

This jar contains Tomcat libraries. To confirm this, we can rename it to .zip and look at the lib directory.



You’ll see various .jar files starting with tomcat- . Some of these will clash with a running instance of Tomcat. We need to tell Spring Boot to move them.

To WAR! AKA: Build Your WAR Files

First, we must tell Spring Boot we want a WAR file as output. This is as easy as adding one line to our pom.xml.

<packaging>war</packaging> 1 2 < packaging > war < / packaging >

Now when we build the package with

$ mvn clean package 1 2 $ mvn clean package

we will see a .war file inside our target directory:



As before we can rename the file to .zip to see what’s inside. Everything is basically the same, just slightly re-ordered. Now lib is inside of WEB-INF and demo` (where our project code sits) is in WEB-INF/classes.



Renaming Tomcat

Next, we tell Spring Boot to move our Tomcat libraries out of this folder. In our previous pom.xml we included three dependencies for our project – one for REST, one for data access, and another for the database.

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> </dependencies> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 < dependencies > < dependency > < groupId > org . springframework . boot < / groupId > < artifactId > spring - boot - starter - data - rest < / artifactId > < / dependency > < dependency > < groupId > org . springframework . boot < / groupId > < artifactId > spring - boot - starter - data - jpa < / artifactId > < / dependency > < dependency > < groupId > com . h2database < / groupId > < artifactId > h2 < / artifactId > < / dependency > < / dependencies >

Now we append the Spring Boot Tomcat Starter to this (which links to the Tomcat libraries you need when embedding) and set the scope of the dependency to provided.

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> </dependencies> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 < dependencies > < dependency > < groupId > org . springframework . boot < / groupId > < artifactId > spring - boot - starter - data - rest < / artifactId > < / dependency > < dependency > < groupId > org . springframework . boot < / groupId > < artifactId > spring - boot - starter - data - jpa < / artifactId > < / dependency > < dependency > < groupId > com . h2database < / groupId > < artifactId > h2 < / artifactId > < / dependency > < dependency > < groupId > org . springframework . boot < / groupId > < artifactId > spring - boot - starter - tomcat < / artifactId > < scope > provided < / scope > < / dependency > < / dependencies >

This will still include the .jar files as before but will put them in a new folder called lib-provided.

We can see this if we follow the same procedure as before. Once we mvn clean package and rename our .war to .zip we’ll see inside WEB-INF the new folder has appeared. Inside are all the embedded Tomcat libraries (and you’ll see they are no longer in lib).



Now our application will happily reside in a servlet container without clashing with its libraries.

Setting Up a Servlet

The only other thing we need to do is wire our application up to start as a servlet. And to do this we need to modify our application definition.

In the REST app mentioned our Application.java used the SpringBootApplication annotation on the main class and defined a main method.

package demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 package demo ; import org . springframework . boot . SpringApplication ; import org . springframework . boot . autoconfigure . SpringBootApplication ; @ SpringBootApplication public class Application { public static void main ( String [ ] args ) { SpringApplication . run ( Application . class , args ) ; } }

To set the app up as a servlet we extend the main class with SpringBootServletInitializer and override the configure method using SpringApplicationBuilder.

package demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package demo ; import org . springframework . boot . SpringApplication ; import org . springframework . boot . autoconfigure . SpringBootApplication ; import org . springframework . boot . context . web . SpringBootServletInitializer ; import org . springframework . boot . builder . SpringApplicationBuilder ; @ SpringBootApplication public class Application extends SpringBootServletInitializer { @ Override protected SpringApplicationBuilder configure ( SpringApplicationBuilder application ) { return application . sources ( Application . class ) ; } public static void main ( String [ ] args ) { SpringApplication . run ( Application . class , args ) ; } }

And that’s it! This application will now happily run inside a Tomcat container!

Installing Tomcat

Deploying WAR files to Tomcat is as easy as copying the file to Tomcat’s webapps directory. But first, you need to install Tomcat. On Ubuntu, you can use apt-get .

$ sudo apt-get install tomcat7 1 2 $ sudo apt - get install tomcat7

This will install and start the server automatically on port 8080.

On Windows it’s just as easy – download and extract the binary distribution .zip file and run startup.bat in the bin directory. This will open up a console window showing the output of Catalina.



In both cases, you can check to see if everything is running by browsing to localhost:8080 . You should see the Tomcat default homepage.



(Who knew Tomcat was so easy to use?!)

Copy the WAR File

The last step is copying the WAR to webapps . Here the name is important – whatever filename we choose will be used to map HTTP requests to our application. (All done automatically! I think this is amazing.) In an attempt to be more URL-friendly, I’m going to use demo.war .

On Ubuntu, this can be done with:

$ sudo cp target/demo-0.0.1-SNAPSHOT.war /var/lib/tomcat7/webapps/demo.war 1 2 $ sudo cp target / demo - 0.0.1 - SNAPSHOT . war / var / lib / tomcat7 / webapps / demo . war

In Windows, use Explorer for the copy and then wait for the console window to show deployment messages.



And that’s it! Just by copying one file across our app is automatically booted and running side-by-side with the default Tomcat servlet.

Test Your WAR File Deployment

As before we test this by making calls using curl. Normally we called get on localhost but now our application is mapped to /demo/ .

$ curl localhost:8080/demo/ 1 2 $ curl localhost : 8080 / demo /

This shows you available URLs. To see what people objects are available you can use:

$ curl localhost:8080/demo/people 1 2 $ curl localhost : 8080 / demo / people

Or, create new ones with:

$ curl -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Karl", "lastName" : "Penzhorn" }' localhost:8080/demo/persons 1 2 $ curl - X POST - H "Content-Type:application/json" - d '{ "firstName" : "Karl", "lastName" : "Penzhorn" }' localhost : 8080 / demo / persons

Note: In my testing I found the deploy on Windows to be somewhat brittle. Sometimes I needed to close and rerun startup.bat .

Run as a Standalone Application

One last thing – because our Tomcat libraries are still there (just moved) we are able to run this application on it’s own. So mvn spring-boot:run still works !

$ mvn spring-boot:run 1 2 $ mvn spring - boot : run

Learn More

Ready to add authentication and user management to your application? Interested in learning more about Spring Boot? We’ve got some other great resources to help you out:

Happy coding!