nntrn
4/11/2019 - 9:47 AM

[snippets for spring boot]

[snippets for spring boot]

application.properties provides a sensible default property value for name.

import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;

@Component
public class MyBean {

    @Value("${name}")
    private String name;

    // ...

}

On your application classpath (for example, inside your jar) you can have an application.properties file that provides a sensible default property value for name. When running in a new environment, an application.properties file can be provided outside of your jar that overrides the name.

For one-off testing, you can launch with a specific command line switch (for example, java -jar app.jar --name="Spring").


Placeholders in Properties

The values in application.properties are filtered through the existing Environment when they are used, so you can refer back to previously defined values (for example, from System properties).

app.name=MyApp
app.description=${app.name} is a Spring Boot application

Getters and setters are usually mandatory, since binding is through standard Java Beans property descriptors, just like in Spring MVC.

A setter may be omitted in the following cases:

  • Maps, as long as they are initialized, need a getter but not necessarily a setter, since they can be mutated by the binder.
  • Collections and arrays can be accessed either through an index (typically with YAML) or by using a single comma-separated value (properties).
    • In the latter case, a setter is mandatory. We recommend to always add a setter for such types.
    • If you initialize a collection, make sure it is not immutable (as in the preceding example).
  • If nested POJO properties are initialized (like the Security field in the preceding example), a setter is not required. If you want the binder to create the instance on the fly by using its default constructor, you need a setter.

Thymeleaf + Spring Security

https://github.com/thymeleaf/thymeleaf-extras-springsecurity

The Thymeleaf Extras Spring Security library provides a dialect that allows integrating several authorization and authentication aspects of Spring Security (versions 3.x, 4.x and 5.x) into Thymeleaf-based applications. Features:

Thymeleaf-based equivalent to the Spring Security JSP tag library.

  • Adds new expression utility objects like #authentication and #authorization for integrating Spring Security capabilities into Thymeleaf expressions.
  • Adds new attributes like sec:authentication and sec:authorized for easier configuration of security.

With this library, role-based access restrictions defined in Spring Security can be easily used:

<div sec:authorize="hasRole('ROLE_ADMIN')">
  This will only be displayed if authenticated user has role ROLE_ADMIN.
</div>
The security-related objects can also be included in your normal Thymeleaf expressions:

<div th:text="${#authentication.name}">
  The value of the "name" property of the authentication object should appear here.
</div>

https://www.thymeleaf.org/ecosystem.html

Thymeleaf Spring Data Dialect

Data pagination made easy with thymeleaf and spring data.

This is a dialect for Thymeleaf that provides some attributes to create pagination and sorting elements, bootstrap style, based on Spring Data.

Maven dependency:

<dependency>
    <groupId>io.github.jpenren</groupId>
    <artifactId>thymeleaf-spring-data-dialect</artifactId>
    <version>3.4.0</version>
</dependency>

Add the Spring Data dialect to your existing Thymeleaf template engine:

templateEngine.addDialect(new SpringDataDialect());     // This line adds the dialect to Thymeleaf

If using Spring Boot you can add the following line and the ThymeleafAutoConfiguration class will add the dialect to the template engine.

    @Bean
    public SpringDataDialect springDataDialect() {
        return new SpringDataDialect();
    }

This will introduce the sd namespace, and the new attribute processors that you to use in your pages: pagination, pagination-sort, pagination-summary, pagination-url, page-object, pagination-qualifier and page-size-selector.

Examples

In your @Controller

@RequestMapping("/users")
public String list(ModelMap model, @SortDefault("username") Pageable pageable){
    model.addAttribute("page", userService.find(pageable));

    return "users/list";
}

Your html page looks like:

<table class="table table-striped table-hover">
    <thead>
        <tr>
          <th><a class="sorted" sd:pagination-sort="username" >Username</a></th>
          <th><a class="sorted" sd:pagination-sort="firstName" >First name</a></th>
          <th>Last Name</th>
          <th></th>
        </tr>
    </thead>
    <tbody>
        <tr th:each="row : ${page}">
          <th scope="row" th:text="${row.username}">Username</th>
          <td th:text="${row.firstName}">Name</td>
          <td th:text="${row.lastName}">Last Name</td>
          <td><a href="#">edit</a></td>
        </tr>
    </tbody>
</table>

<div class="row">
    <div class="col-sm-6">
        <div sd:pagination-summary="">info</div>
    </div>
    <div class="col-sm-6">
        <nav class="pull-right">
        <ul class="pagination" sd:pagination-split="7" sd:pagination="full">
            <!-- Pagination created by SpringDataDialect, this content is just for mockup -->
            <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
            <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
        </ul>
    </nav>
    </div>
</div>

Use optional attribute sd:pagination-split to configure the number of links to show.

Pagination with pager:

<nav>
    <ul class="pagination" sd:pagination="pager">
        <!-- Pagination created by SpringDataDialect, this content is just for mockup -->
        <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
        <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
    </ul>
</nav>

Aligned links:

<nav>
    <ul class="pagination" sd:pagination="aligned-links">
        <!-- Pagination created by SpringDataDialect, this content is just for mockup -->
        <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
        <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
    </ul>
</nav>

Compact pager:

<div>
    <span sd:pagination-summary="compact">info</span>
    <div class="btn-group pager-compact" sd:pagination="compact-pager">
        <!-- Pagination created by SpringDataDialect, this content is just for mockup -->
        <a href="#" class="btn btn-default disabled"><span class="glyphicon glyphicon-chevron-left"></span></a>
        <a href="#" class="btn btn-default"><span class="glyphicon glyphicon-chevron-right"></span></a>
    </div>
</div>

Page size selector (default requires your own javascript code, no action associated):

Show <span sd:page-size-selector="default"></span> entries

Page size selector (with javascript code implemented):

Show <span sd:page-size-selector="javascript"></span> entries

Page size selector (dropdown):

<div class="btn-group dropup" sd:page-size-selector="dropdown"></div>

Multiple tables on the same page:

On your @Controller

@RequestMapping("/users")
public String list(ModelMap model, @Qualifier("foo") Pageable first, @Qualifier("bar") Pageable second){
    model.addAttribute("page", userService.find(first));
    model.addAttribute("barPage", userService.find(second));

    return "users/list";
}
<div class="row">
    <div class="col-md-6" sd:page-object="${page}" sd:pagination-qualifier="foo">
        <div class="panel panel-default">
        <div class="panel-body">
            <table class="table table-striped table-hover">
                <thead>
                    <tr>
                      <th><a class="sorted" sd:pagination-sort="username" >Username</a></th>
                      <th><a class="sorted" sd:pagination-sort="firstName" >First name</a></th>
                    </tr>
                </thead>
                <tbody>
                    <tr th:each="row : ${page}">
                      <td th:text="${row.username}">First Name</td>
                      <td th:text="${row.firstName}">Last Name</td>
                    </tr>
                </tbody>
            </table>

            <nav>
                <ul class="pagination" sd:pagination="full">
                    <!-- Pagination created by SpringDataDialect, this content is just for mockup -->
                    <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
                    <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
                </ul>
            </nav>
        </div>
        </div>
    </div>
    <div class="col-md-6" sd:page-object="${barPage}" sd:pagination-qualifier="bar">
        <div class="panel panel-default">
        <div class="panel-body">
            <table class="table table-striped table-hover">
                <thead>
                    <tr>
                      <th><a class="sorted" sd:pagination-sort="username" >Username</a></th>
                      <th><a class="sorted" sd:pagination-sort="firstName" >First name</a></th>
                    </tr>
                </thead>
                <tbody>
                    <tr th:each="row : ${barPage}">
                      <td th:text="${row.username}">First Name</td>
                      <td th:text="${row.firstName}">Last Name</td>
                    </tr>
                </tbody>
            </table>

            <nav class="">
                <ul class="pagination" sd:pagination="full">
                    <!-- Pagination created by SpringDataDialect, this content is just for mockup -->
                    <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
                    <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
                </ul>
            </nav>
        </div>
        </div>
    </div>
</div>

By default SpringDataDialect search in the request for the attribute "page" or if one attribute of type org.springframework.data.domain.Page<?> exists. To use another model attribute, use sd:page-object="${attrName}"

To specify the pagination url use sd:pagination-url tag:

<nav>
    <ul class="pagination" sd:pagination="pager" sd:pagination-url="@{/some-url}">
        <!-- Pagination created by SpringDataDialect, this content is just for mockup -->
        <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
        <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
    </ul>
</nav>

Sort Icons

The generated HTML has the CSS classes sorted, sorted-asc and sorted-desc. This allows you to quite easily add some custom CSS to have sort icons in the table headers.

Example with FontAwesome:

table.table thead .sorted:after{
    display: inline-block;
    font-family: 'FontAwesome';
    opacity: 0.8;
    margin-left: 1em;
}
table.table thead .sorted.sorted-desc:after{
    content: "\f15e";
}
table.table thead .sorted.sorted-asc:after{
    content: "\f15d";
}

Example with Unicode characters:

.sorted-desc::after, .sorted-asc::after {
    float: right;
}

.sorted-desc::after{
    content:"\25BC";
}

.sorted-asc::after{
    content: "\25B2";
}