2

This is the sort of weird question one runs into when shamelessly copying examples from the Internet. I am using Spring MVC 4, Apache Tiles 3, Java 8, and Tomcat 8.

I absolutely must have a views.properties file. BUT it doesn't need to have any actual mappings in it. So the question is not so much why do I need it, but why don't I need it.

As you can see from the views.properties file it has one entry that has nothing at all to do with userList. If the file is missing completely the DispatcherServlet throws an Exception. But with this pitiful entry everything works fine. Granted it does list the TilesView class, and supplies a somewhat general idea of where one might look for JSPs. But everything I've read says each JSP must be meticulously listed in the views.properties file. That simply isn't true.

On one hand this is good because it is a lot less to maintain. But on the other it makes me feel like I am really missing something important. Disclaimer: I haven't yet cracked the static resource resolver, which is proving quite recalcitrant. That seems completely unrelated to this, other than both being general issues with Spring finding my resources.

The infamous views.properties (ENTIRE FILE)

messages.(class)=org.springframework.web.servlet.view.tiles3.TilesView
messages.url=/WEB-INF/xxxx/messages.jsp (for example)

Obligatory code examples:

@Configuration Class

...
@Bean
TilesConfigurer tilesConfigurer() {
    TilesConfigurer tilesConfigurer = new TilesConfigurer();
    tilesConfigurer.setDefinitions("WEB-INF/tiles/tiles.xml"); 
    return tilesConfigurer;
}

@Bean
ResourceBundleViewResolver viewResolver() {
    ResourceBundleViewResolver resourceBundleViewResolver = new ResourceBundleViewResolver();
    resourceBundleViewResolver.setBasename("views");
    return resourceBundleViewResolver;
}

@Bean
TilesViewResolver tilesVewResolver() {
    return new TilesViewResolver();
}
...

tiles.xml

<tiles-definitions>
<definition name="baseLayout" template="/WEB-INF/tiles/maintemplate.jspx">
    <put-attribute name="header" value="/WEB-INF/tiles/header.jspx" />
    <put-attribute name="menu" value="/WEB-INF/tiles/menu.jspx" />
    <put-attribute name="body" value="" />
    <put-attribute name="footer" value="/WEB-INF/tiles/footer.jspx" />
</definition>

<!-- USERS -->
<definition name="userEdit" extends="baseLayout">
    <put-attribute name="title" value="Edit User" />
    <put-attribute name="body" value="/WEB-INF/views/users/edit.jspx" />
</definition>
<definition name="userList" extends="baseLayout">
    <put-attribute name="title" value="List Users" />
    <put-attribute name="body" value="/WEB-INF/views/users/list.jspx" />
</definition>
...

UserController.java

...
@PreAuthorize("isAuthenticated()")
@RequestMapping(method = RequestMethod.GET)
public String list(Locale locale, HttpServletRequest request, HttpServletResponse response, Model uiModel) {

    themeResolver.setThemeName(request, response, "defaultTheme");

    List<User> users = userRepository.findAll();
    uiModel.addAttribute("users", users);
    return "userList";
}
...
Terry
  • 911
  • 10
  • 26
  • 1
    You are using tiles which is quite different from using normal JSP files. What you say applies ONLY if you don't use things like tiles. So if you use a general `InternalResourceView` or `JstlView` you would have to list each single one. Tiles is different as there is a single source containing all views, the tiles configuration. The view name here references a tiles definition. Also I strongly suspect you have multiple view resolvers and not only a `ResourceBundleViewResolver`. I even think that your `ResourceBundleViewResolver` isn't even used. – M. Deinum May 02 '15 at 08:09
  • Thanks, that is very instructive. I commented out the ResourceViewResolver and removed views.properties and the app still works fine. I do indeed have a TilesViewResolver as you guessed (I added it above). – Terry May 02 '15 at 16:21

1 Answers1

1

The ResourceBundleViewResolver requires an additional configuration file which contains a configuration for every view it can handle. By default the basename of views is used. If this file isn't there the ResourceBundleViewResolver will fail to load/start.

Judging by the behavior you describe and the fact that you use Tiles I suspect that you also have a TilesViewResolver. For tiles the name of the view returned, here userList, must correspond to a tiles view definition.

When using Spring MVC all configured ViewResolvers are consulted to resolve the name of the view to an actual View implementation. In your case the ResourceBundleViewResolver will return null for the view resolution as it can only handle a view named messages, next the TilesViewResolver is consulted which will return a view as there is a tiles view definition for userList.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224