Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Spring Boot With External Tomcat

DZone 's Guide to

Spring Boot With External Tomcat

Let's look at some common problems you might fave when starting a project from scratch.

· Java Zone ·
Free Resource

Over the last few months, I disappeared. The reason is that I began a very exciting project that became a real challenge. Hence, I couldn’t take care of my blog, but now, I am here and would like to share you my experience. Let’s look at the most common problems you face when starting a project from scratch, specifically how to run a Spring Boot app with external Tomcat.

The Spring Boot Approach

In my Spring Boot article, I wrote about the basic fundamentals of how this technology works and what benefits it has over the core framework.

One of the main advantages of using Spring Boot is the ability to easily set up your web applications with the built-in embedded Tomcat. By default, the auto-configurer sets up your project with Tomcat. You simply hit the run button, and your web server starts up with your application. In your application.yaml or properties file, you can configure this Tomcat server easily like below:

server:
   port: 9091 //set the port number of our running application
   servlet:
      context-path: /springapplication /set the context path of our application


To run our application, we only need a single main method:

@SpringBootApplication
public class App 
{
    public static void main( String[] args )
    {
    SpringApplication.run(App.class, args);
    }
}


If you aren't familiar with how to create a single Spring Boot application, check my article for the details where I went through the basics step-by-step.

Problem with spring boot with external tomcat

The Problem With External Tomcat

It can be a common expectation for the application to run on an external Tomcat server. Usually, it happens because of the operational infrastructure. At this point, some problems come. Your Spring Boot application won’t start by simply deploying it to the web server. It has several reasons:

  • By default, Spring Boot creates a .jar file as an output. The Tomcat needs a .war file.
  • In a Tomcat environment, you wouldn’t like to use the embedded server.
  • The Tomcat server won’t hit your main method. Hence, you need to start your application as a normal Spring app.

Spring Boot is a cutting edge technology and mainly supports runs in a containerized environment. What can you do if you would like to operate your application in the standard way?

First, you could go back to a native Spring, which you normally do not want. Second, you could do some modifications that prepare your application to run on an old school Tomcat server. So, I will show you how.

Running Spring boot with external tomcat


Running Spring Boot With External Tomcat

Firstly, you need to do some modifications in your pom.xml:

Set war packaging for your artifact:

<packaging>war</packaging>


Set the Tomcat server dependency to provide:

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


If some of your Spring Boot libraries contain it by default, exclude it:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
</dependency>

And lastly, this makes the trick: modify your Application’s default class:
@SpringBootApplication
public class App extends SpringBootServletInitializer
{
    public static void main( String[] args )
    {
    SpringApplication.run(App.class, args);
    }
}


The SpringBootServerInitializer class does the following (taken from the original class header):

 * An opinionated {@link WebApplicationInitializer} to run a {@link SpringApplication} from a traditional WAR deployment. Binds {@link Servlet}, {@link Filter} and {@link ServletContextInitializer} beans from the application context to the server.

 * To configure the application either override the {@link #configure(SpringApplicationBuilder)} method (calling {@link SpringApplicationBuilder#sources(Class...)}) or make the initializer itself a {@code @Configuration}. If you are using {@link SpringBootServletInitializer} in combination with other {@link WebApplicationInitializer WebApplicationInitializers} you might also want to add an {@code @Ordered} annotation to configure a specific startup order.

 * Note that a WebApplicationInitializer is only needed if you are building a war file and deploying it. If you prefer to run an embedded web server then you won't need this at all.


After you do these modifications, you will be able to run your application from a traditional war deployment.


The External Configuration of Your Spring Boot App on Tomcat

It could be a general expectation to read your configuration file from an external source where the IT operation can handle it easily.

To achieve this, you need to override the configure method from the mentioned class above in our main class.

In the following example, I brought a real-time example. Here, I needed to read the config path from an environment variable. They set it in the Tomcat’s server setenv.sh file.

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {

String configLocation = System.getProperty("global.appconf.dir"); //get the default config directory location

    String configPath = configLocation + File.separator + "springApplication"  + File.separator + "application.yml"; //set the configpath of this application instance exclusively

    log.info("Configpath: " + configPath);
    log.info("Starting to run Spring boot app...");

    if(configLocation != null && !configLocation.isEmpty()) {
    Properties props = new Properties();
    props.setProperty("spring.config.location", configPath); //set the config file to use    
    application.application().setDefaultProperties(props);
    }else{
    log.info("No global.appconf.dir property found, starting with default on classpath");
    }

return application.sources(SpringApplication.class);
}


Note that when you run on external Tomcat, the settings under your server node in your configuration file don’t take effect. These properties only influence embedded Tomcat.

Summary

In this article, I demonstrated how you can run your Spring Boot application on external Tomcat. For me, this was a real-world scenario where I had to solve this problem. 

Hopefully, this will provide some useful information when you will face a similar problem. If you like my post, do not forget to share!

Lastly, for deeper knowledge, I recommend you to read the official Spring documentation here.

Topics:
tomcat ,spring boot ,java ,challenges ,tutorial ,external configuration ,configuration ,spring boot app

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}