Issue
I am having an issue after switching to Java 11 and adding modules to a Spring Boot application that acts as a REST API. I am not getting any errors when running the application and it shuts down after initialization with exit code 0. The Tomcat embedded server does not start, nor the dispatch server, which would prevent the application from closing and listen for incoming requests.
To me it looks like it does not start the embedded container because the modularization is preventing the Spring Boot Autoconfigure to find some Conditional Beans to initiate the REST server.
There is no error. It acts like if you run the application without a controller, it will shutdown without errors since there is no server to block it. I have listed the beans in the context and the HelloController
is there, but like I said I can not find any beans that should exist for a running server, like web.servlet.DispatcherServlet
.
I have tried searching for this, but unfortunately the fact that the term module existed long before Java 9 with a different meaning, makes it hard to find any answer. I apologize if somewhere deep in SO this question was already posted.
Even the basic example I can not make it work
Application.java
@SpringBootApplication()
public class SchoolsApplication {
public static void main(String[] args) {
SpringApplication.run(SchoolsApplication.class, args);
}
}
HelloController.java
@RestController
public class HelloController {
@GetMapping("hello")
public String hello(){
return "hello";
}
}
module-info.java
module controllers {
requires spring.boot;
requires spring.boot.autoconfigure;
requires spring.context;
requires spring.beans;
requires spring.web;
requires com.fasterxml.jackson.databind;
opens package.controllers to spring.core;
}
I am using Spring 2.3.4.RELEASE
and I am in fact using JDK14, but target is Java 11.
I have tried to play with the required modules (i.e. spring.webmvc, tomcat.embedded.core) or search for the exact Spring beans to include, but with no success.
EDIT
When adding explicitly requires org.apache.tomcat.embed.core;
the server starts and crashes with the error
org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory]: Factory method 'tomcatServletWebServerFactory' threw exception
...
java.util.ServiceConfigurationError: org.apache.juli.logging.Log: module org.apache.tomcat.embed.core does not declare `uses`
The Tomcat version is 9.0.38
Solution
I managed to pinpoint the error to the Tomcat embedded server. The version used by spring-web-starter
is tomcat-embed-core:9.0.38
. The issue was fixed in tomcat-embed-core:9.0.39
with
open module org.apache.tomcat.embed.core {
...
uses org.apache.juli.logging.Log;
}
So I resolved this through maven dependency management.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.39</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.39</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Answered By - Radu Ionescu
Answer Checked By - Timothy Miller (JavaFixing Admin)