Traditional deployment
If you are not using the built-in servlet container, just disable the white shortcut by adding it to your application.properties
:
server.error.whitelabel.enabled = false
Embedded Tomcat Script
Add tomcat-embed-jasper
as your dependency:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency>
And name your controller as error
:
@Controller("error") public class AppErrorController implements ErrorController { ... }
Or you can disable the white label instead of renaming the bean:
server.error.whitelabel.enabled = false
Why does the name matter?
After a little digging in the automatic configuration of ErrorMvcAutoConfiguration
, I came across the following configuration:
@Configuration @ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true) @Conditional(ErrorTemplateMissingCondition.class) protected static class WhitelabelErrorViewConfiguration { private final SpelView defaultErrorView = new SpelView( "<html><body><h1>Whitelabel Error Page</h1>" + "<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>" + "<div id='created'>${timestamp}</div>" + "<div>There was an unexpected error (type=${error}, status=${status}).</div>" + "<div>${message}</div></body></html>"); @Bean(name = "error") @ConditionalOnMissingBean(name = "error") public View defaultErrorView() { return this.defaultErrorView; }
This timestamp issue is related to defaultErrorView
type SpelView
. Therefore, if you register another bean named error
:
@ConditionalOnMissingBean(name = "error") public View defaultErrorView() { ... }
Or disable the white label:
@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true)
This submission will not be registered and you will avoid this strange exception.
How about a Jasper dependency?
There is a JspTemplateAvailabilityProvider
that provides accessibility information for JSP view templates. This class has an isTemplateAvailable
method that looks like this:
public boolean isTemplateAvailable(String view, Environment environment, ClassLoader classLoader, ResourceLoader resourceLoader) { if (ClassUtils.isPresent("org.apache.jasper.compiler.JspConfig", classLoader)) { String prefix = getProperty(environment, "spring.mvc.view.prefix", "spring.view.prefix", WebMvcAutoConfiguration.DEFAULT_PREFIX); String suffix = getProperty(environment, "spring.mvc.view.suffix", "spring.view.suffix", WebMvcAutoConfiguration.DEFAULT_SUFFIX); return resourceLoader.getResource(prefix + view + suffix).exists(); } return false; }
So, if org.apache.jasper.compiler.JspConfig
not present in the classpath, it will not display the jsp view, so we added the required dependency to it, which is tomcat-embed-jasper
.
There may be a better and less hacky way for this problem, but this is the solution I came across, and this is what it is!