skip to content

What does RedirectAttributes do, and what is the difference between addAttribute and addFlashAttribute?

level: middleimportance: must knowfreq 60%

answer

  1. RedirectAttributes extends Model, gates redirect data
  2. addAttribute -> URL (path var / query, String, visible)
  3. addFlashAttribute -> flash map, one redirect, server-side
  4. SessionFlashMapManager, output->input FlashMap
  5. classic POST-Redirect-Get success message

basics

~20 s

RedirectAttributes controls data passed through a redirect. addAttribute puts values in the redirect URL (path/query params, visible). addFlashAttribute stores objects server-side in a flash map that survives exactly one redirect, so they aren't in the URL and can be complex objects.

solid answer

~40 s

`RedirectAttributes` (a sub-interface of `Model`) exists so that only attributes you explicitly designate survive a `redirect:` — ordinary model attributes would otherwise leak into a `RedirectView`'s URL. `addAttribute(name, value)` contributes to the target URL: it fills URI template variables and otherwise becomes a query-string parameter, so values are visible, String-ified, and bookmarkable. `addFlashAttribute(name, value)` stores the object in the **flash map**, managed by a `FlashMapManager` (session-backed by default). It survives exactly one redirect: it's saved as an *output* flash map, and on the next request the `DispatcherServlet` retrieves it as *input* flash attributes and merges them into that handler's model, then removes them. Use flash for POST-redirect-GET success messages or non-serializable/complex objects you don't want in the URL.

code

java · 19 lines
java
@Controller
class CheckoutController {

    @PostMapping("/checkout")
    String submit(@Valid CartForm form, BindingResult binding, RedirectAttributes ra) {
        if (binding.hasErrors()) return "checkout"; // no redirect: RA ignored
        Order o = orders.place(form);
        ra.addAttribute("id", o.getId());                 // fills {id} in the target URL
        ra.addFlashAttribute("notice", "Payment received"); // one-shot, not in URL
        return "redirect:/orders/{id}";                     // -> /orders/1001
    }

    @GetMapping("/orders/{id}")
    String view(@PathVariable Long id, Model model) {
        // model already contains "notice" for this one render, then it is removed
        model.addAttribute("order", orders.find(id));
        return "orders/view";
    }
}

go deeper

for a junior

Know addAttribute = URL, addFlashAttribute = one-shot server-side message.

for a middle

Explain the output/input FlashMap lifecycle, session backing, and POST-Redirect-Get.

for a senior

Discuss FlashMapManager, path matching, RedirectView URL expansion, and stateless caveats.

for a principal

Weigh flash vs URL vs session/DB for cross-request state, clustering serialization, and refresh semantics.

### Why RedirectAttributes exists When a controller returns `"redirect:/orders/42"`, Spring uses a `RedirectView`. By default a `RedirectView` can append the *current model* to the redirect URL as query parameters — which is almost never what you want (it leaks internals into the URL). To make this explicit and safe, Spring 3.1 added **`RedirectAttributes`**, a `Model` sub-interface. **When you declare a `RedirectAttributes` parameter, Spring stops using the default model for redirect URL expansion** and uses only what you put in `RedirectAttributes`. ### `addAttribute(name, value)` — URL attributes - Contributes to the **target URL**. - If the redirect path has a URI template variable (`/orders/{id}`), a matching attribute fills it (`addAttribute("id", 42)` → `/orders/42`). - Any leftover attributes become **query-string parameters** (`?status=OK`). - Values are converted to **Strings** and are **visible in the URL** (bookmarkable, logged, size-limited). Good for simple, shareable state (an id, a page number). ### `addFlashAttribute(name, value)` — flash scope - Stores the object in a **flash map**, not the URL. - Lifecycle: the handler that redirects writes to the **output FlashMap**; the `FlashMapManager` (default `SessionFlashMapManager`) persists it (in the HTTP session) keyed by the target path; on the **next** request `DispatcherServlet` finds the matching **input FlashMap**, exposes its entries as model attributes to the target handler, and then **deletes** them. Net effect: the value survives **exactly one** redirect. - Because it's server-side, it can be a **complex/non-String object** and stays out of the URL. Classic use: **POST-Redirect-Get** with a `successMessage` shown after the GET. ### End-to-end POST-Redirect-Get ``` @PostMapping("/orders") String create(@Valid OrderForm form, RedirectAttributes ra) { Order o = service.create(form); ra.addAttribute("id", o.getId()); // -> /orders/{id} ra.addFlashAttribute("flash", "Order created"); // survives one redirect, not in URL return "redirect:/orders/{id}"; } ``` On the following GET of `/orders/42`, `flash` is available in the model (e.g. `${flash}`), then discarded — a browser refresh won't re-show it. ### Which resolver injects it `RedirectAttributesMethodArgumentResolver` supports the `RedirectAttributes` parameter and creates a `RedirectAttributesModelMap`. ### Gotchas / edge cases - **Flash requires a session** by default (SessionFlashMapManager). Fully stateless setups may not carry flash attributes. - Flash attributes are matched to the **target path**; a mismatch (wrong redirect path) means they're never picked up. - Because they survive exactly one request, they're **gone after refresh** — desirable for one-shot messages, wrong for data the page needs on every load. - `addAttribute` values are **String-converted**; don't push large or sensitive objects there (they're in the URL). - If you declare `RedirectAttributes` but do **not** end up redirecting (return a normal view), its contents are **ignored** and the normal model is used — so guard your branches. - Flash-attribute values should be **serializable** if the session is persisted/clustered. ### When to use which - **`addAttribute`**: identifiers, filters, pagination — simple, shareable, belongs in the URL. - **`addFlashAttribute`**: transient UI messages, or a just-created/complex object you want available once after the redirect without exposing it in the URL.

  • Where are flash attributes physically stored and how long do they live?
    In a FlashMap managed by a FlashMapManager (default SessionFlashMapManager, backed by the HTTP session). They live from the redirecting request until the very next matching request retrieves them, then are removed — surviving exactly one redirect.
  • You put a value in addFlashAttribute but never redirect. What happens?
    Nothing useful — flash attributes are only propagated across a redirect. If the handler returns a normal view instead, the flash entries are not exposed the way you expect; you generally must actually issue the redirect for them to be picked up on the next request.

saying these in an interview costs you the question

  • Claiming addFlashAttribute puts data in the URL
  • Saying flash attributes persist indefinitely or across multiple redirects
  • Thinking RedirectAttributes is needed for a normal (non-redirect) view
  • Believing flash works with no session/state at all by default

context