Guide to implement ViewDecorator

Updated at 1775662829000
ViewDecorator is the place where shared data is added to a View before the UI is rendered. Instead of repeatedly passing the same variables from multiple controllers, we can centralize this common view-preparation logic in a decorator so templates can use the data directly.

What is ViewDecorator used for?

During request processing, after a controller returns a View, the system invokes ViewDecorator to add more data into that view. That data is then available to the template engine when rendering HTML.
ViewDecorator is suitable for cases such as:
  • adding shared variables for multiple pages,
  • preparing data for layouts,
  • providing display configuration values,
  • exposing current user information to the UI,
  • setting default values for templates.
In short, if a variable is reused across many pages, it is a strong candidate for ViewDecorator.

How it works

The ViewDecorator flow can be understood as follows:
  1. A client sends a request to the system.
  2. The controller processes the request and returns a View.
  3. ViewDecorator is invoked to add data into the View.
  4. The template uses those variables to render the UI.
flowchart TD
    A[Client sends request] --> B[Controller processes request]
    B --> C[Controller returns View]
    C --> D[ViewDecorator adds shared variables]
    D --> E[Template renders HTML]
    E --> F[Response is returned to client]
Because the decorator runs before rendering, every value added to the view at this stage can be accessed directly from the template.

When should you use ViewDecorator?

You should use ViewDecorator when:
  • the same data is needed across multiple pages,
  • you want to separate view-preparation logic from controller logic,
  • you want layouts to always have some default variables,
  • you want to reduce duplicated code across controllers.
On the other hand, if some data is only needed for one very specific page, keeping it in the controller is usually clearer.

How to implement a ViewDecorator

Typically, you create a dedicated ViewDecorator class inside your UI module and implement the decorate(...) method.
Example:
package your.package.web.view;

import com.tvd12.ezyfox.bean.annotation.EzySingleton;
import com.tvd12.ezyhttp.server.core.view.View;

import javax.servlet.http.HttpServletRequest;

@EzySingleton
public class WebMyProjectViewDecorator {

    public void decorate(HttpServletRequest request, View view) {
        view.setVariableIfAbsent("siteName", "My Project");
        view.setVariableIfAbsent("supportEmail", "support@example.com");
    }
}
The most important part here is the decorate(...) method. This is where you add shared data into the view.

Example usage

For example, if you want every page to have the site name and current year, you can do this:
@Override
public void decorate(HttpServletRequest request, View view) {
    view.setVariableIfAbsent("siteName", "My Project");
    view.setVariableIfAbsent("currentYear", 2026);
}
Then in the template, you can use those variables directly:
<footer>
    <span th:text=""></span>
    <span th:text=""></span>
</footer>

Why use setVariableIfAbsent

When working with ViewDecorator, you should prefer setVariableIfAbsent(...) instead of manually checking whether a variable already exists.
This approach has a few benefits:
  • the code is shorter,
  • it is easier to read,
  • it avoids overwriting values that were already set earlier,
  • it matches the decorator’s role of supplying default values for the view.
flowchart TD
    A[ViewDecorator is invoked] --> B{Does the variable already exist in View?}
    B -->|Yes| C[Keep the existing value]
    B -->|No| D[Set default value with setVariableIfAbsent]
    C --> E[Template renders the data]
    D --> E
Example:
@Override
public void decorate(HttpServletRequest request, View view) {
    view.setVariableIfAbsent("siteName", "My Project");
    view.setVariableIfAbsent("pageSize", 20);
}
If siteName or pageSize has already been assigned elsewhere, the decorator will not override them.

Best practices

When implementing a ViewDecorator, it is recommended to follow these principles:
  • Only add data that is truly shared.
  • Avoid putting complex business logic inside the decorator.
  • Minimize heavy queries, because the decorator may run on many requests.
  • For default values, prefer setVariableIfAbsent(...) to avoid overwriting existing data.
  • Use clear variable names so templates remain easy to read and use.

Benefits of ViewDecorator

Using ViewDecorator properly provides several clear benefits:
  • Controllers become cleaner.
  • Shared UI data is centralized in one place.
  • Templates become easier to use because common variables are already available.
  • The UI becomes easier to maintain and extend.

Conclusion

ViewDecorator is a very useful extension point for preparing shared UI data before rendering. When you put the right kind of data into it and use setVariableIfAbsent(...) for default values, your controllers stay cleaner, your templates stay clearer, and the overall UI becomes more consistent.

Table Of Contents