Merge pull request #684 from apache/dependabot/maven/org.testng-testng-7.5.1

Bump testng from 7.5 to 7.5.1
diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java b/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
index 4fc70bb..4f72330 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 @@
         }
         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 5fd676b..fb7b0ab 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 @@
  */
 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 @@
 
     /**
      * 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
@@ -158,6 +130,15 @@
     }
 
     /**
+     * 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
      *
      * @param actionContext context to bind to the thread
@@ -211,13 +192,7 @@
      * 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 @@
      * 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 @@
      * 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 @@
      * 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 @@
 
         if (locale == null) {
             locale = Locale.getDefault();
-            setLocale(locale);
+            withLocale(locale);
         }
 
         return locale;
@@ -336,14 +293,8 @@
     /**
      * 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;
@@ -354,15 +305,6 @@
      *
      * @return the name of the current action.
      */
-    public String getName() {
-        return (String) get(ACTION_NAME);
-    }
-
-    /**
-     * Gets the name of the current Action.
-     *
-     * @return the name of the current action.
-     */
     public String getActionName() {
         return (String) get(ACTION_NAME);
     }
@@ -372,10 +314,6 @@
      *
      * @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 @@
      * 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;
@@ -421,14 +353,8 @@
     /**
      * Sets the OGNL value stack.
      *
-     * @param stack the OGNL value stack.
-     * @deprecated Use {@link #withValueStack(ValueStack)} instead
+     * @param valueStack the OGNL value stack.
      */
-    @Deprecated
-    public void setValueStack(ValueStack stack) {
-        put(VALUE_STACK, stack);
-    }
-
     public ActionContext withValueStack(ValueStack valueStack) {
         put(VALUE_STACK, valueStack);
         return this;
@@ -446,14 +372,8 @@
     /**
      * 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 ec7a8d7..402af38 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 @@
     }
 
     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 61d4b83..e60550c 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 @@
  * <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 @@
  * &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 @@
  *              &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 @@
  *      &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 @@
  *      &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 @@
  * <!-- 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 @@
                 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 @@
 
     /**
      * Handles the logging of the exception.
-     * 
+     *
      * @param e the exception to log.
      */
     protected void handleLogging(Exception e) {
@@ -231,10 +231,10 @@
     		doLog(LOG, e);
     	}
     }
-    
+
     /**
      * Performs the actual logging.
-     * 
+     *
      * @param logger  the provided logger to use.
      * @param e  the exception to log.
      */
@@ -243,7 +243,7 @@
     		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/NoParameters.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/NoParameters.java
index 6c918d0..4657380 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/NoParameters.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/NoParameters.java
@@ -30,7 +30,8 @@
  * parameters cannot be set by malicious users.
  * </p>
  *
- * @author Dick Zetterberg (dick@transitor.se)
+ * @deprecated since Struts 6.2.0, use {@link org.apache.struts2.action.NoParameters}
  */
+@Deprecated
 public interface NoParameters {
 }
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 3f0414a..b695c7b 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 @@
  * <!-- 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 @@
  * </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 @@
  *   &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 @@
  * &lt;/action&gt;
  * <!-- END SNIPPET: example -->
  * </pre>
- * 
+ *
  * @author Gabe
  */
 public class ParameterFilterInterceptor extends AbstractInterceptor {
@@ -133,7 +133,7 @@
             }
         }
 
-        invocation.getInvocationContext().setParameters(parameters);
+        invocation.getInvocationContext().withParameters(parameters);
 
         return invocation.invoke();
     }
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java
index 1003be9..c0f8376 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java
@@ -23,120 +23,102 @@
 import com.opensymphony.xwork2.util.TextParseUtil;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.apache.struts2.dispatcher.Parameter;
+import org.apache.struts2.action.NoParameters;
 import org.apache.struts2.dispatcher.HttpParameters;
+import org.apache.struts2.dispatcher.Parameter;
 
 import java.util.Collections;
 import java.util.Set;
 
 /**
- * <!-- START SNIPPET: description -->
  * This is a simple XWork interceptor that allows parameters (matching
- * one of the paramNames attribute csv value) to be 
+ * one of the paramNames attribute csv value) to be
  * removed from the parameter map if they match a certain value
- * (matching one of the paramValues attribute csv value), before they 
- * are set on the action. A typical usage would be to want a dropdown/select 
- * to map onto a boolean value on an action. The select had the options 
- * none, yes and no with values -1, true and false. The true and false would 
- * map across correctly. However the -1 would be set to false. 
- * This was not desired as one might needed the value on the action to stay null. 
- * This interceptor fixes this by preventing the parameter from ever reaching 
+ * (matching one of the paramValues attribute csv value), before they
+ * are set on the action. A typical usage would be to want a dropdown/select
+ * to map onto a boolean value on an action. The select had the options
+ * none, yes and no with values -1, true and false. The true and false would
+ * map across correctly. However the -1 would be set to false.
+ * This was not desired as one might needed the value on the action to stay null.
+ * This interceptor fixes this by preventing the parameter from ever reaching
  * the action.
- * <!-- END SNIPPET: description -->
- * 
- * 
- * <!-- START SNIPPET: parameters -->
+ *
  * <ul>
- * 	<li>paramNames - A comma separated value (csv) indicating the parameter name 
- * 								    whose param value should be considered that if they match any of the
- *                                     comma separated value (csv) from paramValues attribute, shall be 
- *                                     removed from the parameter map such that they will not be applied
- *                                     to the action</li>
- * 	<li>paramValues - A comma separated value (csv) indicating the parameter value that if 
- * 							      matched shall have its parameter be removed from the parameter map 
- * 							      such that they will not be applied to the action</li>
+ * 	<li>paramNames - A comma separated value (csv) indicating the parameter name
+ *                   whose param value should be considered that if they match any of the
+ *                   comma separated value (csv) from paramValues attribute, shall be
+ *                   removed from the parameter map such that they will not be applied
+ *                   to the action</li>
+ * 	<li>paramValues - A comma separated value (csv) indicating the parameter value that if
+ *                    matched shall have its parameter be removed from the parameter map
+ *                    such that they will not be applied to the action</li>
  * </ul>
- * <!-- END SNIPPET: parameters -->
- * 
- * 
- * <!-- START SNIPPET: extending -->
+ * <p>
  * No intended extension point
- * <!-- END SNIPPET: extending -->
- * 
+ *
  * <pre>
- * <!-- START SNIPPET: example -->
- *	
  * &lt;action name="sample" class="org.martingilday.Sample"&gt;
  * 	&lt;interceptor-ref name="paramRemover"&gt;
- *   		&lt;param name="paramNames"&gt;aParam,anotherParam&lt;/param&gt;
- *   		&lt;param name="paramValues"&gt;--,-1&lt;/param&gt;
+ *          &lt;param name="paramNames"&gt;aParam,anotherParam&lt;/param&gt;
+ *          &lt;param name="paramValues"&gt;--,-1&lt;/param&gt;
  * 	&lt;/interceptor-ref&gt;
  * 	&lt;interceptor-ref name="defaultStack" /&gt;
  * 	...
  * &lt;/action&gt;
- *  
- * <!-- END SNIPPET: example -->
  * </pre>
- *  
- *  
- * @author martin.gilday
  */
 public class ParameterRemoverInterceptor extends AbstractInterceptor {
 
-	private static final Logger LOG = LogManager.getLogger(ParameterRemoverInterceptor.class);
+    private static final Logger LOG = LogManager.getLogger(ParameterRemoverInterceptor.class);
 
-	private static final long serialVersionUID = 1;
+    private Set<String> paramNames = Collections.emptySet();
+    private Set<String> paramValues = Collections.emptySet();
 
-	private Set<String> paramNames = Collections.emptySet();
-	private Set<String> paramValues = Collections.emptySet();
+    /**
+     * Decide if the parameter should be removed from the parameter map based on
+     * <code>paramNames</code> and <code>paramValues</code>.
+     *
+     * @see com.opensymphony.xwork2.interceptor.AbstractInterceptor
+     */
+    @Override
+    public String intercept(ActionInvocation invocation) throws Exception {
+        if (!(invocation.getAction() instanceof NoParameters)
+            && (null != this.paramNames)) {
+            ActionContext ac = invocation.getInvocationContext();
+            HttpParameters parameters = ac.getParameters();
 
-	
-	/**
-	 * Decide if the parameter should be removed from the parameter map based on
-	 * <code>paramNames</code> and <code>paramValues</code>.
-	 * 
-	 * @see com.opensymphony.xwork2.interceptor.AbstractInterceptor
-	 */
-	@Override
-	public String intercept(ActionInvocation invocation) throws Exception {
-		if (!(invocation.getAction() instanceof NoParameters)
-				&& (null != this.paramNames)) {
-			ActionContext ac = invocation.getInvocationContext();
-			HttpParameters parameters = ac.getParameters();
-
-			if (parameters != null) {
+            if (parameters != null) {
                 for (String removeName : paramNames) {
-					try {
-						Parameter parameter = parameters.get(removeName);
-						if (parameter.isDefined() && this.paramValues.contains(parameter.getValue())) {
-							parameters.remove(removeName);
-						}
-					} catch (Exception e) {
-						LOG.error("Failed to convert parameter to string", e);
-					}
+                    try {
+                        Parameter parameter = parameters.get(removeName);
+                        if (parameter.isDefined() && this.paramValues.contains(parameter.getValue())) {
+                            parameters.remove(removeName);
+                        }
+                    } catch (Exception e) {
+                        LOG.error("Failed to convert parameter to string", e);
+                    }
                 }
-			}
-		}
-		return invocation.invoke();
-	}
+            }
+        }
+        return invocation.invoke();
+    }
 
-	/**
-	 * Allows <code>paramNames</code> attribute to be set as comma-separated-values (csv).
-	 * 
-	 * @param paramNames the paramNames to set
-	 */
-	public void setParamNames(String paramNames) {
-		this.paramNames = TextParseUtil.commaDelimitedStringToSet(paramNames);
-	}
+    /**
+     * Allows <code>paramNames</code> attribute to be set as comma-separated-values (csv).
+     *
+     * @param paramNames the paramNames to set
+     */
+    public void setParamNames(String paramNames) {
+        this.paramNames = TextParseUtil.commaDelimitedStringToSet(paramNames);
+    }
 
+    /**
+     * Allows <code>paramValues</code> attribute to be set as a comma-separated-values (csv).
+     *
+     * @param paramValues the paramValues to set
+     */
+    public void setParamValues(String paramValues) {
+        this.paramValues = TextParseUtil.commaDelimitedStringToSet(paramValues);
+    }
 
-	/**
-	 * Allows <code>paramValues</code> attribute to be set as a comma-separated-values (csv).
-	 * 
-	 * @param paramValues the paramValues to set
-	 */
-	public void setParamValues(String paramValues) {
-		this.paramValues = TextParseUtil.commaDelimitedStringToSet(paramValues);
-	}
 }
-
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 f4079b8..9d32a8a 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 @@
             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 4fc6b1f..8309d61 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 @@
             }
         }
 
-        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 d21bcb4..9e488a9 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 @@
 
         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/interceptor/NoParameters.java b/core/src/main/java/org/apache/struts2/action/NoParameters.java
similarity index 96%
rename from core/src/main/java/org/apache/struts2/interceptor/NoParameters.java
rename to core/src/main/java/org/apache/struts2/action/NoParameters.java
index c42aa80..80424a5 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/NoParameters.java
+++ b/core/src/main/java/org/apache/struts2/action/NoParameters.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.interceptor;
+package org.apache.struts2.action;
 
 /**
  * This marker interface should be implemented by actions that do not want any parameters set on
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 74780a1..f7c3ad7 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 @@
                                                 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 79cd0cc..69aa708 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 @@
 
     /**
      * 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 @@
         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 a3bbfaf..6bc8672 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 @@
                 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/main/resources/template/simple/datetext.ftl b/core/src/main/resources/template/simple/datetextfield.ftl
similarity index 92%
rename from core/src/main/resources/template/simple/datetext.ftl
rename to core/src/main/resources/template/simple/datetextfield.ftl
index 6d8396c..c43a338 100644
--- a/core/src/main/resources/template/simple/datetext.ftl
+++ b/core/src/main/resources/template/simple/datetextfield.ftl
@@ -18,4 +18,4 @@
  * under the License.
  */
 -->
-<#lt/><div>Tag <pre style="display: inline-block">&lt;s:datetext/&gt;</pre> works only with the JavaTemplates Plugin!</div><#rt/>
+<#lt/><div>Tag <pre style="display: inline-block">&lt;s:datetextfield/&gt;</pre> works only with the JavaTemplates Plugin!</div><#rt/>
diff --git a/core/src/main/resources/template/xhtml/datetext.ftl b/core/src/main/resources/template/xhtml/datetextfield.ftl
similarity index 93%
rename from core/src/main/resources/template/xhtml/datetext.ftl
rename to core/src/main/resources/template/xhtml/datetextfield.ftl
index d15b24a..3efeab4 100644
--- a/core/src/main/resources/template/xhtml/datetext.ftl
+++ b/core/src/main/resources/template/xhtml/datetextfield.ftl
@@ -19,5 +19,5 @@
  */
 -->
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
-<#include "/${parameters.templateDir}/simple/datetext.ftl" />
+<#include "/${parameters.templateDir}/simple/datetextfield.ftl" />
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/site/resources/tags/datetextfield.html b/core/src/site/resources/tags/datetextfield.html
index 330c3df..daec66f 100644
--- a/core/src/site/resources/tags/datetextfield.html
+++ b/core/src/site/resources/tags/datetextfield.html
@@ -12,7 +12,10 @@
 		<h2>Description</h2>
 		<p>
 		<!-- START SNIPPET: tagdescription -->
-		Render an HTML input fields with the date time
+		Render an HTML input fields with the date time.
+		<br/>
+		<br/>
+		<b>Hint:</b> This tag works only with the JavaTemplates plugin see <a href="https://struts.apache.org/plugins/javatemplates/ for more details.">the plugin documentation</a> for more details.
 		<!-- END SNIPPET: tagdescription -->
 		</p>
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java b/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
index f5f9af2..bf86971 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 @@
         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 de0b5c1..454e02d 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 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 e0f13c4..9b8ac87 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 @@
         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 cc4f017..4ef2ad8 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 @@
         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 0a357e8..65c38d3 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 @@
         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 6ad6b84..db6e21b 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 @@
         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 39c598a..511e6a8 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 @@
     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 3c962a4..d1fd7e2 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 @@
 
 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 @@
     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 7d46932..b52b9d4 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 @@
 
         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 @@
         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 @@
         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 @@
         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 @@
         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 cf91282..3218729 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 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 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 @@
         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 @@
         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 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 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 @@
         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 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 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 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 a1fb332..bef05ca 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 @@
         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 @@
 
         Locale locale = new Locale("pl", "PL");
 
-        ActionContext context = ActionContext.of(new HashMap<>())
+        ActionContext context = ActionContext.of()
             .withLocale(locale)
             .withValueStack(stack);
 
@@ -102,7 +102,7 @@
 
         Locale locale = new Locale("fr", "FR");
 
-        ActionContext context = ActionContext.of(new HashMap<>())
+        ActionContext context = ActionContext.of()
             .withLocale(locale)
             .withValueStack(stack);
 
@@ -121,7 +121,7 @@
 
         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 9ca0e0e..192fe87 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.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 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 @@
         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 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 @@
         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 @@
         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 @@
         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 00e9141..16108ef 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 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 d809e4b..0c6fd27 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 @@
         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 d2a0f83..628c069 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 @@
         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 d14b2b8..5ef177d 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 @@
         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 79b23ce..da7cefc 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 @@
         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 928d13f..60131d9 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 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 @@
  */
 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 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 @@
         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 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 @@
         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 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 @@
         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 245e868..6f28dae 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 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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 @@
             }
         };
 
-        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 @@
             }
         };
 
-        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 @@
         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 @@
         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 @@
             "@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 @@
         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 @@
         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 @@
         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 @@
         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 6938d30..39358f2 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 @@
         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 4f996f6..e393ce2 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 @@
 
         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 @@
 
         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 @@
 
         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 79a126b..642fc34 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 @@
         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 7e39be0..5799830 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 @@
         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 ead2045..7f9b676 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 @@
         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 @@
         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 @@
         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 @@
         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 5921db0..f66b85c 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 @@
         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 @@
         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 98a5ed0..e4a8a73 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 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 233952c..c6f4b3d 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 @@
         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 41da48f..971517c 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 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 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 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 @@
         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 500824c..2569ca6 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 @@
         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 @@
         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 fefece9..f42af3e 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 @@
         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 4a24ca8..560c5d5 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 @@
         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 af59461..6014b27 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 @@
         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 abada8f..aa176c9 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 @@
         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 b2e1f2a..76f9a24 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 @@
         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 @@
             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 @@
         //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 @@
         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 @@
         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 @@
         // 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 100521a..0bb3195 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 @@
         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 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 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 @@
         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 @@
         //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 @@
         //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 241864a..d19b778 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 @@
 
         // 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 @@
 
         // 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 @@
 
         // 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 @@
 
         // 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 @@
 
         // 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 @@
 
         // 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 c228d06..0fe5268 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 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 @@
 		interceptor.init();
 		interceptor.intercept(ai);
 		interceptor.destroy();
-		
+
 		assertEquals(1, ai.getInvocationContext().getParameters().keySet().size());
 	}
 
@@ -81,7 +81,7 @@
 		interceptor.init();
 		interceptor.intercept(ai);
 		interceptor.destroy();
-		
+
 		assertEquals(2, ai.getInvocationContext().getParameters().keySet().size());
 	}
 
@@ -204,5 +204,5 @@
 		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 2928648..8bd4e60 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 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 5abd109..d603335 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 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 @@
 		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 @@
 		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 5c5f6c9..0e68740 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 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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 @@
                 "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 @@
                 "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 e27ad43..a8fd842 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 @@
         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 @@
         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 4413099..e451f59 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 @@
         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 @@
 
         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 @@
         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 @@
         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 @@
         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 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 6b85930..9fdcf3e 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 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 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 @@
         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 @@
         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 @@
     }
 
 
-}
\ 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 88800e4..43c9a81 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 @@
         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 @@
         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 @@
         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 @@
         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 c95e2c6..dd57019 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 @@
         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 @@
         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 2208047..7c3624e 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 @@
         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 @@
         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 2ee6478..e8746aa 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 @@
         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 b581812..f9b4892 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 @@
         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 @@
         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 @@
 
         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 e1bd5d7..4eba8f1 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 @@
         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 @@
     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 dc35e36..4d3eb3b 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 @@
         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 @@
 
         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 @@
 
         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 @@
 
         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 @@
 
         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 0390866..c41aabe 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 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 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 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 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 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 @@
         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 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 @@
         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 fa153e0..c8e0f24 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 @@
         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 @@
         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 @@
         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 4bcec0c..2a06a65 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 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 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 @@
                 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 @@
             .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 @@
         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 @@
         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 @@
         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 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 @@
         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 @@
         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 @@
             return "Foo is: " + title;
         }
     }
-    
+
     public static class ValueHolder {
         private String value;
 
@@ -2147,13 +2147,13 @@
         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 @@
                 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 d6d62e1..64d7ca7 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 @@
 
         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 @@
 
         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 6d0abd4..c44ca33 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 @@
     @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 4a8eee2..128462b 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 @@
 

         EasyMock.replay(container);

 

-        ActionContext.of(new HashMap<>())

+        ActionContext.of()

             .withParameters(HttpParameters.create(params).build())

             .withServletRequest(request)

             .withServletResponse(response)

diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/TextAreaHandler.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/TextAreaHandler.java
index 6274096..6b1cfa1 100644
--- a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/TextAreaHandler.java
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/TextAreaHandler.java
@@ -41,7 +41,9 @@
                 .addIfExists("id", params.get("id"))
                 .addIfExists("class", params.get("cssClass"))
                 .addIfExists("style", params.get("cssStyle"))
-                .addIfExists("title", params.get("title"));
+                .addIfExists("title", params.get("title"))
+                .addIfExists("minlength", params.get("minlength"))
+                .addIfExists("maxlength", params.get("maxlength"));
         start("textarea", attrs);
         String value = (String) params.get("nameValue");
         if (StringUtils.isNotEmpty(value))
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 d0f0896..e1ad3f9 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 @@
         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 e7df647..84b76a1 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 @@
     }
 
     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 6e7c5f9..80a954f 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 @@
 
         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 f0d9e7e..6083108 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 @@
     }
 
     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 b170af3..61b22c2 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 @@
 
     /**
      * 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 56d7cb0..acea0be 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 @@
  * 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 @@
     }
 
     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 @@
 
     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 4994a13..60946f6 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 @@
 

         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 @@
         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 f33f122..a5dc07b 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 @@
         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 3e2a41e..8522668 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 @@
         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 @@
                 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 45d82e4..33e3dd3 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 @@
         }, 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 0398ebf..55351d6 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 @@
             "</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 @@
                 .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 732643b..3d036d2 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 @@
         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 65a3700..559f59b 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 @@
         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 970c3ee..10697f3 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 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 4c801f4..a1e1c69 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 @@
  *
  *
  * <!-- 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 @@
         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");