or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

api-versioning.mdasync.mdconfiguration.mdcontent-negotiation.mdcontroller-annotations.mdcore-framework.mdcors.mddata-binding.mdexception-handling.mdflash-attributes.mdfunctional-endpoints.mdi18n.mdindex.mdinterceptors.mdmultipart.mdrequest-binding.mdresource-handling.mdresponse-handling.mduri-building.mdview-resolution.md
tile.json

flash-attributes.mddocs/

Flash Attributes

Flash attributes for passing data between requests during redirects, commonly used for the Post/Redirect/Get pattern to display messages or preserve form data.

Capabilities

FlashMap

Storage for flash attributes that survive a redirect.

/**
 * A FlashMap provides a way for one request to store attributes intended for
 * use in another. This is most commonly needed when redirecting from one URL
 * to another -- e.g. the Post/Redirect/Get pattern. A FlashMap is saved before
 * the redirect (typically in the session) and is made available after the
 * redirect and removed immediately.
 */
public class FlashMap extends HashMap<String, Object> implements Comparable<FlashMap> {
    /**
     * Provide a URL path to help identify the target request for this FlashMap.
     * The path may be absolute (e.g. "/application/resource") or relative to the
     * current request (e.g. "../resource").
     *
     * @param path the URI path
     */
    public void setTargetRequestPath(String path) {}

    /**
     * Return the target URL path (or null if none specified).
     *
     * @return the target request path
     */
    public String getTargetRequestPath() {}

    /**
     * Provide request parameters identifying the request for this FlashMap.
     * If set, the target request must have matching parameters.
     *
     * @param params a Map with the names and values of expected parameters
     * @return this FlashMap instance for chaining
     */
    public FlashMap addTargetRequestParams(MultiValueMap<String, String> params) {}

    /**
     * Return the parameters identifying the target request, or an empty map.
     *
     * @return the target request parameters
     */
    public MultiValueMap<String, String> getTargetRequestParams() {}

    /**
     * Start the expiration period for this instance.
     */
    public void startExpirationPeriod() {}

    /**
     * Set the expiration time for the FlashMap. This is provided for
     * use in unit tests only.
     *
     * @param timeToLive the time to live in seconds
     */
    public void setExpirationTime(int timeToLive) {}

    /**
     * Return the expiration time or -1 if not set.
     *
     * @return the expiration time
     */
    public long getExpirationTime() {}

    /**
     * Return whether this instance has expired.
     *
     * @return true if expired, false otherwise
     */
    public boolean isExpired() {}

    @Override
    public int compareTo(FlashMap other) {}
}

Usage Example:

@Controller
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public String createUser(@ModelAttribute @Valid User user,
                           BindingResult result,
                           RedirectAttributes redirectAttributes) {
        if (result.hasErrors()) {
            return "user/form";
        }

        userService.save(user);

        // Add flash attribute
        redirectAttributes.addFlashAttribute("message", "User created successfully");
        redirectAttributes.addFlashAttribute("messageType", "success");

        return "redirect:/users";
    }

    @GetMapping
    public String listUsers(Model model) {
        // Flash attributes are automatically added to the model
        // "message" and "messageType" will be available if set in previous request
        model.addAttribute("users", userService.findAll());
        return "user/list";
    }

    @PostMapping("/{id}/delete")
    public String deleteUser(@PathVariable Long id, RedirectAttributes redirectAttributes) {
        try {
            userService.delete(id);
            redirectAttributes.addFlashAttribute("message", "User deleted successfully");
            redirectAttributes.addFlashAttribute("messageType", "success");
        } catch (Exception e) {
            redirectAttributes.addFlashAttribute("message", "Failed to delete user");
            redirectAttributes.addFlashAttribute("messageType", "error");
        }

        return "redirect:/users";
    }
}

FlashMapManager

Strategy interface for managing FlashMap instances.

/**
 * A strategy interface for saving and retrieving FlashMap instances.
 * See FlashMap for a general overview of flash attributes.
 */
public interface FlashMapManager {
    /**
     * Find a FlashMap saved by a previous request that matches the current request,
     * remove it from underlying storage, and also remove other expired FlashMap instances.
     * This method is invoked in the beginning of every request in contrast to
     * saveOutputFlashMap which is invoked only when there are flash attributes to be saved -
     * i.e. before a redirect.
     *
     * @param request the current request
     * @param response the current response
     * @return a FlashMap matching the current request or null
     */
    FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);

    /**
     * Save the given FlashMap, in some underlying storage and set the start of
     * its expiration period. NOTE: Invoke this method prior to a redirect in order
     * to allow saving the FlashMap in the HTTP session or in a response cookie before
     * the response is committed.
     *
     * @param flashMap the FlashMap to save
     * @param request the current request
     * @param response the current response
     */
    void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request,
                           HttpServletResponse response);
}

RedirectAttributes

Interface that extends Model and provides a way to select attributes for a redirect scenario.

/**
 * A specialization of the Model interface that controllers can use to select
 * attributes for a redirect scenario. Since the intent of adding redirect
 * attributes is very explicit, attribute names can be left empty if the value
 * is a non-null object; attribute names can be inferred in that case.
 *
 * Whether an attribute is selected as a redirect attribute or as a temporary
 * flash attribute does not affect the view rendering. The DispatcherServlet
 * always makes all model attributes available to a view that is rendering the
 * request.
 */
public interface RedirectAttributes extends Model {
    /**
     * Add the given flash attribute.
     *
     * @param attributeName the attribute name; never null
     * @param attributeValue the attribute value; may be null
     * @return this instance for chaining
     */
    RedirectAttributes addFlashAttribute(String attributeName, Object attributeValue);

    /**
     * Add the given flash attribute with a generated name.
     *
     * @param attributeValue the flash attribute value; never null
     * @return this instance for chaining
     */
    RedirectAttributes addFlashAttribute(Object attributeValue);

    /**
     * Return the attributes candidate for flash storage or an empty Map.
     *
     * @return a Map with flash attributes, or an empty Map
     */
    Map<String, ?> getFlashAttributes();

    /**
     * Add the given attribute as a redirect model attribute.
     *
     * @param attributeName the attribute name; never null
     * @param attributeValue the attribute value; may be null
     * @return this instance for chaining
     */
    @Override
    RedirectAttributes addAttribute(String attributeName, Object attributeValue);

    /**
     * Add the given attribute with a generated name.
     *
     * @param attributeValue the attribute value; never null
     * @return this instance for chaining
     */
    @Override
    RedirectAttributes addAttribute(Object attributeValue);

    /**
     * Copy all given attributes to this instance.
     *
     * @param attributes the attributes to add; may be null
     * @return this instance for chaining
     */
    @Override
    RedirectAttributes addAllAttributes(Map<String, ?> attributes);

    /**
     * Merge the supplied attributes with the attributes in this Map.
     * Supplied attributes will override attributes in this Map.
     *
     * @param attributes the attributes to merge; may be null
     * @return this instance for chaining
     */
    @Override
    RedirectAttributes mergeAttributes(Map<String, ?> attributes);
}

Usage Example:

@Controller
public class FormController {

    @PostMapping("/submit-form")
    public String submitForm(@ModelAttribute FormData formData,
                           BindingResult result,
                           RedirectAttributes redirectAttributes) {
        if (result.hasErrors()) {
            // Preserve form data as flash attribute
            redirectAttributes.addFlashAttribute("formData", formData);
            redirectAttributes.addFlashAttribute("errors", result.getAllErrors());
            return "redirect:/form";
        }

        processService.process(formData);

        // Add success message
        redirectAttributes.addFlashAttribute("successMessage", "Form submitted successfully");

        // Add URL parameters (not flash attributes)
        redirectAttributes.addAttribute("id", formData.getId());

        // Redirect to: /success?id=123
        return "redirect:/success";
    }

    @GetMapping("/form")
    public String showForm(Model model) {
        // Flash attributes are automatically added to model
        if (!model.containsAttribute("formData")) {
            model.addAttribute("formData", new FormData());
        }
        return "form";
    }

    @GetMapping("/success")
    public String showSuccess(@RequestParam Long id, Model model) {
        // successMessage flash attribute available if set
        model.addAttribute("recordId", id);
        return "success";
    }
}

// REST API example with flash-like behavior using session
@RestController
@RequestMapping("/api/wizard")
public class WizardController {

    @PostMapping("/step1")
    public ResponseEntity<Map<String, String>> step1(
            @RequestBody Step1Data data,
            RedirectAttributes redirectAttributes) {
        // Store data for next step
        redirectAttributes.addFlashAttribute("step1Data", data);

        Map<String, String> response = new HashMap<>();
        response.put("nextStep", "/api/wizard/step2");
        return ResponseEntity.ok(response);
    }

    @PostMapping("/step2")
    public ResponseEntity<Result> step2(
            @RequestBody Step2Data data,
            @ModelAttribute("step1Data") Step1Data step1Data) {
        // Use data from step 1
        Result result = wizardService.process(step1Data, data);
        return ResponseEntity.ok(result);
    }
}

Types

SessionFlashMapManager

Default FlashMapManager implementation that stores FlashMap instances in the HTTP session.

/**
 * Store and retrieve FlashMap instances to and from the HTTP session.
 */
public class SessionFlashMapManager extends AbstractFlashMapManager {
    /**
     * The default amount of time in seconds before a FlashMap expires.
     */
    private static final int DEFAULT_FLASH_TIMEOUT = 180;

    /**
     * Set the amount of time in seconds before a FlashMap expires.
     * The default value is 180 seconds.
     *
     * @param flashTimeout the timeout in seconds
     */
    public void setFlashTimeout(int flashTimeout) {}

    /**
     * Return the amount of time in seconds before a FlashMap expires.
     *
     * @return the timeout in seconds
     */
    public int getFlashTimeout() {}

    @Override
    protected List<FlashMap> retrieveFlashMaps(HttpServletRequest request) {}

    @Override
    protected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest request,
                                  HttpServletResponse response) {}
}