Issue
I'm following the guide Building an Application with Spring Boot. My goal is to run the project in my Tomcat server.
First, I could run the project locally in intellij.
Then, I created a war called sample.war
and deployed it to my Tomcat server by following 12.17.1. Create a Deployable War File. I then put the war
to the directory webapps/sample.war
. However, it fails to run. The key error (for full log please see below):
2021-08-26 16:40:37,453 [localhost-startStop-15] ERROR o.s.b.SpringApplication - Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'formContentFilter' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.filter.OrderedFormContentFilter]: Factory method 'formContentFilter' threw exception; nested exception is java.lang.VerifyError: Bad return type
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'formContentFilter' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.filter.OrderedFormContentFilter]: Factory method 'formContentFilter' threw exception; nested exception is java.lang.VerifyError: Bad return type
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>2.5.2</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>serving-web-content-complete</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>serving-web-content-complete</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
servingwebcontent\GreetingController.java
:
package com.example.servingwebcontent;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class GreetingController {
@GetMapping("/greeting")
public String greeting(@RequestParam(name = "name", required = false, defaultValue = "World") String name, Model model) {
model.addAttribute("name", name);
return "greeting";
}
}
ServingWebContentApplication.java
package com.example.servingwebcontent;
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 ServingWebContentApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ServingWebContentApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ServingWebContentApplication.class, args);
}
}
Server information:
Server version: Apache Tomcat/8.5.20
Server number: 8.5.20.0
OS Name: Linux
OS Version: 5.4.0-77-generic
Below please see the error log from catalina.out
:
26-Aug-2021 16:40:35.813 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.undeploy Undeploying context [/sample]
26-Aug-2021 16:40:35.824 INFO [localhost-startStop-15] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [/opt/apache-tomcat-8.5.20/webapps/sample.war]
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/apache-tomcat-8.5.20/lib/news-client-0.7.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/apache-tomcat-8.5.20/webapps/sample/WEB-INF/lib/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.2)
2021-08-26 16:40:37,453 [localhost-startStop-15] ERROR o.s.b.SpringApplication - Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'formContentFilter' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.filter.OrderedFormContentFilter]: Factory method 'formContentFilter' threw exception; nested exception is java.lang.VerifyError: Bad return type
Exception Details:
Location:
org/springframework/http/converter/json/Jackson2ObjectMapperBuilder$SmileFactoryInitializer.create()Lcom/fasterxml/jackson/core/JsonFactory; @7: areturn
Reason:
Type 'com/fasterxml/jackson/dataformat/smile/SmileFactory' (current frame, stack[0]) is not assignable to 'com/fasterxml/jackson/core/JsonFactory' (from method signature)
Current Frame:
bci: @7
flags: { }
locals: { 'org/springframework/http/converter/json/Jackson2ObjectMapperBuilder$SmileFactoryInitializer' }
stack: { 'com/fasterxml/jackson/dataformat/smile/SmileFactory' }
Bytecode:
0x0000000: bb00 0359 b700 04b0
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:163)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:175)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:155)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:97)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:752)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:728)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:988)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1860)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'formContentFilter' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.filter.OrderedFormContentFilter]: Factory method 'formContentFilter' threw exception; nested exception is java.lang.VerifyError: Bad return type
[nipped with more of the same errors]
26-Aug-2021 16:40:37.531 INFO [localhost-startStop-15] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [/opt/apache-tomcat-8.5.20/webapps/sample.war] has finished in [1,708] ms
Here's what I've tried so far:
I have the exact problem mentioned in ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean. I've followed the advice of the three cases but to no avail:
Case 1:
@SpringBootApplication
annotation isn't missingCase 2: not applicable because my project is a web project
Case 3: I don't use
spring-boot-starter-webflux
I have the exact problems mentioned in Unable to start embedded Tomcat org.springframework.context.ApplicationContextException but we don't have the same cause.
I have tried adding using an older version of
com.fasterxml.jackson.core
like 2.8.10 as mentioned in java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory, but to no avail.
Any help is very, very much appreciated.
Solution
As stated in the comments, the problem comes from a jackson-dataformat-smile
library that your system administrator put in Tomcat's classpath.
If you really can't get rid of it you can use one of three solutions:
Add the library to your project dependencies (it will override the one in Tomcat's classpath),
Disable the
MappingJackson2SmileHttpMessageConverter
: unlike previously stated theSmileFactory
is not detected by theServiceLoader
, but called explicitly by Spring if it detects the factory on its classpath (cf.WebMvcConfigurationSupport #addDefaultMessageConverters
). This is the price of features "magically" appearing by adding a library to the classpath.Fortunately you can override the default message converters: just add a
WebMvcConfigurer
and override itsconfigureMessageConverters
. You can even do it in your@SpringBootApplication
class:@SpringBootApplication public class YourSpringApplication implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // add configuration here } ... }
You can copy parts of the aforementioned
addDefaultMessageConverters
.Change the classloader's search order by adding to your context file (cf. Documentation on the ways to do it and change the
delegate
attribute of your loader:<Context> <Loader delegate="true" /> ... </Context>
Answered By - Piotr P. Karwasz
Answer Checked By - Senaida (JavaFixing Volunteer)