Search code examples
javaspring-mvcwebtemplate-enginemustache

mustache and Internalviewresolvers - Spring MVC


I'm trying out mustache templates with spring mvc project. I've some code that is using JSPs and I would like to add mustache templating for some pages only. To do that, I added a new mustacheViewResolver and my existing InternalResourceViewResolver as below.

@Bean
public InternalResourceViewResolver viewResolver() {
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setViewClass(JstlView.class);
    viewResolver.setPrefix("/WEB-INF/views/jsp/");
    viewResolver.setSuffix(".jsp");
    viewResolver.setOrder(2);
    return viewResolver;
}

@Bean
public ViewResolver mustacheViewResolver() {
    ScriptTemplateViewResolver viewResolver = new ScriptTemplateViewResolver();
    viewResolver.setPrefix("/static/templates/");
    viewResolver.setSuffix(".html");
    viewResolver.setOrder(1);
    return viewResolver;
}

Only either of them works but not both. When in intend to go to userform.jsp, it goes to userform.html.

[WARNING] /myproject/users/add
java.io.FileNotFoundException: class path resource [static/templates/users/userform.html] cannot be opened because it does not exist
    at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)
    at org.springframework.web.servlet.view.script.ScriptTemplateView.getTemplate(ScriptTemplateView.java:369)
    at org.springframework.web.servlet.view.script.ScriptTemplateView.renderMergedOutputModel(ScriptTemplateView.java:349)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1243)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1027)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:971)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:499)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.lang.Thread.run(Thread.java:745)

Any clues on how to use templating and JSP viewresolvers at the same time?


Solution

  • The ScriptTemplateView is not properly checking if the template file is available, which it should according to its Javadoc. This is a bug - check SPR-14729.

    Please upgrade to the relevant Spring version.

    Note that you should also keep your view resolver ordering like this, because unlike other templating engines, InternalResourceViewResolver and JSPs can't check for template existence and indeed throw exceptions, which is why they're often configured at the end of the chain.