I have an already existing client module with apache tiles and thymeleaf, what works well. I wanted to convert it to spring-boot and wanted to do it step by step, but I am really stucking with it. I dont want to change to much once, I would love it when someone can tell me, what step I should do first and bring it to run. I already tried to write the servlets in javaConfig, but I am stucking then too. Maybe someone can help me please. If more information is needed, please dont hesitate to ask.
Other question would be, do I need to change from xml to javaconfig? I would prefer the most easy way. But as soon I add spring-starter dependency to pom, application doesnt work anymore.
=======
POM:
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.compax.bbsng</groupId>
<artifactId>bbsng-client</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>
<artifactId>bbsng-client-mvc</artifactId>
<name>bbsng-client-mvc</name>
<packaging>war</packaging>
<properties>
<org.apache.tiles-version>2.2.2</org.apache.tiles-version>
<org.thymeleaf-version>2.0.16</org.thymeleaf-version>
<slf4j-version>1.7.5</slf4j-version>
<jackson.version>1.9.10</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Apache Tiles -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-template</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-servlet</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<!-- ThyMeLeaf ... -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${org.thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring3</artifactId>
<version>${org.thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-tiles2</artifactId>
<version>2.0.0</version>
</dependency>
<!-- Jackson JSON Mapper -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- Servlet ... -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- COMMONS ... -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<additionalBuildcommands>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
</buildCommand>
</additionalBuildcommands>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
<warName>${project.name}-${project.version}</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
</plugin>
</plugins>
</build>
======
rest-servlet-context.xml
<mvc:annotation-driven>
<mvc:async-support default-timeout="120000">
<mvc:callable-interceptors>
<bean class="at.compax.bbsng.client.mvc.TimeoutCallableProcessingInterceptor" />
</mvc:callable-interceptors>
</mvc:async-support>
</mvc:annotation-driven>
<context:component-scan base-package="at.compax.bbsng.client.mvc.rest" />
=====
application-servlet-context.xml
<!-- **************************************************************** -->
<!-- RESOURCE FOLDERS CONFIGURATION -->
<!-- Dispatcher configuration for serving static resources -->
<!-- **************************************************************** -->
<mvc:resources location="/images/" mapping="/images/**" />
<mvc:resources location="/css/" mapping="/css/**" />
<!-- **************************************************************** -->
<!-- SPRING ANNOTATION PROCESSING -->
<!-- **************************************************************** -->
<mvc:annotation-driven>
<mvc:async-support default-timeout="120000">
<mvc:callable-interceptors>
<bean class="at.compax.bbsng.client.mvc.TimeoutCallableProcessingInterceptor" />
</mvc:callable-interceptors>
</mvc:async-support>
</mvc:annotation-driven>
<context:component-scan base-package="at.compax.bbsng.client.mvc.web" />
<!-- **************************************************************** -->
<!-- MESSAGE EXTERNALIZATION/INTERNATIONALIZATION -->
<!-- Standard Spring MessageSource implementation -->
<!-- **************************************************************** -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="Messages" />
</bean>
<!-- **************************************************************** -->
<!-- THYMELEAF-SPECIFIC ARTIFACTS -->
<!-- TemplateResolver <- TemplateEngine <- ViewResolver -->
<!-- **************************************************************** -->
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.tiles2.dialect.TilesDialect"/>
</set>
</property>
</bean>
<!-- Configures the Tiles layout system using a specific thymeleaf-enabled Tiles Configurer -->
<bean id="tilesConfigurer" class="org.thymeleaf.extras.tiles2.spring.web.configurer.ThymeleafTilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/**/views.xml</value>
</list>
</property>
</bean>
<!-- Resolves view names returned by Controllers as names of Tiles definitions -->
<bean id="tilesViewResolver" class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
<property name="viewClass" value="org.thymeleaf.extras.tiles2.spring.web.view.ThymeleafTilesView"/>
<property name="templateEngine" ref="templateEngine"/>
</bean>
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
</bean>
=========
SECOND STEP EDIT:
I did few steps so that I can now start my application by running applicationClass from ECLIPSE.
What I did until now:
====
POM: Please keep a view, that I removed thymeleaf-starter from classpath, because I didnt get started it with thymeleaf-starter
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- <dependency> -->
<!-- <groupId>org.springframework.boot</groupId> -->
<!-- <artifactId>spring-boot-starter-thymeleaf</artifactId> -->
<!-- </dependency> -->
<!-- Apache Tiles -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-template</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-servlet</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<!-- ThyMeLeaf ... -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-tiles2-spring4</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
====
WebMvcConfig for configuration ThyMeLeaf
@Configuration
@ComponentScan
public class WebMvcConfig {
@Bean
public ThymeleafTilesConfigurer tilesConfigurer() {
final ThymeleafTilesConfigurer configurer = new ThymeleafTilesConfigurer();
configurer.setDefinitions("/WEB-INF/**/views.xml");
return configurer;
}
@Bean
public ThymeleafViewResolver viewResolver() {
final ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setViewClass(ThymeleafTilesView.class);
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding(UTF_8);
return resolver;
}
private SpringTemplateEngine templateEngine() {
final SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.setAdditionalDialects(dialects());
return engine;
}
private ServletContextTemplateResolver templateResolver() {
final ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCharacterEncoding(UTF_8);
return resolver;
}
private Set<IDialect> dialects() {
final Set<IDialect> set = new HashSet<IDialect>();
set.add(new TilesDialect());
return set;
}
}
=====
Spring Boot Starter Class ThyMeLeaf Autoconfiguration has been deactivated, cos I didnt get it work with apache tiles
@Configuration
@Import({ ServiceConfig.class, RestMvcConfig.class, WebMvcConfig.class })
@EnableAutoConfiguration(exclude = { ThymeleafAutoConfiguration.class })
public class ApplicationClientMvc implements WebApplicationInitializer {
public static void main(final String[] args) {
SpringApplication.run(ApplicationClientMvc.class, args);
}
@Bean
public ServletRegistrationBean applicationDispatcherRegistration(final DispatcherServlet dispatcherServlet) {
final ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.setName("applicationServlet");
registration.addUrlMappings("/app/*");
registration.setAsyncSupported(true);
registration.setLoadOnStartup(1);
registration.addInitParameter("contextConfigLocation", "at.compax.bbsng.client.mvc.web.WebMvcConfig");
registration.setOrder(1);
return registration;
}
@Bean
public ServletRegistrationBean restDispatcherRegistration(final DispatcherServlet dispatcherServlet) {
final ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.setName("restServlet");
registration.addUrlMappings("/rest/*");
registration.setAsyncSupported(true);
registration.setLoadOnStartup(0);
registration.addInitParameter("contextConfigLocation", "at.compax.bbsng.client.mvc.rest.RestMvcConfig");
registration.setOrder(0);
return registration;
}
@Override
public void onStartup(final ServletContext servletContext) throws ServletException {
final FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encoding-filter", new CharacterEncodingFilter());
encodingFilter.setInitParameter("encoding", UTF_8);
encodingFilter.setInitParameter("forceEncoding", "true");
encodingFilter.addMappingForUrlPatterns(null, true, "/*");
}
}
====
When I start that application via Eclipse by starting Spring-Boot Start class, application works.
This example demonstrate how to configure Thymeleaf with Apache tiles, but it is letting spring boot to autoconfigure Thymeleaf. This way you can still use all spring-boot predefined environment variables like spring.thymeleaf.* in your application.properties
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java#L116
Okay guys,
I got it and I hope it helps for other developers with similar problems.
In POM I removed all Spring-Dependencies and I use only Spring-Starter-Dependencies like following snippet:
In my Starter-Class I actived Thymeleaf Autoconfiguration again, my full class looks like follows. Be attended, I use two different servlets, one for REST, one for Thymeleaf.
====
My WebMVCConfig Class looks like follows, is in package
....mvc.rest
:===
My RestConfig Class is pretty simple
===
I moved all my html-files or thymeleaf-templates to template-folder under src/main/resources. Also in same folder you can put all client resources like images, js and css under the folder static. The folder static and templates are keywords and will be found by Spring-Boot automatically. There are no special configurations in application.properties what would be needed for thymeleaf and apache tiles.
====
That your application is able to find the resources, you can configure the path like follows:
===
Folder
java/src/webapp
is no more needed!!!====
If this helps for you, dont hesitate to vote ;-). If you need more information, just comment, I will try to answer within few days.
======
SECOND STEP
Okay, until now it only works under Eclipse. When I do executable jar, I get still an error. Maybe someone wants to help ;-)
Stacktrace is :
The Structure of my JAR is like:
======
SOLUTION:
I don't know exactly why, but additional I have to fix the url-paths for my templates, what works like it is in Eclipse, but not as executable jar. To get it run in both environments, I had to fix all template urls like follows, have a special look on attribute value:
BEFORE:
AFTER:
Finally it works under Eclipse and as executable jars. Converting from normal Spring-Project to Spring-Boot Project was not really easy running, I hope it will help to other developers and I hope that post is worth to vote. ;-)