In this tutorial, we will create an application that can post messages and retrieve profile information from Facebook and Twitter. We will use Spring Social to implement these features. To secure our application we will use Spring Security, and to manage our views, we will use Thymeleaf.
Retrieve profile information from Facebook and Twitter
Secure the application
Allow login and creation of new users
Create a page for managing users
Here's our Use Case diagrams:
[User]-(Post to Facebook)
[User]-(Post to Twitter)
[User]-(Retrieve info from Facebook)
[User]-(Retrieve info from Twitter)
[User]-(Sign in)
[User]-(Sign up)
//http://yuml.me/
In the previous section, we have discussed the functional requirements of our application. In this section we will study how to generate OAuth keys for Facebook and Twitter. These are required so that Spring Social can communicate with these social media sites.
In the previous section, we have shown the steps on how to generate and retrieve the OAuth secret keys from Facebook and Twitter. In this section we will setup the Spring Social configuration settings through JavaConfig.
Spring Social is an extension of the Spring Framework that allows you to connect your applications with Software-as-a-Service (SaaS) providers such as Facebook and Twitter.
Features:
An extensible service provider framework that greatly simplifies the process of connecting local user accounts to hosted provider accounts.
A connect controller that handles the authorization flow between your Java/Spring web application, a service provider, and your users.
Java bindings to popular service provider APIs such as Facebook, Twitter, LinkedIn, TripIt, and GitHub.
A sign-in controller that enables users to authenticate with your application by signing in through a service provider.
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
Let me explain the contents of this configuration:
We have autowired the environment properties and the datasource
We have declared a ConnectionFactoryLocator which allows us to register connections to Facebook and Twitter. Notice how we passed the OAuth secret IDs and secret keys to the locator
We've declared a TextEncryptor for encrypting strings. This is required by Spring Social's JdbcUsersConnectionRepository
JdbcUsersConnectionRepository is used for persisting connections to a database through JDBC
ConnectionRepository allows a specific user to save and retrieve connections. We need to use this in conjunction with Spring Security because it provides us ready-made authenticated users. Notice how we assigned the current authenticated user
ConnectController is a controller for managing the connection flow to social media sites
HiddenHttpMethodFilter is required by Spring Social so that users can disconnect from social media sites. The filter needs to be declared in the web.xml or ApplicationInitializer
Note: If you need an in-depth explanation of each classes, please see the official Spring Social docs
Next
In the next section, we will focus on Spring Security-related configuration. Click here to proceed.
In the previous section, we have discussed the Spring Social-related configuration. In this section we will focus on Spring Security for securing our application.
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
Spring Security is one of the most mature and widely used Spring projects. Founded in 2003 and actively maintained by SpringSource since, today it is used to secure numerous demanding environments including government agencies, military applications and central banks. It is released under an Apache 2.0 license so you can confidently use it in your projects.
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
First, we declare a DelegatingFilterProxy bean using JavaConfig. This allows Spring Security to intercept requests to our application and verify if the required authentication and authorization are met. This bean needs to be registered in the web.xml (or ApplicationInitializer) as a filter (see next section).
Second, we declare the usual XML-based configuration. This allows us to define the intercept-url patterns. Why are we not using JavaConfig here? Because the XML-based configuration is simpler, less-verbose, and easier:
spring-security.xml
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
In the previous section, we have discussed the Spring Security-related configurations. In this section we will discuss the remaining configuration of our application.
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).
ApplicationInitializer.java The ApplicationInitializer.java is the equivalent of web.xml. Here's where we declare the DispatcherServlet and also we've registered two filters: one for Spring Security and another for Spring Social.
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
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
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
@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
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({DataConfig.class, ThymeleafConfig.class, SocialConfig.class, SecurityConfig.class})
- This allows us to import JavaConfig-based config. Notice we have imported four configuration classes
@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
@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
DataConfig.java The DataConfig.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
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
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
These allows to redirect virtual path requests to specific templates within our application. We need to do this because the ConnectController from Spring Social has its own built-in controller path requests. And we need to redirect the resulting views that matches our template path.
For example, when connecting to Facebook, ConnectController will use the connect/facebookConnect path and you are required to provide a view. Using the addTemplateAlias() method, we can provide a custom view, in this case, the view points to the directory in the WEB-INF/templates/facebook/connect.
Also, we've disabled the caching feature so that we can easily update and test our html pages.
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
SecurityConfig.java The SecurityConfig.java contains a single bean DelegatingFilterProxy. This is required for Spring Security.
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
spring.properties spring.properties contains the property settings of our application. You need to declare your Facebook and Twitter OAuth settings here. Here's also where you declare your database.
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
messages_en.properties This is for internationalization of messages. The default language is English. If you need to provide custom language, create a new properties file and replace the values according to the language you've chosen. Please see the Spring documentation for more info on internationalization.
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
signup.hasaccount=Already have an account? Sign in!
#welcome.html
welcome.title=Welcome
#post.html
post.title.fb=Post to Facebook
post.title.tw=Post to Twitter
post.form.legend.fb=Update your status:
post.form.legend.tw=Tweet a message:
post.form.action.fb=/fb/post
post.form.action.tw=/tw/post
post.form.submit.fb=Post it!
post.form.submit.tw=Tweet it!
#posted.html
posted.title.fb=Facebook
posted.title.tw=Twitter
posted.success.fb=The following message has been posted:
posted.success.tw=The following message has been tweeted:
posted.failure.fb=Unable to post to your Facebook account!
posted.failure.tw=Unable to post to your Twitter account!
#profile.html
profile.title.fb=Facebook Profile
profile.title.tw=Twitter Profile
profile.h3.fb=Facebook Profile
profile.h3.tw=Twitter Profile
profile.id.fb=Facebook ID:
profile.id.tw=Twitter ID:
profile.name.fb=Name:
profile.name.tw=Screen Name
profile.loc.fb=Email:
profile.loc.tw=Location:
profile.url.fb=Profile Url:
profile.url.tw=Profile Url:
#connect.html
connect.title.fb=Connect to Facebook
connect.title.tw=Connect to Twitter
connect.h3.fb=Connect to Facebook
connect.h3.tw=Connect to Twitter
connect.form.action.fb=/connect/facebook
connect.form.action.tw=/connect/twitter
connect.message.fb=You haven't created any connections with Facebook yet. Click the button to create a connection between your account and your Facebook profile. (You'll be redirected to Facebook where you'll be asked to authorize the connection)
connect.message.tw=You haven't created any connections with Twitter yet. Click the button to create a connection between your account and your Twitter profile. (You'll be redirected to Twitter where you'll be asked to authorize the connection)
connect.button.fb=Connect with Facebook
connect.button.tw=Connect with Tweeter
#connected.html
connected.title.fb=Facebook Connected
connected.title.tw=Twitter Connected
connected.h3.fb=Facebook Connected
connected.h3.tw=Twitter Connected
connected.message.fb=is now connected to your Facebook account. Click the button if you wish to disconnect. Try loading your profile or posting a message to test your connection.
connected.message.tw=is now connected to your Tweeter account. Click the button if you wish to disconnect. Try loading your profile or posting a message to test your connection.
#include.html
disconnect.url.fb=/connect/facebook
disconnect.url.tw=/connect/twitter
disconnect.button.fb=Disconnect from Facebook
disconnect.button.tw=Disconnect from Twitter
#users.html
users.title=User Management
users.table.caption=Site Users
user.id.label=Id
user.firstname.label=First Name
user.lastname.label=Last Name
user.username.label=Username
user.password.label=Password
user.role.label=Role
user.role.1=admin
user.role.2=regular
new.user.table.caption=New User
new.user.button.label=add
update.user.table.caption=Existing User
update.user.button.label=update
error.profile.fb=Failure! An error has occurred while trying to retrieve your profile!
error.profile.tw=Failure! An error has occurred while trying to retrieve your profile!
error.post.fb=Failure! We are unable to process your request!
error.post.tw=Failure! We are unable to process your request!
#errors
error.access.denied=Access denied! You're not allowed to access that!
status.login.failure=Unable to login. Invalid credentials!
status.logout.success=You have successfully logged out!
In the previous section, we have discussed the remaining JavaConfig configurations. In this section, we will discuss the View layer along with Thymeleaf.
The goal of this section is not to teach you everything about Thymeleaf but to point out the important sections. If you need a full Thymeleaf documentation, please see the official docs.
What is Thymeleaf?
Thymeleaf is a Java library. It is an XML / XHTML / HTML5 template engine (extensible to other formats) that can work both in web and non-web environments. It is better suited for serving XHTML/HTML5 at the view layer of web applications, but it can process any XML file even in offline environments.
It provides an optional module for integration with Spring MVC, so that you can use it as a complete substitute of JSP in your applications made with this technology, even with HTML5.
The main goal of Thymeleaf is to provide an elegant and well-formed way of creating templates. Its Standard and SpringStandard dialects allow you to create powerful natural templates, that can be correctly displayed by browsers and therefore work also as static prototypes. You can also extend Thymeleaf by developing your own dialects.
Since we have numerous html pages with duplicate setup, I will focus on the ones that are most instructive.
Facebook profile.html
This displays our Facebook profile information.
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
Declares a resource relative to the context of the app. When testing the html mockup, the th:href attribute is ignored by the browser. When running the app, Thymeleaf's preprocessor will ignore the value of the href attribute and use the value in the th:ref attribute.
Declares the usual title element. When testing the html mockup, the th:text attribute is ignored by the browser. When running the app, Thymeleaf's preprocessor will ignore the value of the title and use the value in the th:text attribute.
This is a common attribute. So pay attention to this one.
th:include attribute
<div th:include="include :: menu"></div>
Includes an html fragment. The fragment is declared in the include.html
Declares an image element. The attribute th:src is similar with the th:href behavior.
The value of th:src contains two parts: 'http://graph.facebook.com/' which is a literal string and ${profileInfo.id} is a model attribute. The value is sent by our Spring controller (see below):
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
A conditional expression. This states "if the profileInfo.email attribute is empty, print out 'no email listed', but if it's not empty, then print out the value.
Note: To see the remaining html pages, please visit the Github repository. I've omitted them here because most of the Thymeleaf tags we've discussed here are also the same ones we've used on those pages.
login.html
This is the login page. We've shown it here because this is used by Spring Security for rendering the login page.
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
In the previous section, we have discussed the View layer along with Thymeleaf. In this section, we will focus on the Domain, Repository, Service, and Controller classes.
Our domain layer consists of two simple classes: User.java and Role.java. By annotating these classes with @Entity we're declaring these classes as JPA entities and consequently will be persisted to a database.
The User class contains the following properties: first name, last name, username, role, and password. For the Role class, we only have two values: an admin and a regular user.
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
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
Although this is not part of the domain layer, we've included the UserDto here. This DTO is used for transferring user information to the view layer.
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
AccessController is responsible for managing login and signup requests
FacebookController is responsible for handling Facebook requests
TwitterController is responsible for handling Twitter requests
UserController is responsible for handling User CRUD operations
MediatorController simply handles call to the root page
AccessController.java
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
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
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
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
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
We have a simple repository. There's nothing much to explain here.
UserRepository.java
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
UserService is used for handling user-related CRUD operations
RepositoryBasedUserDetailsService is used for retrieving user details for authentication purposes
UserService.java
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
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
In the next section, we will study how to build and run our application. We will use Maven, Tomcat, and Jetty to run the app. We'll also study how to import the project in Eclipse. Click here to proceed.
In the previous section, we have discussed the Domain, Repository, Service, Controller layers. In this section, we will build and run our sample application. We will verify if our application is able to communicate with Facebook and Twitter. We will also show how to import the project in Eclipse.
Open W3C Markup Validation Service at http://validator.w3.org/#validate_by_input
Paste the HTML source and wait for the validation result
You should see a similar output:
Conclusion
We've have completed our Spring Social-based application using JavaConfig. We're able to post and retrieve profile information from Facebook and Twitter. To provide authentication and security we've added Spring Security. For managing the view layer, we've integrated Thymeleaf as our template engine. As a bonus, we've also provided an XML-based application.
I hope you've enjoyed this tutorial. Don't forget to check my other tutorials at the Tutorials section.
In this tutorial, we will create a CRUD application based on Spring MVC 3.x and Spring Data JPA. We will utilize JavaConfig instead of XML to configure our application. For the view layer, we will use Thymeleaf as our template engine instead of JSP to process our html pages.
In the next section, we will focus on the view layer. We'll start writing the HTML mockup template; then we'll integrate it with Thymeleaf. Click here to proceed.
In the previous section, we have read the functional specs of the application. In this section, we will focus on the view layer, create an HTML mockup, and integrate our mockup with Thymeleaf.
In designing our application we'll start with the view layer because we can. Thanks to Thymeleaf creating HTML mockups is easy. Thymeleaf allows us to use these mockups as our HTML templates without any aesthetic changes. In addition, it passes W3C Markup Validation Service with flying colors.
What is Thymeleaf?
Thymeleaf is a Java library. It is an XML / XHTML / HTML5 template engine (extensible to other formats) that can work both in web and non-web environments. It is better suited for serving XHTML/HTML5 at the view layer of web applications, but it can process any XML file even in offline environments.
It provides an optional module for integration with Spring MVC, so that you can use it as a complete substitute of JSP in your applications made with this technology, even with HTML5.
The main goal of Thymeleaf is to provide an elegant and well-formed way of creating templates. Its Standard and SpringStandard dialects allow you to create powerful natural templates, that can be correctly displayed by browsers and therefore work also as static prototypes. You can also extend Thymeleaf by developing your own dialects.
Let's create our HTML mockup. You can see the final mockup below:
First, we create a new HTML page. Note that this is a very simple HTML document that validates with W3C Markup Validation Service.
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
Next, we create an external CSS file. Because I'm not really a designer, I have scoured the web for a simple but elegant table style. I found one from Top 10 CSS Table Designs.
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
Then, open a browser and test the HTML mockup. You should see something similar to the following image:
Thymeleaf Integration
It's time to integrate Thymeleaf with our HTML mockup template. To integrate Thymeleaf we'll use its attribute-based template engine. Browsers will normally ignore unknown HTML attributes, so it won't affect our mockups.
Before we proceed, let me provide you a short description of the specific Thymeleaf attributes we'll be using:
The important attributes
The # means to resolve the attribute from the messages bundle
The $ means to resolve the attribute from the model
The # and $ can be combined together so that messages can be dynamically generated from the model and internationalized from the messages bundle
th:fragment="header"
This allows us to include template fragments from other templates. For example, we can reuse them in footers, headers, and menus. For this tutorial, we won't be reusing the header, but I've added it anyway for future tutorials.
th:each="u : ${users}
This allows us to loop a list of records. This is equivalent to Java's for-loop construct.
th:text="${u.id}"
This allows to dynamically set the label of an element.
th:href="@{/users/delete(id=${u.id})}">
This allows us to define a dynamic URL.
th:field="*{id}"
This allows us to define the field where an input's field will be attached to.
th:remove="all"
This allows us to setup mockup data. Thymeleaf will automatically remove any element contained within this attribute.
Let's now apply these attributes. Here's our updated HTML mockup template:
users.html
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
The th:text attribute allows us to externalize text and with the support of Spring's MessageSource, we are able to parameterize and provide internationalization support.
What is MessageSource?
Strategy interface for resolving messages, with support for the parameterization and internationalization of such messages.
Spring provides two out-of-the-box implementations for production:
ResourceBundleMessageSource, built on top of the standard ResourceBundle
ReloadableResourceBundleMessageSource, being able to reload message definitions without restarting the VM
Notice the th:text attributes. Some of them refer to a dot notation object. Where does Thymeleaf retrieve this information?
The information is retrieved from the messages_en.properties resource bundle:
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
We've declared that in the ApplicationContext.java configuration (see next section):
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
In order for our html page to display data from the Controller, we need to pass a Model attribute. The model attribute is represented by the UserDto.
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
The fields we declared on the users.html form is based from the fields of the UserDto:
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
Notice the form has a form-backing object declared named commanduser. Using Thymeleaf's attribute th:object, we're able to declare this form-backing object.
This object passed from the UserController.
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
In the next section, we will focus on the configuration layer. We'll study how to declare a JavaConfig-based configuration. We'll also provide an XML-based configuration for comparison purposes. Click here to proceed.
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.
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
@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
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({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
@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
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
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
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
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
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
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
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.
In the previous section, we declared our configuration using JavaConfig and compared it side-by-side with an XML-based configuration. In this section, we will discuss the remaining layers of our application.
Here we'll discuss the Domain, Repository, Service and Controller layers.
Domain
Our domain layer consists of two simple classes: User.java and Role.java. If you'd been following my previous tutorials, you will notice that these are the same domain classes we'd been using before. Both classes had been annotated with @Entity which means these are JPA entities and will be persisted to a database.
These classes represent a user with the following properties: first name, last name, username, role, and password (we're not actively using the password field).
For role, we only have two values: an admin or a regular user.
User.java
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
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
commanduser - the form backing object or the command object of the form
usertype - an attribute to determine if the request is a new user or existing user
UserController.java
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
We have created two repositories: UserRepository and RoleRepository(not shown). We will be using UserRepository as our primary data access object. Notice we have declared a custom method findByUsername but beyond that, this repository is pretty much standard. UserRepository.java
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
Our service layer basically delegates to the repository. It provides an extra logic to filter out duplicate usernames. UserService.java
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
In the next section, we will study how to build and run our application. We will be using Maven, Tomcat, and Jetty to run the app. We'll also study how to import the project in Eclipse. Click here to proceed.
In the previous section, we have discussed the Domain, Repository, Service, and Controller classes. In this section, we will build and run our app. We will also study how to import the project in Eclipse.
Open W3C Markup Validation Service at http://validator.w3.org/#validate_by_input
Paste the HTML source and wait for the validation result
You should see a similar output:
Conclusion
We've have completed our Spring MVC application with Thymeleaf as our template engine . We've studied how to convert our HTML mockup into a Thymeleaf template that validates with W3C validator service. We've also discussed how to create a JavaConfig-based application. As a bonus, we've also provided an XML-based application.
I hope you've enjoyed this tutorial. Don't forget to check my other tutorials at the Tutorials section.
Includes functional sample projects that demonstrate the described concepts in action and help you start experimenting right away
Provides step-by-step instructions and a lot of code examples that are easy to follow and help you to get started from page one
Full review
My initial impression of this book is that it's too short and lacks full coverage because it only focuses on Spring Data JPA and Spring Data Redis. We all know how big the Spring Data umbrella projects are. But it turns out this is the strength of the book. By focusing on a subset of Spring Data umbrella projects, it's able to focus better on what matters most.
As I read the book, I slowly realized that this book is a gem. If you need a solid understanding of Spring Data JPA, read this book. It tells you step-by-step all the possible query technologies, usage patterns, and their pros and cons. The book gradually prepares the reader to the value of Spring Data.
The Spring Data JPA coverage is quite extensive. It teaches you how to download and install the necessary libraries. Configuration is based on programmatic configuration instead of the usual XML configuration files. I think this is good but also bad. It would be great if the book offers sample configuration both in XML and Java-based config. Since most users are familiar with XML configuration, translating from Java-based config would require extra effort to comprehend for most Spring users. Anyway, that's a minor weakness that we can live-up with.
The book is successful in demonstrating how to provide CRUD support through Spring Data JPA and how to implement your own custom repository. There are various way to perform queries in Spring Data JPA, and I think the book has managed to cover all of them, including QueryDSL.
The book's coverage on Spring Data Redis is extensive. It covers installation and configuration, connector types, Redis data structures, and of course, Spring Data support for Redis. The book teaches how to save relational data and perform CRUD operations in a NoSQL manner. It also covers messaging and caching support with Redis. Overall it's a pleasant read. It's interesting how the book has smoothly transitioned from Spring Data JPA to Redis.
Overall, Spring Data from Packt Publishing is a solid book that I recommend to everyone to read.