Spring Download Using Apache Tiles

I am trying to port a Java application to Spring Boot. I am currently running Spring MVC 3.2 using Apache Tiles. When I switched to Spring Boot, my controllers still work fine, they pass the view to Resolver, but when Tiles goes to pull out the JSP file, everything falls apart. The error message I get is:

13:48:46,387 TRACE org.springframework.web.servlet.handler.SimpleUrlHandlerMapping:127 - No handler mapping found for [/jsp/layout/layout.jsp] 

Has anyone successfully used Apache Tiles with Spring Boot? Any ideas how to do this?

Thanks in advance for any ideas!


More details:

 @Bean public UrlBasedViewResolver viewResolver(){ LOGGER.trace("Entering tiles configurer"); UrlBasedViewResolver viewResolver = new UrlBasedViewResolver(); viewResolver.setViewClass(TilesView.class); return viewResolver; } @Bean public TilesConfigurer tilesConfigurer(){ LOGGER.trace("Entering tiles configurer"); System.out.println("Entering tiles configurer"); TilesConfigurer tilesConfigurer = new TilesConfigurer(); String[] defs = {"/WEB-INF/tiles-defs.xml"}; tilesConfigurer.setDefinitions(defs); return tilesConfigurer; } 

controller:

  @RequestMapping(value="/") public ModelAndView index(ModelAndView mav, HttpServletRequest request, HttpServletResponse resp,RedirectAttributes ra){ LOGGER.trace("Arrived in Home Controller"); mav.addObject("profile",appContext.getEnvironment().getActiveProfiles()[0]); mav.setViewName("home"); return mav; } 

tile definitions:

  <definition name="layout" template = "/jsp/layout/layout.jsp"> </definition> <definition name="home" extends="layout"> <put-attribute name="body" value = "/jsp/home.jsp" /> </definition> 
+7
spring spring-boot apache tiles apache-tiles
source share
6 answers

I also ran into a similar problem and was able to solve it using the various answers above. To help others who might run into this problem in the future, I created a simple Maven project at https://github.com/barryku/spring-boot-tiles to enable the minimum settings needed to use tiles with Spring Download. Listed below are some points to keep in mind:

  • tomcat-embed-jasper is required to display JSP pages
  • Remember to use the org.springframework.web.servlet.view.tiles3 package, not the tiles2 files.
  • jstl is used by Spring tiles3 integration, so it must be enabled

I added the necessary files step by step so you can take a look at the commit history at https://github.com/barryku/spring-boot-tiles/commits/master to better understand what was added at each step.

+5
source share

I have my main layouts in /src/main/webapp/WEB-INF/layouts/layouts.xml with examples, for example:

 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN" "http://tiles.apache.org/dtds/tiles-config_2_1.dtd"> <tiles-definitions> <definition name="default" template="/WEB-INF/layouts/default.jspx"> <put-attribute name="menu" value="/WEB-INF/views/menu.jspx"/> <put-attribute name="sidebar" value="/WEB-INF/views/sidebar.jspx"/> <put-attribute name="header" value="/WEB-INF/views/header.jspx" /> <put-attribute name="footer" value="/WEB-INF/views/footer.jspx" /> </definition> <definition name="public" template="/WEB-INF/layouts/default.jspx"> <put-attribute name="menu" value="/WEB-INF/views/menu.jspx"/> <put-attribute name="sidebar" value="/WEB-INF/views/sidebar.jspx"/> <put-attribute name="header" value="/WEB-INF/views/header.jspx" /> <put-attribute name="footer" value="/WEB-INF/views/footer.jspx" /> </definition> </tiles-definitions> 

And then more specific fragment definitions in /src/main/webapp/WEB-INF/views/views.xml with examples, for example:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN" "http://tiles.apache.org/dtds/tiles-config_2_1.dtd"> <tiles-definitions> <definition extends="default" name="index"> <put-attribute name="body" value="/WEB-INF/views/index.jspx"/> </definition> <definition extends="public" name="login"> <put-attribute name="sidebar" value=""></put-attribute> <put-attribute name="body" value="/WEB-INF/views/login.jspx"/> </definition> </tiles-definitions> 

Then you need your configuration class:

 @EnableWebMvc @Configuration public class RootMvcConfiguration extends WebMvcConfigurerAdapter { ... @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); registry.addViewController("/login").setViewName("login"); } ... } 

Beans in this class that are interlaced are dependent - if you want to use JSP or Thymeleaf.

For JSP you should have:

  @Bean public UrlBasedViewResolver tilesViewResolver(){ UrlBasedViewResolver tilesViewResolver = new UrlBasedViewResolver(); tilesViewResolver.setViewClass(TilesView.class); return tilesViewResolver; } @Bean public TilesConfigurer tilesConfigurer(){ String[] definitions = new String[] { "/WEB-INF/layouts/layouts.xml", "/WEB-INF/views/**/views.xml" /*Scans directories for Tiles configurations */ }; TilesConfigurer tilesConfigurer = new TilesConfigurer(); tilesConfigurer.setDefinitions(definitions); return tilesConfigurer; } 

If you are using Thymeleaf, you should have something like this:

 @Bean public MessageSource messageSource(){ ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); messageSource.setBasenames("classpath:META-INF/i18n/messages"); messageSource.setFallbackToSystemLocale(false); return messageSource; } @Bean public ServletContextTemplateResolver templateResolver() { ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); resolver.setPrefix("/WEB-INF/"); resolver.setSuffix(".html"); resolver.setTemplateMode("HTML5"); resolver.setOrder(2); resolver.setCacheable(false); return resolver; } @Bean public SpringTemplateEngine templateEngine() throws Exception { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setTemplateResolver(templateResolver()); engine.setTemplateEngineMessageSource(messageSource()); engine.addDialect(new TilesDialect()); engine.addDialect(new SpringSecurityDialect()); engine.afterPropertiesSet(); return engine; } @Bean public TilesConfigurer tilesConfigurer(){ String[] definitions = new String[] { "/WEB-INF/layouts/layouts.xml", "/WEB-INF/views/**/views.xml" /*Scans directories for Tiles configurations */ }; ThymeleafTilesConfigurer tilesConfigurer = new ThymeleafTilesConfigurer(); tilesConfigurer.setDefinitions(definitions); return tilesConfigurer; } 

Then you can expand your views.xml and point view names in your jsp or html files, and an example controller might be the following:

 @RequestMapping("/roles") @Controller public class RoleController { @RequestMapping(value = "/{id}", method = RequestMethod.GET) public String show(@PathVariable("id") Integer id, Model uiModel) { uiModel.addAttribute("role", Role.findRole(id)); uiModel.addAttribute("itemId", id); return "roles/show"; } } 

If you are using Maven, here are some examples of lib versions:

 <properties> <thymeleaf.version>2.0.19</thymeleaf.version> <thymeleaf.extras.version>2.0.0</thymeleaf.extras.version> <thymeleaf.extras.security.version>2.0.0</thymeleaf.extras.security.version> <tiles.version>2.2.2</tiles.version> </properties> ... <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>org.apache.tiles</groupId> <artifactId>tiles-core</artifactId> <version>${tiles.version}</version> </dependency> <dependency> <groupId>org.apache.tiles</groupId> <artifactId>tiles-jsp</artifactId> <version>${tiles.version}</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>${thymeleaf.version}</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring3</artifactId> <version>${thymeleaf.version}</version> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity3</artifactId> <version>${thymeleaf.extras.security.version}</version> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-tiles2</artifactId> <version>${thymeleaf.extras.version}</version> </dependency> 
+4
source share

You will have to pack the application as a war. Spring-boot, jsp and jar packaging don't get along very well. Also make sure your pom.xml has the following:

  <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> 
+1
source share

Your definitions should be:

  <definition name="layout" template = "/WEB-INF/jsp/layout/layout.jsp"> </definition> <definition name="home" extends="layout"> <put-attribute name="body" value = "/WEB-INF/jsp/home.jsp" /> </definition> 
0
source share

I had the same problems as in this question . The problem was the paths and prefixes. In the Tiles definitions, I had paths like /WEB-INF/views/test.html , and that was a mistake. Below I set the full working configuration for the Spring application (Thymeleaf 2, Tiles 2) and sample files. Maybe this will help someone.

Beans

 @Configuration public class WebConfiguration extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/test").setViewName("tiles/test"); } @Bean public ServletContextTemplateResolver servletContextTemplateResolver() { ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".html"); resolver.setTemplateMode("HTML5"); resolver.setCharacterEncoding("UTF-8"); return resolver; } /** * Tiles view resolver * @param templateEngine * @return */ @Bean public ViewResolver vr(SpringTemplateEngine templateEngine) { ThymeleafViewResolver th = new ThymeleafViewResolver(); th.setTemplateEngine(templateEngine); th.setViewClass(ThymeleafTilesView.class); th.setCharacterEncoding("UTF-8"); th.setOrder(Ordered.LOWEST_PRECEDENCE); return th; } /** * Basic view resolver * @param templateEngine * @return */ @Bean public ViewResolver thymeleafViewResolver(SpringTemplateEngine templateEngine) { ThymeleafViewResolver vr = new ThymeleafViewResolver(); vr.setTemplateEngine(templateEngine); vr.setCharacterEncoding("UTF-8"); vr.setOrder(Ordered.HIGHEST_PRECEDENCE); // all tiles/* views will not be handled by this resolver; vr.setExcludedViewNames(new String[]{"tiles/*"}); return vr; } @Bean public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver); log.info(templateResolver); templateEngine.addDialect(new SpringSecurityDialect()); templateEngine.addDialect(new TilesDialect()); return templateEngine; } @Bean @SuppressWarnings("deprecation") public ThymeleafTilesConfigurer tilesConfigurer() { ThymeleafTilesConfigurer ttc = new ThymeleafTilesConfigurer(); ttc.setDefinitions(new String[]{"/WEB-INF/tiles.xml"}); return ttc; } } 

Tile definitions - src / main / webapp / WEB-INF / tiles.xml

Template paths are prefixed with templateResolver and without a suffix. When I use full paths, it does not work and gets an exception, for example

Error resolution template "/WEB-INF/views/layout.html", the template may not exist or may not be available for any of the configured Resolvers templates

 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN" "http://tiles.apache.org/dtds/tiles-config_2_1.dtd"> <tiles-definitions> <definition name="baseLayout" template="layout"> </definition> <definition name="tiles/test" extends="baseLayout"> <put-attribute name="body" value="test"/> <put-attribute name="title" value="Test Page"/> </definition> </tiles-definitions> 

Src / home / web application / WEB-INF / views / layout.html

 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:tiles="http://tiles.apache.org/tags-tiles"> <head> <title tiles:string="title">blah blah blah</title> <style type="text/css"></style> </head> <body> <div class="container"> <div tiles:replace="body"></div> </div> </body> </html> 

Src / home / web application / WEB-INF / views / test.html

 2+2=<span xmlns:th="http://www.thymeleaf.org" th:text="2+2"></span> 
0
source share
0
source share

All Articles