Comprehensive Guide to Deploying a Spring Boot Application on Tomcat with Environment Variables

Deploying a Spring Boot application on Apache Tomcat is a common practice for developers seeking to leverage the robustness of Tomcat’s servlet container while benefiting from Spring Boot’s streamlined configuration and development experience. This guide provides a step-by-step approach to successfully deploy your Spring Boot application as a WAR file on Tomcat, including the configuration of environment variables for enhanced flexibility and security.

Introduction

Spring Boot simplifies the process of building and deploying Java applications by offering embedded servers and auto-configuration. However, deploying a Spring Boot application to an external servlet container like Tomcat can be advantageous for scenarios requiring centralized management, specific configurations, or integration with existing infrastructure.

This guide walks you through deploying a Spring Boot application on Tomcat, emphasizing the use of environment variables to manage configurations securely and efficiently.

Prerequisites

Before proceeding, ensure you have the following:

  • Java Development Kit (JDK): Version 8 or higher.
  • Apache Tomcat: Version 9 or higher (Tomcat 11 is also supported).
  • Maven or Gradle: For building your Spring Boot application.
  • Spring Boot Application: A pre-existing Spring Boot project.

Packaging Spring Boot Application as WAR

By default, Spring Boot applications are packaged as executable JARs with embedded servers. To deploy on Tomcat, you need to package your application as a WAR file.

Update pom.xml for Maven Projects

Modify your pom.xml to change the packaging type and exclude the embedded Tomcat server.

<project>
<!-- Other configurations -->

<packaging>war</packaging>

<dependencies>
<!-- Spring Boot Starter Web excluding embedded Tomcat -->
<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>

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

<!-- Other dependencies -->
</dependencies>

<build>
<plugins>
<!-- Spring Boot Maven Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>true</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>
</project>

For Gradle Projects

If you’re using Gradle, adjust your build.gradle accordingly.

plugins {
    id 'war'
}

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-web') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
    }
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    // Other dependencies
}

Configuring Spring Boot for Tomcat Deployment

To enable your Spring Boot application to work as a WAR in Tomcat, you need to extend SpringBootServletInitializer and override the configure method.

Modify the Main Application Class

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;

@SpringBootApplication
public class YourApplication extends SpringBootServletInitializer {

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(YourApplication.class);
    }
}

Remove the Embedded Server Dependency

Setting Up Environment Variables

Environment variables are crucial for managing configurations outside your application code, enhancing security and flexibility.

Define Environment Variables

For instance, to set the ZING_HOME environment variable:

Linux/MacOS”

export ZING_HOME=/home/ocpp

Windows

set ZING_HOME=C:\path\to\ocpp

Configure Tomcat to Recognize Environment Variables

Tomcat needs to be aware of these environment variables, especially when running as a service.

Using setenv.sh or setenv.bat

Unix/Linux (setenv.sh):

Create or edit the setenv.sh file in Tomcat’s bin directory:

#!/bin/sh
export ZING_HOME=/home/ocpp

Ensure it has executable permissions:

chmod +x setenv.sh

Windows (setenv.bat):

Create or edit the setenv.bat file in Tomcat’s bin directory:

set ZING_HOME=C:\path\to\ocpp

<h3?Setting Environment Variables Globally (System-Wide)

Alternatively, set environment variables globally:

Linux (Systemd-based systems):

sudo systemctl edit tomcat

Add:

[Service]
Environment="ZING_HOME=/home/ocpp"

Reload and restart Tomcat:

sudo systemctl daemon-reload
sudo systemctl restart tomcat

Windows:

Set environment variables via System Properties > Environment Variables.

Externalizing Configuration with application.properties

Managing configurations externally allows for greater flexibility and security, especially when handling sensitive information like database credentials.

Modify application.properties

Add the following line to import external configuration:

spring.config.import=optional:file:${ZING_HOME}/config/zing.properties

Note: Ensure there are no quotes around the value to prevent misinterpretation.

Create zing.properties

At the path specified by ZING_HOME, create a zing.properties file with necessary configurations. For example:

spring.datasource.url=jdbc:mysql://localhost:3306/zing_db
spring.datasource.username=zing_user
spring.datasource.password=secure_password
# Additional configurations

Ensure File Accessibility

Make sure the zing.properties file is readable by the Tomcat process:

chmod 644 /home/ocpp/config/zing.properties
chown ocpp:ocpp /home/ocpp/config/zing.properties

Deploying WAR to Tomcat

With your application packaged as a WAR and configurations externalized, proceed to deploy the WAR file to Tomcat.

Locate Tomcat’s webapps Directory

Typically found at /path/to/tomcat/webapps/.

Deploy the WAR File

Copy your WAR file to the webapps directory:

cp target/your-application.war /path/to/tomcat/webapps/

Tomcat will automatically deploy the WAR upon startup or when placed in the webapps directory.

Restart Tomcat

To ensure the deployment takes effect:

sudo systemctl restart tomcat

Or use the appropriate startup script:

/path/to/tomcat/bin/shutdown.sh
/path/to/tomcat/bin/startup.sh

Testing the Deployment

After deploying, verify that your application is running correctly. Open a web browser and navigate to:

https://localhost:8080/your-application/

Replace 8080 with your Tomcat’s HTTP port and your-application with your WAR file name (without the .war extension).

Troubleshooting Common Issues

1. Application Fails to Start

Check Tomcat Logs: Inspect catalina.out or relevant log files for error messages.
Verify zing.properties Path: Ensure ZING_HOME is correctly set and the file exists.
Check File Permissions: Ensure Tomcat has read access to zing.properties.

2. Environment Variables Not Recognized

Ensure Variables are Set Before Tomcat Starts: Environment variables must be available to the Tomcat process at startup.
Verify with Logging: Use logging statements to confirm the values are correctly loaded.

3. Configuration Not Overridden

Check spring.config.import Syntax: Ensure no quotes and correct path formatting.
Confirm Property Names: Ensure properties in zing.properties correctly match those in application.properties.

4. Port Conflicts

Verify Tomcat’s Ports: Ensure no other applications are using the same ports.
Change Tomcat’s Default Ports: Modify server.xml if necessary.

Best Practices

Externalize Sensitive Configurations:

Use environment variables or external properties files to manage sensitive data like database credentials.

Use Spring Profiles:

Manage different configurations for various environments (development, testing, production) using Spring Profiles.

Secure Configuration Files:

Restrict access to external configuration files to prevent unauthorized access.

Automate Deployment:

Use CI/CD pipelines to automate the building and deployment process, ensuring consistency and reliability.

Monitor Application Health:

Implement monitoring and logging to track application performance and detect issues early.

Maintain Version Control:

Keep configuration files under version control, excluding sensitive information, to track changes and facilitate collaboration.

Conclusion

Deploying a Spring Boot application on Apache Tomcat while leveraging environment variables for configuration management offers a blend of Spring Boot’s rapid development capabilities and Tomcat’s stability as a servlet container. By following this comprehensive guide, you can ensure a smooth deployment process, maintain secure and flexible configurations, and harness the full potential of both Spring Boot and Tomcat in your Java applications.

Whether you’re deploying for development, testing, or production environments, understanding and implementing these deployment strategies will enhance your application’s scalability, security, and maintainability.

This article is inspired by real-world challenges we tackle in our projects. If you're looking for expert solutions or need a team to bring your idea to life,

Let's talk!

    Please fill your details, and we will contact you back

      Please fill your details, and we will contact you back