Review
In the previous section, we focused on the view layer and created an HTML mockup template. In this section, we will focus on configuration and declare them using JavaConfig. We will also provide an XML-based config.
Table of Contents
Click on a link to jump to that section:
- Functional Specs
- Creating the View
- HTML Mockup
- Thymeleaf Integration
- JavaConfig
- ApplicationContext.java
- SpringDataConfig.java
- ThymeleafConfig.java
- ApplicationInitializer.java
- Layers
- Domain
- Service
- Controller
- Running the application
- Clone from GitHub
- Create the Database
- Run with Maven and Tomcat 7
- Run with Maven and Jetty 8
- Import to Eclipse
- Validate with W3C
JavaConfig
As stated in the introduction, we will be using JavaConfig-based configuration instead of the usual XML config. However, I don't want to alienate our readers who are used to XML. As a result, I've decided to provide both implementations. However, our focus here is still on JavaConfig.
Note: With JavaConfig, we can now omit the ubiquitous web.xml. But in order to that, we need to run a Servlet 3.0 web container. For this tutorial, I have tested the application with Tomcat 7.0.30 (Maven plugin), 7.0.33 (standalone Tomcat), and Jetty 8.1.5.v20120716 (Maven plugin).
ApplicationContext.java
The ApplicationContext.java contains our main configuration. It's responsible for loading other configurations, either as JavaConfig or XML config.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.config; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.ComponentScan; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.context.annotation.Import; | |
import org.springframework.context.annotation.ImportResource; | |
import org.springframework.context.annotation.PropertySource; | |
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; | |
import org.springframework.context.support.ResourceBundleMessageSource; | |
import org.springframework.core.io.ClassPathResource; | |
import org.springframework.core.io.Resource; | |
import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; | |
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; | |
@Configuration | |
@ComponentScan(basePackages = {"org.krams"}) | |
@EnableWebMvc | |
@Import({SpringDataConfig.class, ThymeleafConfig.class}) | |
@ImportResource("classpath:trace-context.xml") | |
@PropertySource("classpath:spring.properties") | |
public class ApplicationContext extends WebMvcConfigurerAdapter { | |
// Maps resources path to webapp/resources | |
@Override | |
public void addResourceHandlers(ResourceHandlerRegistry registry) { | |
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); | |
} | |
// Only needed if we are using @Value and ${...} when referencing properties | |
@Bean | |
public static PropertySourcesPlaceholderConfigurer properties() { | |
PropertySourcesPlaceholderConfigurer propertySources = new PropertySourcesPlaceholderConfigurer(); | |
Resource[] resources = new ClassPathResource[] { | |
new ClassPathResource("spring.properties") }; | |
propertySources.setLocations(resources); | |
propertySources.setIgnoreUnresolvablePlaceholders(true); | |
return propertySources; | |
} | |
// Provides internationalization of messages | |
@Bean | |
public ResourceBundleMessageSource messageSource() { | |
ResourceBundleMessageSource source = new ResourceBundleMessageSource(); | |
source.setBasename("messages"); | |
return source; | |
} | |
} |
Let's describe each annotation:
@Configuration
- Marks a class as a JavaConfig
@ComponentScan(basePackages = {"org.krams"})
- Configures scanning of Spring components
This is equivalent in XML as:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters<context:annotation-config /> <context:component-scan base-package="org.krams" />
@EnableWebMvc
- Activates Spring's MVC support
This is equivalent in XML as:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters<mvc:annotation-driven />
@Import({SpringDataConfig.class, ThymeleafConfig.class})
- This allows us to import JavaConfig-based config. Notice we are importing two external configuration classes: SpringDataConfig and ThymeleafConfig
@ImportResource("classpath:trace-context.xml")
- This allows us to import XML-based config files. (As a side note why can't we just declare this as a JavaConfig? It turns out there's no direct translation for the trace-context.xml, so we'll have to import it as XML).
This is equivalent in XML as:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters<import resource="trace-context.xml"/>
@PropertySource("classpath:spring.properties")
- This allows us to import property files
@Bean
- Declares a Spring bean
Here's the equivalent XML configuration:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<beans xmlns="http://www.springframework.org/schema/beans" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:context="http://www.springframework.org/schema/context" | |
xmlns:p="http://www.springframework.org/schema/p" | |
xmlns:mvc="http://www.springframework.org/schema/mvc" | |
xsi:schemaLocation="http://www.springframework.org/schema/beans | |
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd | |
http://www.springframework.org/schema/context | |
http://www.springframework.org/schema/context/spring-context-3.1.xsd | |
http://www.springframework.org/schema/mvc | |
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"> | |
<context:property-placeholder properties-ref="deployProperties" /> | |
<!-- Activates various annotations to be detected in bean classes --> | |
<context:annotation-config /> | |
<!-- Scans the classpath for annotated components that will be auto-registered as Spring beans. | |
For example @Controller and @Service. Make sure to set the correct base-package --> | |
<context:component-scan base-package="org.krams" /> | |
<!-- Configures the annotation-driven Spring MVC Controller programming model. | |
Note that, with Spring 3.0, this tag works in Servlet MVC only! --> | |
<mvc:annotation-driven /> | |
<!-- Maps resources path to webapp/resources --> | |
<mvc:resources mapping="/resources/**" location="/resources/" /> | |
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" | |
p:basename="messages" /> | |
<!-- Imports logging configuration --> | |
<import resource="trace-context.xml"/> | |
<!-- Imports datasource configuration --> | |
<import resource="spring-data.xml"/> | |
<bean id="deployProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean" | |
p:location="/WEB-INF/spring.properties" /> | |
</beans> |
SpringDataConfig.java
The SpringDataConfig.java contains our Spring Data configuration. This is where we declare our data source, transaction manager, and JPA entity manager.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.config; | |
import javax.sql.DataSource; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.core.env.Environment; | |
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; | |
import org.springframework.orm.jpa.JpaTransactionManager; | |
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; | |
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; | |
import org.springframework.transaction.annotation.EnableTransactionManagement; | |
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; | |
import com.mchange.v2.c3p0.ComboPooledDataSource; | |
@Configuration | |
@EnableTransactionManagement | |
@EnableJpaRepositories("org.krams.repository") | |
public class SpringDataConfig extends WebMvcConfigurerAdapter { | |
@Autowired | |
private Environment env; | |
// Declare a datasource that has pooling capabilities | |
@Bean | |
public DataSource dataSource() { | |
try { | |
ComboPooledDataSource ds = new ComboPooledDataSource(); | |
ds.setDriverClass(env.getRequiredProperty("app.jdbc.driverClassName")); | |
ds.setJdbcUrl(env.getRequiredProperty("app.jdbc.url")); | |
ds.setUser(env.getRequiredProperty("app.jdbc.username")); | |
ds.setPassword(env.getRequiredProperty("app.jdbc.password")); | |
ds.setAcquireIncrement(5); | |
ds.setIdleConnectionTestPeriod(60); | |
ds.setMaxPoolSize(100); | |
ds.setMaxStatements(50); | |
ds.setMinPoolSize(10); | |
return ds; | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
// Declare a JPA entityManagerFactory | |
@Bean | |
public LocalContainerEntityManagerFactoryBean entityManagerFactory() { | |
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); | |
em.setPersistenceXmlLocation("classpath*:META-INF/persistence.xml"); | |
em.setPersistenceUnitName("hibernatePersistenceUnit"); | |
em.setDataSource(dataSource()); | |
HibernateJpaVendorAdapter vendor = new HibernateJpaVendorAdapter(); | |
vendor.setShowSql(false); | |
em.setJpaVendorAdapter(vendor); | |
return em; | |
} | |
// Declare a transaction manager | |
@Bean | |
public JpaTransactionManager transactionManager() { | |
JpaTransactionManager transactionManager = new JpaTransactionManager(); | |
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); | |
return transactionManager; | |
} | |
} |
Here's the equivalent XML configuration:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<beans xmlns="http://www.springframework.org/schema/beans" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:p="http://www.springframework.org/schema/p" | |
xmlns:tx="http://www.springframework.org/schema/tx" | |
xmlns:context="http://www.springframework.org/schema/context" | |
xmlns:jdbc="http://www.springframework.org/schema/jdbc" | |
xmlns:jpa="http://www.springframework.org/schema/data/jpa" | |
xmlns:util="http://www.springframework.org/schema/util" | |
xsi:schemaLocation=" | |
http://www.springframework.org/schema/beans | |
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd | |
http://www.springframework.org/schema/tx | |
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd | |
http://www.springframework.org/schema/context | |
http://www.springframework.org/schema/context/spring-context-3.1.xsd | |
http://www.springframework.org/schema/jdbc | |
http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd | |
http://www.springframework.org/schema/data/jpa | |
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd | |
http://www.springframework.org/schema/util | |
http://www.springframework.org/schema/util/spring-util-3.1.xsd"> | |
<context:property-placeholder properties-ref="deployProperties" /> | |
<tx:annotation-driven transaction-manager="transactionManager" /> | |
<!-- Activate Spring Data JPA repository support --> | |
<jpa:repositories base-package="org.krams.repository" /> | |
<!-- Declare a datasource that has pooling capabilities--> | |
<bean id="jpaDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" | |
destroy-method="close" | |
p:driverClass="${app.jdbc.driverClassName}" | |
p:jdbcUrl="${app.jdbc.url}" | |
p:user="${app.jdbc.username}" | |
p:password="${app.jdbc.password}" | |
p:acquireIncrement="5" | |
p:idleConnectionTestPeriod="60" | |
p:maxPoolSize="100" | |
p:maxStatements="50" | |
p:minPoolSize="10" /> | |
<!-- Declare a JPA entityManagerFactory --> | |
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" | |
p:persistenceXmlLocation="classpath*:META-INF/persistence.xml" | |
p:persistenceUnitName="hibernatePersistenceUnit" | |
p:dataSource-ref="jpaDataSource" | |
p:jpaVendorAdapter-ref="hibernateVendor"/> | |
<!-- Specify our ORM vendor --> | |
<bean id="hibernateVendor" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" | |
p:showSql="false"/> | |
<!-- Declare a transaction manager--> | |
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" | |
p:entityManagerFactory-ref="entityManagerFactory"/> | |
</beans> |
ThymeleafConfig.java
The ThymeleafConfig.java contains our Thymeleaf configuration. This is where we declare our Thymeleaf view resolver.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.config; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.thymeleaf.spring3.SpringTemplateEngine; | |
import org.thymeleaf.spring3.view.ThymeleafViewResolver; | |
import org.thymeleaf.templateresolver.ServletContextTemplateResolver; | |
@Configuration | |
public class ThymeleafConfig { | |
@Bean | |
public ServletContextTemplateResolver templateResolver() { | |
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); | |
resolver.setPrefix("/WEB-INF/templates/"); | |
resolver.setSuffix(".html"); | |
resolver.setTemplateMode("HTML5"); | |
resolver.setOrder(1); | |
return resolver; | |
} | |
@Bean | |
public SpringTemplateEngine templateEngine() { | |
SpringTemplateEngine engine = new SpringTemplateEngine(); | |
engine.setTemplateResolver(templateResolver()); | |
return engine; | |
} | |
@Bean | |
public ThymeleafViewResolver thymeleafViewResolver() { | |
ThymeleafViewResolver resolver = new ThymeleafViewResolver(); | |
resolver.setTemplateEngine(templateEngine()); | |
return resolver; | |
} | |
} |
Here's the equivalent XML configuration:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<beans xmlns="http://www.springframework.org/schema/beans" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:p="http://www.springframework.org/schema/p" | |
xsi:schemaLocation="http://www.springframework.org/schema/beans | |
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> | |
<!-- Declare a Thymeleaf resolver --> | |
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver" | |
p:prefix="/WEB-INF/templates/" | |
p:suffix=".html" | |
p:templateMode="HTML5" | |
p:order="1"/> | |
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine" | |
p:templateResolver-ref="templateResolver" /> | |
<bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver" | |
p:templateEngine-ref="templateEngine"/> | |
</beans> |
ApplicationInitializer.java
The ApplicationInitializer.java is the equivalent of web.xml. Here's where we declare the DispatcherServlet.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.krams.config; | |
import javax.servlet.ServletContext; | |
import javax.servlet.ServletException; | |
import javax.servlet.ServletRegistration; | |
import org.springframework.web.WebApplicationInitializer; | |
import org.springframework.web.context.ContextLoaderListener; | |
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; | |
import org.springframework.web.servlet.DispatcherServlet; | |
public class ApplicationInitializer implements WebApplicationInitializer { | |
@Override | |
public void onStartup(ServletContext servletContext) throws ServletException { | |
//Load application context | |
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); | |
rootContext.register(ApplicationContext.class); | |
rootContext.setDisplayName("Spring Thymeleaf Tutorial"); | |
//Context loader listener | |
servletContext.addListener(new ContextLoaderListener(rootContext)); | |
//Dispatcher servlet | |
ServletRegistration.Dynamic dispatcher = | |
servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext)); | |
dispatcher.setLoadOnStartup(1); | |
dispatcher.addMapping("/"); | |
} | |
} |
Here's the equivalent XML configuration:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<web-app xmlns="http://java.sun.com/xml/ns/javaee" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" | |
version="2.5"> | |
<display-name>Spring Thymeleaf Tutorial</display-name> | |
<listener> | |
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> | |
</listener> | |
<servlet> | |
<servlet-name>spring</servlet-name> | |
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> | |
</servlet> | |
<servlet-mapping> | |
<servlet-name>spring</servlet-name> | |
<url-pattern>/</url-pattern> | |
</servlet-mapping> | |
</web-app> |
Next
In the next section, we will focus on the remaining layers of our Java application. We'll study the Domain, Repository, Service, and Controller layers. Click here to proceed.
Share the joy:
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |


Hello, i am using apache tile, thymeleaf and jsp view resolver together, but getting an error. Following is the link for detail of my question.
ReplyDeletehttp://stackoverflow.com/questions/28494408/integrate-thymeleaf-tiles-and-jsp-view-resolver-together-in-spring-mvc
nice post!!
ReplyDeletewow, nice post bro
ReplyDelete