Reputation: 11
I have a multi-module Spring-Boot 3.4.2 application running with Java 21. The application is working fine when I run it on Intellij (entities persist, webservice responds well), but when I generate a war and try to run it on a standalone Tomcat server (10 and 11), the one webservice I created doesn't respond (the entities persist). What would be the problem? Is it on my configuration or on the Tomcat server?
Here is the pom.xml content (properties, dependencies and build ) :
<properties>
<spring-boot.version>3.4.2</spring-boot.version>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--PERSISTENCE-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.6.8.Final</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version> <!-- Jakarta Persistence API -->
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>ca.project.projectApplication</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
and here is the application-properties content :
# PostgreSQL Database Connection Configuration
spring.datasource.url=jdbc:postgresql://localhost:5432/project_db
spring.datasource.username=postgres
spring.datasource.password=****
spring.datasource.driver-class-name=org.postgresql.Driver
# Hibernate Configuration
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.format_sql=true
#Hikary Configuration
spring.datasource.hikari.connectionTimeout=20000
spring.datasource.hikari.idleTimeout=30000
spring.datasource.hikari.maxLifetime=2000000
spring.datasource.hikari.maximumPoolSize=10
logging.level.org.springframework.web=DEBUG
logging.level.org.springframework.boot=DEBUG
#Context
server.servlet.context-path=/project
#Port
server.port=8081
Here is the main class content :
@SpringBootApplication
@ComponentScan(basePackages = {"ca"})
@EntityScan(basePackages = {"ca"})
@EnableJpaRepositories(basePackages = {"ca"})
public class ProjectApplication extends SpringBootServletInitializer{
private static final Logger log = LogManager.getLogger(ProjectApplication.class);
public static void main(String[] args) {
SpringApplication.run(ProjectApplication.class);
log.info("Project backend application started.");
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(ProjectApplication.class);
}
}
And the RestController :
@RestController
@RequestMapping("/")
public class HealthCheckController {
@Autowired
IHealthCheckService healthCheckService;
@GetMapping("health-check")
public String performHealthCheck(){
boolean isHealthy = healthCheckService.testHealth();
if(isHealthy){
return "test ok";
}
return "test ko";
}
}
So I am trying to call this : http://localhost:8081/project/health-check
Here is the log when I am running the WAR on a Tomcat server (10.x or 11.x)
2025-03-02 22:09:55.320 INFO DESKTOP-696GCGE --- [ main] c.c.ProjectApplication : Starting ProjectApplication v0.0.1-SNAPSHOT using Java 21.0.6 with PID 11188 (D:\Logiciels\apache-tomcat-10.1.34\webapps\Project-backend-mainapp-0.0.1-SNAPSHOT\WEB-INF\classes started by MIANGALY in D:\Logiciels\apache-tomcat-10.1.34\bin)
2025-03-02 22:09:55.345 DEBUG DESKTOP-696GCGE --- [ main] c.c.ProjectApplication : Running with Spring Boot v3.4.2, Spring v6.2.2
2025-03-02 22:09:55.349 INFO DESKTOP-696GCGE --- [ main] c.c.ProjectApplication : The following 1 profile is active: "dev"
2025-03-02 22:09:56.658 INFO DESKTOP-696GCGE --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-03-02 22:09:56.701 INFO DESKTOP-696GCGE --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 19 ms. Found 0 JPA repository interfaces.
2025-03-02 22:09:58.026 WARN DESKTOP-696GCGE --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.ws.config.annotation.DelegatingWsConfiguration' of type [org.springframework.ws.config.annotation.DelegatingWsConfiguration$$SpringCGLIB$$0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). The currently created BeanPostProcessor [annotationActionEndpointMapping] is declared through a non-static factory method on that class; consider declaring it as static instead.
2025-03-02 22:09:58.111 INFO DESKTOP-696GCGE --- [ main] .w.s.a.s.AnnotationActionEndpointMapping : Supporting [WS-Addressing August 2004, WS-Addressing 1.0]
2025-03-02 22:09:58.219 INFO DESKTOP-696GCGE --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2786 ms
2025-03-02 22:09:59.105 INFO DESKTOP-696GCGE --- [ main] o.h.j.i.u.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2025-03-02 22:09:59.274 INFO DESKTOP-696GCGE --- [ main] o.h.Version : HHH000412: Hibernate ORM core version 6.6.8.Final
2025-03-02 22:09:59.391 INFO DESKTOP-696GCGE --- [ main] o.h.c.i.RegionFactoryInitiator : HHH000026: Second-level cache disabled
2025-03-02 22:10:00.126 INFO DESKTOP-696GCGE --- [ main] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer
2025-03-02 22:10:00.235 WARN DESKTOP-696GCGE --- [ main] c.z.h.HikariConfig : HikariPool-1 - idleTimeout has been set but has no effect because the pool is operating as a fixed size pool.
2025-03-02 22:10:00.237 INFO DESKTOP-696GCGE --- [ main] c.z.h.HikariDataSource : HikariPool-1 - Starting...
2025-03-02 22:10:01.034 INFO DESKTOP-696GCGE --- [ main] c.z.h.p.HikariPool : HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@1d4d84fb
2025-03-02 22:10:01.039 INFO DESKTOP-696GCGE --- [ main] c.z.h.HikariDataSource : HikariPool-1 - Start completed.
2025-03-02 22:10:01.209 WARN DESKTOP-696GCGE --- [ main] o.h.o.deprecation : HHH90000025: PostgreSQLDialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
2025-03-02 22:10:01.279 INFO DESKTOP-696GCGE --- [ main] o.h.o.c.pooling : HHH10001005: Database info:
Database JDBC URL [Connecting through datasource 'HikariDataSource (HikariPool-1)']
Database driver: undefined/unknown
Database version: 17.2
Autocommit mode: undefined/unknown
Isolation level: undefined/unknown
Minimum pool size: undefined/unknown
Maximum pool size: undefined/unknown
2025-03-02 22:10:03.969 INFO DESKTOP-696GCGE --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2025-03-02 22:10:08.601 INFO DESKTOP-696GCGE --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2025-03-02 22:10:08.895 WARN DESKTOP-696GCGE --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2025-03-02 22:10:09.881 INFO DESKTOP-696GCGE --- [ main] c.c.ProjectApplication : Started ProjectApplication in 15.529 seconds (process running for 37.414)
The result :
When running the application on IntelliJ, and calling the endpoint with Postamn, I get a 200 statuscode and a "test ok" as a response
When running the WAR on Tomcat (10.x or 11.x) , and calling the same enpoint with Postamn, I get and "error ECONNREFUSED 127.7.0.1:8081"
Please note that :
There is no web.xml file in the application
The context path is only set in the application.properties of the project, not anywhere else
I have tried running the war on Tomcat 10.1.34, 10.1.36 and 1.0.4. I have tried to add the "provided" scope to the tomcat dependency but it would fail even the Intellij run. I have tried removing the tomcat dependency, to no avail. I have tried changing the Tomcat server.xml by activating this :
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true"
maxParameterCount="1000"
>
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
certificateKeystorePassword="changeit" type="RSA" />
</SSLHostConfig>
</Connector>
I also tried to run only the code with the RestController, without the entities, but it still didn't work.
Upvotes: 1
Views: 45
Reputation: 3129
So if the test is deployed on Tomcat Server, the URL will be:
http://localhost:8080/project/health-check
The following two settings will not be used when deployed to Tomcat Server
Tomcat Server runs on port 8080 by default.
The context-path default is based on your war file name. If your war file name is hello.war, its context-path will be /hello
. If your war file name is project.war, its context-path will be /project
.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo-springboot-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>demo-springboot-web</name>
<description>Demo project for Spring Boot</description>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<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>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>10.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>project</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Because this war is to be deployed on Tomcat Server, I don't need Spring Boot to use embedded Tomcat, so I exclude the use of 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>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>10.0.0</version>
<scope>provided</scope>
</dependency>
You do not need to include the following:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
</dependency>
You just need to add the following two paragraphs.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
You do not need to set the following:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.6.8.Final</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version> <!-- Jakarta Persistence API -->
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.5</version>
</dependency>
The postgresql version will be configured by spring-boot-starter-data-jpa. hibernate-core will also be configured by spring-boot-starter-data-jpa.
Spring Boot uses SLF4J plus Logback by default. Without any additional configuration (no logback.xml), you can use it directly in your program:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
private static final Logger logger = LoggerFactory.getLogger(ProjectApplication.class);
...
logger.info(">>> ProjectApplication init");
...
ProjectApplication.java
package com.example;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SpringBootApplication
public class ProjectApplication extends SpringBootServletInitializer {
private static final Logger logger = LoggerFactory.getLogger(ProjectApplication.class);
public static void main(String[] args) {
logger.info(">>> BEFORE - Project backend application started.");
SpringApplication.run(ProjectApplication.class, args);
logger.info(">>> AFTER - Project backend application started.");
}
public ProjectApplication(){
logger.info(">>> ProjectApplication init");
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
logger.info(">>> SpringBootServletInitializer configure");
return application.sources(ProjectApplication.class);
}
}
Upvotes: 2