Thymeleaf: Best Way to Display Active Navigation Item

This tutorial is about how to highlight the currently active page in your navigation with Thymeleaf and Spring Boot. Highlighting the active page is a known usability pattern and should help users to find their way around your web application.

Consider this example:

In the navigation above, the navigation item “Cronjob Monitoring” is highlighted.

The menu is generated with this Thymeleaf code:

<nav class="mdl-navigation">
    <a th:classappend="${#request.requestURI.startsWith(navItem.getLink()) ? 'mdl-navigation__link-active':''}" th:each="navItem: ${navigation}" th:id="${navItem.getIdentifier()}" class="mdl-navigation__link"
        th:href="@{${navItem.getLink()}}" th:text="${navItem.getName()}"></a>
</nav>

By using th:each, a link is generated for each navigation entry.

th:classappend is used to conditionally append a CSS class to the <a> element. The class mdl-navigation__link-active in this case simply changes the background color, but you can opt for a less subtle approach.

request.requestURI.startsWith(navItem.getLink()) evaluates to true if the specific navigation item’s URL is currently opened in the user’s web browser. For example:

If https://app.pingmy.tech/dashboard is the result of navigation item’s getLink(), an active URL of https://app.pingmy.tech/dashboard/ will evaluate to true, but so will https://app.pingmy.tech/dashboard/stats or any other subpath.

This method is very powerful because as long as you add all your controller actions with the same prefix, your navigation works out of the box without having to set any variables in the controller methods.

The accompanying CSS may look like this:

.mdl-navigation__link {
    color: #ffffff;
    font-weight: normal;
}

.mdl-navigation__link:hover{
    background-color:#333;
}

.mdl-navigation__link-active {
    font-weight: bold;
    background-color: #554477;
}

Interested in monitoring your background tasks?

https://www.pingmy.tech/ is currently launching as a public beta – it is a new web app which helps you monitoring your periodic background tasks (such as backups, data exports, accounting checks etc) and notifies you via email or slack when your services appear unavailable. Check it out – it is completely free.

Environment-Dependent Code Execution with Spring Boot and Docker

Different deployment environments (e.g., development, testing, staging and production) often require that different pieces of code are switched on and off. For example, you only want to send real emails in production and write to an email log in all other environments instead. Or your code to initialise the database should only run in the staging environment.

A simple but hard to maintain way for such conditional code executions is to define a globally available variable such as isProductionSystem and write code such as this:

if (isProductionSystem) {
  sendMail(...);
} else {
  logMail(...);
}

This is hard to maintain because you end up with large if statements if you have multiple environments. Also, the only way you can adapt in your environment is to change the isProductionSystem variable, which means you either have all of the “production-only” features or none of them.

The @ConditionalOnProperty Annotation

Spring offers a much better way to handle conditional code execution. You can annotate the beans that should only execute depending on an environment flag with the ConditionalOnProperty annotation:

@Bean
@ConditionalOnProperty(value = "emails.enabled")
public EmailJob emailJob() {
    return new EmailJob();
}

In the above example, the email job is only started when the property-value emails.enabled is set to true.

Profile-dependent execution

The code execution can also be dependent on the application profile:

@Profile("prod")
@Bean
public emailJob emailJob() {
    return new EmailJob();
}

As already mentioned, this removes some level of flexibility because you can no longer decide to activate or deactivate individual features at configuration time on the respective environment.

Overriding Configuration Flags in Docker

When using Docker, you can override the default values for the properties by using environment variables with the -e flag of the docker run command:

docker run -it -e SPRING_JPA_DATABASE_PLATFORM=org.hibernate.dialect.PostgreSQLDialect myimage:latest

Spring translates environment variables into the dot-syntax for property-names by substituting dots with underscores and capitalising everything. If you want to override the value of my.property, you need to set the environment variable MY_PROPERTY.

In the above example, you can control whether to actually send emails with the following command:

docker -it -e EMAILS_ENABLED=1 myapp:latest

Conditional Execution on Application Startup

There is another interesting use case for an overridable configuration switch: code that is executed on application startup. For example, a method that creates test instances in an empty database in the staging system but is skipped in production.

This is more verbose but is still readable. Simply extract the configuration value with the @Value annotation (with the default false) into a private variable and check it in a method annotated with the @EventListener annotation listening to the ApplicationReadyEvent:

@Service
public class PostStartService {

    @Value("${init.empty.db:false}")
    private boolean initEmptyDb;

    @EventListener(ApplicationReadyEvent.class)
    public void createTestData() {
        if (!initEmptyDb) {
            return;
        }

        // execute your code here
    }
}

In the above code snippet, you can control whether the body of createTestData is executed via setting the following environment variable in Docker:

docker -it -e INIT_EMPTY_DB=1 myapp:latest

Conclusion

In this article, I presented several techniques to run code depending on the deployment environment. Let me know how what works best for you or if you have different ways of achieving the correct environment configuration.

Thymeleaf: Output Size of List

Question: In my Thymeleaf template, I want to output the size of a list of objects. For example, for the list

List<String> list = Arrays.asList("Go", "Python", "Scala");

the result should be 3. How is this possible using just Thymeleaf syntax?

You can use the following expression:

<span th:text="${#lists.size(myList)}">[Number of Elements]</span>

And just in case you want to check if the list is empty, there is also an easy method for that:

<span th:if="${#lists.isEmpty(myList)}">This list is empty</span>

Send JSON objects via POST to Spring Boot Controllers

Creating and persisting business objects using Spring Boot is amazingly easy. Assume you create an API for simple CRUD methods and want to create an entity based on data entered by your frontend users. In the old times, you would probably populate several POST fields in a key-value style and create your business object manually from those fields.

Spring Boot offers an easier solution. As long as your internal data model equals the frontend’s data model, you can use the @Valid On @RequestBody Controller Method Arguments to automatically create the object from a JSON-serialized request and execute the necessary validation logic.

Continue reading

Creating a VirtualBox-Based Spring Boot Development Environment

In this article, I’ll show how to set up a simple development environment for working with Spring Boot inside a VirtualBox Ubuntu Server. You will learn how to

  • configure port forwarding for interacting with the development server
  • set up shared folders for using an IDE on your client to edit code on the server
  • build and execute the application using maven

Let’s get started!

Prerequisites

You need:

Continue reading