Flash
Flash messages are server-side messages that are only available for a single request after
the current one (this is useful for displaying messages after a redirect).
The Flash instance is available via Session.getFlash()
or using RouteContext.flashXXX()
helpers.
Each Flash message has a content/message and a level that can be:
INFO
SUCCESS
WARNING
ERROR
From technical perspective, Flash it’s an attribute of session (Session.getFlash()
is equivalent with Session.get("flash")
) so the flash messages are stored in session between two succesive reuqests.
Bellow you see a snipet code that put an error message in Flash object:
POST("/login", routeContext -> {
String username = routeContext.getParameter("username").toString();
String password = routeContext.getParameter("password").toString();
if (authenticate(username, password)) {
routeContext.resetSession();
routeContext.setSession("username", username);
routeContext.redirect("/contacts");
} else {
routeContext.flashError("Authentication failed"); // <-- here
routeContext.redirect("/login");
}
});
GET("/login", routeContext -> {
// we already have the flash object in the template model (injected by framework via Response.locals)
routeContext.render("login");
});
The snippet for login template (freemarker engine) can be:
<#if flash.hasError()>
<div class="alert alert-danger">
${flash.getError()}
</div>
</#if>
<form>
<!-- login form components here -->
</form>
Virtually, the flash messages can be splitted in two categories:
- incoming
- outgoing
The incoming messages are messages that are available automatically (via Response.locals
) to templates for the rendering page process.
You can retrieves programmatically this list with Response.getLocals().getFlash()
or Response.getFlash()
.
The outgoing messages are messages that are keeped in session for the next request. You can set such a message using RouteContext.flashXXX()
or Session.getFlash().add()
.
You can retrieves programmatically this list with Session.getFlash()
.
On each request the RouteDispatcher
removes the Flash instance from the session, binds it to the RouteContext
, and creates a new Flash instance.
Are situation when we want to put a flash message directly in incoming (see ValidationApplication.java from pippo-demo-validation project). For these situations we can use:
POST("/", routeContext -> {
Contact contact = routeContext.createEntityFromParameters(Contact.class);
// check for validation
Set<ConstraintViolation<Contact>> violations = validator.validate(contact);
if (violations.isEmpty()) {
routeContext.send(contact.toString());
} else {
// makes violations available to template via flash (response.getLocals().get("flash"))
Flash flash = routeContext.getResponse().getFlash();
for (ConstraintViolation<Contact> violation : violations) {
flash.error(violation.getPropertyPath() + " " + violation.getMessage());
}
routeContext.setLocal("contact", contact); // <-- here
routeContext.render("contact");
}
});