error template resolution Spring Boot
According to the documentation of Spring Boot it is possible to define templates that should be used when a specific HTTP status code occurs.
I have noticed when I place a 404.jte in src/main/resources/templates/error it doesn't work. I have tried the same thing with Thymeleaf and that does work.
Digging through the Spring code I saw that in order to resolve the error view, it goes to the DefaultErrorViewResolver#resolveError, where there is a list of templateAvailabilityProviders. These providers are Thymeleaf, Freemarker, Jsp, ... the supported templating engines of Spring (Boot).
I looked for an easy way to register a custom JteTemplateAvailabilityProvider but found no such luck, the only reference in the Spring Code to for instance ThymeleafTemplateAvailabilityProvider is in the Spring autoconfiguration library, namely in the META-INF/spring.factories file:
# Template Availability Providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
I'm not that experienced with the autoconfiguration bits of Spring Boot, but I tried to add my own META-INF/spring.factories file in my own project:
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
care.animax.pms.web.config.WebConfig.JteTemplateAvailabilityProvider
And the JteTemplateAvailabilityProvider class looks like this:
class JteTemplateAvailabilityProvider implements TemplateAvailabilityProvider {
@Override
public boolean isTemplateAvailable(String view, Environment environment, ClassLoader classLoader, ResourceLoader resourceLoader) {
return resourceLoader.getResource("classpath:/templates/" + view + ".jte").exists();
}
}
This actually worked, when I place a debug point in DefaultErrorViewResolver#resolveError, I now see my own provider listed there as well and the JTE template is resolved properly.
Although this works, I'm not sure it's logical that I add this to my own project, should this not be part of the jte-spring-boot-starter project?
I have tried making it more generic, using the gg.jte.templateLocation and gg.jte.templateSuffix properties, while it works for the suffix, the templateLocation doesn't work.
@casid just wondering if you had time to have a look at this to give me feedback?
@tschuehly perhaps you could have a look as well as I know you have a lot of experience using JTE and Spring Boot together and I think Casid doesn't use Spring Boot that much?
Hey @maxwellt,
Without looking further into it I would say we need to register a bean of type TemplateAvailabilityProvider in the JteAutoConfiguration of the spring boot starter. The spring.factories is for registering Configuration Classes that are being used when using a library as dependency. This is already done for the JteAutoConfiguration.
@maxwellt sorry for the late reply! I don't use Spring Boot, so I'm unfortunately not able to give any meaningful recommendations here.
As a workaround register a custom ErrorViewResolver.
With this method you can use templates in jte/error/.
@Bean
public ErrorViewResolver customErrorViewResolver() {
return (request, status, model) -> {
if (status.is4xxClientError()) {
return new ModelAndView("error/4xx");
}
if (status.is5xxServerError()) {
return new ModelAndView("error/5xx");
}
return null;
};
}
https://docs.spring.io/spring-boot/reference/web/servlet.html#web.servlet.spring-mvc.error-handling