diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/DispatcherServlet.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/DispatcherServlet.java index 7bac3dfb1ba..d6eddaf7d7e 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/DispatcherServlet.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/DispatcherServlet.java @@ -840,14 +840,14 @@ public class DispatcherServlet extends FrameworkServlet { request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); + + FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); + if (inputFlashMap != null) { + request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); + } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); - Map flashMap = this.flashMapManager.getFlashMapForRequest(request); - if (flashMap != null) { - request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, flashMap); - } - try { doDispatch(request, response); } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMap.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMap.java index cb6450ca89b..08b7f736a4a 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMap.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,12 +32,11 @@ import org.springframework.util.StringUtils; *

A FlashMap can be set up with a request path and request parameters to * help identify the target request. Without this information, a FlashMap is * made available to the next request, which may or may not be the intended - * recipient. On a redirect, the target URL is known and for example - * {@code org.springframework.web.servlet.view.RedirectView} has the - * opportunity to automatically update the current FlashMap with target - * URL information. + * recipient. On a redirect, the target URL is known and a FlashMap can be + * updated with that information. This is done automatically when the + * {@code org.springframework.web.servlet.view.RedirectView} is used. * - *

Annotated controllers will usually not use this type directly. + *

Note: annotated controllers will usually not use FlashMap directly. * See {@code org.springframework.web.servlet.mvc.support.RedirectAttributes} * for an overview of using flash attributes in annotated controllers. * @@ -58,25 +57,6 @@ public final class FlashMap extends HashMap implements Comparabl private int timeToLive; - private final int createdBy; - - /** - * Create a new instance with an id uniquely identifying the creator of - * this FlashMap. - * @param createdBy identifies the FlashMapManager instance that created - * and will manage this FlashMap instance (e.g. via a hashCode) - */ - public FlashMap(int createdBy) { - this.createdBy = createdBy; - } - - /** - * Create a new instance. - */ - public FlashMap() { - this.createdBy = 0; - } - /** * 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 @@ -96,7 +76,6 @@ public final class FlashMap extends HashMap implements Comparabl /** * Provide request parameters identifying the request for this FlashMap. - * Null or empty keys and values are skipped. * @param params a Map with the names and values of expected parameters. */ public FlashMap addTargetRequestParams(MultiValueMap params) { @@ -112,8 +91,8 @@ public final class FlashMap extends HashMap implements Comparabl /** * Provide a request parameter identifying the request for this FlashMap. - * @param name the expected parameter name, skipped if {@code null} - * @param value the expected parameter value, skipped if {@code null} + * @param name the expected parameter name, skipped if empty or {@code null} + * @param value the expected value, skipped if empty or {@code null} */ public FlashMap addTargetRequestParam(String name, String value) { if (StringUtils.hasText(name) && StringUtils.hasText(value)) { @@ -151,13 +130,6 @@ public final class FlashMap extends HashMap implements Comparabl } } - /** - * Whether the given id matches the id of the creator of this FlashMap. - */ - public boolean isCreatedBy(int createdBy) { - return this.createdBy == createdBy; - } - /** * Compare two FlashMaps and prefer the one that specifies a target URL * path or has more target URL parameters. Before comparing FlashMap diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMapManager.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMapManager.java index 8440bd636c5..078713194b9 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMapManager.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMapManager.java @@ -16,44 +16,43 @@ package org.springframework.web.servlet; -import java.util.Map; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * A strategy interface for retrieving and saving FlashMap instances. * See {@link FlashMap} for a general overview of flash attributes. - * + * * @author Rossen Stoyanchev * @since 3.1 - * + * * @see FlashMap */ public interface FlashMapManager { /** - * Get a Map with flash attributes saved by a previous request. - * See {@link FlashMap} for details on how FlashMap instances - * identifies the target requests they're saved for. - * If found, the Map is removed from the underlying storage. + * Find a FlashMap saved by a previous request that matches to 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 {@link #saveOutputFlashMap}, which is invoked only when there are + * flash attributes to be saved - i.e. before a redirect. * @param request the current request - * @return a read-only Map with flash attributes or {@code null} + * @param response the current response + * @return a FlashMap matching the current request or {@code null} */ - Map getFlashMapForRequest(HttpServletRequest request); + FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response); /** - * Save the given FlashMap, in some underlying storage, mark the beginning - * of its expiration period, and remove other expired FlashMap instances. - * The method has no impact if the FlashMap is empty and there are no - * expired FlashMap instances to be removed. + * 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 perhaps in a response + * 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 save(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response); + void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response); } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/AbstractFlashMapManager.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/AbstractFlashMapManager.java index 0cfc3b2037d..e745cfb47b8 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/AbstractFlashMapManager.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/AbstractFlashMapManager.java @@ -19,7 +19,6 @@ package org.springframework.web.servlet.support; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import javax.servlet.http.HttpServletRequest; @@ -50,6 +49,8 @@ public abstract class AbstractFlashMapManager implements FlashMapManager { private UrlPathHelper urlPathHelper = new UrlPathHelper(); + private static final Object writeLock = new Object(); + /** * Set the amount of time in seconds after a {@link FlashMap} is saved * (at request completion) and before it expires. @@ -81,34 +82,30 @@ public abstract class AbstractFlashMapManager implements FlashMapManager { return this.urlPathHelper; } - /** - * {@inheritDoc} - *

Does not cause an HTTP session to be created. - */ - public final Map getFlashMapForRequest(HttpServletRequest request) { - List flashMaps = retrieveFlashMaps(request); - if (CollectionUtils.isEmpty(flashMaps)) { + public final FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) { + List allMaps = retrieveFlashMaps(request); + if (CollectionUtils.isEmpty(allMaps)) { return null; } if (logger.isDebugEnabled()) { - logger.debug("Retrieved FlashMap(s): " + flashMaps); + logger.debug("Retrieved FlashMap(s): " + allMaps); } - List result = new ArrayList(); - for (FlashMap flashMap : flashMaps) { - if (isFlashMapForRequest(flashMap, request)) { - result.add(flashMap); - } + List mapsToRemove = getExpiredFlashMaps(allMaps); + FlashMap match = getMatchingFlashMap(allMaps, request); + if (match != null) { + mapsToRemove.add(match); } - if (!result.isEmpty()) { - Collections.sort(result); + if (!mapsToRemove.isEmpty()) { if (logger.isDebugEnabled()) { - logger.debug("Found matching FlashMap(s): " + result); + logger.debug("Removing FlashMap(s): " + allMaps); + } + synchronized (writeLock) { + allMaps = retrieveFlashMaps(request); + allMaps.removeAll(mapsToRemove); + updateFlashMaps(allMaps, request, response); } - FlashMap match = result.remove(0); - flashMaps.remove(match); - return Collections.unmodifiableMap(match); } - return null; + return match; } /** @@ -118,10 +115,44 @@ public abstract class AbstractFlashMapManager implements FlashMapManager { */ protected abstract List retrieveFlashMaps(HttpServletRequest request); + /** + * Return a list of expired FlashMap instances contained in the given list. + */ + private List getExpiredFlashMaps(List allMaps) { + List result = new ArrayList(); + for (FlashMap map : allMaps) { + if (map.isExpired()) { + result.add(map); + } + } + return result; + } + + /** + * Return a FlashMap contained in the given list that matches the request. + * @return a matching FlashMap or {@code null} + */ + private FlashMap getMatchingFlashMap(List allMaps, HttpServletRequest request) { + List result = new ArrayList(); + for (FlashMap flashMap : allMaps) { + if (isFlashMapForRequest(flashMap, request)) { + result.add(flashMap); + } + } + if (!result.isEmpty()) { + Collections.sort(result); + if (logger.isDebugEnabled()) { + logger.debug("Found matching FlashMap(s): " + result); + } + return result.get(0); + } + return null; + } + /** * Whether the given FlashMap matches the current request. - * The default implementation uses the target request path and query params - * saved in the FlashMap. + * The default implementation uses the target request path and query + * parameters saved in the FlashMap. */ protected boolean isFlashMapForRequest(FlashMap flashMap, HttpServletRequest request) { if (flashMap.getTargetRequestPath() != null) { @@ -142,37 +173,21 @@ public abstract class AbstractFlashMapManager implements FlashMapManager { return true; } - /** - * {@inheritDoc} - *

The FlashMap, if not empty, is saved to the HTTP session. - */ - public final void save(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) { - Assert.notNull(flashMap, "FlashMap must not be null"); - - List flashMaps = retrieveFlashMaps(request); - if (flashMap.isEmpty() && (flashMaps == null)) { + public final void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) { + if (CollectionUtils.isEmpty(flashMap)) { return; } - synchronized (this) { - boolean update = false; - flashMaps = retrieveFlashMaps(request); - if (!CollectionUtils.isEmpty(flashMaps)) { - update = removeExpired(flashMaps); - } - if (!flashMap.isEmpty()) { - String path = decodeAndNormalizePath(flashMap.getTargetRequestPath(), request); - flashMap.setTargetRequestPath(path); - flashMap.startExpirationPeriod(this.flashMapTimeout); - if (logger.isDebugEnabled()) { - logger.debug("Saving FlashMap=" + flashMap); - } - flashMaps = (flashMaps == null) ? new CopyOnWriteArrayList() : flashMaps; - flashMaps.add(flashMap); - update = true; - } - if (update) { - updateFlashMaps(flashMaps, request, response); - } + String path = decodeAndNormalizePath(flashMap.getTargetRequestPath(), request); + flashMap.setTargetRequestPath(path); + flashMap.startExpirationPeriod(this.flashMapTimeout); + if (logger.isDebugEnabled()) { + logger.debug("Saving FlashMap=" + flashMap); + } + synchronized (writeLock) { + List allMaps = retrieveFlashMaps(request); + allMaps = (allMaps == null) ? new CopyOnWriteArrayList() : allMaps; + allMaps.add(flashMap); + updateFlashMaps(allMaps, request, response); } } @@ -197,25 +212,4 @@ public abstract class AbstractFlashMapManager implements FlashMapManager { protected abstract void updateFlashMaps(List flashMaps, HttpServletRequest request, HttpServletResponse response); - /** - * Remove expired FlashMap instances from the given List. - */ - protected boolean removeExpired(List flashMaps) { - List expired = new ArrayList(); - for (FlashMap flashMap : flashMaps) { - if (flashMap.isExpired()) { - if (logger.isTraceEnabled()) { - logger.trace("Removing expired FlashMap: " + flashMap); - } - expired.add(flashMap); - } - } - if (expired.isEmpty()) { - return false; - } - else { - return flashMaps.removeAll(expired); - } - } - } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/SessionFlashMapManager.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/SessionFlashMapManager.java index ef6183e952f..527f89d6335 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/SessionFlashMapManager.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/SessionFlashMapManager.java @@ -25,7 +25,7 @@ import javax.servlet.http.HttpSession; import org.springframework.web.servlet.FlashMap; /** - * Stores {@link FlashMap} instances in the HTTP session. + * Store and retrieve {@link FlashMap} instances to and from the HTTP session. * * @author Rossen Stoyanchev * @since 3.1.1 @@ -35,9 +35,10 @@ public class SessionFlashMapManager extends AbstractFlashMapManager{ private static final String FLASH_MAPS_SESSION_ATTRIBUTE = SessionFlashMapManager.class.getName() + ".FLASH_MAPS"; /** - * Retrieve saved FlashMap instances from the HTTP session. - * @param request the current request - * @return a List with FlashMap instances or {@code null} + * Retrieve saved FlashMap instances from the HTTP Session. + *

Does not cause an HTTP session to be created but may update it if a + * FlashMap matching the current request is found or there are expired + * FlashMap to be removed. */ @SuppressWarnings("unchecked") protected List retrieveFlashMaps(HttpServletRequest request) { @@ -46,7 +47,7 @@ public class SessionFlashMapManager extends AbstractFlashMapManager{ } /** - * Save the given FlashMap instances in the HTTP session. + * Save the given FlashMap instance, if not empty, in the HTTP session. */ protected void updateFlashMaps(List flashMaps, HttpServletRequest request, HttpServletResponse response) { request.getSession().setAttribute(FLASH_MAPS_SESSION_ATTRIBUTE, flashMaps); diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java index 0f931d776bb..43f15df2e9d 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java @@ -276,7 +276,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { } FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request); - flashMapManager.save(flashMap, request, response); + flashMapManager.saveOutputFlashMap(flashMap, request, response); sendRedirect(request, response, targetUrl.toString(), this.http10Compatible); } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/AbstractFlashMapManagerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/AbstractFlashMapManagerTests.java index ccef7060b9b..f4b80f6b1ad 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/AbstractFlashMapManagerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/AbstractFlashMapManagerTests.java @@ -26,7 +26,6 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import javax.servlet.http.HttpServletRequest; @@ -60,7 +59,7 @@ public class AbstractFlashMapManagerTests { } @Test - public void getFlashMapForRequestByPath() { + public void retrieveAndUpdateMatchByPath() { FlashMap flashMap = new FlashMap(); flashMap.put("key", "value"); flashMap.setTargetRequestPath("/path"); @@ -68,16 +67,15 @@ public class AbstractFlashMapManagerTests { this.flashMapManager.setFlashMaps(flashMap); this.request.setRequestURI("/path"); - Map inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertEquals(flashMap, inputFlashMap); - assertEquals("Input FlashMap should have been removed", 0, this.flashMapManager.getFlashMaps().size()); } // SPR-8779 @Test - public void getFlashMapForRequestByOriginatingPath() { + public void retrieveAndUpdateMatchByOriginatingPath() { FlashMap flashMap = new FlashMap(); flashMap.put("key", "value"); flashMap.setTargetRequestPath("/accounts"); @@ -86,14 +84,14 @@ public class AbstractFlashMapManagerTests { this.request.setAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE, "/accounts"); this.request.setRequestURI("/mvc/accounts"); - Map inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertEquals(flashMap, inputFlashMap); assertEquals("Input FlashMap should have been removed", 0, this.flashMapManager.getFlashMaps().size()); } @Test - public void getFlashMapForRequestByPathWithTrailingSlash() { + public void retrieveAndUpdateMatchWithTrailingSlash() { FlashMap flashMap = new FlashMap(); flashMap.put("key", "value"); flashMap.setTargetRequestPath("/path"); @@ -101,14 +99,14 @@ public class AbstractFlashMapManagerTests { this.flashMapManager.setFlashMaps(flashMap); this.request.setRequestURI("/path/"); - Map inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertEquals(flashMap, inputFlashMap); assertEquals("Input FlashMap should have been removed", 0, this.flashMapManager.getFlashMaps().size()); } @Test - public void getFlashMapForRequestWithParams() { + public void retrieveAndUpdateMatchByParams() { FlashMap flashMap = new FlashMap(); flashMap.put("key", "value"); flashMap.addTargetRequestParam("number", "one"); @@ -116,19 +114,19 @@ public class AbstractFlashMapManagerTests { this.flashMapManager.setFlashMaps(flashMap); this.request.setParameter("number", (String) null); - Map inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertNull(inputFlashMap); assertEquals("FlashMap should not have been removed", 1, this.flashMapManager.getFlashMaps().size()); this.request.setParameter("number", "two"); - inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertNull(inputFlashMap); assertEquals("FlashMap should not have been removed", 1, this.flashMapManager.getFlashMaps().size()); this.request.setParameter("number", "one"); - inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertEquals(flashMap, inputFlashMap); assertEquals("Input FlashMap should have been removed", 0, this.flashMapManager.getFlashMaps().size()); @@ -137,7 +135,7 @@ public class AbstractFlashMapManagerTests { // SPR-8798 @Test - public void getFlashMapForRequestWithMultiValueParam() { + public void retrieveAndUpdateMatchWithMultiValueParam() { FlashMap flashMap = new FlashMap(); flashMap.put("name", "value"); flashMap.addTargetRequestParam("id", "1"); @@ -146,20 +144,20 @@ public class AbstractFlashMapManagerTests { this.flashMapManager.setFlashMaps(flashMap); this.request.setParameter("id", "1"); - Map inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertNull(inputFlashMap); assertEquals("FlashMap should not have been removed", 1, this.flashMapManager.getFlashMaps().size()); this.request.addParameter("id", "2"); - inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertEquals(flashMap, inputFlashMap); assertEquals("Input FlashMap should have been removed", 0, this.flashMapManager.getFlashMaps().size()); } @Test - public void getFlashMapForRequestSortOrder() { + public void retrieveAndUpdateSortMultipleMatches() { FlashMap emptyFlashMap = new FlashMap(); FlashMap flashMapOne = new FlashMap(); @@ -174,28 +172,44 @@ public class AbstractFlashMapManagerTests { this.flashMapManager.setFlashMaps(emptyFlashMap, flashMapOne, flashMapTwo); this.request.setRequestURI("/one/two"); - Map inputFlashMap = this.flashMapManager.getFlashMapForRequest(this.request); + FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(this.request, this.response); assertEquals(flashMapTwo, inputFlashMap); + assertEquals("Input FlashMap should have been removed", 2, this.flashMapManager.getFlashMaps().size()); } @Test - public void saveFlashMapEmpty() throws InterruptedException { + public void retrieveAndUpdateRemoveExpired() throws InterruptedException { + List flashMaps = new ArrayList(); + for (int i=0; i < 5; i++) { + FlashMap expiredFlashMap = new FlashMap(); + expiredFlashMap.startExpirationPeriod(-1); + flashMaps.add(expiredFlashMap); + } + this.flashMapManager.setFlashMaps(flashMaps); + this.flashMapManager.retrieveAndUpdate(this.request, this.response); + + assertEquals("Expired instances should be removed even if the saved FlashMap is empty", + 0, this.flashMapManager.getFlashMaps().size()); + } + + @Test + public void saveOutputFlashMapEmpty() throws InterruptedException { FlashMap flashMap = new FlashMap(); - this.flashMapManager.save(flashMap, this.request, this.response); + this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response); List allMaps = this.flashMapManager.getFlashMaps(); assertNull(allMaps); } @Test - public void saveFlashMap() throws InterruptedException { + public void saveOutputFlashMap() throws InterruptedException { FlashMap flashMap = new FlashMap(); flashMap.put("name", "value"); this.flashMapManager.setFlashMapTimeout(-1); // expire immediately so we can check expiration started - this.flashMapManager.save(flashMap, this.request, this.response); + this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response); List allMaps = this.flashMapManager.getFlashMaps(); assertNotNull(allMaps); @@ -204,67 +218,52 @@ public class AbstractFlashMapManagerTests { } @Test - public void saveFlashMapDecodeTargetPath() throws InterruptedException { + public void saveOutputFlashMapDecodeTargetPath() throws InterruptedException { FlashMap flashMap = new FlashMap(); flashMap.put("key", "value"); flashMap.setTargetRequestPath("/once%20upon%20a%20time"); - this.flashMapManager.save(flashMap, this.request, this.response); + this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response); assertEquals("/once upon a time", flashMap.getTargetRequestPath()); } @Test - public void saveFlashMapNormalizeTargetPath() throws InterruptedException { + public void saveOutputFlashMapNormalizeTargetPath() throws InterruptedException { FlashMap flashMap = new FlashMap(); flashMap.put("key", "value"); flashMap.setTargetRequestPath("."); this.request.setRequestURI("/once/upon/a/time"); - this.flashMapManager.save(flashMap, this.request, this.response); + this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response); assertEquals("/once/upon/a", flashMap.getTargetRequestPath()); flashMap.setTargetRequestPath("./"); this.request.setRequestURI("/once/upon/a/time"); - this.flashMapManager.save(flashMap, this.request, this.response); + this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response); assertEquals("/once/upon/a/", flashMap.getTargetRequestPath()); flashMap.setTargetRequestPath(".."); this.request.setRequestURI("/once/upon/a/time"); - this.flashMapManager.save(flashMap, this.request, this.response); + this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response); assertEquals("/once/upon", flashMap.getTargetRequestPath()); flashMap.setTargetRequestPath("../"); this.request.setRequestURI("/once/upon/a/time"); - this.flashMapManager.save(flashMap, this.request, this.response); + this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response); assertEquals("/once/upon/", flashMap.getTargetRequestPath()); flashMap.setTargetRequestPath("../../only"); this.request.setRequestURI("/once/upon/a/time"); - this.flashMapManager.save(flashMap, this.request, this.response); + this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response); assertEquals("/once/only", flashMap.getTargetRequestPath()); } - @Test - public void saveFlashMapAndRemoveExpired() throws InterruptedException { - List flashMaps = new ArrayList(); - for (int i=0; i < 5; i++) { - FlashMap flashMap = new FlashMap(); - flashMap.startExpirationPeriod(-1); - flashMaps.add(flashMap); - } - this.flashMapManager.setFlashMaps(flashMaps); - this.flashMapManager.save(new FlashMap(), request, response); - - assertEquals("Expired instances should be removed even if the saved FlashMap is empty", - 0, this.flashMapManager.getFlashMaps().size()); - } - private static class TestFlashMapManager extends AbstractFlashMapManager {