docs
Flash attributes for passing data between requests during redirects, commonly used for the Post/Redirect/Get pattern to display messages or preserve form data.
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";
}
}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);
}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);
}
}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) {}
}