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:
http://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.