CustomMenu

Monday, February 17, 2014

Spring MVC 4 - Thymeleaf CRUD - Part 1

This example builds on the last post, Spring MVC 4 - Thymeleaf Prep and Mockup, where our application was prepared to use Thymeleaf.  In this example we will replace the mock up Thymeleaf page with working CRUD pages using the Strategy controller.  There are four posts in this series, the links to the other three posts are listed below.

1. Update the pom.xml to include a newer hibernate version and to include the hibernate validator.
<properties>
        . . .
        <hibernate.version>4.3.1.Final</hibernate.version>
        . . .
</properties>

<dependencies>
        . . .
        <!-- JDBC -->
        . . .
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        . . .
<dependencies>

2. Cleanup time.  If you are starting from where we left off in the last blog post, delete the jsp files in the pages directory and the html files in the views directory.  These directories should now be empty.

3. Create the home.html that will be our initial entry point to the application.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:th="http://www.thymeleaf.org">
 
<head th:fragment="header">
    <meta charset="utf-8" />
 <link type="text/css" rel="stylesheet" href="/resources/css/style.css"/>
 <title th:text="#{user.page.title}">Title</title>
</head>

<body>
<h1 data-th-text="#{home.page.title}">Title</h1>
<p>
<a href="strategy/list.html">Strategy list</a><br/>
</p>
</body>
</html>

4. With Thymeleaf it is common for value objects/data transfer objects to be passed between the Thymeleaf layer and the Spring MVC layer.  We will preemptively create the strategy data transfer object in anticipation of this need.  Additionally we will add a get string method to our strategy model class...this will help with logging later.

Here is the new getString() method added to our Strategy class in the model package:
  . . .
 public String getString() {
  return String.format("Strategy - Id: [%s]  Type: [%s]  Name: [%s]", this.id, this.type, this.name);
 }
 . . .

Here is the data transfer object in the new dto package.  We included the hibernate validator in the pom.xml for use by this class, specifically with the @NotNull and @NotEmpty annotations.  This object is scoped at the session level and the proxy mode is set at TARGET_CLASS.  More information on scope can be found in the Spring Docs.
package com.dtr.oas.dto;

import java.io.Serializable;

import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;

@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class StrategyDTO implements Serializable {
 
 private static final long serialVersionUID = -6518171412015203128L;
 
 private Integer id;

 @NotNull
 @NotEmpty
 private String type;
 
 @NotNull
 @NotEmpty
 private String name;

 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getType() {
  return type;
 }

 public void setType(String type) {
  this.type = type;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
 
 public String getString() {
  return String.format("StrategyDTO - Id: [%s]  Type: [%s]  Name: [%s]", this.id, this.type, this.name);
 }

}

The StrategyMapper class is just a helper class to convert back and forth between the Strategy and StrategyDTO types.
package com.dtr.oas.dto;

import com.dtr.oas.model.Strategy;

public class StrategyMapper {

 public static Strategy getStrategy(StrategyDTO dto) {
  Strategy strategy = new Strategy();
  strategy.setId(dto.getId());
  strategy.setName(dto.getName());
  strategy.setType(dto.getType());
  return strategy;
 }
 
 public static StrategyDTO getDTO(Strategy strategy) {
  StrategyDTO dto = new StrategyDTO();
  dto.setId(strategy.getId());
  dto.setName(strategy.getName());
  dto.setType(strategy.getType());
  return dto;
 }
}

5. The project will eventually have the Eclipse structure shown in the image below.  The rest of our coding will take place in the StrategyController, the Thymeleaf html files, and the messages_en.properties file that we will create shortly.

6. We will now modify the StrategyController code to provide a list of strategies to display.  Here are the old and new versions of the relevant method.  They are essentially the same except for the addition of the StrategyDTO created earlier.  The DTO is required for future "add strategy" functionality that we will add in Part 2 of this blog post.
 @RequestMapping(value="/list")
 public ModelAndView listOfStrategies() {
     ModelAndView modelAndView = new ModelAndView("strategy-list");
     List<Strategy> strategies = strategyService.getStrategies();
     modelAndView.addObject("strategies", strategies);
     return modelAndView;
 }
 @RequestMapping(value="/list",  method=RequestMethod.GET)
 public ModelAndView listOfStrategies() {
     StrategyDTO strategyDTO = new StrategyDTO();
     ModelAndView modelAndView = new ModelAndView("strategy-list");
     List<Strategy> strategies = strategyService.getStrategies();
     modelAndView.addObject("strategies", strategies);
     modelAndView.addObject("strategyDTO", strategyDTO);
     return modelAndView;
 }

7. Create the file strategy-list.html in the views directory.  The edit and delete functionality have been stubbed out, and the add functionality is not included yet.  The data-th-text references starting with a # sign are references to properties in a properties file.  We will create this file in step 8.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org">
    
<head data-th-fragment="header">
    <meta charset="utf-8" />
    <link type="text/css" rel="stylesheet" href="../../resources/css/style.css" data-th-href="@{/resources/css/style.css}"/>
    <title data-th-text="#{strategy.list.page.title}">Title</title>
</head>

<body>
<div>
    <table class="box-table-a">
        <caption data-th-text="#{strategy.list.table.title}">Temp table title</caption>
        <thead>
            <tr>
                <th scope="col" data-th-text="#{strategy.list.id.label}">Temp ID</th>
                <th scope="col" data-th-text="#{strategy.list.type.label}">Temp Type</th>
                <th scope="col" data-th-text="#{strategy.list.name.label}">Temp Name</th>
                <th scope="col" data-th-text="#{strategy.list.actions.label}">Temp Action</th>
            </tr>
        </thead>
        <tbody>
            <tr data-th-each="strategy : ${strategies}">
                <td data-th-text="${strategy.id}">1</td>
                <td data-th-text="${strategy.type}">Iron Butterfly</td>
                <td data-th-text="${strategy.name}">Triple Butter</td>
                <td><a href="#" >delete</a> | 
                    <a href="#" >edit</a>
                </td>
            </tr>
            <tr data-th-remove="all">
                <td>2</td>
                <td>Iron Condor</td>
                <td>High Prob Hedged</td>
                <td><a href="#">delete</a> | <a href="#">edit</a></td>
            </tr>
        </tbody>
    </table>
    
</div>
</body>
</html>

8. Create the properties file, messages_en.properties, used for static text and labels in the html files.  The property file below contains all of the entries for the functioning example.
home.page.title=Home Page

delete.button.label=Delete
cancel.button.label=Cancel
save.button.label=Save
update.button.label=Update
add.button.label=Add

strategy.list.page.title=Strategy List
strategy.list.head.title=Strategy List
strategy.list.body.title=Strategy List
strategy.list.table.title=Strategy List
strategy.list.id.label=Strategy Id
strategy.list.type.label=Strategy Type
strategy.list.name.label=Strategy Name
strategy.list.actions.label=Actions
strategy.list.add.title=Add Strategy

strategy.delete.page.title=Delete Strategy
strategy.delete.head.title=Delete Strategy
strategy.delete.body.title=Delete Strategy
strategy.delete.form.title=Delete Strategy

strategy.edit.page.title=Edit Strategy
strategy.edit.head.title=Edit Strategy
strategy.edit.body.title=Edit Strategy
strategy.edit.form.title=Edit Strategy

9. Right-click on the project and Run As->Run On Server.  If there are no errors, then the home page should be displayed.

10. Select the link and you should see an empty list page like the one below.

In Part 2, we will create the add functionality so that we can add strategies to the database.

Code at GitHub: https://github.com/dtr-trading/spring-ex04

No comments:

Post a Comment