Fork me on GitHub

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

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.setSession("username", username);
	} else {
		routeContext.flashError("Authentication failed"); // <-- here

GET("/login", routeContext -> {
	// we already have the flash object in the template model (injected by framework via Response.locals)

The snippet for login template (freemarker engine) can be:

<#if flash.hasError()>
	<div class="alert alert-danger">

	<!-- login form components here -->

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 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()) {
	} 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