Monday, February 24, 2014

Thymeleaf integration with Spring (Part 2)

1   Introduction

This is the second part of the Thymeleaf integration with Spring tutorial. You can read the first part here, where you will learn how to configure this project.

As explained at the beginning of the first part of this tutorial, the web application will send two types of requests:
  • Insert a new guest: Sends a synchronous request to the server for adding a new guest. This will demonstrate how Thymeleaf is integrated with Spring’s form backing beans.
  • List guests: Sends an AJAX request that will update a region (fragment) of the page in order to show the guest list returned from the server.

Let's see how we will accomplish this.

2   Handling forms

In this section we are going to see how a form is submitted with Thymeleaf. We will basically need three attributes:


The first two are defined in the form element:

The th:action attribute rewrites the action url, prefixing the application context to it.

The th:object attribute in the form element is the object selection. It can then be referenced within the form. What we do here is bind the form backing bean to the model attribute, which we defined in the controller before rendering the view:

As we see, th:object refers to the Guest form backing bean, while th:field will refer to its properties.  Take a look at the form body:

What th:field will do is assign the value of its input element to the backing bean property. So, when the user submits the form, all these th:field will set the form backing bean properties.

At the controller, we will receive the Guest instance:

Now the guest can be inserted into the database.

3   Sending AJAX requests

When trying to find a simple example of sending an AJAX request with Thymeleaf, I have found examples with Spring Webflow (render fragments). I also read others saying that you need Tiles in order to accomplish that.

I didn't want to use those frameworks so in this section I'm using jQuery to send an AJAX request to the server, wait for the response and partially update the view (fragment rendering).

The form

This form contains an input text with a search string (searchSurname) that will be sent to the server. There's also a region (resultsBlock div) which will be updated with the response received from the server.

When the user clicks the button, the retrieveGuests() function will be invoked.

The jQuery load function makes a request to the server at the specified url and places the returned HTML into the specified element (resultsBlock div).

If the user enters a search string, it will search for all guests with the specified surname. Otherwise, it will return the complete guest list. These two requests will reach the following controller request mappings:

Since Spring is integrated with Thymeleaf, it will now be able to return fragments of HTML. In the above example, the return string "results :: resultsList" is referring to a fragment named resultsList which is located in the results page. Let's take a look at this results page:

The fragment, which is a table with registered guests, will be inserted in the results block:

4   Conclusion

After integrating both frameworks, we learnt how forms are linked to the Spring MVC model. We also learnt how to send AJAX requests and partially update the view.

I'm publishing my new posts on Google plus and Twitter. Follow me if you want to be updated with new content.

Monday, February 17, 2014

Thymeleaf integration with Spring (Part 1)

1   Introduction

This article is focused on how Thymeleaf can be integrated with the Spring framework. This will let our MVC web application take advantage of Thymeleaf HTML5 template engine without losing any of the Spring features. The data layer uses Spring Data to interact with a mongoDB database.

The example consists in a Hotel's single page web application from where we can send two different requests:

  • Insert a new guest: A synchronous request that shows how Thymeleaf is integrated with Spring's form backing beans.
  • List guests: An asynchronous request that shows how to handle fragment rendering with AJAX.

This tutorial expects you to know the basics of Thymeleaf. If not, you should first read this article.

Here's an example of the application flow:

This example is based on Thymeleaf 2.1 and Spring 4 versions.

The source code can be found at github.

2   Configuration

This tutorial takes the JavaConfig approach to configure the required beans. This means xml configuration files are no longer necessary.

Since we want to use JavaConfig, we need to specify AnnotationConfigWebApplicationContext as the class that will configure the Spring container. If we don't specify it, it will use XmlWebApplicationContext by default.

When defining where the configuration files are located, we can specify classes or packages. Here, I'm indicating my configuration class.

Spring Configuration
My configuration is split in two classes: thymeleaf-spring integration (WebAppConfiguration class) and mongoDB configuration (MongoDBConfiguration class).

Things to highlight from looking at the above code:
  • @EnableWebMvc: This enables Spring MVC annotations like @RequestMapping. This would be the same as the xml namespace <mvc:annotation-driven />
  • @ComponentScan(“xpadro.thymeleaf”): Activates component scanning in the xpadro.thymeleaf package and subpackages. Classes annotated with @Component and related annotations will be registered as beans.
  • We are registering three beans which are necessary to configure Thymeleaf and integrate it with the Spring framework.
    • template resolver: Resolves template names and delegates them to a servlet context resource resolver.
    • template engine: Integrates with Spring framework, establishing the Spring specific dialect as the default dialect.
    • view resolver: Thymeleaf implementation of the Spring MVC view resolver interface in order to resolve Thymeleaf views.

This class extends AbstracMongoConfiguration, which defines mongoFactory and mongoTemplate beans.  
The @EnableMongoRepositories will scan the specified package in order to find interfaces extending MongoRepository. Then, it will create a bean for each one. We will see this later, at the data access layer section.

3   Thymeleaf – Spring MVC Integration

The controller is responsible for accessing the service layer, construct the view model from the result and return a view. With the configuration that we set in the previous section, now MVC Controllers will be able to return a view Id that will be resolved as a Thymeleaf view.

Below we can see a fragment of the controller where it handles the initial request (http://localhost:8080/th-spring-integration/spring/home):

A typical MVC Controller that returns a "home" view id. Thymeleaf template resolver will look for a template named "home.html" which is located in /WEB-INF/html/ folder, as indicated in the configuration. Additionally, a view attribute named "hotelData" will be exposed to the Thymeleaf view, containing hotel information that needs to be displayed on the initial view.

This fragment of the home view shows how it accesses some of the properties of the view attribute by using Spring Expression Language (Spring EL):

Another nice feature is that Thymeleaf will be able to resolve Spring managed message properties, which have been configured through the MessageSource interface. 

Error handling
Trying to add a new user will raise an exception if a user with the same id already exists. The exception will be handled and the home view will be rendered with an error message.

Since we only have one controller, there's no need to use @ControllerAdvice. We will instead use a @ExceptionHandler annotated method. You can notice that we are returning an internationalized message as the error message:

Thymeleaf will resolve the view attribute with ${} and then it will resolve the message #{}:

The th:unless Thymeleaf attribute will only render the span element if an error message has been returned.

4   The Service layer

The service layer accesses the data access layer and adds some business logic. 

5   The Data Access layer

The HotelRepository extends the Spring Data class MongoRepository

This is just an interface, we won't implement it. If you remember the configuration class, we added the following annotation:

Since this is the package where the repository is located, Spring will create a bean and inject a mongoTemplate to it. Extending this interface provides us with generic CRUD operations. If you need additional operations, you can add them with the @Query annotation (see code above).

6   Conclusion

We have configured Thymeleaf to resolve views in a Spring managed web application. This allows the view to access to Spring Expression Language and message resolving. The next part of this tutorial is going to show how forms are linked to Spring form backing beans and how we can reload fragments by sending an AJAX request.

Read the next part of this tutorial: Thymeleaf integration with Spring (Part 2)

I'm publishing my new posts on Google plus and Twitter. Follow me if you want to be updated with new content.