I am trying to run a spring boot project which runs perfectly on embedded tomcat but when deployed to wildfly 21.x throws java.lang.NoClassDefFoundError: org/apache/catalina/connector/Connector
Any help would be appreciated.
Below is my code snippet.
Main file:-
import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class CdPlaylistadapterApplication {
@Value("${http.port}")
private int httpPort;
public static void main(String[] args) {
SpringApplication.run(CdPlaylistadapterApplication.class, args);
}
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(httpPort);
return connector;
}
}
My pom.xml snippet
<cxf.version>3.4.0</cxf.version>
</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>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
Error:-
Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.att.dtss.playlistadapter.CdPlaylistadapterApplication] from ClassLoader [ModuleClassLoader for Module "deployment.cd-playlistadapter-0.0.1-SNAPSHOT.war" from Service Module Loader]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:481)
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:455)
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:151)
... 39 more
Caused by: java.lang.NoClassDefFoundError: org/apache/catalina/connector/Connector
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463)
... 41 more
Caused by: java.lang.ClassNotFoundException: org.apache.catalina.connector.Connector from [Module "deployment.cd-playlistadapter-0.0.1-SNAPSHOT.war" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
... 45 more
The class org.apache.catalina.connector.Connector
is part of Tomcat. In order for your application to work correctly on external servlet containers, the embedded copy of Tomcat must not be on the classpath of the web application (i.e. in /WEB-INF/lib
). You set it correctly by setting the scope of the spring-boot-starter-tomcat
to provided
.
However now you have a problem, because the CdPlaylistadapterApplication
has Connector
in one of its method signatures and Spring Boot fails while creating an instance of the CdPlaylistadapterApplication
class.
To solve it you need to move Tomcat specific configuration to another class (even nested) and protect it with the @ConditionalOnClass
annotation:
@SpringBootApplication
public class CdPlaylistadapterApplication extends SpringBootServletInitializer {
@Configuration
@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})
static class EmbeddedConfiguration {
@Value("${http.port}")
private int httpPort;
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(httpPort);
return connector;
}
}
public static void main(String[] args) {
SpringApplication.run(CdPlaylistadapterApplication.class, args);
}
}