You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2023/04/10 12:51:13 UTC

[struts] branch WW-5304-depreacted updated (0d2a67ad3 -> e2482b872)

This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a change to branch WW-5304-depreacted
in repository https://gitbox.apache.org/repos/asf/struts.git


 discard 0d2a67ad3 WW-5304 Drops deprecated methods and fields in ActionContext
     new e2482b872 WW-5304 Drops deprecated methods and fields in ActionContext

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (0d2a67ad3)
            \
             N -- N -- N   refs/heads/WW-5304-depreacted (e2482b872)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 core/src/main/java/com/opensymphony/xwork2/ActionContext.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


[struts] 01/01: WW-5304 Drops deprecated methods and fields in ActionContext

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5304-depreacted
in repository https://gitbox.apache.org/repos/asf/struts.git

commit e2482b872f062db7c1843dd654bf57db7a8f4b2e
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Sun Apr 9 16:00:03 2023 +0200

    WW-5304 Drops deprecated methods and fields in ActionContext
---
 .../com/opensymphony/xwork2/ActionChainResult.java |   2 +-
 .../com/opensymphony/xwork2/ActionContext.java     | 118 ++++-----------------
 .../com/opensymphony/xwork2/XWorkTestCase.java     |   2 +-
 .../interceptor/ExceptionMappingInterceptor.java   |  32 +++---
 .../interceptor/ParameterFilterInterceptor.java    |  28 ++---
 .../interceptor/StaticParametersInterceptor.java   |   2 +-
 .../AnnotationParameterFilterInterceptor.java      |   2 +-
 .../validators/VisitorFieldValidator.java          |   2 +-
 .../org/apache/struts2/dispatcher/Dispatcher.java  |   2 +-
 .../ActionMappingParametersInterceptor.java        |   4 +-
 .../struts2/result/ServletDispatcherResult.java    |   2 +-
 .../com/opensymphony/xwork2/ActionContextTest.java |   2 +-
 .../xwork2/ActionContextThreadLocalTest.java       |   2 +-
 .../opensymphony/xwork2/ActionInvocationTest.java  |   6 +-
 .../com/opensymphony/xwork2/ActionNestingTest.java |   2 +-
 .../com/opensymphony/xwork2/ActionSupportTest.java |   2 +-
 .../xwork2/DefaultActionInvocationTest.java        |   8 +-
 .../xwork2/DefaultTextProviderTest.java            |   2 +-
 .../opensymphony/xwork2/ProxyInvocationTest.java   |   7 +-
 .../xwork2/config/ConfigurationTest.java           |  28 +++--
 .../xwork2/conversion/impl/DateConverterTest.java  |  23 ++--
 .../conversion/impl/XWorkBasicConverterTest.java   |   8 +-
 .../xwork2/conversion/impl/XWorkConverterTest.java |  44 ++------
 .../xwork2/interceptor/AliasInterceptorTest.java   |   6 +-
 .../interceptor/ChainingInterceptorTest.java       |   2 +-
 .../DefaultWorkflowInterceptorTest.java            |   2 +-
 .../ExceptionMappingInterceptorTest.java           |   2 +-
 .../ParameterFilterInterceptorTest.java            |  36 +++----
 .../ParameterRemoverInterceptorTest.java           |  23 ++--
 .../interceptor/ParametersInterceptorTest.java     |  80 ++++++--------
 .../ScopedModelDrivenInterceptorTest.java          |   2 +-
 .../StaticParametersInterceptorTest.java           |   6 +-
 .../interceptor/ValidationErrorAwareTest.java      |   2 +-
 ...ationInterceptorPrefixMethodInvocationTest.java |   2 +-
 .../AnnotationParameterFilterInterceptorTest.java  |  16 +--
 .../opensymphony/xwork2/util/MyBeanActionTest.java |  10 +-
 .../xwork2/validator/DateRangeValidatorTest.java   |   7 +-
 .../DefaultActionValidatorManagerTest.java         |   2 +-
 .../validator/DoubleRangeFieldValidatorTest.java   |  17 ++-
 .../xwork2/validator/ExpressionValidatorTest.java  |  10 +-
 .../xwork2/validator/IntRangeValidatorTest.java    |   5 +-
 .../xwork2/validator/LongRangeValidatorTest.java   |   5 +-
 .../validator/ModelDrivenValidationTest.java       |   5 +-
 .../xwork2/validator/ShortRangeValidatorTest.java  |   5 +-
 .../validator/SimpleActionValidationTest.java      |  24 ++---
 .../xwork2/validator/ValidatorAnnotationTest.java  |  32 +++---
 .../apache/struts2/dispatcher/DispatcherTest.java  |  24 ++---
 .../interceptor/CheckboxInterceptorTest.java       |  14 +--
 .../interceptor/ClearSessionInterceptorTest.java   |   6 +-
 .../interceptor/DateTextFieldInterceptorTest.java  |  14 +--
 .../interceptor/FileUploadInterceptorTest.java     |  14 +--
 .../struts2/interceptor/I18nInterceptorTest.java   |   4 +-
 .../interceptor/MessageStoreInterceptorTest.java   |  30 +++---
 .../MessageStorePreResultListenerTest.java         |  26 +++--
 .../interceptor/MultiselectInterceptorTest.java    |   8 +-
 .../interceptor/ServletConfigInterceptorTest.java  |   4 +-
 .../struts2/interceptor/TokenInterceptorTest.java  |   4 +-
 .../struts2/result/ServletRedirectResultTest.java  |   2 +-
 .../struts2/util/InvocationSessionStoreTest.java   |   9 +-
 .../org/apache/struts2/util/TokenHelperTest.java   |   9 +-
 .../apache/struts2/views/jsp/ActionTagTest.java    |  10 +-
 .../apache/struts2/views/jsp/NumberTagTest.java    |  16 +--
 .../org/apache/struts2/views/jsp/TextTagTest.java  |  13 +--
 .../org/apache/struts2/views/jsp/URLTagTest.java   |  70 ++++++------
 .../apache/struts2/views/jsp/ui/HiddenTest.java    |   4 +-
 .../PackageBasedActionConfigBuilderTest.java       |   2 +-
 .../org/apache/struts2/EmbeddedJSPResultTest.java  |   2 +-
 .../struts2/views/java/simple/TokenTest.java       |   5 +-
 .../apache/struts2/junit/StrutsJUnit4TestCase.java |   2 +-
 .../apache/struts2/junit/StrutsRestTestCase.java   |   2 +-
 .../org/apache/struts2/junit/StrutsTestCase.java   |   2 +-
 .../struts2/osgi/OsgiConfigurationProvider.java    |   4 +-
 .../apache/struts2/StrutsTestCasePortletTests.java |   6 +-
 .../struts2/portlet/result/PortletResultTest.java  |   9 +-
 .../struts2/portlet/util/PortletUrlHelperTest.java |   2 +-
 .../rest/ContentTypeHandlerManagerTest.java        |   4 +-
 .../struts2/rest/RestWorkflowInterceptorTest.java  |   2 +-
 .../struts2/rest/handler/JuneauXmlHandlerTest.java |   4 +-
 .../struts2/rest/handler/XStreamHandlerTest.java   |   2 +-
 .../xwork2/spring/ActionsFromSpringTest.java       |   5 +-
 .../ActionAutowiringInterceptorTest.java           |   2 +-
 .../apache/struts2/views/tiles/TilesResult.java    |   4 +-
 82 files changed, 416 insertions(+), 555 deletions(-)

diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java b/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
index 4fc70bbaa..4f7233046 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
@@ -218,7 +218,7 @@ public class ActionChainResult implements Result {
         }
         addToHistory(finalNamespace, finalActionName, finalMethodName);
 
-        Map<String, Object> extraContext = ActionContext.of(new HashMap<>())
+        Map<String, Object> extraContext = ActionContext.of()
             .withValueStack(invocation.getInvocationContext().getValueStack())
             .withParameters(invocation.getInvocationContext().getParameters())
             .with(CHAIN_HISTORY, ActionChainResult.getChainHistory())
diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
index 5fd676b14..d884f3117 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
@@ -58,79 +58,52 @@ import java.util.Map;
  */
 public class ActionContext implements Serializable {
 
-    static ThreadLocal<ActionContext> actionContext = new ThreadLocal<>();
+    private static final ThreadLocal<ActionContext> actionContext = new ThreadLocal<>();
 
     /**
      * Constant for the name of the action being executed.
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String ACTION_NAME = "com.opensymphony.xwork2.ActionContext.name";
+    private static final String ACTION_NAME = "org.apache.struts2.ActionContext.name";
 
     /**
      * Constant for the {@link com.opensymphony.xwork2.util.ValueStack OGNL value stack}.
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String VALUE_STACK = ValueStack.VALUE_STACK;
+    private static final String VALUE_STACK = ValueStack.VALUE_STACK;
 
     /**
      * Constant for the action's session.
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String SESSION = "com.opensymphony.xwork2.ActionContext.session";
+    private static final String SESSION = "org.apache.struts2.ActionContext.session";
 
     /**
      * Constant for the action's application context.
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String APPLICATION = "com.opensymphony.xwork2.ActionContext.application";
+    private static final String APPLICATION = "org.apache.struts2.ActionContext.application";
 
     /**
      * Constant for the action's parameters.
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String PARAMETERS = "com.opensymphony.xwork2.ActionContext.parameters";
+    private static final String PARAMETERS = "org.apache.struts2.ActionContext.parameters";
 
     /**
      * Constant for the action's locale.
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String LOCALE = "com.opensymphony.xwork2.ActionContext.locale";
+    private static final String LOCALE = "org.apache.struts2.ActionContext.locale";
 
     /**
      * Constant for the action's {@link com.opensymphony.xwork2.ActionInvocation invocation} context.
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String ACTION_INVOCATION = "com.opensymphony.xwork2.ActionContext.actionInvocation";
+    private static final String ACTION_INVOCATION = "org.apache.struts2.ActionContext.actionInvocation";
 
     /**
      * Constant for the map of type conversion errors.
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String CONVERSION_ERRORS = "com.opensymphony.xwork2.ActionContext.conversionErrors";
+    private static final String CONVERSION_ERRORS = "org.apache.struts2.ActionContext.conversionErrors";
 
     /**
      * Constant for the container
-     *
-     * @deprecated scope will be narrowed to "private", use helper methods instead
      */
-    @Deprecated
-    public static final String CONTAINER = "com.opensymphony.xwork2.ActionContext.container";
+    private static final String CONTAINER = "org.apache.struts2.ActionContext.container";
 
     private final Map<String, Object> context;
 
@@ -145,7 +118,6 @@ public class ActionContext implements Serializable {
 
     /**
      * Creates a new ActionContext based on passed in Map
-     * and assign this instance to the current thread
      *
      * @param context a map with context values
      * @return new ActionContext
@@ -157,6 +129,15 @@ public class ActionContext implements Serializable {
         return new ActionContext(context);
     }
 
+    /**
+     * Creates a new ActionContext based on empty Map
+     *
+     * @return new ActionContext
+     */
+    public static ActionContext of() {
+        return of(new HashMap<>());
+    }
+
     /**
      * Binds the provided context with the current thread
      *
@@ -211,13 +192,7 @@ public class ActionContext implements Serializable {
      * Sets the action invocation (the execution state).
      *
      * @param actionInvocation the action execution state.
-     * @deprecated use {@link #withActionInvocation(ActionInvocation)} instead
      */
-    @Deprecated
-    public void setActionInvocation(ActionInvocation actionInvocation) {
-        put(ACTION_INVOCATION, actionInvocation);
-    }
-
     public ActionContext withActionInvocation(ActionInvocation actionInvocation) {
         put(ACTION_INVOCATION, actionInvocation);
         return this;
@@ -236,13 +211,7 @@ public class ActionContext implements Serializable {
      * Sets the action's application context.
      *
      * @param application the action's application context.
-     * @deprecated use {@link #withApplication(Map)} instead
      */
-    @Deprecated
-    public void setApplication(Map<String, Object> application) {
-        put(APPLICATION, application);
-    }
-
     public ActionContext withApplication(Map<String, Object> application) {
         put(APPLICATION, application);
         return this;
@@ -271,13 +240,7 @@ public class ActionContext implements Serializable {
      * Sets conversion errors which occurred when executing the action.
      *
      * @param conversionErrors a Map of errors which occurred when executing the action.
-     * @deprecated use {@link #withConversionErrors(Map)} instead
      */
-    @Deprecated
-    public void setConversionErrors(Map<String, ConversionData> conversionErrors) {
-        put(CONVERSION_ERRORS, conversionErrors);
-    }
-
     public ActionContext withConversionErrors(Map<String, ConversionData> conversionErrors) {
         put(CONVERSION_ERRORS, conversionErrors);
         return this;
@@ -304,13 +267,7 @@ public class ActionContext implements Serializable {
      * Sets the Locale for the current action.
      *
      * @param locale the Locale for the current action.
-     * @deprecated use {@link #withLocale(Locale)} instead
      */
-    @Deprecated
-    public void setLocale(Locale locale) {
-        put(LOCALE, locale);
-    }
-
     public ActionContext withLocale(Locale locale) {
         put(LOCALE, locale);
         return this;
@@ -327,7 +284,7 @@ public class ActionContext implements Serializable {
 
         if (locale == null) {
             locale = Locale.getDefault();
-            setLocale(locale);
+            withLocale(locale);
         }
 
         return locale;
@@ -336,28 +293,13 @@ public class ActionContext implements Serializable {
     /**
      * Sets the name of the current Action in the ActionContext.
      *
-     * @param name the name of the current action.
-     * @deprecated use {@link #withActionName(String)} instead
+     * @param actionName the name of the current action.
      */
-    @Deprecated
-    public void setName(String name) {
-        put(ACTION_NAME, name);
-    }
-
     public ActionContext withActionName(String actionName) {
         put(ACTION_NAME, actionName);
         return this;
     }
 
-    /**
-     * Gets the name of the current Action.
-     *
-     * @return the name of the current action.
-     */
-    public String getName() {
-        return (String) get(ACTION_NAME);
-    }
-
     /**
      * Gets the name of the current Action.
      *
@@ -372,10 +314,6 @@ public class ActionContext implements Serializable {
      *
      * @param parameters the parameters for the current action.
      */
-    public void setParameters(HttpParameters parameters) {
-        put(PARAMETERS, parameters);
-    }
-
     public ActionContext withParameters(HttpParameters parameters) {
         put(PARAMETERS, parameters);
         return this;
@@ -396,13 +334,7 @@ public class ActionContext implements Serializable {
      * Sets a map of action session values.
      *
      * @param session the session values.
-     * @deprecated use {@link #withSession(Map)} instead
      */
-    @Deprecated
-    public void setSession(Map<String, Object> session) {
-        put(SESSION, session);
-    }
-
     public ActionContext withSession(Map<String, Object> session) {
         put(SESSION, session);
         return this;
@@ -446,14 +378,8 @@ public class ActionContext implements Serializable {
     /**
      * Gets the container for this request
      *
-     * @param cont The container
-     * @deprecated use {@link #withContainer(Container)} instead
+     * @param container The container
      */
-    @Deprecated
-    public void setContainer(Container cont) {
-        put(CONTAINER, cont);
-    }
-
     public ActionContext withContainer(Container container) {
         put(CONTAINER, container);
         return this;
diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
index ec7a8d755..402af38e5 100644
--- a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
+++ b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
@@ -101,7 +101,7 @@ public abstract class XWorkTestCase extends TestCase {
     }
 
     protected Map<String, Object> createContextWithLocale(Locale locale) {
-        return ActionContext.of(new HashMap<>())
+        return ActionContext.of()
             .withLocale(locale)
             .getContextMap();
     }
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java
index 61d4b83df..e60550ca6 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java
@@ -52,9 +52,9 @@ import java.util.Map;
  * <ul>
  *
  * <li>logEnabled (optional) - Should exceptions also be logged? (boolean true|false)</li>
- * 
+ *
  * <li>logLevel (optional) - what log level should we use (<code>trace, debug, info, warn, error, fatal</code>)? - defaut is <code>debug</code></li>
- * 
+ *
  * <li>logCategory (optional) - If provided we would use this category (eg. <code>com.mycompany.app</code>).
  * Default is to use <code>com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor</code>.</li>
  *
@@ -102,7 +102,7 @@ import java.util.Map;
  * &lt;/xwork&gt;
  * <!-- END SNIPPET: example -->
  * </pre>
- * 
+ *
  * <p>
  * This second example will also log the exceptions using our own category
  * <code>com.mycompany.app.unhandled</code> at WARN level.
@@ -117,8 +117,8 @@ import java.util.Map;
  *              &lt;interceptor-ref name="exception"&gt;
  *                  &lt;param name="logEnabled"&gt;true&lt;/param&gt;
  *                  &lt;param name="logCategory"&gt;com.mycompany.app.unhandled&lt;/param&gt;
- *                  &lt;param name="logLevel"&gt;WARN&lt;/param&gt;	        		
- *              &lt;/interceptor-ref&gt;	
+ *                  &lt;param name="logLevel"&gt;WARN&lt;/param&gt;
+ *              &lt;/interceptor-ref&gt;
  *              &lt;interceptor-ref name="i18n"/&gt;
  *              &lt;interceptor-ref name="staticParams"/&gt;
  *              &lt;interceptor-ref name="params"/&gt;
@@ -129,7 +129,7 @@ import java.util.Map;
  *      &lt;/interceptors&gt;
  *
  *      &lt;default-interceptor-ref name="exceptionmappingStack"/&gt;
- *    
+ *
  *      &lt;global-results&gt;
  *           &lt;result name="unhandledException"&gt;/unhandled-exception.jsp&lt;/result&gt;
  *      &lt;/global-results&gt;
@@ -137,12 +137,12 @@ import java.util.Map;
  *      &lt;global-exception-mappings&gt;
  *           &lt;exception-mapping exception="java.lang.Exception" result="unhandledException"/&gt;
  *      &lt;/global-exception-mappings&gt;
- *        
+ *
  *      &lt;action name="exceptionDemo" class="org.apache.struts2.showcase.exceptionmapping.ExceptionMappingAction"&gt;
  *          &lt;exception-mapping exception="org.apache.struts2.showcase.exceptionmapping.ExceptionMappingException"
  *                             result="damm"/&gt;
  *          &lt;result name="input"&gt;index.jsp&lt;/result&gt;
- *          &lt;result name="success"&gt;success.jsp&lt;/result&gt;            
+ *          &lt;result name="success"&gt;success.jsp&lt;/result&gt;
  *          &lt;result name="damm"&gt;damm.jsp&lt;/result&gt;
  *      &lt;/action&gt;
  *
@@ -151,18 +151,18 @@ import java.util.Map;
  * <!-- END SNIPPET: example2 -->
  * </pre>
  *
- * @author Matthew E. Porter (matthew dot porter at metissian dot com) 
+ * @author Matthew E. Porter (matthew dot porter at metissian dot com)
  * @author Claus Ibsen
  */
 public class ExceptionMappingInterceptor extends AbstractInterceptor {
-    
+
     private static final Logger LOG = LogManager.getLogger(ExceptionMappingInterceptor.class);
 
     protected Logger categoryLogger;
     protected boolean logEnabled = false;
     protected String logCategory;
     protected String logLevel;
-    
+
 
     public boolean isLogEnabled() {
         return logEnabled;
@@ -204,7 +204,7 @@ public class ExceptionMappingInterceptor extends AbstractInterceptor {
                 Map<String, String> mappingParams = mappingConfig.getParams();
                 // create a mutable HashMap since some interceptors will remove parameters, and parameterMap is immutable
                 HttpParameters parameters = HttpParameters.create(mappingParams).build();
-                invocation.getInvocationContext().setParameters(parameters);
+                invocation.getInvocationContext().withParameters(parameters);
                 result = mappingConfig.getResult();
                 publishException(invocation, new ExceptionHolder(e));
             } else {
@@ -217,7 +217,7 @@ public class ExceptionMappingInterceptor extends AbstractInterceptor {
 
     /**
      * Handles the logging of the exception.
-     * 
+     *
      * @param e the exception to log.
      */
     protected void handleLogging(Exception e) {
@@ -231,10 +231,10 @@ public class ExceptionMappingInterceptor extends AbstractInterceptor {
     		doLog(LOG, e);
     	}
     }
-    
+
     /**
      * Performs the actual logging.
-     * 
+     *
      * @param logger  the provided logger to use.
      * @param e  the exception to log.
      */
@@ -243,7 +243,7 @@ public class ExceptionMappingInterceptor extends AbstractInterceptor {
     		logger.debug(e.getMessage(), e);
     		return;
     	}
-    	
+
     	if ("trace".equalsIgnoreCase(logLevel)) {
     		logger.trace(e.getMessage(), e);
     	} else if ("debug".equalsIgnoreCase(logLevel)) {
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptor.java
index 3f0414a31..b695c7bc8 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptor.java
@@ -34,33 +34,33 @@ import java.util.TreeMap;
  * <!-- START SNIPPET: description -->
  *
  * The Parameter Filter Interceptor blocks parameters from getting
- * to the rest of the stack or your action. You can use multiple 
+ * to the rest of the stack or your action. You can use multiple
  * parameter filter interceptors for a given action, so, for example,
  * you could use one in your default stack that filtered parameters
- * you wanted blocked from every action and those you wanted blocked 
+ * you wanted blocked from every action and those you wanted blocked
  * from an individual action you could add an additional interceptor
  * for each action.
- * 
+ *
  * <!-- END SNIPPET: description -->
- * 
+ *
  * <!-- START SNIPPET: parameters -->
  *
  * <ul>
  * <li>allowed - a comma delimited list of parameter prefixes
  *  that are allowed to pass to the action</li>
- * <li>blocked - a comma delimited list of parameter prefixes 
+ * <li>blocked - a comma delimited list of parameter prefixes
  * that are not allowed to pass to the action</li>
  * <li>defaultBlock - boolean (default to false) whether by
  * default a given parameter is blocked. If true, then a parameter
- * must have a prefix in the allowed list in order to be able 
+ * must have a prefix in the allowed list in order to be able
  * to pass to the action
  * </ul>
- * 
+ *
  * <p>The way parameters are filtered for the least configuration is that
  * if a string is in the allowed or blocked lists, then any parameter
  * that is a member of the object represented by the parameter is allowed
  * or blocked respectively.</p>
- * 
+ *
  * <p>For example, if the parameters are:
  * <ul>
  * <li>blocked: person,person.address.createDate,personDao</li>
@@ -69,16 +69,16 @@ import java.util.TreeMap;
  * </ul>
  *
  * <p>
- * The parameters person.name, person.phoneNum etc would be blocked 
+ * The parameters person.name, person.phoneNum etc would be blocked
  * because 'person' is in the blocked list. However, person.address.street
  * and person.address.city would be allowed because person.address is
- * in the allowed list (the longer string determines permissions).</p> 
+ * in the allowed list (the longer string determines permissions).</p>
  * <!-- END SNIPPET: parameters -->
  *
  * <!-- START SNIPPET: extending -->
  * There are no known extension points to this interceptor.
  * <!-- END SNIPPET: extending -->
- * 
+ *
  * <pre>
  * <!-- START SNIPPET: example -->
  * &lt;interceptors&gt;
@@ -86,7 +86,7 @@ import java.util.TreeMap;
  *   &lt;interceptor name="parameterFilter" class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/&gt;
  *   ...
  * &lt;/interceptors&gt;
- * 
+ *
  * &lt;action ....&gt;
  *   ...
  *   &lt;interceptor-ref name="parameterFilter"&gt;
@@ -96,7 +96,7 @@ import java.util.TreeMap;
  * &lt;/action&gt;
  * <!-- END SNIPPET: example -->
  * </pre>
- * 
+ *
  * @author Gabe
  */
 public class ParameterFilterInterceptor extends AbstractInterceptor {
@@ -133,7 +133,7 @@ public class ParameterFilterInterceptor extends AbstractInterceptor {
             }
         }
 
-        invocation.getInvocationContext().setParameters(parameters);
+        invocation.getInvocationContext().withParameters(parameters);
 
         return invocation.invoke();
     }
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java
index f4079b834..9d32a8a18 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java
@@ -236,6 +236,6 @@ public class StaticParametersInterceptor extends AbstractInterceptor {
             combinedParams = HttpParameters.create(newParams);
             combinedParams = combinedParams.withExtraParams(previousParams);
         }
-        ac.setParameters(combinedParams.build());
+        ac.withParameters(combinedParams.build());
     }
 }
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptor.java
index 4fc6b1fe6..8309d61d2 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptor.java
@@ -104,7 +104,7 @@ public class AnnotationParameterFilterInterceptor extends AbstractInterceptor {
             }
         }
 
-        invocation.getInvocationContext().setParameters(parameters);
+        invocation.getInvocationContext().withParameters(parameters);
 
         return invocation.invoke();
     }
diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java
index d21bcb490..9e488a9b4 100644
--- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java
+++ b/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java
@@ -138,7 +138,7 @@ public class VisitorFieldValidator extends FieldValidatorSupport {
 
         stack.push(object);
 
-        String visitorContext = (context == null) ? ActionContext.getContext().getName() : context;
+        String visitorContext = (context == null) ? ActionContext.getContext().getActionName() : context;
 
         if (value instanceof Collection) {
             Collection coll = (Collection) value;
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java b/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
index 74780a15a..f7c3ad764 100644
--- a/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
+++ b/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
@@ -757,7 +757,7 @@ public class Dispatcher {
                                                 Map<String, Object> applicationMap,
                                                 HttpServletRequest request,
                                                 HttpServletResponse response) {
-        Map<String, Object> extraContext = ActionContext.of(new HashMap<>())
+        Map<String, Object> extraContext = ActionContext.of()
             .withParameters(parameters)
             .withSession(sessionMap)
             .withApplication(applicationMap)
diff --git a/core/src/main/java/org/apache/struts2/interceptor/ActionMappingParametersInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/ActionMappingParametersInterceptor.java
index 79cd0ccb4..69aa7083c 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/ActionMappingParametersInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/ActionMappingParametersInterceptor.java
@@ -75,7 +75,7 @@ public class ActionMappingParametersInterceptor extends ParametersInterceptor {
 
     /**
      * Get the parameter map from ActionMapping associated with the provided ActionContext.
-     * 
+     *
      * @param ac The action context
      * @return the parameters from the action mapping in the context.  If none found, returns an empty map.
      */
@@ -102,6 +102,6 @@ public class ActionMappingParametersInterceptor extends ParametersInterceptor {
         HttpParameters previousParams = ac.getParameters();
         HttpParameters.Builder combinedParams = HttpParameters.create().withParent(previousParams).withExtraParams(newParams);
 
-        ac.setParameters(combinedParams.buildNoNestedWrapping());
+        ac.withParameters(combinedParams.buildNoNestedWrapping());
     }
 }
diff --git a/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java b/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
index a3bbfaf97..6bc86725d 100644
--- a/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
+++ b/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
@@ -143,7 +143,7 @@ public class ServletDispatcherResult extends StrutsResultSupport {
                 Map<String, Object> queryParams = queryStringParser.parse(queryString, true);
                 if (queryParams != null && !queryParams.isEmpty()) {
                     parameters = HttpParameters.create(queryParams).withParent(parameters).build();
-                    invocation.getInvocationContext().setParameters(parameters);
+                    invocation.getInvocationContext().withParameters(parameters);
                     // put to extraContext, see Dispatcher#createContextMap
                     invocation.getInvocationContext().getContextMap().put("parameters", parameters);
                 }
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java b/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
index f5f9af2f8..bf8697137 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
@@ -65,7 +65,7 @@ public class ActionContextTest extends XWorkTestCase {
         assertTrue(ActionContext.getContext().getApplication().containsKey(APPLICATION_KEY));
         assertTrue(ActionContext.getContext().getSession().containsKey(SESSION_KEY));
         assertTrue(ActionContext.getContext().getParameters().contains(PARAMETERS_KEY));
-        assertEquals(ActionContext.getContext().getName(), ACTION_NAME);
+        assertEquals(ActionContext.getContext().getActionName(), ACTION_NAME);
     }
 
     public void testGetContext() {
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionContextThreadLocalTest.java b/core/src/test/java/com/opensymphony/xwork2/ActionContextThreadLocalTest.java
index de0b5c1a5..454e02df4 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ActionContextThreadLocalTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionContextThreadLocalTest.java
@@ -38,7 +38,7 @@ public class ActionContextThreadLocalTest extends TestCase {
     }
 
     public void testSetContext() {
-        ActionContext context = ActionContext.of(new HashMap<>()).bind();
+        ActionContext context = ActionContext.of().bind();
 
         assertEquals(context, ActionContext.getContext());
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionInvocationTest.java b/core/src/test/java/com/opensymphony/xwork2/ActionInvocationTest.java
index e0f13c42a..9b8ac87c7 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ActionInvocationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionInvocationTest.java
@@ -95,11 +95,11 @@ public class ActionInvocationTest extends XWorkTestCase {
         HashMap<String, Object> params = new HashMap<>();
         params.put("blah", "this is blah");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of()
+                .withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", "Foo", null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", "Foo", null, extraContext.getContextMap());
             proxy.execute();
             assertEquals("this is blah", proxy.getInvocation().getStack().findValue("[1].blah"));
         } catch (Exception e) {
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionNestingTest.java b/core/src/test/java/com/opensymphony/xwork2/ActionNestingTest.java
index cc4f01799..4ef2ad8ae 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ActionNestingTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionNestingTest.java
@@ -93,7 +93,7 @@ public class ActionNestingTest extends XWorkTestCase {
         ValueStack stack = ActionContext.getContext().getValueStack();
         assertEquals(VALUE, stack.findValue(KEY));
 
-        Map<String, Object> extraContext = ActionContext.of(new HashMap<>())
+        Map<String, Object> extraContext = ActionContext.of()
             .withValueStack(stack)
             .getContextMap();
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java b/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
index 0a357e862..65c38d38e 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
@@ -159,7 +159,7 @@ public class ActionSupportTest extends XWorkTestCase {
         ActionContext.getContext().withLocale(Locale.ITALY);
         assertEquals(Locale.ITALY, as.getLocale());
 
-        ActionContext.of(new HashMap<>()).bind();
+        ActionContext.of().bind();
         assertEquals(defLocale, as.getLocale()); // ActionContext will create a new context, when it was set to null before
     }
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java
index 6ad6b8422..db6e21b64 100644
--- a/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java
@@ -367,13 +367,13 @@ public class DefaultActionInvocationTest extends XWorkTestCase {
         HashMap<String, Object> params = new HashMap<>();
         params.put("blah", "this is blah");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of()
+                .withParameters(HttpParameters.create(params).build());
 
-        DefaultActionInvocation defaultActionInvocation = new DefaultActionInvocation(extraContext, true);
+        DefaultActionInvocation defaultActionInvocation = new DefaultActionInvocation(extraContext.getContextMap(), true);
         container.inject(defaultActionInvocation);
 
-        ActionProxy actionProxy = actionProxyFactory.createActionProxy("", "LazyFoo", null, extraContext);
+        ActionProxy actionProxy = actionProxyFactory.createActionProxy("", "LazyFoo", null, extraContext.getContextMap());
         defaultActionInvocation.init(actionProxy);
         defaultActionInvocation.invoke();
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/DefaultTextProviderTest.java b/core/src/test/java/com/opensymphony/xwork2/DefaultTextProviderTest.java
index 39c598a6d..511e6a884 100644
--- a/core/src/test/java/com/opensymphony/xwork2/DefaultTextProviderTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/DefaultTextProviderTest.java
@@ -129,7 +129,7 @@ public class DefaultTextProviderTest extends XWorkTestCase {
     protected void setUp() throws Exception {
         super.setUp();
 
-        ActionContext.of(new HashMap<>()).withLocale(Locale.CANADA).bind();
+        ActionContext.of().withLocale(Locale.CANADA).bind();
 
         container.getInstance(LocalizedTextProvider.class).addDefaultResourceBundle(DefaultTextProviderTest.class.getName());
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/ProxyInvocationTest.java b/core/src/test/java/com/opensymphony/xwork2/ProxyInvocationTest.java
index 3c962a47a..d1fd7e251 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ProxyInvocationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ProxyInvocationTest.java
@@ -20,6 +20,7 @@ package com.opensymphony.xwork2;
 
 import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
 import org.apache.struts2.config.StrutsXmlConfigurationProvider;
+import org.apache.struts2.dispatcher.HttpParameters;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -53,9 +54,9 @@ public class ProxyInvocationTest extends XWorkTestCase {
     private Map<String, Object> createDummyContext() {
         Map<String, Object> params = new HashMap<>();
         params.put("blah", "this is blah");
-        Map<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, params);
-        return extraContext;
+        return ActionContext.of()
+            .withParameters(HttpParameters.create(params).build())
+            .getContextMap();
     }
 
     @Override
diff --git a/core/src/test/java/com/opensymphony/xwork2/config/ConfigurationTest.java b/core/src/test/java/com/opensymphony/xwork2/config/ConfigurationTest.java
index 7d46932d7..b52b9d48c 100644
--- a/core/src/test/java/com/opensymphony/xwork2/config/ConfigurationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/config/ConfigurationTest.java
@@ -53,8 +53,8 @@ public class ConfigurationTest extends XWorkTestCase {
 
         try {
             ActionProxy proxy = actionProxyFactory.createActionProxy("/nonAbstract", "test", null, null);
-            assertTrue(proxy.getActionName().equals("test"));
-            assertTrue(proxy.getConfig().getClassName().equals(SimpleAction.class.getName()));
+            assertEquals("test", proxy.getActionName());
+            assertEquals(proxy.getConfig().getClassName(), SimpleAction.class.getName());
         } catch (Exception e) {
             e.printStackTrace();
             fail();
@@ -65,11 +65,11 @@ public class ConfigurationTest extends XWorkTestCase {
         HashMap<String, String> params = new HashMap<>();
         params.put("blah", "this is blah");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of()
+                .withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("/does/not/exist", "Foo", null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("/does/not/exist", "Foo", null, extraContext.getContextMap());
             proxy.execute();
             assertEquals("this is blah", proxy.getInvocation().getStack().findValue("[1].blah"));
         } catch (Exception e) {
@@ -94,13 +94,12 @@ public class ConfigurationTest extends XWorkTestCase {
         ActionConfig config = configuration.getActionConfig("", "WildCard/Simple/input");
 
         assertNotNull(config);
-        assertTrue("Wrong class name, " + config.getClassName(),
-            "com.opensymphony.xwork2.SimpleAction".equals(config.getClassName()));
-        assertTrue("Wrong method name", "input".equals(config.getMethodName()));
+        assertEquals("Wrong class name, " + config.getClassName(), "com.opensymphony.xwork2.SimpleAction", config.getClassName());
+        assertEquals("Wrong method name", "input", config.getMethodName());
 
         Map<String, String> p = config.getParams();
-        assertTrue("Wrong parameter, " + p.get("foo"), "Simple".equals(p.get("foo")));
-        assertTrue("Wrong parameter, " + p.get("bar"), "input".equals(p.get("bar")));
+        assertEquals("Wrong parameter, " + p.get("foo"), "Simple", p.get("foo"));
+        assertEquals("Wrong parameter, " + p.get("bar"), "input", p.get("bar"));
     }
 
     public void testWildcardNamespace() {
@@ -109,12 +108,11 @@ public class ConfigurationTest extends XWorkTestCase {
         ActionConfig config = configuration.getActionConfig("/animals/dog", "commandTest");
 
         assertNotNull(config);
-        assertTrue("Wrong class name, " + config.getClassName(),
-            "com.opensymphony.xwork2.SimpleAction".equals(config.getClassName()));
+        assertEquals("Wrong class name, " + config.getClassName(), "com.opensymphony.xwork2.SimpleAction", config.getClassName());
 
         Map<String, String> p = config.getParams();
-        assertTrue("Wrong parameter, " + p.get("0"), "/animals/dog".equals(p.get("0")));
-        assertTrue("Wrong parameter, " + p.get("1"), "dog".equals(p.get("1")));
+        assertEquals("Wrong parameter, " + p.get("0"), "/animals/dog", p.get("0"));
+        assertEquals("Wrong parameter, " + p.get("1"), "dog", p.get("1"));
     }
 
     public void testGlobalResults() {
@@ -206,7 +204,7 @@ public class ConfigurationTest extends XWorkTestCase {
         assertNotNull(configuration.getActionConfig("", MockConfigurationProvider.FOO_ACTION_NAME));
     }
 
-    public void testMultipleContainerProviders() throws Exception {
+    public void testMultipleContainerProviders() {
         // to start from scratch
         configurationManager.destroyConfiguration();
         // to build basic configuration
diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/DateConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/DateConverterTest.java
index cf91282f0..3218729d0 100644
--- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/DateConverterTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/DateConverterTest.java
@@ -59,7 +59,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
     public void testSqlTimeType() {
         DateConverter converter = new DateConverter();
 
-        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale);
+        ActionContext context = ActionContext.of().withLocale(mxLocale);
 
         Object value = converter.convertValue(context.getContextMap(), null, null, null, TIME_01_59_10, Time.class);
         assertEquals("01:59:10", value.toString());
@@ -68,7 +68,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
     public void testSqlTimestampType() {
         DateConverter converter = new DateConverter();
 
-        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale);
+        ActionContext context = ActionContext.of().withLocale(mxLocale);
 
         Object value = converter.convertValue(context.getContextMap(), null, null, null, INPUT_TIME_STAMP_STR,
                 Timestamp.class);
@@ -83,8 +83,9 @@ public class DateConverterTest extends StrutsInternalTestCase {
         ValueStack stack = new StubValueStack();
         stack.push(new StubTextProvider(map));
 
-        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(new Locale("es_MX", "MX"))
-                .withValueStack(stack);
+        ActionContext context = ActionContext.of()
+            .withLocale(new Locale("es_MX", "MX"))
+            .withValueStack(stack);
 
         Object value = converter.convertValue(context.getContextMap(), null, null, null, DATE_STR, Date.class);
         assertTrue(value.toString().startsWith(DATE_CONVERTED));
@@ -98,7 +99,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
         ValueStack stack = new StubValueStack();
         stack.push(new StubTextProvider(map));
 
-        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(new Locale("es_MX", "MX"))
+        ActionContext context = ActionContext.of().withLocale(new Locale("es_MX", "MX"))
                 .withValueStack(stack);
 
         try {
@@ -113,7 +114,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
     public void testTypeConversionExceptionWhenUsingLongConstructor() {
         DateConverter converter = new DateConverter();
 
-        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale);
+        ActionContext context = ActionContext.of().withLocale(mxLocale);
 
         try {
             converter.convertValue(context.getContextMap(), null, null, null, INPUT_WHEN_LONG_CONSTRUCTOR_STR, null);
@@ -127,7 +128,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
     public void testLocalDateTimeType() {
         DateConverter converter = new DateConverter();
 
-        ActionContext context = ActionContext.of(new HashMap<>());
+        ActionContext context = ActionContext.of();
 
         Object value = converter.convertValue(context.getContextMap(), null, null, null, LOCALDATETIME_STR,
                 LocalDateTime.class);
@@ -142,7 +143,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
         ValueStack stack = new StubValueStack();
         stack.push(new StubTextProvider(map));
 
-        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale)
+        ActionContext context = ActionContext.of().withLocale(mxLocale)
                 .withValueStack(stack);
 
         Object value = converter.convertValue(context.getContextMap(), null, null, null, LOCALDATETIME1_STR,
@@ -153,7 +154,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
     public void testLocalDateTimeTypeConversionExceptionWhenParseError() {
         DateConverter converter = new DateConverter();
 
-        ActionContext context = ActionContext.of(new HashMap<>());
+        ActionContext context = ActionContext.of();
 
         try {
             converter.convertValue(context.getContextMap(), null, null, null, INVALID_LOCALDATETIME,
@@ -168,7 +169,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
     public void testLocalDateType() {
         DateConverter converter = new DateConverter();
 
-        ActionContext context = ActionContext.of(new HashMap<>());
+        ActionContext context = ActionContext.of();
 
         Object value = converter.convertValue(context.getContextMap(), null, null, null, LOCALDATE_STR,
                 LocalDate.class);
@@ -178,7 +179,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
     public void testLocalTimeType() {
         DateConverter converter = new DateConverter();
 
-        ActionContext context = ActionContext.of(new HashMap<>());
+        ActionContext context = ActionContext.of();
 
         Object value = converter.convertValue(context.getContextMap(), null, null, null, LOCALTIME_STR,
                 LocalTime.class);
diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java
index a1fb332d1..bef05ca89 100644
--- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java
@@ -64,7 +64,7 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
         ValueStack stack = new StubValueStack();
         stack.push(new StubTextProvider(map));
 
-        ActionContext context = ActionContext.of(new HashMap<>())
+        ActionContext context = ActionContext.of()
             .withLocale(new Locale("es_MX", "MX"))
             .withValueStack(stack);
 
@@ -83,7 +83,7 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
 
         Locale locale = new Locale("pl", "PL");
 
-        ActionContext context = ActionContext.of(new HashMap<>())
+        ActionContext context = ActionContext.of()
             .withLocale(locale)
             .withValueStack(stack);
 
@@ -102,7 +102,7 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
 
         Locale locale = new Locale("fr", "FR");
 
-        ActionContext context = ActionContext.of(new HashMap<>())
+        ActionContext context = ActionContext.of()
             .withLocale(locale)
             .withValueStack(stack);
 
@@ -121,7 +121,7 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
 
         Locale locale = new Locale("en", "US");
 
-        ActionContext context = ActionContext.of(new HashMap<>())
+        ActionContext context = ActionContext.of()
             .withLocale(locale)
             .withValueStack(stack);
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
index 9ca0e0ece..192fe8703 100644
--- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
@@ -26,6 +26,7 @@ import com.opensymphony.xwork2.util.Bar;
 import com.opensymphony.xwork2.util.Cat;
 import com.opensymphony.xwork2.util.Foo;
 import com.opensymphony.xwork2.util.FurColor;
+import com.opensymphony.xwork2.util.ValueStack;
 import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
 import ognl.OgnlRuntime;
 import ognl.TypeConverter;
@@ -46,43 +47,12 @@ import static org.junit.Assert.assertArrayEquals;
 import java.util.Date;
 import java.util.Set;
 
-/**
- * @author $Author$
- * @version $Revision$
- */
 public class XWorkConverterTest extends XWorkTestCase {
 
     Map<String, Object> context;
     XWorkConverter converter;
     OgnlValueStack stack;
 
-//    public void testConversionToSetKeepsOriginalSetAndReplacesContents() {
-//        ValueStack stack = ValueStackFactory.getFactory().createValueStack();
-//
-//        Map stackContext = stack.getContext();
-//        stackContext.put(InstantiatingNullHandler.CREATE_NULL_OBJECTS, Boolean.TRUE);
-//        stackContext.put(XWorkMethodAccessor.DENY_METHOD_EXECUTION, Boolean.TRUE);
-//        stackContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
-//
-//        String[] param = new String[] {"abc", "def", "ghi"};
-//        List paramList = Arrays.asList(param);
-//
-//        List originalList = new ArrayList();
-//        originalList.add("jkl");
-//        originalList.add("mno");
-//
-//        User user = new User();
-//        user.setList(originalList);
-//        stack.push(user);
-//
-//        stack.setValue("list", param);
-//
-//        List userList = user.getList();
-//        assertEquals(3,userList.size());
-//        assertEquals(paramList,userList);
-//        assertSame(originalList,userList);
-//    }
-
     public void testArrayToNumberConversion() {
         String[] value = new String[]{"12345"};
         assertEquals(12345, converter.convertValue(context, null, null, null, value, Integer.class));
@@ -131,7 +101,7 @@ public class XWorkConverterTest extends XWorkTestCase {
         TextProvider tp = new StubTextProvider(lookupMap);
         StubValueStack valueStack = new StubValueStack();
         valueStack.push(tp);
-        context.put(ActionContext.VALUE_STACK, valueStack);
+        context.put(ValueStack.VALUE_STACK, valueStack);
 
         String dateToFormat = "2017---06--15";
         Object unparseableDate = converter.convertValue(context, null, null, null, dateToFormat, Date.class);
@@ -477,7 +447,7 @@ public class XWorkConverterTest extends XWorkTestCase {
     }
 
     public void testStringToCustomTypeUsingCustomConverter() {
-        // the converter needs to be registered as the Bar.class converter 
+        // the converter needs to be registered as the Bar.class converter
         // it won't be detected from the Foo-conversion.properties
         // because the Foo-conversion.properties file is only used when converting a property of Foo
         converter.registerConverter(Bar.class.getName(), new FooBarConverter());
@@ -658,7 +628,7 @@ public class XWorkConverterTest extends XWorkTestCase {
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", Double.class));
         assertEquals(1234d, converter.convertValue(context, null, null, null, "1,234", Double.class));
         assertEquals(1234.12, converter.convertValue(context, null, null, null, "1,234.12", Double.class));
-        // WRONG: locale separator is wrongly placed 
+        // WRONG: locale separator is wrongly placed
         assertEquals(123d, converter.convertValue(context, null, null, null, "1,23", Double.class));
         assertEquals(1.234, converter.convertValue(context, null, null, null, "1.234", Double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1.234,12", Double.class));
@@ -675,14 +645,14 @@ public class XWorkConverterTest extends XWorkTestCase {
         assertEquals(1234.12, converter.convertValue(context, null, null, null, "1.234,12", Double.class));
 
     }
-    
+
     public void testStringToEnum() {
         assertEquals(FurColor.BLACK, converter.convertValue(context, null, null, null, "BLACK", FurColor.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "black", FurColor.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "red", FurColor.class));
     }
 
-    // Testing for null result on non-primitive Number types supplied as empty String or 
+    // Testing for null result on non-primitive Number types supplied as empty String or
     public void testNotPrimitiveDefaultsToNull() {
         assertNull(converter.convertValue(context, null, null, null, null, Double.class));
         assertNull(converter.convertValue(context, null, null, null, "", Double.class));
@@ -829,4 +799,4 @@ class ListAction {
         this.ints = ints;
     }
 
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/AliasInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/AliasInterceptorTest.java
index 00e91411e..16108ef29 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/AliasInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/AliasInterceptorTest.java
@@ -164,15 +164,15 @@ public class AliasInterceptorTest extends XWorkTestCase {
     }
 
     public void testNotExisting() throws Exception {
-        Map<String, Object> params = new HashMap<>();
         Map<String, Object> httpParams = new HashMap<>();
         httpParams.put("notExisting", "from http parameter");
-        params.put(ActionContext.PARAMETERS, HttpParameters.create(httpParams).build());
+        ActionContext context = ActionContext.of()
+            .withParameters(HttpParameters.create(httpParams).build());
 
         XmlConfigurationProvider provider = new StrutsXmlConfigurationProvider("xwork-sample.xml");
         container.inject(provider);
         loadConfigurationProviders(provider);
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", "aliasTest", null, params);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", "aliasTest", null, context.getContextMap());
         SimpleAction actionOne = (SimpleAction) proxy.getAction();
 
         // prevent ERROR result
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java
index d809e4bca..0c6fd274a 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java
@@ -154,7 +154,7 @@ public class ChainingInterceptorTest extends XWorkTestCase {
         mockInvocation = new Mock(ActionInvocation.class);
         mockInvocation.expectAndReturn("getStack", stack);
         mockInvocation.expectAndReturn("invoke", Action.SUCCESS);
-        mockInvocation.expectAndReturn("getInvocationContext", ActionContext.of(new HashMap<>()).bind());
+        mockInvocation.expectAndReturn("getInvocationContext", ActionContext.of().bind());
         mockInvocation.expectAndReturn("getResult", new ActionChainResult());
         invocation = (ActionInvocation) mockInvocation.proxy();
         interceptor = new ChainingInterceptor();
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptorTest.java
index d2a0f831f..628c06918 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptorTest.java
@@ -183,7 +183,7 @@ public class DefaultWorkflowInterceptorTest extends XWorkTestCase {
         EasyMock.replay(action);
         EasyMock.replay(proxy);
 
-        ActionContext.of(new HashMap<>())
+        ActionContext.of()
             .withActionInvocation(invocation)
             .bind();
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptorTest.java
index d14b2b8bf..5ef177d9b 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptorTest.java
@@ -293,7 +293,7 @@ public class ExceptionMappingInterceptorTest extends XWorkTestCase {
         stack = ActionContext.getContext().getValueStack();
         mockInvocation = new Mock(ActionInvocation.class);
         mockInvocation.expectAndReturn("getStack", stack);
-        mockInvocation.expectAndReturn("getInvocationContext", ActionContext.of(new HashMap<>()).bind());
+        mockInvocation.expectAndReturn("getInvocationContext", ActionContext.of().bind());
         interceptor = new ExceptionMappingInterceptor();
         interceptor.init();
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptorTest.java
index 79b23cead..da7cefc03 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptorTest.java
@@ -64,64 +64,64 @@ public class ParameterFilterInterceptorTest extends XWorkTestCase {
         runFilterTest(null,null,true,new String[] {"blah", "bladeblah", "bladebladeblah"});
         assertEquals(0, getParameterNames().size());
     }
-    
+
     public void testBasicAllowed() throws Exception {
         runFilterTest("blah",null,true,new String[] {"blah"});
-        assertEquals(1, getParameterNames().size()); 
+        assertEquals(1, getParameterNames().size());
     }
-    
+
     public void testBasicBlocked() throws Exception {
         runFilterTest(null,"blah",false,new String[] {"blah"});
-        assertEquals(0, getParameterNames().size()); 
-    }      
+        assertEquals(0, getParameterNames().size());
+    }
     public void testAllSubpropertiesBlocked() throws Exception {
         runFilterTest(null,"blah",false,new String[] {"blah.deblah", "blah.somethingelse", "blah(22)"});
-        assertEquals(0, getParameterNames().size()); 
+        assertEquals(0, getParameterNames().size());
     }
 
     public void testAllSubpropertiesAllowed() throws Exception {
         runFilterTest("blah",null,true,
                 new String[] {"blah.deblah", "blah.somethingelse", "blah(22)"});
-        assertEquals(3, getParameterNames().size()); 
+        assertEquals(3, getParameterNames().size());
     }
-    
+
     public void testTreeBlocking() throws Exception {
         runFilterTest("blah.deblah","blah,blah.deblah.deblah",false,
                 new String[] {"blah", "blah.deblah", "blah.deblah.deblah"});
         assertEquals(1, getParameterNames().size());
         assertEquals(getParameterNames().iterator().next(),"blah.deblah");
     }
-    
+
     public void testEnsureOnlyPropsBlocked() throws Exception {
         runFilterTest(null,"blah",false,new String[] {"blahdeblah"});
-        assertEquals(1, getParameterNames().size()); 
+        assertEquals(1, getParameterNames().size());
     }
-  
-    
+
+
     private void runFilterTest(String allowed, String blocked, boolean defaultBlocked, String[] paramNames) throws Exception {
         interceptor.setAllowed(allowed);
         interceptor.setBlocked(blocked);
         interceptor.setDefaultBlock(defaultBlocked);
         setUpParameters(paramNames);
         runAction();
-        
+
     }
-    
+
     private void setUpParameters(String [] paramNames) {
         Map<String, String> params = new HashMap<>();
         for (String paramName : paramNames) {
             params.put(paramName, "irrelevant what this is");
 
         }
-        ActionContext.getContext().setParameters(HttpParameters.create(params).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(params).build());
     }
-    
+
     private Collection<String> getParameterNames() {
         return ActionContext.getContext().getParameters().keySet();
     }
-    
+
     public void runAction() throws Exception  {
         interceptor.intercept(invocation);
     }
-    
+
 }
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptorTest.java
index 928d13fd6..60131d919 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptorTest.java
@@ -24,8 +24,8 @@ import com.opensymphony.xwork2.ActionSupport;
 import junit.framework.TestCase;
 import org.apache.struts2.dispatcher.HttpParameters;
 
+import java.util.HashMap;
 import java.util.LinkedHashMap;
-import java.util.Map;
 
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.expect;
@@ -38,15 +38,12 @@ import static org.easymock.EasyMock.verify;
  */
 public class ParameterRemoverInterceptorTest extends TestCase {
 
-    protected Map<String, Object> contextMap;
-    protected ActionContext context;
-    protected ActionInvocation actionInvocation;
+    private ActionContext context;
+    private ActionInvocation actionInvocation;
 
     @Override
     protected void setUp() throws Exception {
-        contextMap = new LinkedHashMap<>();
-        context = ActionContext.of(contextMap).bind();
-
+        context = ActionContext.of();
         actionInvocation = createMock(ActionInvocation.class);
         expect(actionInvocation.getAction()).andStubReturn(new SampleAction());
         expect(actionInvocation.getInvocationContext()).andStubReturn(context);
@@ -54,7 +51,7 @@ public class ParameterRemoverInterceptorTest extends TestCase {
     }
 
     public void testInterception1() throws Exception {
-        contextMap.put(ActionContext.PARAMETERS, HttpParameters.create(new LinkedHashMap<String, Object>() {
+        context.withParameters(HttpParameters.create(new LinkedHashMap<String, Object>() {
             {
                 put("param1", new String[]{"paramValue1"});
                 put("param2", new String[]{"paramValue2"});
@@ -70,7 +67,7 @@ public class ParameterRemoverInterceptorTest extends TestCase {
         interceptor.setParamValues("paramValue1,paramValue2");
         interceptor.intercept(actionInvocation);
 
-        HttpParameters params = (HttpParameters) contextMap.get(ActionContext.PARAMETERS);
+        HttpParameters params = context.getParameters();
         assertEquals(params.keySet().size(), 2);
         assertTrue(params.contains("param3"));
         assertTrue(params.contains("param"));
@@ -82,7 +79,7 @@ public class ParameterRemoverInterceptorTest extends TestCase {
 
 
     public void testInterception2() throws Exception {
-        contextMap.put(ActionContext.PARAMETERS, HttpParameters.create(new LinkedHashMap<String, Object>() {
+        context.withParameters(HttpParameters.create(new LinkedHashMap<String, Object>() {
             {
                 put("param1", new String[]{"paramValue2"});
                 put("param2", new String[]{"paramValue1"});
@@ -96,7 +93,7 @@ public class ParameterRemoverInterceptorTest extends TestCase {
         interceptor.setParamValues("paramValue1,paramValue2");
         interceptor.intercept(actionInvocation);
 
-        HttpParameters params = (HttpParameters) contextMap.get(ActionContext.PARAMETERS);
+        HttpParameters params = context.getParameters();
         assertEquals(params.keySet().size(), 0);
 
         verify(actionInvocation);
@@ -104,7 +101,7 @@ public class ParameterRemoverInterceptorTest extends TestCase {
 
 
     public void testInterception3() throws Exception {
-        contextMap.put(ActionContext.PARAMETERS, HttpParameters.create(new LinkedHashMap<String, Object>() {
+        context.withParameters(HttpParameters.create(new LinkedHashMap<String, Object>() {
             {
                 put("param1", new String[]{"paramValueOne"});
                 put("param2", new String[]{"paramValueTwo"});
@@ -118,7 +115,7 @@ public class ParameterRemoverInterceptorTest extends TestCase {
         interceptor.setParamValues("paramValue1,paramValue2");
         interceptor.intercept(actionInvocation);
 
-        HttpParameters params = (HttpParameters) contextMap.get(ActionContext.PARAMETERS);
+        HttpParameters params = context.getParameters();
         assertEquals(params.keySet().size(), 2);
         assertTrue(params.contains("param1"));
         assertTrue(params.contains("param2"));
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java
index 245e868ad..6f28dae07 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java
@@ -220,10 +220,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("@java.lang.System@exit(1).dummy", "dumb value");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.MODEL_DRIVEN_PARAM_TEST, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.MODEL_DRIVEN_PARAM_TEST, null, extraContext.getContextMap());
         assertEquals(Action.SUCCESS, proxy.execute());
 
         String property = System.getProperty("xwork.security.test");
@@ -239,10 +238,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         params.put("name", nameVal);
         params.put("count", "15");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.MODEL_DRIVEN_PARAM_TEST, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.MODEL_DRIVEN_PARAM_TEST, null, extraContext.getContextMap());
         assertEquals(Action.SUCCESS, proxy.execute());
 
         ModelDrivenAction action = (ModelDrivenAction) proxy.getAction();
@@ -265,10 +263,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         params.put("('\u0023'%2b'session['user5']')(unused)", "0wn3d");
         params.put("('\\u0023'%2b'session['user5']')(unused)", "0wn3d");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         ValueStack stack = proxy.getInvocation().getStack();
         HashMap<String, Object> session = new HashMap<>();
         stack.getContext().put("session", session);
@@ -340,10 +337,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         params.put("('(aaa)(('\\u0023context[\\'xwork.MethodAccessor.denyMethodExecution\\']\\u003d\\u0023foo')(\\u0023foo\\u003dnew java.lang.Boolean(\"true\")))", "");
         params.put("(asdf)(('\\u0023rt.exit(1)')(\\u0023rt\\u003d@java.lang.Runtime@getRuntime()))", "1");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         ValueStack stack = proxy.getInvocation().getStack();
 
         // when
@@ -361,10 +357,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("blah", "This is blah");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         assertEquals("This is blah", ((SimpleAction) proxy.getAction()).getBlah());
     }
@@ -376,10 +371,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         params.put("theProtectedMap[' p0p1 ']", "test3");
         params.put("theProtectedMap[' p0 p1 ']", "test4");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         Map<String, String> existingMap = ((SimpleAction) proxy.getAction()).getTheProtectedMap();
         assertEquals(0, existingMap.size());
@@ -389,10 +383,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("theProtectedMap['名字']", "test1");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         Map<String, String> existingMap = ((SimpleAction) proxy.getAction()).getTheProtectedMap();
         assertEquals(1, existingMap.size());
@@ -445,10 +438,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
             }
         };
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
 
         ActionConfig config = configuration.getRuntimeConfiguration().getActionConfig("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME);
         ParametersInterceptor pi = (ParametersInterceptor) config.getInterceptors().get(0).getInterceptor();
@@ -476,10 +468,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
             }
         };
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
 
         ActionConfig config = configuration.getRuntimeConfiguration().getActionConfig("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME);
         ParametersInterceptor pi = (ParametersInterceptor) config.getInterceptors().get(0).getInterceptor();
@@ -499,10 +490,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         params.put("protectedMap.foo", "This is blah");
         params.put("theProtectedMap.boo", "This is blah");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         SimpleAction action = (SimpleAction) proxy.getAction();
         assertEquals(1, action.getTheProtectedMap().size());
@@ -515,10 +505,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         params.put("theSemiProtectedMap.foo", "This is blah");
         params.put("theProtectedMap.boo", "This is blah");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         SimpleAction action = (SimpleAction) proxy.getAction();
         assertEquals(1, action.getTheProtectedMap().size());
@@ -539,10 +528,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
             "@java.lang.Runtime@getRuntime().exec('mkdir /tmp/PWNAGE'))(meh)");
         params.put("top['blah'](0)", "true");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         @SuppressWarnings("unused")
         SimpleAction action = (SimpleAction) proxy.getAction();
@@ -557,10 +545,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         Map<String, Object> params = new LinkedHashMap<>();
         params.put("existingMap.boo", "This is blah");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         SimpleAction action = (SimpleAction) proxy.getAction();
         assertEquals(1, action.getTheExistingMap().size());
@@ -576,12 +563,11 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("not_a_property", "There is no action property named like this");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         ActionConfig config = configuration.getRuntimeConfiguration().getActionConfig("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME);
         container.inject(config.getInterceptors().get(0).getInterceptor());
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         final String actionMessage = "" + ((SimpleAction) proxy.getAction()).getActionMessages().toArray()[0];
         assertTrue(actionMessage.contains("Error setting expression 'not_a_property' with value 'There is no action property named like this'"));
@@ -595,12 +581,11 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("not_a_property", "There is no action property named like this");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         ActionConfig config = configuration.getRuntimeConfiguration().getActionConfig("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME);
         container.inject(config.getInterceptors().get(0).getInterceptor());
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         assertTrue(((SimpleAction) proxy.getAction()).getActionMessages().isEmpty());
     }
@@ -763,11 +748,10 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("beanList.name", new String[]{"Superman"});
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         ActionProxy proxy = actionProxyFactory.createActionProxy("",
-            MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext);
+            MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         SimpleAction action = (SimpleAction) proxy.getAction();
         assertNotNull(action);
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptorTest.java
index 6938d30e6..39358f264 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptorTest.java
@@ -124,7 +124,7 @@ public class ScopedModelDrivenInterceptorTest extends XWorkTestCase {
         User user = new User();
         user.setName("King George");
         Map session = new HashMap();
-        ActionContext.getContext().setSession(session);
+        ActionContext.getContext().withSession(session);
         ActionContext.getContext().getSession().put("king", user);
 
         ScopedModelDriven action = new MyUserScopedModelDrivenAction();
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptorTest.java
index 4f996f617..e393ce2cc 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptorTest.java
@@ -130,7 +130,7 @@ public class StaticParametersInterceptorTest extends XWorkTestCase {
 
         User user = new User();
         ActionContext.getContext().getValueStack().push(user);
-        ActionContext.getContext().setParameters(HttpParameters.create().build());
+        ActionContext.getContext().withParameters(HttpParameters.create().build());
         int before = ActionContext.getContext().getValueStack().size();
         interceptor.setMerge("false");
         interceptor.intercept(mai);
@@ -152,7 +152,7 @@ public class StaticParametersInterceptorTest extends XWorkTestCase {
 
         Map<String, String> existingParams = new HashMap<>();
         existingParams.put("name", "Akash");
-        ActionContext.getContext().setParameters(HttpParameters.create(existingParams).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(existingParams).build());
         int before = ActionContext.getContext().getValueStack().size();
 
         interceptor.setOverwrite("true");
@@ -175,7 +175,7 @@ public class StaticParametersInterceptorTest extends XWorkTestCase {
 
         Map<String, String> existingParams = new HashMap<>();
         existingParams.put("name", "Akash");
-        ActionContext.getContext().setParameters(HttpParameters.create(existingParams).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(existingParams).build());
         int before = ActionContext.getContext().getValueStack().size();
 
         interceptor.setOverwrite("false");
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java
index 79a126b2d..642fc348f 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java
@@ -87,7 +87,7 @@ public class ValidationErrorAwareTest extends XWorkTestCase {
         EasyMock.replay(action);
         EasyMock.replay(proxy);
 
-        ActionContext.of(new HashMap<>())
+        ActionContext.of()
             .withActionInvocation(invocation)
             .bind();
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationInterceptorPrefixMethodInvocationTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationInterceptorPrefixMethodInvocationTest.java
index 7e39be087..5799830e5 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationInterceptorPrefixMethodInvocationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationInterceptorPrefixMethodInvocationTest.java
@@ -101,7 +101,7 @@ public class ValidationInterceptorPrefixMethodInvocationTest extends XWorkTestCa
         EasyMock.replay(action);
         EasyMock.replay(proxy);
 
-        ActionContext.of(new HashMap<>())
+        ActionContext.of()
             .withActionInvocation(invocation)
             .bind();
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptorTest.java
index ead2045b2..7f9b6766a 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptorTest.java
@@ -55,8 +55,8 @@ public class AnnotationParameterFilterInterceptorTest extends TestCase {
         parameterMap.put("job", "Baker");
         parameterMap.put("name", "Martin");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create(parameterMap).build());
+        ActionContext actionContext = ActionContext.of().bind();
+        actionContext.withParameters(HttpParameters.create(parameterMap).build());
 
         Action action = new BlockingByDefaultAction();
         stack.push(action);
@@ -92,8 +92,8 @@ public class AnnotationParameterFilterInterceptorTest extends TestCase {
         parameterMap.put("job", "Baker");
         parameterMap.put("name", "Martin");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create(parameterMap).build());
+        ActionContext actionContext = ActionContext.of().bind();
+        actionContext.withParameters(HttpParameters.create(parameterMap).build());
 
         Action action = new AllowingByDefaultAction();
         stack.push(action);
@@ -131,8 +131,8 @@ public class AnnotationParameterFilterInterceptorTest extends TestCase {
         parameterMap.put("m1", "s1");
         parameterMap.put("m2", "s2");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create(parameterMap).build());
+        ActionContext actionContext = ActionContext.of().bind();
+        actionContext.withParameters(HttpParameters.create(parameterMap).build());
         stack.push(new BlockingByDefaultModel());
 
         Mock mockInvocation = new Mock(ActionInvocation.class);
@@ -170,8 +170,8 @@ public class AnnotationParameterFilterInterceptorTest extends TestCase {
         parameterMap.put("m1", "s1");
         parameterMap.put("m2", "s2");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create(parameterMap).build());
+        ActionContext actionContext = ActionContext.of().bind();
+        actionContext.withParameters(HttpParameters.create(parameterMap).build());
         stack.push(new AllowingByDefaultModel());
 
         Mock mockInvocation = new Mock(ActionInvocation.class);
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/MyBeanActionTest.java b/core/src/test/java/com/opensymphony/xwork2/util/MyBeanActionTest.java
index 5921db0dd..f66b85c28 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/MyBeanActionTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/MyBeanActionTest.java
@@ -42,11 +42,10 @@ public class MyBeanActionTest extends XWorkTestCase {
         params.put("annotatedBeanList(1234567890).name", "This is the bla bean by annotation");
         params.put("annotatedBeanList(1234567891).name", "This is the 2nd bla bean by annotation");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", "MyBean", null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", "MyBean", null, extraContext.getContextMap());
             proxy.execute();
             assertEquals(2, Integer.parseInt(proxy.getInvocation().getStack().findValue("beanList.size").toString()));
             assertEquals(MyBean.class.getName(), proxy.getInvocation().getStack().findValue("beanList.get(0)").getClass().getName());
@@ -85,11 +84,10 @@ public class MyBeanActionTest extends XWorkTestCase {
         params.put("annotatedBeanMap[1234567890].name", "This is the bla bean by annotation");
         params.put("annotatedBeanMap[1234567891].name", "This is the 2nd bla bean by annotation");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", "MyBean", null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", "MyBean", null, extraContext.getContextMap());
             proxy.execute();
             MyBeanAction action = (MyBeanAction) proxy.getInvocation().getAction();
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/DateRangeValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/DateRangeValidatorTest.java
index 98a5ed051..e4a8a7369 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/DateRangeValidatorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/DateRangeValidatorTest.java
@@ -44,13 +44,12 @@ public class DateRangeValidatorTest extends XWorkTestCase {
     public void testRangeValidation() throws Exception {
         Calendar date = Calendar.getInstance();
         date.set(2002, Calendar.NOVEMBER, 20);
-        Map<String, Object> context = new HashMap<>();
         HashMap<String, Object> params = new HashMap<>();
         params.put("date", date.getTime());
-        context.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
-        context.put(ActionContext.LOCALE, Locale.US);  // Force US Locale for date conversion tests on JDK9+
+        ActionContext context = ActionContext.of().withParameters(HttpParameters.create(params).build())
+                .withLocale(Locale.US);  // Force US Locale for date conversion tests on JDK9+
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, context);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, context.getContextMap());
         proxy.execute();
         assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/DefaultActionValidatorManagerTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/DefaultActionValidatorManagerTest.java
index 233952c89..c6f4b3d6f 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/DefaultActionValidatorManagerTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/DefaultActionValidatorManagerTest.java
@@ -67,7 +67,7 @@ public class DefaultActionValidatorManagerTest extends XWorkTestCase {
         actionValidatorManager.setValidatorFactory((ValidatorFactory)mockValidatorFactory.proxy());
 
         stubValueStack = new StubValueStack();
-        ActionContext.of(new HashMap<>())
+        ActionContext.of()
             .withValueStack(stubValueStack)
             .bind();
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/DoubleRangeFieldValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/DoubleRangeFieldValidatorTest.java
index 41da48fd3..971517ca6 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/DoubleRangeFieldValidatorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/DoubleRangeFieldValidatorTest.java
@@ -52,12 +52,11 @@ public class DoubleRangeFieldValidatorTest extends XWorkTestCase {
 
     public void testRangeValidationWithError() throws Exception {
         //Explicitly set an out-of-range double for DoubleRangeValidatorTest
-        Map<String, Object> context = new HashMap<>();
         HashMap<String, Object> params = new HashMap<>();
         params.put("percentage", 100.12);
-        context.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext context = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, context);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, context.getContextMap());
         proxy.execute();
         assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
@@ -73,12 +72,11 @@ public class DoubleRangeFieldValidatorTest extends XWorkTestCase {
     }
 
     public void testRangeValidationNoError() throws Exception {
-        Map<String, Object> context = new HashMap<>();
         HashMap<String, Object> params = new HashMap<>();
         params.put("percentage", 1.234567d);
-        context.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext context = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", "percentage", null, context);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", "percentage", null, context.getContextMap());
         proxy.execute();
         assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
@@ -200,12 +198,11 @@ public class DoubleRangeFieldValidatorTest extends XWorkTestCase {
 
     public void testRangeValidationWithExpressionsFail() throws Exception {
         //Explicitly set an out-of-range double for DoubleRangeValidatorTest
-        Map<String, Object> context = new HashMap<>();
         HashMap<String, Object> params = new HashMap<>();
         params.put("percentage", 100.12);
-        context.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext context = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.EXPRESSION_VALIDATION_ACTION, null, context);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.EXPRESSION_VALIDATION_ACTION, null, context.getContextMap());
         proxy.execute();
         assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
@@ -311,7 +308,7 @@ public class DoubleRangeFieldValidatorTest extends XWorkTestCase {
         loadConfigurationProviders(provider, new MockConfigurationProvider());
         val = new DoubleRangeFieldValidator();
         val.setValueStack(ActionContext.getContext().getValueStack());
-        ActionContext.getContext().setParameters(HttpParameters.create().build());
+        ActionContext.getContext().withParameters(HttpParameters.create().build());
         tpf = container.getInstance(TextProviderFactory.class);
     }
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/ExpressionValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/ExpressionValidatorTest.java
index 500824cf8..2569ca68d 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/ExpressionValidatorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/ExpressionValidatorTest.java
@@ -71,10 +71,9 @@ public class ExpressionValidatorTest extends XWorkTestCase {
         params.put("foo", "5");
         params.put("bar", "7");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         assertTrue(((ValidationAware) proxy.getAction()).hasActionErrors());
 
@@ -94,10 +93,9 @@ public class ExpressionValidatorTest extends XWorkTestCase {
         params.put("foo", "10");
         params.put("bar", "7");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext.getContextMap());
         proxy.execute();
         assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/IntRangeValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/IntRangeValidatorTest.java
index fefece9a9..f42af3ee6 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/IntRangeValidatorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/IntRangeValidatorTest.java
@@ -41,11 +41,10 @@ public class IntRangeValidatorTest extends XWorkTestCase {
         HashMap<String, String> params = new HashMap<>();
         params.put("bar", "5");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext.getContextMap());
             proxy.execute();
             assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/LongRangeValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/LongRangeValidatorTest.java
index 4a24ca8b4..560c5d50f 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/LongRangeValidatorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/LongRangeValidatorTest.java
@@ -38,11 +38,10 @@ public class LongRangeValidatorTest extends XWorkTestCase {
         HashMap<String, String> params = new HashMap<>();
         params.put("longFoo", "200");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext.getContextMap());
             proxy.execute();
             assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/ModelDrivenValidationTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/ModelDrivenValidationTest.java
index af594617b..6014b279b 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/ModelDrivenValidationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/ModelDrivenValidationTest.java
@@ -44,13 +44,12 @@ public class ModelDrivenValidationTest extends XWorkTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("count", new String[]{"11"});
 
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext context = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         XmlConfigurationProvider provider = new StrutsXmlConfigurationProvider("xwork-sample.xml");
         container.inject(provider);
         loadConfigurationProviders(provider);
-        ActionProxy proxy = actionProxyFactory.createActionProxy(null, "TestModelDrivenValidation", null, context);
+        ActionProxy proxy = actionProxyFactory.createActionProxy(null, "TestModelDrivenValidation", null, context.getContextMap());
         assertEquals(Action.SUCCESS, proxy.execute());
 
         ModelDrivenAction action = (ModelDrivenAction) proxy.getAction();
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/ShortRangeValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/ShortRangeValidatorTest.java
index abada8f3d..aa176c978 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/ShortRangeValidatorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/ShortRangeValidatorTest.java
@@ -38,11 +38,10 @@ public class ShortRangeValidatorTest extends XWorkTestCase {
         HashMap<String, Object> params = new HashMap<>();
         params.put("shortFoo", "200");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext.getContextMap());
             proxy.execute();
             assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
index b2e1f2a48..76f9a24ab 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
@@ -54,7 +54,7 @@ public class SimpleActionValidationTest extends XWorkTestCase {
         params.put("date", "12/23/2002");
         params.put("percentage", "1.23456789");
 
-        Map<String, Object> extraContext = ActionContext.of(new HashMap<>())
+        Map<String, Object> extraContext = ActionContext.of()
             .withParameters(HttpParameters.create(params).build())
             .bind()
             .getContextMap();
@@ -67,7 +67,7 @@ public class SimpleActionValidationTest extends XWorkTestCase {
             assertFalse(validationAware.hasFieldErrors());
 
             params.put("bar", "42");
-            extraContext = ActionContext.of(new HashMap<>())
+            extraContext = ActionContext.of()
                 .withParameters(HttpParameters.create(params).build())
                 .bind()
                 .getContextMap();
@@ -106,11 +106,10 @@ public class SimpleActionValidationTest extends XWorkTestCase {
         //valid values
         params.put("bar", "7");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext.getContextMap());
             proxy.execute();
             assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
@@ -131,11 +130,10 @@ public class SimpleActionValidationTest extends XWorkTestCase {
         HashMap<String, Object> params = new HashMap<>();
         params.put("foo", "200");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext.getContextMap());
             ValueStack stack = ActionContext.getContext().getValueStack();
             stack.getActionContext().withLocale(Locale.US);
 
@@ -183,11 +181,10 @@ public class SimpleActionValidationTest extends XWorkTestCase {
         HashMap<String, Object> params = new HashMap<>();
         params.put("bar", "42");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext.getContextMap());
             proxy.execute();
             assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
@@ -218,11 +215,10 @@ public class SimpleActionValidationTest extends XWorkTestCase {
         // this should cause a message
         params.put("bean.count", "100");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         try {
-            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_SUBPROPERTY_NAME, null, extraContext);
+            ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_SUBPROPERTY_NAME, null, extraContext.getContextMap());
             proxy.execute();
             assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/ValidatorAnnotationTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/ValidatorAnnotationTest.java
index 100521a35..0bb3195bf 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/ValidatorAnnotationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/ValidatorAnnotationTest.java
@@ -42,10 +42,9 @@ public class ValidatorAnnotationTest extends XWorkTestCase {
         params.put("foo", "5");
         params.put("bar", "7");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", "notAnnotatedMethod", null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", "notAnnotatedMethod", null, extraContext.getContextMap());
         proxy.execute();
         assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
 
@@ -54,11 +53,9 @@ public class ValidatorAnnotationTest extends XWorkTestCase {
     }
 
     public void testNotAnnotatedMethodSuccess2() throws Exception {
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create().build());
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create().build());
-
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", "notAnnotatedMethod", null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", "notAnnotatedMethod", null, extraContext.getContextMap());
         proxy.execute();
         assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
 
@@ -67,11 +64,9 @@ public class ValidatorAnnotationTest extends XWorkTestCase {
     }
 
     public void testAnnotatedMethodFailure() throws Exception {
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create().build());
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create().build());
-
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", "annotatedMethod", null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", "annotatedMethod", null, extraContext.getContextMap());
         proxy.execute();
         assertTrue(((ValidationAware) proxy.getAction()).hasActionErrors());
         Collection errors = ((ValidationAware) proxy.getAction()).getActionErrors();
@@ -88,10 +83,9 @@ public class ValidatorAnnotationTest extends XWorkTestCase {
         params.put("param1", "key1");
         params.put("param2", "key2");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", "annotatedMethod", null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", "annotatedMethod", null, extraContext.getContextMap());
         proxy.execute();
         assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
     }
@@ -102,10 +96,9 @@ public class ValidatorAnnotationTest extends XWorkTestCase {
         //make it not fail
         params.put("param2", "key2");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", "annotatedMethod", null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", "annotatedMethod", null, extraContext.getContextMap());
         proxy.execute();
         assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
     }
@@ -116,10 +109,9 @@ public class ValidatorAnnotationTest extends XWorkTestCase {
         //make it not fail
         params.put("param1", "key1");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
-        ActionProxy proxy = actionProxyFactory.createActionProxy("", "annotatedMethod", null, extraContext);
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", "annotatedMethod", null, extraContext.getContextMap());
         proxy.execute();
         assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
     }
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java b/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java
index 241864aff..d19b77803 100644
--- a/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java
+++ b/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java
@@ -462,10 +462,10 @@ public class DispatcherTest extends StrutsInternalTestCase {
 
         // When
         testDispatcher.prepare(request, response);
-        Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
+        ActionContext context = ActionContext.of(createTestContextMap(testDispatcher, request, response));
 
         // Then
-        assertEquals(Locale.GERMANY, contextMap.get(ActionContext.LOCALE));  // Expect the Dispatcher defaultLocale value "de_DE" from the test configuration.
+        assertEquals(Locale.GERMANY, context.getLocale());  // Expect the Dispatcher defaultLocale value "de_DE" from the test configuration.
         mock.verify();
     }
 
@@ -488,10 +488,10 @@ public class DispatcherTest extends StrutsInternalTestCase {
 
         // When
         testDispatcher.prepare(request, response);
-        Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
+        ActionContext context = ActionContext.of(createTestContextMap(testDispatcher, request, response));
 
         // Then
-        assertEquals(Locale.CANADA_FRENCH, contextMap.get(ActionContext.LOCALE));  // Expect the Dispatcher defaultLocale value.
+        assertEquals(Locale.CANADA_FRENCH, context.getLocale());  // Expect the Dispatcher defaultLocale value.
         mock.verify();
     }
 
@@ -516,10 +516,10 @@ public class DispatcherTest extends StrutsInternalTestCase {
 
         // When
         testDispatcher.prepare(request, response);
-        Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
+        ActionContext context = ActionContext.of(createTestContextMap(testDispatcher, request, response));
 
         // Then
-        assertEquals(Locale.UK, contextMap.get(ActionContext.LOCALE));  // Expect the request set value from Mock.
+        assertEquals(Locale.UK, context.getLocale());  // Expect the request set value from Mock.
         mock.verify();
     }
 
@@ -544,10 +544,10 @@ public class DispatcherTest extends StrutsInternalTestCase {
 
         // When
         testDispatcher.prepare(request, response);
-        Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
+        ActionContext context = ActionContext.of(createTestContextMap(testDispatcher, request, response));
 
         // Then
-        assertEquals(Locale.getDefault(), contextMap.get(ActionContext.LOCALE));  // Expect the system default value, when BOTH Dispatcher default Locale AND request access fail.
+        assertEquals(Locale.getDefault(), context.getLocale());  // Expect the system default value, when BOTH Dispatcher default Locale AND request access fail.
         mock.verify();
     }
 
@@ -574,10 +574,10 @@ public class DispatcherTest extends StrutsInternalTestCase {
 
         // When
         testDispatcher.prepare(request, response);
-        Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
+        ActionContext context = ActionContext.of(createTestContextMap(testDispatcher, request, response));
 
         // Then
-        assertEquals(Locale.CANADA_FRENCH, contextMap.get(ActionContext.LOCALE));  // Expect the request set value from Mock.
+        assertEquals(Locale.CANADA_FRENCH, context.getLocale());  // Expect the request set value from Mock.
         mock.verify();
     }
 
@@ -604,10 +604,10 @@ public class DispatcherTest extends StrutsInternalTestCase {
 
         // When
         testDispatcher.prepare(request, response);
-        Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
+        ActionContext context = ActionContext.of(createTestContextMap(testDispatcher, request, response));
 
         // Then
-        assertEquals(Locale.getDefault(), contextMap.get(ActionContext.LOCALE));  // Expect the system default value when Mock request access fails.
+        assertEquals(Locale.getDefault(), context.getLocale());  // Expect the system default value when Mock request access fails.
         mock.verify();
     }
 
diff --git a/core/src/test/java/org/apache/struts2/interceptor/CheckboxInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CheckboxInterceptorTest.java
index c228d0641..0fe526864 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/CheckboxInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/CheckboxInterceptorTest.java
@@ -29,25 +29,25 @@ import com.opensymphony.xwork2.mock.MockActionInvocation;
 import org.apache.struts2.dispatcher.HttpParameters;
 
 /**
- * Unit test for ChecboxInterceptor. 
+ * Unit test for ChecboxInterceptor.
  */
 public class CheckboxInterceptorTest extends StrutsInternalTestCase {
 
     private CheckboxInterceptor interceptor;
     private MockActionInvocation ai;
     private Map<String, Object> param;
-    
+
     protected void setUp() throws Exception {
     	super.setUp();
     	param = new HashMap<>();
-    	
+
     	interceptor = new CheckboxInterceptor();
     	ai = new MockActionInvocation();
     	ai.setInvocationContext(ActionContext.getContext());
     }
 
 	private void prepare(ActionInvocation ai) {
-		ai.getInvocationContext().setParameters(HttpParameters.create(param).build());
+		ai.getInvocationContext().withParameters(HttpParameters.create(param).build());
 	}
 
 	public void testNoParam() throws Exception {
@@ -68,7 +68,7 @@ public class CheckboxInterceptorTest extends StrutsInternalTestCase {
 		interceptor.init();
 		interceptor.intercept(ai);
 		interceptor.destroy();
-		
+
 		assertEquals(1, ai.getInvocationContext().getParameters().keySet().size());
 	}
 
@@ -81,7 +81,7 @@ public class CheckboxInterceptorTest extends StrutsInternalTestCase {
 		interceptor.init();
 		interceptor.intercept(ai);
 		interceptor.destroy();
-		
+
 		assertEquals(2, ai.getInvocationContext().getParameters().keySet().size());
 	}
 
@@ -204,5 +204,5 @@ public class CheckboxInterceptorTest extends StrutsInternalTestCase {
 		assertEquals("yes", parameters.get("superpower").getValue());
 		assertEquals("no", parameters.get("cool").getValue());
 	}
-	
+
 }
diff --git a/core/src/test/java/org/apache/struts2/interceptor/ClearSessionInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/ClearSessionInterceptorTest.java
index 292864857..8bd4e60dd 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/ClearSessionInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/ClearSessionInterceptorTest.java
@@ -34,15 +34,15 @@ public class ClearSessionInterceptorTest extends StrutsInternalTestCase {
     public void testCreateSession() throws Exception {
         ClearSessionInterceptor interceptor = new ClearSessionInterceptor();
         MockActionInvocation invocation = new MockActionInvocation();
-        ActionContext context = ActionContext.of(new HashMap<>()).bind();
+        ActionContext context = ActionContext.of().bind();
         Map<String, Object> session = new HashMap<>();
         session.put("Test1", "Test1");
         session.put("Test2", "Test2");
         session.put("Test3", "Test3");
-        context.setSession(session);
+        context.withSession(session);
         invocation.setInvocationContext(context);
         interceptor.intercept(invocation);
-        
+
         assertEquals(0, session.size());
     }
 }
diff --git a/core/src/test/java/org/apache/struts2/interceptor/DateTextFieldInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/DateTextFieldInterceptorTest.java
index 5abd10969..d60333529 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/DateTextFieldInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/DateTextFieldInterceptorTest.java
@@ -30,25 +30,25 @@ import com.opensymphony.xwork2.mock.MockActionInvocation;
 import org.apache.struts2.dispatcher.HttpParameters;
 
 /**
- * Unit test for DateTextFieldInterceptor. 
+ * Unit test for DateTextFieldInterceptor.
  */
 public class DateTextFieldInterceptorTest extends StrutsInternalTestCase {
 
     private DateTextFieldInterceptor interceptor;
     private MockActionInvocation ai;
     private Map<String, Object> param;
-    
+
     protected void setUp() throws Exception {
     	super.setUp();
     	param = new HashMap<>();
-    	
+
     	interceptor = new DateTextFieldInterceptor();
     	ai = new MockActionInvocation();
     	ai.setInvocationContext(ActionContext.getContext());
     }
-	
+
 	public void testNoParam() throws Exception {
-		ActionContext.getContext().setParameters(HttpParameters.create(param).build());
+		ActionContext.getContext().withParameters(HttpParameters.create(param).build());
 
 		interceptor.init();
 		interceptor.intercept(ai);
@@ -62,7 +62,7 @@ public class DateTextFieldInterceptorTest extends StrutsInternalTestCase {
 		param.put("__month_name", new String[]{"06"});
 		param.put("__day_name", new String[]{"15"});
 
-		ActionContext.getContext().setParameters(HttpParameters.create(param).build());
+		ActionContext.getContext().withParameters(HttpParameters.create(param).build());
 
 		interceptor.init();
 		interceptor.intercept(ai);
@@ -74,7 +74,7 @@ public class DateTextFieldInterceptorTest extends StrutsInternalTestCase {
 		assertFalse(parameters.contains("__day_name"));
 		assertTrue(parameters.contains("name"));
 		assertEquals(1, parameters.keySet().size());
-		Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2000-06-15"); 
+		Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2000-06-15");
 		assertEquals(date, parameters.get("name").getObject());
 	}
 
diff --git a/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java
index 5c5f6c985..0e6874086 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java
@@ -234,7 +234,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
         mai.setResultCode("success");
         mai.setInvocationContext(ActionContext.getContext());
 
-        ActionContext.getContext().setParameters(HttpParameters.create().build());
+        ActionContext.getContext().withParameters(HttpParameters.create().build());
         ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequestMaxSize(req, 2000));
 
         interceptor.intercept(mai);
@@ -256,7 +256,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
         mai.setResultCode("success");
         mai.setInvocationContext(ActionContext.getContext());
 
-        ActionContext.getContext().setParameters(HttpParameters.create().build());
+        ActionContext.getContext().withParameters(HttpParameters.create().build());
         ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequestMaxSize(req, 2000));
 
         interceptor.intercept(mai);
@@ -287,7 +287,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
         mai.setResultCode("success");
         mai.setInvocationContext(ActionContext.getContext());
         Map<String, Object> param = new HashMap<>();
-        ActionContext.getContext().setParameters(HttpParameters.create(param).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(param).build());
         ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequestMaxSize(req, 2000));
 
         interceptor.intercept(mai);
@@ -348,7 +348,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
         mai.setResultCode("success");
         mai.setInvocationContext(ActionContext.getContext());
         Map<String, Object> param = new HashMap<String, Object>();
-        ActionContext.getContext().setParameters(HttpParameters.create(param).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(param).build());
         ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequestMaxSize(req, 2000));
 
         interceptor.setAllowedTypes("text/html");
@@ -401,7 +401,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
         mai.setResultCode("success");
         mai.setInvocationContext(ActionContext.getContext());
         Map<String, Object> param = new HashMap<>();
-        ActionContext.getContext().setParameters(HttpParameters.create(param).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(param).build());
         ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequestMaxFiles(req, 3));
 
         interceptor.setAllowedTypes("text/html");
@@ -427,7 +427,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
                 "Unit test of FileUploadInterceptor" +
                 "\r\n" +
                 "-----1234--\r\n");
-        req.setContent(content.getBytes("US-ASCII"));
+        req.setContent(content.getBytes(StandardCharsets.US_ASCII));
 
         MyFileupAction action = container.inject(MyFileupAction.class);
 
@@ -466,7 +466,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
                 "Unit test of FileUploadInterceptor" +
                 "\r\n" +
                 "-----1234--\r\n");
-        req.setContent(content.getBytes("US-ASCII"));
+        req.setContent(content.getBytes(StandardCharsets.US_ASCII));
 
         MyFileupAction action = container.inject(MyFileupAction.class);
 
diff --git a/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
index e27ad435a..a8fd8420f 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
@@ -278,7 +278,7 @@ public class I18nInterceptorTest extends TestCase {
         Map<String, Serializable> params = new HashMap<>();
         params.put(key, value);
 
-        mai.getInvocationContext().setParameters(HttpParameters.create(params).build());
+        mai.getInvocationContext().withParameters(HttpParameters.create(params).build());
     }
 
     public void setUp() throws Exception {
@@ -287,7 +287,7 @@ public class I18nInterceptorTest extends TestCase {
         interceptor.init();
         session = new HashMap<>();
 
-        ac = ActionContext.of(new HashMap<>())
+        ac = ActionContext.of()
             .bind()
             .withSession(session)
             .withParameters(HttpParameters.create().build());
diff --git a/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java
index 441309990..e451f59cd 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java
@@ -66,8 +66,8 @@ public class MessageStoreInterceptorTest extends StrutsInternalTestCase {
         action.addActionMessage("some action message 1");
         action.addFieldError("field2", "some field error 2");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create().build());
+        ActionContext actionContext = ActionContext.of().bind();
+        actionContext.withParameters(HttpParameters.create().build());
 
         HttpSession mockedSession = EasyMock.createControl().createMock(HttpSession.class);
         HttpServletRequest mockedRequest = EasyMock.createControl().createMock(HttpServletRequest.class);
@@ -141,9 +141,10 @@ public class MessageStoreInterceptorTest extends StrutsInternalTestCase {
 
         EasyMock.replay(mockedRequest);
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create().build());
-        actionContext.setSession(sessionMap);
+        ActionContext actionContext = ActionContext.of()
+            .withParameters(HttpParameters.create().build())
+            .withSession(sessionMap)
+            .bind();
 
         mockActionInvocation.getInvocationContext();
         EasyMock.expectLastCall().andReturn(actionContext);
@@ -193,9 +194,10 @@ public class MessageStoreInterceptorTest extends StrutsInternalTestCase {
         action.addFieldError("field1", "some field error 1");
         action.addFieldError("field2", "some field error 2");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create().build());
-        actionContext.setSession(sessionMap);
+        ActionContext actionContext = ActionContext.of()
+            .withParameters(HttpParameters.create().build())
+            .withSession(sessionMap)
+            .bind();
 
         HttpSession mockedSession = EasyMock.createControl().createMock(HttpSession.class);
         HttpServletRequest mockedRequest = EasyMock.createControl().createMock(HttpServletRequest.class);
@@ -236,8 +238,8 @@ public class MessageStoreInterceptorTest extends StrutsInternalTestCase {
         Map<String, Object> paramMap = new LinkedHashMap<>();
         paramMap.put("operationMode", new String[]{MessageStoreInterceptor.RETRIEVE_MODE});
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create(paramMap).build());
+        ActionContext actionContext = ActionContext.of().bind();
+        actionContext.withParameters(HttpParameters.create(paramMap).build());
 
         ActionInvocation mockActionInvocation = EasyMock.createControl().createMock(ActionInvocation.class);
         mockActionInvocation.getInvocationContext();
@@ -259,8 +261,8 @@ public class MessageStoreInterceptorTest extends StrutsInternalTestCase {
         Map<String, Object> paramMap = new LinkedHashMap<>();
         paramMap.put("operationMode", new String[]{MessageStoreInterceptor.STORE_MODE});
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create(paramMap).build());
+        ActionContext actionContext = ActionContext.of().bind();
+        actionContext.withParameters(HttpParameters.create(paramMap).build());
 
         ActionInvocation mockActionInvocation = EasyMock.createControl().createMock(ActionInvocation.class);
         mockActionInvocation.getInvocationContext();
@@ -279,8 +281,8 @@ public class MessageStoreInterceptorTest extends StrutsInternalTestCase {
 
     public void testRequestOperationMode3() {
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create().build());
+        ActionContext actionContext = ActionContext.of().bind();
+        actionContext.withParameters(HttpParameters.create().build());
 
         ActionInvocation mockActionInvocation = EasyMock.createControl().createMock(ActionInvocation.class);
         mockActionInvocation.getInvocationContext();
diff --git a/core/src/test/java/org/apache/struts2/interceptor/MessageStorePreResultListenerTest.java b/core/src/test/java/org/apache/struts2/interceptor/MessageStorePreResultListenerTest.java
index 6b85930a1..9fdcf3e27 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/MessageStorePreResultListenerTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/MessageStorePreResultListenerTest.java
@@ -43,8 +43,9 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
 
     public void testSessionWasInvalidated() {
         // given
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create().build());
+        ActionContext actionContext = ActionContext.of()
+            .withParameters(HttpParameters.create().build())
+            .bind();
 
         ActionInvocation mockActionInvocation = EasyMock.createControl().createMock(ActionInvocation.class);
 
@@ -84,8 +85,9 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
 
     public void testResponseWasComitted() {
         // given
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create().build());
+        ActionContext actionContext = ActionContext.of()
+            .withParameters(HttpParameters.create().build())
+            .bind();
 
         ActionInvocation mockActionInvocation = EasyMock.createControl().createMock(ActionInvocation.class);
 
@@ -131,9 +133,10 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
         action.addFieldError("field1", "some field error 1");
         action.addFieldError("field2", "some field error 2");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create().build());
-        actionContext.setSession(sessionMap);
+        ActionContext actionContext = ActionContext.of()
+            .withParameters(HttpParameters.create().build())
+            .withSession(sessionMap)
+            .bind();
 
         HttpSession mockedSession = EasyMock.createControl().createMock(HttpSession.class);
         HttpServletRequest mockedRequest = EasyMock.createControl().createMock(HttpServletRequest.class);
@@ -212,9 +215,10 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
         action.addFieldError("field1", "some field error 1");
         action.addFieldError("field2", "some field error 2");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setParameters(HttpParameters.create().build());
-        actionContext.setSession(sessionMap);
+        ActionContext actionContext = ActionContext.of()
+            .withParameters(HttpParameters.create().build())
+            .withSession(sessionMap)
+            .bind();
 
         HttpSession mockedSession = EasyMock.createControl().createMock(HttpSession.class);
         HttpServletRequest mockedRequest = EasyMock.createControl().createMock(HttpServletRequest.class);
@@ -283,4 +287,4 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
     }
 
 
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/org/apache/struts2/interceptor/MultiselectInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/MultiselectInterceptorTest.java
index 88800e433..43c9a819f 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/MultiselectInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/MultiselectInterceptorTest.java
@@ -44,7 +44,7 @@ public class MultiselectInterceptorTest extends StrutsInternalTestCase {
         interceptor = new MultiselectInterceptor();
         ai = new MockActionInvocation();
         ai.setInvocationContext(ActionContext.getContext());
-        ActionContext.getContext().setParameters(HttpParameters.create(param).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(param).build());
     }
 
     public void testNoParam() throws Exception {
@@ -81,7 +81,7 @@ public class MultiselectInterceptorTest extends StrutsInternalTestCase {
         param.put("__multiselect_superpower", "");
         assertTrue(param.containsKey("__multiselect_superpower"));
 
-        ai.getInvocationContext().setParameters(HttpParameters.create(param).build());
+        ai.getInvocationContext().withParameters(HttpParameters.create(param).build());
 
         interceptor.init();
         interceptor.intercept(ai);
@@ -99,7 +99,7 @@ public class MultiselectInterceptorTest extends StrutsInternalTestCase {
         param.put("__multiselect_superpower", "");
         assertTrue(param.containsKey("__multiselect_superpower"));
 
-        ai.getInvocationContext().setParameters(HttpParameters.create(param).build());
+        ai.getInvocationContext().withParameters(HttpParameters.create(param).build());
 
         interceptor.init();
         interceptor.intercept(ai);
@@ -120,7 +120,7 @@ public class MultiselectInterceptorTest extends StrutsInternalTestCase {
         assertTrue(param.containsKey("__multiselect_superpower"));
         assertTrue(param.containsKey("__multiselect_cool"));
 
-        ai.getInvocationContext().setParameters(HttpParameters.create(param).build());
+        ai.getInvocationContext().withParameters(HttpParameters.create(param).build());
 
         interceptor.init();
         interceptor.intercept(ai);
diff --git a/core/src/test/java/org/apache/struts2/interceptor/ServletConfigInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/ServletConfigInterceptorTest.java
index c95e2c685..dd57019ac 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/ServletConfigInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/ServletConfigInterceptorTest.java
@@ -89,7 +89,7 @@ public class ServletConfigInterceptorTest extends StrutsInternalTestCase {
         MockActionInvocation mai = createActionInvocation(mock);
 
         HttpParameters params = HttpParameters.create().build();
-        mai.getInvocationContext().setParameters(params);
+        mai.getInvocationContext().withParameters(params);
 
         mock.withParameters(params);
         expectLastCall().times(1);
@@ -105,7 +105,7 @@ public class ServletConfigInterceptorTest extends StrutsInternalTestCase {
         MockActionInvocation mai = createActionInvocation(mock);
 
         Map<String, Object> session = new HashMap<String, Object>();
-        mai.getInvocationContext().setSession(session);
+        mai.getInvocationContext().withSession(session);
 
         mock.withSession(session);
         expectLastCall().times(1);
diff --git a/core/src/test/java/org/apache/struts2/interceptor/TokenInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/TokenInterceptorTest.java
index 220804700..7c3624e42 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/TokenInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/TokenInterceptorTest.java
@@ -98,7 +98,7 @@ public class TokenInterceptorTest extends StrutsInternalTestCase {
         request.getParameterMap().put(TokenHelper.DEFAULT_TOKEN_NAME, new String[]{
             token
         });
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext.of(extraContext).withParameters(HttpParameters.create(params).build());
     }
 
     protected void setUp() throws Exception {
@@ -125,7 +125,7 @@ public class TokenInterceptorTest extends StrutsInternalTestCase {
         oldContext = ActionContext.of(stack.getContext()).bind();
     }
 
-    protected ActionProxy buildProxy(String actionName) throws Exception {
+    protected ActionProxy buildProxy(String actionName) {
         return actionProxyFactory.createActionProxy("", actionName, null, extraContext);
     }
 }
diff --git a/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java b/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java
index 2ee6478f5..e8746aa8d 100644
--- a/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java
+++ b/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java
@@ -294,7 +294,7 @@ public class ServletRedirectResultTest extends StrutsInternalTestCase implements
         ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
 
         ValueStack mockValueStack = control.createMock(ValueStack.class);
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).withContainer(container);
+        ActionContext actionContext = ActionContext.of().withContainer(container);
 
         expect(mockInvocation.getStack()).andReturn(mockValueStack);
         expect(mockValueStack.getActionContext()).andReturn(actionContext);
diff --git a/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java b/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java
index b5818123e..f9b4892b0 100644
--- a/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java
+++ b/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java
@@ -69,8 +69,9 @@ public class InvocationSessionStoreTest extends StrutsInternalTestCase {
         ActionContext actionContext = ActionContext.getContext();
         InvocationSessionStore.storeInvocation(INVOCATION_KEY, TOKEN_VALUE, invocation);
 
-        ActionContext actionContext2 = ActionContext.of(new HashMap<>()).bind();
-        actionContext2.setSession(session);
+        ActionContext actionContext2 = ActionContext.of()
+            .withSession(session)
+            .bind();
 
         assertEquals(actionContext2, ActionContext.getContext());
 
@@ -91,7 +92,7 @@ public class InvocationSessionStoreTest extends StrutsInternalTestCase {
         ByteArrayInputStream bais = new ByteArrayInputStream(b);
         ObjectInputStream ois = new ObjectInputStream(bais);
         session = (Map<String, Object>) ois.readObject();
-        ActionContext.getContext().setSession(session);
+        ActionContext.getContext().withSession(session);
         ois.close();
         bais.close();
 
@@ -116,7 +117,7 @@ public class InvocationSessionStoreTest extends StrutsInternalTestCase {
 
         InvocationSessionStore.storeInvocation(INVOCATION_KEY, TOKEN_VALUE, invocation);
 
-        ActionContext actionContext2 = ActionContext.of(new HashMap<>())
+        ActionContext actionContext2 = ActionContext.of()
             .withSession(session)
             .withPageContext(mockPreviousPageContext)
             .bind();
diff --git a/core/src/test/java/org/apache/struts2/util/TokenHelperTest.java b/core/src/test/java/org/apache/struts2/util/TokenHelperTest.java
index e1bd5d78b..4eba8f1b8 100644
--- a/core/src/test/java/org/apache/struts2/util/TokenHelperTest.java
+++ b/core/src/test/java/org/apache/struts2/util/TokenHelperTest.java
@@ -71,7 +71,7 @@ public class TokenHelperTest extends TestCase {
         params.put(TokenHelper.TOKEN_NAME_FIELD, new String[]{tokenName});
         params.put(tokenName, new String[]{token});
 
-        ActionContext.getContext().setParameters(HttpParameters.create(params).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(params).build());
 
         assertTrue(TokenHelper.validToken());
     }
@@ -87,9 +87,10 @@ public class TokenHelperTest extends TestCase {
     protected void setUp() throws Exception {
         session = new HashMap<>();
         Map<String, Object> ctxMap = new TreeMap<>();
-        ActionContext ctx = ActionContext.of(ctxMap).bind();
-        ctx.setSession(session);
-        ctx.setParameters(HttpParameters.create().build());
+        ActionContext ctx = ActionContext.of(ctxMap)
+            .withSession(session)
+            .withParameters(HttpParameters.create().build())
+            .bind();
     }
 
     protected void tearDown() {
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java
index dc35e3646..4d3eb3b3e 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java
@@ -438,7 +438,7 @@ public class ActionTagTest extends AbstractTagTest {
         tag.setNamespace("");
         tag.setName("testActionTagAction");
         tag.setExecuteResult(true);
-        ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInv.proxy());
+        ActionContext.getContext().withActionInvocation((ActionInvocation) mockActionInv.proxy());
 
         ActionInvocation oldInvocation = ActionContext.getContext().getActionInvocation();
         assertNotNull(oldInvocation);
@@ -471,7 +471,7 @@ public class ActionTagTest extends AbstractTagTest {
 
         Map<String, String[]> params = new HashMap<>();
         params.put("user", new String[]{"Santa Claus"});
-        ActionContext.getContext().setParameters(HttpParameters.create(params).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(params).build());
 
         tag.doStartTag();
 
@@ -505,7 +505,7 @@ public class ActionTagTest extends AbstractTagTest {
 
         Map<String, String[]> params = new HashMap<>();
         params.put("user", new String[]{"Santa Claus"});
-        ActionContext.getContext().setParameters(HttpParameters.create(params).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(params).build());
 
         tag.doStartTag();
         setComponentTagClearTagState(tag, true);  // Ensure component tag state clearing is set true (to match tag).
@@ -540,7 +540,7 @@ public class ActionTagTest extends AbstractTagTest {
 
         Map<String, String[]> params = new HashMap<>();
         params.put("user", new String[]{"Santa Claus"});
-        ActionContext.getContext().setParameters(HttpParameters.create(params).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(params).build());
 
         tag.doStartTag();
 
@@ -573,7 +573,7 @@ public class ActionTagTest extends AbstractTagTest {
 
         Map<String, String[]> params = new HashMap<>();
         params.put("user", new String[] { "Santa Claus" });
-        ActionContext.getContext().setParameters(HttpParameters.create(params).build());
+        ActionContext.getContext().withParameters(HttpParameters.create(params).build());
 
         tag.doStartTag();
         setComponentTagClearTagState(tag, true);  // Ensure component tag state clearing is set true (to match tag).
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/NumberTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/NumberTagTest.java
index 0390866f6..c41aabeaf 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/NumberTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/NumberTagTest.java
@@ -55,7 +55,7 @@ public class NumberTagTest extends AbstractTagTest {
 
     public void testSimpleFloatFormat_clearTagStateSet() throws Exception {
         // given
-        context.put(ActionContext.LOCALE, Locale.US);
+        ActionContext.of(context).withLocale(Locale.US);
 
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.0f);
@@ -85,7 +85,7 @@ public class NumberTagTest extends AbstractTagTest {
     public void testSimpleCurrencyUSFormat() throws Exception {
         // given
         context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
-        
+
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.0f);
 
@@ -110,7 +110,7 @@ public class NumberTagTest extends AbstractTagTest {
 
     public void testSimpleCurrencyUSFormat_clearTagStateSet() throws Exception {
         // given
-        context.put(ActionContext.LOCALE, Locale.US);
+        ActionContext.of(context).withLocale(Locale.US);
 
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.0f);
@@ -140,7 +140,7 @@ public class NumberTagTest extends AbstractTagTest {
     public void testSimpleCurrencyPLFormat() throws Exception {
         // given
         context = ActionContext.of(context).withLocale(new Locale("pl", "PL")).getContextMap();
-        
+
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.0f);
 
@@ -170,7 +170,7 @@ public class NumberTagTest extends AbstractTagTest {
 
     public void testSimpleCurrencyPLFormat_clearTagStateSet() throws Exception {
         // given
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        ActionContext.of(context).withLocale(new Locale("pl", "PL"));
 
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.0f);
@@ -187,7 +187,7 @@ public class NumberTagTest extends AbstractTagTest {
         tag.doEndTag();
 
         // then
-        NumberFormat format = NumberFormat.getCurrencyInstance((Locale) context.get(ActionContext.LOCALE));
+        NumberFormat format = NumberFormat.getCurrencyInstance(ActionContext.of(context).getLocale());
         format.setRoundingMode(RoundingMode.CEILING);
         String expected = format.format(120.0f);
 
@@ -234,7 +234,7 @@ public class NumberTagTest extends AbstractTagTest {
 
     public void testSimpleRoundingCeiling_clearTagStateSet() throws Exception {
         // given
-        context.put(ActionContext.LOCALE, Locale.US);
+        ActionContext.of(context).withLocale(new Locale("pl", "PL"));
 
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.45f);
@@ -251,7 +251,7 @@ public class NumberTagTest extends AbstractTagTest {
         tag.doEndTag();
 
         // then
-        NumberFormat format = NumberFormat.getInstance((Locale) context.get(ActionContext.LOCALE));
+        NumberFormat format = NumberFormat.getInstance(ActionContext.of(context).getLocale());
         format.setRoundingMode(RoundingMode.DOWN);
         String expected = format.format(120.45f);
 
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java
index fa153e013..c8e0f2488 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java
@@ -397,8 +397,9 @@ public class TextTagTest extends AbstractTagTest {
         final StringBuffer buffer = writer.getBuffer();
         buffer.delete(0, buffer.length());
         ValueStack newStack = container.getInstance(ValueStackFactory.class).createValueStack();
-        newStack.getContext().put(ActionContext.LOCALE, foreignLocale);
-        newStack.getContext().put(ActionContext.CONTAINER, container);
+        ActionContext.of(newStack.getContext())
+            .withLocale(foreignLocale)
+                .withContainer(container);
         newStack.push(container.inject(TestAction1.class));
         request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, newStack);
         assertNotSame(ActionContext.getContext().getValueStack().peek(), newStack.peek());
@@ -466,7 +467,7 @@ public class TextTagTest extends AbstractTagTest {
         Locale foreignLocale = getForeignLocale();
         assertNotSame(defaultLocale, foreignLocale);
 
-        ActionContext.getContext().setLocale(defaultLocale);
+        ActionContext.getContext().withLocale(defaultLocale);
         String key = "simpleKey";
         String value_default = getLocalizedMessage(defaultLocale);
         tag.setPerformClearTagStateForTagPoolingServers(true);  // Explicitly request tag state clearing.
@@ -489,9 +490,9 @@ public class TextTagTest extends AbstractTagTest {
         String value_int = getLocalizedMessage(foreignLocale);
         assertFalse(value_default.equals(value_int));
         ValueStack newStack = container.getInstance(ValueStackFactory.class).createValueStack(stack);
-        newStack.getContext().put(ActionContext.LOCALE, foreignLocale);
-        newStack.getContext().put(ActionContext.CONTAINER, container);
-        assertNotSame(newStack.getContext().get(ActionContext.LOCALE), ActionContext.getContext().getLocale());
+        ActionContext.of(newStack.getContext())
+            .withLocale(foreignLocale)
+                .withContainer(container);
         request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, newStack);
         assertEquals(ActionContext.getContext().getValueStack().peek(), newStack.peek());
         tag.setName(key);  // Required as WW-5124 fix clears tag state.
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java
index 4bcec0c53..2a06a65b1 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java
@@ -294,22 +294,22 @@ public class URLTagTest extends AbstractUITagTest {
      */
     public void testIterableParameters() throws Exception {
         tag.setValue("/TestAction.action?p0=z");
-        
+
         tag.doStartTag();
         //Iterable
         List<ValueHolder> list = new ArrayList<>();
         list.add(new ValueHolder("a"));
         list.add(new ValueHolder("b"));
         tag.component.addParameter("p1", list);
-        
+
         //String[]
         tag.component.addParameter("p2", new String[] { "d", "e" });
         //ValueHolder[]
         tag.component.addParameter("p3", new ValueHolder[] {
                 new ValueHolder("f"), new ValueHolder("g") });
-        
+
         tag.doEndTag();
-        
+
         assertEquals("/TestAction.action?p0=z&amp;p1=a&amp;p1=b&amp;p2=d&amp;p2=e&amp;p3=f&amp;p3=g", writer.toString());
 
         // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
@@ -1524,11 +1524,11 @@ public class URLTagTest extends AbstractUITagTest {
     public void testEmptyActionCustomMapper() throws Exception {
         Map<String,String> props = new HashMap<>();
         props.put("config", "struts-default.xml,struts-plugin.xml,struts.xml,org/apache/struts2/views/jsp/WW3090-struts.xml");
-        
+
         this.tearDown();
-        
+
         Dispatcher du = this.initDispatcher(props);
-        
+
         /**
          * create our standard mock objects
          */
@@ -1565,7 +1565,7 @@ public class URLTagTest extends AbstractUITagTest {
                 response);
         // let's not set the locale -- there is a test that checks if Dispatcher actually picks this up...
         // ... but generally we want to just use no locale (let it stay system default)
-        extraContext.remove(ActionContext.LOCALE);
+        ActionContext.of(extraContext).withLocale(null);
         stack.getContext().putAll(extraContext);
 
         context.put(ServletActionContext.HTTP_REQUEST, request);
@@ -1577,7 +1577,7 @@ public class URLTagTest extends AbstractUITagTest {
             .withServletResponse(response)
             .withServletContext(servletContext)
             .bind();
-        
+
         // Make sure we have an action invocation available
         ActionContext.getContext().withActionInvocation(new DefaultActionInvocation(null, true));
         DefaultActionProxyFactory apFactory = new DefaultActionProxyFactory();
@@ -1593,9 +1593,9 @@ public class URLTagTest extends AbstractUITagTest {
         tag.setPageContext(pageContext);
         JspWriter jspWriter = new StrutsMockJspWriter(writer);
         pageContext.setJspWriter(jspWriter);
-        
+
         request.setRequestURI("/context/someAction.action");
-        
+
         tag.setAction(null);
         tag.setValue(null);
         tag.doStartTag();
@@ -1610,14 +1610,14 @@ public class URLTagTest extends AbstractUITagTest {
         assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
                 strutsBodyTagsAreReflectionEqual(tag, freshTag));
-        
+
         writer = new StringWriter();
         jspWriter = new StrutsMockJspWriter(writer);
         pageContext.setJspWriter(jspWriter);
-        
+
         tag.doStartTag();
         tag.doEndTag();
-        
+
         assertEquals("/hello.action-blue", writer.toString());
 
         // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
@@ -1625,16 +1625,16 @@ public class URLTagTest extends AbstractUITagTest {
         assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
                 strutsBodyTagsAreReflectionEqual(tag, freshTag));
-        
+
         writer = new StringWriter();
         jspWriter = new StrutsMockJspWriter(writer);
         pageContext.setJspWriter(jspWriter);
-        
+
         tag.doStartTag();
         tag.doEndTag();
-        
+
         assertEquals("/hello.action-red", writer.toString());
-        
+
         // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
         // URLTag clears component in doEndTag and has no additional state set here, so it compares as equal with the default tag clear state as well.
         assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set.  " +
@@ -1645,11 +1645,11 @@ public class URLTagTest extends AbstractUITagTest {
     public void testEmptyActionCustomMapper_clearTagStateSet() throws Exception {
         Map<String,String> props = new HashMap<String, String>();
         props.put("config", "struts-default.xml,struts-plugin.xml,struts.xml,org/apache/struts2/views/jsp/WW3090-struts.xml");
-        
+
         this.tearDown();
-        
+
         Dispatcher du = this.initDispatcher(props);
-        
+
         action = this.getAction();
         stack = ActionContext.getContext().getValueStack();
         context = stack.getContext();
@@ -1708,9 +1708,9 @@ public class URLTagTest extends AbstractUITagTest {
         tag.setPageContext(pageContext);
         JspWriter jspWriter = new StrutsMockJspWriter(writer);
         pageContext.setJspWriter(jspWriter);
-        
+
         request.setRequestURI("/context/someAction.action");
-        
+
         tag.setAction(null);
         tag.setValue(null);
         tag.doStartTag();
@@ -1726,32 +1726,32 @@ public class URLTagTest extends AbstractUITagTest {
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
                 strutsBodyTagsAreReflectionEqual(tag, freshTag));
-        
+
         writer = new StringWriter();
         jspWriter = new StrutsMockJspWriter(writer);
         pageContext.setJspWriter(jspWriter);
-        
+
         tag.doStartTag();
         setComponentTagClearTagState(tag, true);  // Ensure component tag state clearing is set true (to match tag).
         tag.doEndTag();
-        
+
         assertEquals("/hello.action-blue", writer.toString());
 
         // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
                 strutsBodyTagsAreReflectionEqual(tag, freshTag));
-        
+
         writer = new StringWriter();
         jspWriter = new StrutsMockJspWriter(writer);
         pageContext.setJspWriter(jspWriter);
-        
+
         tag.doStartTag();
         setComponentTagClearTagState(tag, true);  // Ensure component tag state clearing is set true (to match tag).
         tag.doEndTag();
-        
+
         assertEquals("/hello.action-red", writer.toString());
-        
+
         // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
@@ -2135,7 +2135,7 @@ public class URLTagTest extends AbstractUITagTest {
             return "Foo is: " + title;
         }
     }
-    
+
     public static class ValueHolder {
         private String value;
 
@@ -2147,13 +2147,13 @@ public class URLTagTest extends AbstractUITagTest {
         public String toString() {
             return value;
         }
-        
-        
+
+
     }
 
     @SuppressWarnings("unused")
     public static class RedBlueActionMapper extends DefaultActionMapper {
-        
+
         @Override
         public String getUriFromActionMapping(ActionMapping mapping) {
             String baseUri = super.getUriFromActionMapping(mapping);
@@ -2168,6 +2168,6 @@ public class URLTagTest extends AbstractUITagTest {
                 return baseUri + "-blue";
             }
         }
-        
+
     }
 }
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java
index d6d62e1a0..64d7ca7e5 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java
@@ -136,7 +136,7 @@ public class HiddenTest extends AbstractUITagTest {
 
         MockActionInvocation ai = new MockActionInvocation();
         ai.setAction(action);
-        ActionContext.getContext().setActionInvocation(ai);
+        ActionContext.getContext().withActionInvocation(ai);
 
         HiddenTag tag = new HiddenTag();
         tag.setPageContext(pageContext);
@@ -167,7 +167,7 @@ public class HiddenTest extends AbstractUITagTest {
 
         MockActionInvocation ai = new MockActionInvocation();
         ai.setAction(action);
-        ActionContext.getContext().setActionInvocation(ai);
+        ActionContext.getContext().withActionInvocation(ai);
 
         HiddenTag tag = new HiddenTag();
         tag.setPerformClearTagStateForTagPoolingServers(true);  // Explicitly request tag state clearing.
diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java b/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
index 6d0abd499..c44ca335a 100644
--- a/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
+++ b/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
@@ -89,7 +89,7 @@ public class PackageBasedActionConfigBuilderTest extends TestCase {
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        ActionContext.of(new HashMap<>())
+        ActionContext.of()
             .withContainer(new DummyContainer())
             .bind();
     }
diff --git a/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java b/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java
index 4a8eee285..128462bb3 100644
--- a/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java
+++ b/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java
@@ -359,7 +359,7 @@ public class EmbeddedJSPResultTest extends TestCase {
 
         EasyMock.replay(container);
 
-        ActionContext.of(new HashMap<>())
+        ActionContext.of()
             .withParameters(HttpParameters.create(params).build())
             .withServletRequest(request)
             .withServletResponse(response)
diff --git a/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/TokenTest.java b/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/TokenTest.java
index d0f0896c3..e1ad3f907 100644
--- a/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/TokenTest.java
+++ b/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/TokenTest.java
@@ -50,8 +50,9 @@ public class TokenTest extends AbstractTest {
         super.setUp();
         this.tag = new Token(stack, request, response);
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setSession(new HashMap<>());
+        ActionContext.of()
+            .withSession(new HashMap<>())
+            .bind();
     }
 
     @Override
diff --git a/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsJUnit4TestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsJUnit4TestCase.java
index e7df6476d..84b76a1b6 100644
--- a/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsJUnit4TestCase.java
+++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsJUnit4TestCase.java
@@ -136,7 +136,7 @@ public abstract class StrutsJUnit4TestCase<T> extends XWorkJUnit4TestCase {
     }
 
     protected void initActionContext(ActionContext actionContext) {
-        actionContext.setParameters(HttpParameters.create(request.getParameterMap()).build());
+        actionContext.withParameters(HttpParameters.create(request.getParameterMap()).build());
         initSession(actionContext);
         // set the action context to the one used by the proxy
         ActionContext.bind(actionContext);
diff --git a/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java
index 6e7c5f93c..80a954f8e 100644
--- a/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java
+++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java
@@ -121,7 +121,7 @@ public class StrutsRestTestCase<T> extends StrutsJUnit4TestCase<T> {
 
         ActionContext invocationContext = proxy.getInvocation().getInvocationContext();
         invocationContext.getContextMap().put(ServletActionContext.ACTION_MAPPING, mapping);
-        invocationContext.setParameters(HttpParameters.create(request.getParameterMap()).build());
+        invocationContext.withParameters(HttpParameters.create(request.getParameterMap()).build());
         // set the action context to the one used by the proxy
         ActionContext.bind(invocationContext);
 
diff --git a/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsTestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsTestCase.java
index f0d9e7ea6..608310838 100644
--- a/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsTestCase.java
+++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsTestCase.java
@@ -119,7 +119,7 @@ public abstract class StrutsTestCase extends XWorkTestCase {
     }
 
     protected void initActionContext(ActionContext actionContext) {
-        actionContext.setParameters(HttpParameters.create(request.getParameterMap()).build());
+        actionContext.withParameters(HttpParameters.create(request.getParameterMap()).build());
         initSession(actionContext);
         applyAdditionalParams(actionContext);
         // set the action context to the one used by the proxy
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java
index b170af376..61b22c281 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java
@@ -136,11 +136,9 @@ public class OsgiConfigurationProvider implements PackageProvider, BundleListene
 
     /**
      * Creates a new empty ActionContext instance and binds it to the current thread.
-     * 
-     * @return 
      */
     protected ActionContext createActionContext() {
-        return ActionContext.of(new HashMap<>()).bind();
+        return ActionContext.of().bind();
     }
 
     /**
diff --git a/plugins/portlet/src/test/java/org/apache/struts2/StrutsTestCasePortletTests.java b/plugins/portlet/src/test/java/org/apache/struts2/StrutsTestCasePortletTests.java
index 56d7cb06f..acea0bec3 100644
--- a/plugins/portlet/src/test/java/org/apache/struts2/StrutsTestCasePortletTests.java
+++ b/plugins/portlet/src/test/java/org/apache/struts2/StrutsTestCasePortletTests.java
@@ -45,7 +45,7 @@ import org.springframework.mock.web.MockServletContext;
  * Changes:  This is a copy of org.apache.struts2.StrutsTestCase from the Struts 2 junit-plugin, kept in
  *           in the same package org.apache.struts2 and renamed.  Removed some unused imports, made
  *           imports alphabetical and made some whitespace changes and modified a comment.
- *           The StrutsTestCasePortletTests is needed in order to break a dependency-cycle between the 
+ *           The StrutsTestCasePortletTests is needed in order to break a dependency-cycle between the
  *           portlet-plugin and junit-plugin with respect to StrutsTestCase.
  *
  * Note:     If the junit-plugin StrutsTestCase is updated/modified, it may be appropriate to update
@@ -130,7 +130,7 @@ public abstract class StrutsTestCasePortletTests extends XWorkTestCase {
     }
 
     protected void initActionContext(ActionContext actionContext) {
-        actionContext.setParameters(HttpParameters.create(request.getParameterMap()).build());
+        actionContext.withParameters(HttpParameters.create(request.getParameterMap()).build());
         initSession(actionContext);
         applyAdditionalParams(actionContext);
         // set the action context to the one used by the proxy
@@ -139,7 +139,7 @@ public abstract class StrutsTestCasePortletTests extends XWorkTestCase {
 
     protected void initSession(ActionContext actionContext) {
         if (actionContext.getSession() == null) {
-            actionContext.setSession(new HashMap<>());
+            actionContext.withSession(new HashMap<>());
             request.setSession(new MockHttpSession(servletContext));
         }
     }
diff --git a/plugins/portlet/src/test/java/org/apache/struts2/portlet/result/PortletResultTest.java b/plugins/portlet/src/test/java/org/apache/struts2/portlet/result/PortletResultTest.java
index 4994a13b0..60946f643 100644
--- a/plugins/portlet/src/test/java/org/apache/struts2/portlet/result/PortletResultTest.java
+++ b/plugins/portlet/src/test/java/org/apache/struts2/portlet/result/PortletResultTest.java
@@ -65,9 +65,10 @@ public class PortletResultTest extends MockObjectTestCase implements StrutsStati
 
         Map<String, Object> sessionMap = new HashMap<>();
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
-        actionContext.setSession(sessionMap);
-        actionContext.setParameters(HttpParameters.create().build());
+        ActionContext actionContext = ActionContext.of()
+            .withSession(sessionMap)
+            .withParameters(HttpParameters.create().build())
+            .bind();
         actionContext.put(STRUTS_PORTLET_CONTEXT, mockCtx.proxy());
 
         mockProxy.stubs().method("getNamespace").will(returnValue("/test"));
@@ -160,7 +161,7 @@ public class PortletResultTest extends MockObjectTestCase implements StrutsStati
         ActionContext ctx = ActionContext.getContext();
 
         Map<String, Object> session = new HashMap<>();
-        ctx.setSession(session);
+        ctx.withSession(session);
 
         ctx.put(REQUEST, mockRequest.proxy());
         ctx.put(RESPONSE, mockResponse.proxy());
diff --git a/plugins/portlet/src/test/java/org/apache/struts2/portlet/util/PortletUrlHelperTest.java b/plugins/portlet/src/test/java/org/apache/struts2/portlet/util/PortletUrlHelperTest.java
index f33f12253..a5dc07b3a 100644
--- a/plugins/portlet/src/test/java/org/apache/struts2/portlet/util/PortletUrlHelperTest.java
+++ b/plugins/portlet/src/test/java/org/apache/struts2/portlet/util/PortletUrlHelperTest.java
@@ -69,7 +69,7 @@ public class PortletUrlHelperTest extends TestCase {
         modeNamespaceMap.put("edit", "/edit");
         modeNamespaceMap.put("help", "/help");
 
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
+        ActionContext actionContext = ActionContext.of().bind();
         actionContext.put(REQUEST, renderRequest);
         actionContext.put(RESPONSE, renderResponse);
         actionContext.put(PHASE, PortletPhase.RENDER_PHASE);
diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/ContentTypeHandlerManagerTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/ContentTypeHandlerManagerTest.java
index 3e2a41e98..8522668c9 100644
--- a/plugins/rest/src/test/java/org/apache/struts2/rest/ContentTypeHandlerManagerTest.java
+++ b/plugins/rest/src/test/java/org/apache/struts2/rest/ContentTypeHandlerManagerTest.java
@@ -58,7 +58,7 @@ public class ContentTypeHandlerManagerTest extends TestCase {
         mockResponse = new MockHttpServletResponse();
         mockRequest = new MockHttpServletRequest();
         mockRequest.setMethod("GET");
-        ActionContext actionContext = ActionContext.of(new HashMap<>()).bind();
+        ActionContext actionContext = ActionContext.of().bind();
         actionContext.withServletRequest(mockRequest);
         actionContext.withServletResponse(mockResponse);
 
@@ -135,7 +135,7 @@ public class ContentTypeHandlerManagerTest extends TestCase {
                 C.eq(ContentTypeHandlerManager.STRUTS_REST_HANDLER_OVERRIDE_PREFIX+"xml")), "xmlOverride");
         mockContainer.expectAndReturn("getInstance", C.args(C.eq(String.class),
                 C.eq(ContentTypeHandlerManager.STRUTS_REST_HANDLER_OVERRIDE_PREFIX+"json")), null);
-        
+
         DefaultContentTypeHandlerManager mgr = new DefaultContentTypeHandlerManager();
         mgr.setContainer((Container) mockContainer.proxy());
 
diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/RestWorkflowInterceptorTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/RestWorkflowInterceptorTest.java
index 45d82e4d6..33e3dd386 100644
--- a/plugins/rest/src/test/java/org/apache/struts2/rest/RestWorkflowInterceptorTest.java
+++ b/plugins/rest/src/test/java/org/apache/struts2/rest/RestWorkflowInterceptorTest.java
@@ -51,7 +51,7 @@ public class RestWorkflowInterceptorTest extends TestCase {
         }, null);
         wf.setContentTypeHandlerManager((ContentTypeHandlerManager) mockContentTypeHandlerManager.proxy());
 
-        ActionContext.of(new HashMap<>())
+        ActionContext.of()
             .withActionMapping(new ActionMapping())
             .bind();
 
diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java
index 0398ebf2e..55351d63d 100644
--- a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java
+++ b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java
@@ -51,7 +51,7 @@ public class JuneauXmlHandlerTest extends XWorkTestCase {
             "</object>";
         handler = new JuneauXmlHandler();
         ai = new MockActionInvocation();
-        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(Locale.US);
+        ActionContext context = ActionContext.of().withLocale(Locale.US);
         ((MockActionInvocation) ai).setInvocationContext(context);
     }
 
@@ -95,4 +95,4 @@ public class JuneauXmlHandlerTest extends XWorkTestCase {
                 .containsExactly("Adam", "Ewa");
     }
 
-}
\ No newline at end of file
+}
diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java
index 732643bdc..3d036d2ee 100644
--- a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java
+++ b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java
@@ -56,7 +56,7 @@ public class XStreamHandlerTest extends XWorkTestCase {
         handler = new XStreamHandler();
         ai = new MockActionInvocation();
         ActionSupport action = new ActionSupport();
-        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(Locale.US);
+        ActionContext context = ActionContext.of().withLocale(Locale.US);
         ai.setInvocationContext(context);
         ai.setAction(action);
     }
diff --git a/plugins/spring/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java b/plugins/spring/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java
index 65a3700af..559f59b98 100644
--- a/plugins/spring/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java
+++ b/plugins/spring/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java
@@ -135,11 +135,10 @@ public class ActionsFromSpringTest extends XWorkTestCase {
         params.put("exposeProxy", "true");
         params.put("issueId", "S2-047");
 
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+        ActionContext extraContext = ActionContext.of().withParameters(HttpParameters.create(params).build());
 
         ActionProxy proxy = actionProxyFactory.createActionProxy(null,
-            "chaintoAOPedTestSubBeanAction", null, extraContext);
+            "chaintoAOPedTestSubBeanAction", null, extraContext.getContextMap());
 
         // when
         proxy.execute();
diff --git a/plugins/spring/src/test/java/com/opensymphony/xwork2/spring/interceptor/ActionAutowiringInterceptorTest.java b/plugins/spring/src/test/java/com/opensymphony/xwork2/spring/interceptor/ActionAutowiringInterceptorTest.java
index 970c3ee8d..10697f3fc 100644
--- a/plugins/spring/src/test/java/com/opensymphony/xwork2/spring/interceptor/ActionAutowiringInterceptorTest.java
+++ b/plugins/spring/src/test/java/com/opensymphony/xwork2/spring/interceptor/ActionAutowiringInterceptorTest.java
@@ -110,7 +110,7 @@ public class ActionAutowiringInterceptorTest extends XWorkTestCase {
     }
 
     public void testIfApplicationContextIsNullThenBeanWillNotBeWiredUp() throws Exception {
-        ActionContext.of(new HashMap<>())
+        ActionContext.of()
             .withApplication(new HashMap<>())
             .bind();
 
diff --git a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
index 4c801f4aa..a1e1c69d7 100644
--- a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
+++ b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
@@ -76,7 +76,7 @@ import org.apache.tiles.request.servlet.ServletUtil;
  *
  *
  * <!-- START SNIPPET: tilesconfig -->
- * You have to configure tiles itself. Therefore you can add <code>tiles.xml</code> either 
+ * You have to configure tiles itself. Therefore you can add <code>tiles.xml</code> either
  * to resources or WEB-INF. You may also use annotations like {@link TilesDefinition}.
  *
  * <!-- END SNIPPET: tilesconfig -->
@@ -109,7 +109,7 @@ public class TilesResult extends ServletDispatcherResult {
         StrutsTilesAnnotationProcessor annotationProcessor = new StrutsTilesAnnotationProcessor();
         TilesDefinition tilesDefinition = null;
         Object action = invocation.getAction();
-        String actionName = invocation.getInvocationContext().getName();
+        String actionName = invocation.getInvocationContext().getActionName();
 
         if (StringUtils.isEmpty(location)) {
             LOG.trace("location not set -> action must have one @TilesDefinition");