I have an app that works perfectly when started within IntelliJ or via gradle bootRun.
However, if I do gradle bootRepackage and then try and run the resulting jar, I end up with:
2014-12-02 21:46:14.086 ERROR 9839 --- [nio-2014-exec-2] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-2014-exec-2] Exception processing template "/login": Error resolving template "/login", template might not exist or might not be accessible by any of the configured Template Resolvers
2014-12-02 21:46:14.087 ERROR 9839 --- [nio-2014-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: Error resolving template "/login", template might not exist or might not be accessible by any of the configured Template Resolvers] with root cause
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "/login", template might not exist or might not be accessible by any of the configured Template Resolvers
This gives an EXTREMELY BAD impression of spring boot. Extremely.
In my case, I was pretty much ready to move into UAT... Quote I to my manager: "now I'll simply package it up, and we're ready to go..."
And...Crash.
Red faces all round. Mine especially. I don't like the feeling. Worse, I now have a manger who is nervous about Spring Boot. The immortal phrase "unknown unknowns" was used more than once in discussion.
LOTS of frantic searching ensued. Too much searching was required before I came across issue 1744. I admit,I should have looked here earlier in the process but still...
What is particularly galling is that it seems to indicate that none of the SB examples have been run via jars. This error is so straightforward that it would have been seen immediately in any jarred exemplar. Without the workaround, the whole idea of jarring is killed dead.
I have seen https://github.com/spring-projects/spring-boot/issues/1744. I strongly believe that this should be re-considered.
Also see: http://stackoverflow.com/questions/27249078/spring-boot-gives-templateinputexception-error-resolving-template-when-runnin?noredirect=1#comment42982098_27249078. I describe how I used the workaround from issue 1744.
I estimate this bug as HIGH priority.
Comment From: transentia
Forgot to mention that this is with SB 1.2.0.RC2.
Comment From: philwebb
We don't have automated tests to run packaged JARs, however, we do test things manually before each release. I've just tried running the spring-boot-sample-web-ui sample thymeleaf application as a packaged JAR and it works fine.
As mentioned in the stackoverflow answer there seems to be a number of factors that when combined cause the problem. I'll take another look at #1744 to see if there is anything that we can do to improve things.
In the meantime, simply removing the leading / from your view names should fix your issue.
Comment From: philwebb
Closing in favor of #1744
Comment From: philwebb
Comment from #1744 ...
I originally didn't have preceding '/' characters on my view names. The problem came when I introduced spring security:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
http
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home")
.failureUrl("/login?error")
.permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.logoutSuccessUrl("/login?logout")
.permitAll();
}
I found that I could not use simply 'login' instead of '/login', etc. (maybe SS is dong something different to Thymeleaf?) So I needed to find a solution that preserved the slash at the beginning of view names, while stripping the duplicate away. Thus I adopted the classpath configuration:
spring:
thymeleaf:
cache: false
prefix: classpath:/templates
Comment From: philwebb
Having reviewed #1744 adding double slash detection is not something that I think we should do. I want to keep our classloader as near to the standard classloader as possible.
Comment From: philwebb
@transentia The security configuration is referring to URLs that should be used for login, success and failure. How are you mapping those URLs to your templates? Are you using something like this:
@Bean
WebMvcConfigurerAdapter mvcViewConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
// ...
}
};
}
Comment From: transentia
I have:
@Configuration
public class GlobalMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("/login");
registry.addViewController("/").setViewName("/login");
}
}
Without the leading slash, i get:
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "login", template might not exist or might not be accessible by any of the configured Template Resolvers
at org.thymeleaf.TemplateRepository.getTemplate(TemplateRepository.java:245)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1104)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011)
I have resources/templates/login.html
This is with my "new, improved" configuration of :
spring:
thymeleaf:
cache: false
prefix: classpath:/templates
If I keep the original configuration for the prefix and use '/login' I get the same error.
Comment From: transentia
Oh! 'Flip' me!
I have:
registry.addViewController("/login").setViewName("/login");
I SHOULD have:
registry.addViewController("/login").setViewName("login");
That leading slash crept in: PEBKAC.
MY FAULT. I am ashamed!
Thanks for your patience, Phil.
Comment From: philwebb
@bowenchen6 I'm afraid this issue has been closed for a little while now. Could you open a new one with some more details if you think you've found a bug. Alternatively, you can ask general questions on stackoverflow.com using the spring-boot tag.
Comment From: mkulasi
@transentia The security configuration is referring to URLs that should be used for login, success and failure. How are you mapping those URLs to your templates? Are you using something like this:
java @Bean WebMvcConfigurerAdapter mvcViewConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); // ... } }; }
By following this comment i was able to resolve similar problem :)