You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2020/04/21 18:27:24 UTC

[struts] branch action-context-boost updated: WW-4789 WW-3788 Marks LOCALE as deprecated on behalf using helper methods

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

lukaszlenart pushed a commit to branch action-context-boost
in repository https://gitbox.apache.org/repos/asf/struts.git


The following commit(s) were added to refs/heads/action-context-boost by this push:
     new 2f27e45  WW-4789 WW-3788 Marks LOCALE as deprecated on behalf using helper methods
2f27e45 is described below

commit 2f27e45ef47f0531d7ce45806b5e0e85255ee8be
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Tue Apr 21 20:27:11 2020 +0200

    WW-4789 WW-3788 Marks LOCALE as deprecated on behalf using helper methods
---
 .../com/opensymphony/xwork2/ActionContext.java     | 100 +++++++++++++++++----
 .../opensymphony/xwork2/TextProviderSupport.java   |   4 +-
 .../com/opensymphony/xwork2/XWorkTestCase.java     |  12 ++-
 .../conversion/impl/DefaultTypeConverter.java      |   2 +-
 .../xwork2/interceptor/AliasInterceptor.java       |   2 +-
 .../xwork2/interceptor/ParametersInterceptor.java  |   2 +-
 .../interceptor/StaticParametersInterceptor.java   |   2 +-
 .../struts2/util/InvocationSessionStore.java       |   2 +-
 .../com/opensymphony/xwork2/ActionSupportTest.java |  14 +--
 .../xwork2/CompositeTextProviderTest.java          |   2 +-
 .../xwork2/DefaultTextProviderTest.java            |   3 +-
 .../com/opensymphony/xwork2/LocaleAwareTest.java   |   4 +-
 .../impl/AnnotationXWorkConverterTest.java         |   5 +-
 .../conversion/impl/NumberConverterTest.java       |  42 ++++-----
 .../conversion/impl/StringConverterTest.java       |  18 ++--
 .../conversion/impl/XWorkBasicConverterTest.java   |  25 ++----
 .../xwork2/conversion/impl/XWorkConverterTest.java |  22 ++---
 .../com/opensymphony/xwork2/ognl/OgnlUtilTest.java |   8 +-
 .../util/StrutsLocalizedTextProviderTest.java      |   2 +-
 ...notationValidationConfigurationBuilderTest.java |   2 +-
 .../validator/SimpleActionValidationTest.java      |   3 +-
 .../validators/DateRangeFieldValidatorTest.java    |  10 ++-
 .../apache/struts2/components/ComponentTest.java   |   2 +-
 .../interceptor/FileUploadInterceptorTest.java     |   8 +-
 .../struts2/interceptor/I18nInterceptorTest.java   |   2 +-
 .../apache/struts2/views/jsp/AbstractTagTest.java  |   5 +-
 .../apache/struts2/views/jsp/NumberTagTest.java    |  14 +--
 .../org/apache/struts2/views/jsp/TextTagTest.java  |   4 +-
 .../org/apache/struts2/views/jsp/URLTagTest.java   |   3 +-
 .../struts2/rest/handler/JuneauXmlHandlerTest.java |   3 +-
 30 files changed, 191 insertions(+), 136 deletions(-)

diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
index 8900aef..5fd676b 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
@@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletResponse;
 import javax.servlet.jsp.PageContext;
 import java.io.Serializable;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.Locale;
 import java.util.Map;
 
@@ -71,6 +70,7 @@ public class ActionContext implements Serializable {
 
     /**
      * Constant for the {@link com.opensymphony.xwork2.util.ValueStack OGNL value stack}.
+     *
      * @deprecated scope will be narrowed to "private", use helper methods instead
      */
     @Deprecated
@@ -78,6 +78,7 @@ public class ActionContext implements Serializable {
 
     /**
      * Constant for the action's session.
+     *
      * @deprecated scope will be narrowed to "private", use helper methods instead
      */
     @Deprecated
@@ -85,6 +86,7 @@ public class ActionContext implements Serializable {
 
     /**
      * Constant for the action's application context.
+     *
      * @deprecated scope will be narrowed to "private", use helper methods instead
      */
     @Deprecated
@@ -92,6 +94,7 @@ public class ActionContext implements Serializable {
 
     /**
      * Constant for the action's parameters.
+     *
      * @deprecated scope will be narrowed to "private", use helper methods instead
      */
     @Deprecated
@@ -99,11 +102,15 @@ public class ActionContext implements Serializable {
 
     /**
      * 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";
 
     /**
      * Constant for the action's {@link com.opensymphony.xwork2.ActionInvocation invocation} context.
+     *
      * @deprecated scope will be narrowed to "private", use helper methods instead
      */
     @Deprecated
@@ -111,6 +118,7 @@ public class ActionContext implements Serializable {
 
     /**
      * Constant for the map of type conversion errors.
+     *
      * @deprecated scope will be narrowed to "private", use helper methods instead
      */
     @Deprecated
@@ -118,6 +126,7 @@ public class ActionContext implements Serializable {
 
     /**
      * Constant for the container
+     *
      * @deprecated scope will be narrowed to "private", use helper methods instead
      */
     @Deprecated
@@ -295,11 +304,18 @@ public class ActionContext implements Serializable {
      * Sets the Locale for the current action.
      *
      * @param locale the Locale for the current action.
+     * @deprecated use {@link #withLocale(Locale)} instead
      */
+    @Deprecated
     public void setLocale(Locale locale) {
         put(LOCALE, locale);
     }
 
+    public ActionContext withLocale(Locale locale) {
+        put(LOCALE, locale);
+        return this;
+    }
+
     /**
      * Gets the Locale of the current action. If no locale was ever specified the platform's
      * {@link java.util.Locale#getDefault() default locale} is used.
@@ -481,60 +497,112 @@ public class ActionContext implements Serializable {
         context.put(key, value);
     }
 
+    /**
+     * Gets ServletContext associated with current action
+     *
+     * @return current ServletContext
+     */
     public ServletContext getServletContext() {
         return (ServletContext) get(StrutsStatics.SERVLET_CONTEXT);
     }
 
+    /**
+     * Assigns ServletContext to action context
+     *
+     * @param servletContext associated with current request
+     * @return ActionContext
+     */
     public ActionContext withServletContext(ServletContext servletContext) {
         put(StrutsStatics.SERVLET_CONTEXT, servletContext);
         return this;
     }
 
+    /**
+     * Gets ServletRequest associated with current action
+     *
+     * @return current ServletRequest
+     */
     public HttpServletRequest getServletRequest() {
         return (HttpServletRequest) get(StrutsStatics.HTTP_REQUEST);
     }
 
+    /**
+     * Assigns ServletRequest to action context
+     *
+     * @param request associated with current request
+     * @return ActionContext
+     */
     public ActionContext withServletRequest(HttpServletRequest request) {
         put(StrutsStatics.HTTP_REQUEST, request);
         return this;
     }
 
+    /**
+     * Gets ServletResponse associated with current action
+     *
+     * @return current ServletResponse
+     */
     public HttpServletResponse getServletResponse() {
         return (HttpServletResponse) get(StrutsStatics.HTTP_RESPONSE);
     }
 
+    /**
+     * Assigns ServletResponse to action context
+     *
+     * @param response associated with current request
+     * @return ActionContext
+     */
     public ActionContext withServletResponse(HttpServletResponse response) {
         put(StrutsStatics.HTTP_RESPONSE, response);
         return this;
     }
 
+    /**
+     * Gets PageContext associated with current action
+     *
+     * @return current PageContext
+     */
     public PageContext getPageContext() {
         return (PageContext) get(StrutsStatics.PAGE_CONTEXT);
     }
 
+    /**
+     * Assigns PageContext to action context
+     *
+     * @param pageContext associated with current request
+     * @return ActionContext
+     */
     public ActionContext withPageContext(PageContext pageContext) {
         put(StrutsStatics.PAGE_CONTEXT, pageContext);
         return this;
     }
 
+    /**
+     * Gets ActionMapping associated with current action
+     *
+     * @return current ActionMapping
+     */
     public ActionMapping getActionMapping() {
         return (ActionMapping) get(StrutsStatics.ACTION_MAPPING);
     }
 
+    /**
+     * Assigns ActionMapping to action context
+     *
+     * @param actionMapping associated with current request
+     * @return ActionContext
+     */
     public ActionContext withActionMapping(ActionMapping actionMapping) {
         put(StrutsStatics.ACTION_MAPPING, actionMapping);
         return this;
     }
 
-    public ActionContext usePageContextOrClear(ActionContext actionContext) {
-        if (actionContext == null) {
-            put(StrutsStatics.PAGE_CONTEXT, null);
-        } else {
-            put(StrutsStatics.PAGE_CONTEXT, actionContext.getPageContext());
-        }
-        return this;
-    }
-
+    /**
+     * Assigns an extra context map to action context
+     *
+     * @param extraContext to add to the current action context
+     * @return ActionContext
+     */
     public ActionContext withExtraContext(Map<String, Object> extraContext) {
         if (extraContext != null) {
             context.putAll(extraContext);
@@ -542,11 +610,13 @@ public class ActionContext implements Serializable {
         return this;
     }
 
-    public ActionContext withLocale(Locale locale) {
-        put(LOCALE, locale);
-        return this;
-    }
-
+    /**
+     * Adds arbitrary key to action context
+     *
+     * @param key   a string
+     * @param value an object
+     * @return ActionContext
+     */
     public ActionContext with(String key, Object value) {
         put(key, value);
         return this;
diff --git a/core/src/main/java/com/opensymphony/xwork2/TextProviderSupport.java b/core/src/main/java/com/opensymphony/xwork2/TextProviderSupport.java
index abb3249..7f8afbc 100644
--- a/core/src/main/java/com/opensymphony/xwork2/TextProviderSupport.java
+++ b/core/src/main/java/com/opensymphony/xwork2/TextProviderSupport.java
@@ -254,7 +254,7 @@ public class TextProviderSupport implements ResourceBundleTextProvider {
         if (stack == null){
         	locale = getLocale();
         }else{
-        	locale = (Locale) stack.getContext().get(ActionContext.LOCALE);
+        	locale = stack.getActionContext().getLocale();
         }
         if (locale == null) {
             locale = getLocale();
@@ -284,7 +284,7 @@ public class TextProviderSupport implements ResourceBundleTextProvider {
         if (stack == null){
         	locale = getLocale();
         }else{
-        	locale = (Locale) stack.getContext().get(ActionContext.LOCALE);
+        	locale = stack.getActionContext().getLocale();
         }
         if (locale == null) {
             locale = getLocale();
diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
index bc6b0a8..330e964 100644
--- a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
+++ b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
@@ -29,6 +29,10 @@ import com.opensymphony.xwork2.util.location.LocatableProperties;
 import junit.framework.TestCase;
 import org.apache.commons.lang3.ClassUtils;
 
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
 /**
  * Base JUnit TestCase to extend for XWork specific JUnit tests. Uses 
  * the generic test setup for logic.
@@ -96,5 +100,11 @@ public abstract class XWorkTestCase extends TestCase {
             }
         });
     }
-    
+
+    protected Map<String, Object> createContextWithLocale(Locale locale) {
+        return ActionContext.of(new HashMap<>())
+            .withLocale(locale)
+            .getContextMap();
+    }
+
 }
diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java
index 731b8f5..6665654 100644
--- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java
+++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java
@@ -324,7 +324,7 @@ public abstract class DefaultTypeConverter implements TypeConverter {
     protected Locale getLocale(Map<String, Object> context) {
         Locale locale = null;
         if (context != null) {
-            locale = (Locale) context.get(ActionContext.LOCALE);
+            locale = ActionContext.of(context).getLocale();
         }
         if (locale == null) {
             LocaleProviderFactory localeProviderFactory = container.getInstance(LocaleProviderFactory.class);
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java
index 44cdd51..992bf94 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java
@@ -158,7 +158,7 @@ public class AliasInterceptor extends AbstractInterceptor {
                     ReflectionContextState.setReportingConversionErrors(context, true);
 
                     //keep locale from original context
-                    context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
+                    newStack.getActionContext().withLocale(stack.getActionContext().getLocale());
                 }
 
                 // override
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
index c3d67d3..1310588 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
@@ -192,7 +192,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
             ReflectionContextState.setReportingConversionErrors(context, true);
 
             //keep locale from original context
-            context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
+            newStack.getActionContext().withLocale(stack.getActionContext().getLocale());
         }
 
         boolean memberAccessStack = newStack instanceof MemberAccessValueStack;
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 14fba78..9f0f117 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java
@@ -164,7 +164,7 @@ public class StaticParametersInterceptor extends AbstractInterceptor {
                     ReflectionContextState.setReportingConversionErrors(context, true);
 
                     //keep locale from original context
-                    context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
+                    newStack.getActionContext().withLocale(stack.getActionContext().getLocale());
                 }
 
                 for (Map.Entry<String, String> entry : parameters.entrySet()) {
diff --git a/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java b/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java
index 93a5ca1..c9fe66e 100644
--- a/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java
+++ b/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java
@@ -64,7 +64,7 @@ public class InvocationSessionStore {
 
             savedInvocation
                 .getInvocationContext()
-                .usePageContextOrClear(previousActionContext)
+                .withPageContext(previousActionContext.getPageContext())
                 .withValueStack(savedInvocation.getStack())
                 .bind();
         }
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java b/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
index 1443d95..0a357e8 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
@@ -39,7 +39,7 @@ public class ActionSupportTest extends XWorkTestCase {
         as = new ActionSupport();
         container.inject(as);
 
-        ActionContext.getContext().setLocale(new Locale("da"));
+        ActionContext.getContext().withLocale(new Locale("da"));
 
         mas = new MyActionSupport();
         container.inject(mas);
@@ -150,13 +150,13 @@ public class ActionSupportTest extends XWorkTestCase {
 
     public void testLocale() {
         Locale defLocale = Locale.getDefault();
-        ActionContext.getContext().setLocale(null);
+        ActionContext.getContext().withLocale(null);
 
         // will never return null, if no locale is set then default is returned
         assertNotNull(as.getLocale());
         assertEquals(defLocale, as.getLocale());
 
-        ActionContext.getContext().setLocale(Locale.ITALY);
+        ActionContext.getContext().withLocale(Locale.ITALY);
         assertEquals(Locale.ITALY, as.getLocale());
 
         ActionContext.of(new HashMap<>()).bind();
@@ -177,7 +177,7 @@ public class ActionSupportTest extends XWorkTestCase {
     }
 
     public void testSimpleGetTextsWithInjectedTextProvider() {
-        ActionContext.getContext().setLocale(new Locale("da"));
+        ActionContext.getContext().withLocale(new Locale("da"));
         MyActionSupport mas = new MyActionSupport();
 
         TextProvider textProvider = container.getInstance(TextProvider.class, "system");
@@ -253,7 +253,7 @@ public class ActionSupportTest extends XWorkTestCase {
     }
 
     public void testGetTextsWithListAndStack() {
-        ActionContext.getContext().setLocale(new Locale("da"));
+        ActionContext.getContext().withLocale(new Locale("da"));
         MyActionSupport mas = container.inject(MyActionSupport.class);
 
         ValueStack stack = ActionContext.getContext().getValueStack();
@@ -271,7 +271,7 @@ public class ActionSupportTest extends XWorkTestCase {
     }
 
     public void testGetTextsWithArrayAndStack() {
-        ActionContext.getContext().setLocale(new Locale("da"));
+        ActionContext.getContext().withLocale(new Locale("da"));
         MyActionSupport mas = container.inject(MyActionSupport.class);
 
         ValueStack stack = ActionContext.getContext().getValueStack();
@@ -303,7 +303,7 @@ public class ActionSupportTest extends XWorkTestCase {
 
     public void testFormattingSupportWithConversionError() {
         ActionContext.getContext().getConversionErrors().put("val", new ConversionData(new String[]{"4567def"}, Double.class));
-        ActionContext.getContext().setLocale(new Locale("da"));
+        ActionContext.getContext().withLocale(new Locale("da"));
         MyActionSupport mas = new MyActionSupport();
         container.inject(mas);
         ActionContext.getContext().getValueStack().push(mas);
diff --git a/core/src/test/java/com/opensymphony/xwork2/CompositeTextProviderTest.java b/core/src/test/java/com/opensymphony/xwork2/CompositeTextProviderTest.java
index 37f0073..0237b65 100644
--- a/core/src/test/java/com/opensymphony/xwork2/CompositeTextProviderTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/CompositeTextProviderTest.java
@@ -97,7 +97,7 @@ public class CompositeTextProviderTest extends XWorkTestCase {
 
         TextProviderFactory tpf = container.getInstance(TextProviderFactory.class);
 
-        ActionContext.getContext().setLocale(Locale.ENGLISH);
+        ActionContext.getContext().withLocale(Locale.ENGLISH);
 
         textProvider = new CompositeTextProvider(new TextProvider[]{
                 tpf.createInstance(ResourceBundle.getBundle("com.opensymphony.xwork2.validator.CompositeTextProviderTestResourceBundle1")),
diff --git a/core/src/test/java/com/opensymphony/xwork2/DefaultTextProviderTest.java b/core/src/test/java/com/opensymphony/xwork2/DefaultTextProviderTest.java
index 60a2c0c..39c598a 100644
--- a/core/src/test/java/com/opensymphony/xwork2/DefaultTextProviderTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/DefaultTextProviderTest.java
@@ -129,8 +129,7 @@ public class DefaultTextProviderTest extends XWorkTestCase {
     protected void setUp() throws Exception {
         super.setUp();
 
-        ActionContext ctx = ActionContext.of(new HashMap<>()).bind();
-        ctx.setLocale(Locale.CANADA);
+        ActionContext.of(new HashMap<>()).withLocale(Locale.CANADA).bind();
 
         container.getInstance(LocalizedTextProvider.class).addDefaultResourceBundle(DefaultTextProviderTest.class.getName());
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/LocaleAwareTest.java b/core/src/test/java/com/opensymphony/xwork2/LocaleAwareTest.java
index c43bd6e..f7c9506 100644
--- a/core/src/test/java/com/opensymphony/xwork2/LocaleAwareTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/LocaleAwareTest.java
@@ -37,7 +37,7 @@ public class LocaleAwareTest extends XWorkTestCase {
     public void testGetText() {
         try {
             ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.FOO_ACTION_NAME, null, null);
-            ActionContext.getContext().setLocale(Locale.US);
+            ActionContext.getContext().withLocale(Locale.US);
 
             TextProvider localeAware = (TextProvider) proxy.getAction();
             assertEquals("Foo Range Message", localeAware.getText("foo.range"));
@@ -50,7 +50,7 @@ public class LocaleAwareTest extends XWorkTestCase {
     public void testLocaleGetText() {
         try {
             ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.FOO_ACTION_NAME, null, null);
-            ActionContext.getContext().setLocale(Locale.GERMANY);
+            ActionContext.getContext().withLocale(Locale.GERMANY);
 
             TextProvider localeAware = (TextProvider) proxy.getAction();
             assertEquals("I don't know German", localeAware.getText("foo.range"));
diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/AnnotationXWorkConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/AnnotationXWorkConverterTest.java
index a4e501b..e9b0247 100644
--- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/AnnotationXWorkConverterTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/AnnotationXWorkConverterTest.java
@@ -209,7 +209,7 @@ public class AnnotationXWorkConverterTest extends XWorkTestCase {
         Locale locale = Locale.GERMANY;
         DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
         String dateString = df.format(date);
-        context.put(ActionContext.LOCALE, locale);
+        context = ActionContext.of(context).withLocale(locale).getContextMap();
         assertEquals(dateString, converter.convertValue(context, null, null, null, date, String.class));
     }
 
@@ -471,8 +471,7 @@ public class AnnotationXWorkConverterTest extends XWorkTestCase {
         super.setUp();
         converter = container.getInstance(XWorkConverter.class);
 
-        ac = ActionContext.getContext();
-        ac.setLocale(Locale.US);
+        ac = ActionContext.getContext().withLocale(Locale.US);
         context = ac.getContextMap();
     }
 
diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java
index 698afd8..2b6f34b 100644
--- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java
@@ -18,14 +18,11 @@
  */
 package com.opensymphony.xwork2.conversion.impl;
 
-import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.SimpleFooAction;
 import com.opensymphony.xwork2.XWorkTestCase;
 import org.apache.commons.lang3.StringUtils;
 
 import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
@@ -34,8 +31,7 @@ public class NumberConverterTest extends XWorkTestCase {
     public void testStringToNumberConversionPL() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         SimpleFooAction foo = new SimpleFooAction();
 
@@ -49,8 +45,7 @@ public class NumberConverterTest extends XWorkTestCase {
     public void testStringToNumberConversionUS() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("en", "US"));
+        Map<String, Object> context = createContextWithLocale(new Locale("en", "US"));
 
         SimpleFooAction foo = new SimpleFooAction();
 
@@ -64,12 +59,11 @@ public class NumberConverterTest extends XWorkTestCase {
     public void testStringToBigDecimalConversionPL() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when a bit bigger than double
         String aBitBiggerThanDouble = "17976931348623157" + StringUtils.repeat('0', 291) + "1,"
-                + StringUtils.repeat('0', 324) + "49";
+            + StringUtils.repeat('0', 324) + "49";
         Object value = converter.convertValue(context, null, null, null, aBitBiggerThanDouble, BigDecimal.class);
 
         // then does not lose integer and fraction digits
@@ -79,8 +73,7 @@ public class NumberConverterTest extends XWorkTestCase {
     public void testStringToBigDecimalConversionWithDotsPL() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when
         Object value = converter.convertValue(context, null, null, null, "1 234,4", BigDecimal.class);
@@ -88,12 +81,11 @@ public class NumberConverterTest extends XWorkTestCase {
         // then
         assertEquals(BigDecimal.valueOf(1234.4), value);
     }
-    
+
     public void testStringToBigDecimalConversionWithCommasEN() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("en", "US"));
+        Map<String, Object> context = createContextWithLocale(new Locale("en", "US"));
 
         // when
         Object value = converter.convertValue(context, null, null, null, "100,234.4", BigDecimal.class);
@@ -105,19 +97,18 @@ public class NumberConverterTest extends XWorkTestCase {
     public void testStringToDoubleConversionPL() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when has max fraction digits
         Object value = converter.convertValue(context, null, null, null,
-                "0," + StringUtils.repeat('0', 323) + "49", Double.class);
+            "0," + StringUtils.repeat('0', 323) + "49", Double.class);
 
         // then does not lose fraction digits
         assertEquals(Double.MIN_VALUE, value);
 
         // when has max integer digits
         value = converter.convertValue(context, null, null, null,
-                "17976931348623157" + StringUtils.repeat('0', 292) + ",0", Double.class);
+            "17976931348623157" + StringUtils.repeat('0', 292) + ",0", Double.class);
 
         // then does not lose integer digits
         assertEquals(Double.MAX_VALUE, value);
@@ -126,8 +117,7 @@ public class NumberConverterTest extends XWorkTestCase {
     public void testStringToDoubleConversionWithDotsPL() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when
         Object value = converter.convertValue(context, null, null, null, "1 234,4", Double.class);
@@ -139,19 +129,18 @@ public class NumberConverterTest extends XWorkTestCase {
     public void testStringToFloatConversionPL() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when has max fraction digits
         Object value = converter.convertValue(context, null, null, null,
-                "0," + StringUtils.repeat('0', 44) + "1401298464324817", Float.class);
+            "0," + StringUtils.repeat('0', 44) + "1401298464324817", Float.class);
 
         // then does not lose fraction digits
         assertEquals(Float.MIN_VALUE, value);
 
         // when has max integer digits
         value = converter.convertValue(context, null, null, null,
-                "34028234663852886" + StringUtils.repeat('0', 22) + ",0", Float.class);
+            "34028234663852886" + StringUtils.repeat('0', 22) + ",0", Float.class);
 
         // then does not lose integer digits
         assertEquals(Float.MAX_VALUE, value);
@@ -160,8 +149,7 @@ public class NumberConverterTest extends XWorkTestCase {
     public void testStringToFloatConversionWithDotsPL() throws Exception {
         // given
         NumberConverter converter = new NumberConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when
         Object value = converter.convertValue(context, null, null, null, "1 234,4", Float.class);
diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/StringConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/StringConverterTest.java
index b565dd1..8eef6d1 100644
--- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/StringConverterTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/StringConverterTest.java
@@ -32,8 +32,7 @@ public class StringConverterTest extends StrutsInternalTestCase {
     public void testIntegerToStringConversionPL() throws Exception {
         // given
         StringConverter converter = new StringConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when
         Object value = converter.convertValue(context, null, null, null, Integer.MIN_VALUE, null);
@@ -45,8 +44,7 @@ public class StringConverterTest extends StrutsInternalTestCase {
     public void testDoubleToStringConversionPL() throws Exception {
         // given
         StringConverter converter = new StringConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when has max fraction digits
         Object value = converter.convertValue(context, null, null, null, Double.MIN_VALUE, null);
@@ -70,8 +68,7 @@ public class StringConverterTest extends StrutsInternalTestCase {
     public void testFloatToStringConversionPL() throws Exception {
         // given
         StringConverter converter = new StringConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when has max fraction digits
         Object value = converter.convertValue(context, null, null, null, Float.MIN_VALUE, null);
@@ -95,8 +92,7 @@ public class StringConverterTest extends StrutsInternalTestCase {
     public void testBigDecimalToStringConversionPL() throws Exception {
         // given
         StringConverter converter = new StringConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when a bit bigger than double
         String aBitBiggerThanDouble = "17976931348623157" + StringUtils.repeat('0', 291) + "1."
@@ -111,8 +107,7 @@ public class StringConverterTest extends StrutsInternalTestCase {
     public void testStringArrayToStringConversion() {
         // given
         StringConverter converter = new StringConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when
         Object value = converter.convertValue(context, null, null, null, new String[] {"foo", "baz"}, null);
@@ -124,8 +119,7 @@ public class StringConverterTest extends StrutsInternalTestCase {
     public void testArrayOfNullToStringConversion() {
         // given
         StringConverter converter = new StringConverter();
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
 
         // when
         Object value = converter.convertValue(context, null, null, null, new String[] {null}, null);
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 72b26e0..5c67924 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
@@ -60,12 +60,11 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
 
     public void testDateWithLocalePoland() throws Exception {
 
-        Map<String, Object> map = new HashMap<>();
         Locale locale = new Locale("pl", "PL");
-        map.put(ActionContext.LOCALE, locale);
+        Map<String, Object> context = createContextWithLocale(locale);
 
         String reference = "2009-01-09";
-        Object convertedObject = basicConverter.convertValue(map, null, null, null, reference, Date.class);
+        Object convertedObject = basicConverter.convertValue(context, null, null, null, reference, Date.class);
 
         assertNotNull(convertedObject);
 
@@ -73,13 +72,11 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
     }
 
     public void testDateWithLocaleFrance() throws Exception {
-
-        Map<String, Object> map = new HashMap<>();
         Locale locale = new Locale("fr", "FR");
-        map.put(ActionContext.LOCALE, locale);
+        Map<String, Object> context = createContextWithLocale(locale);
 
         String reference = "09/01/2009";
-        Object convertedObject = basicConverter.convertValue(map, null, null, null, reference, Date.class);
+        Object convertedObject = basicConverter.convertValue(context, null, null, null, reference, Date.class);
 
         assertNotNull(convertedObject);
 
@@ -87,13 +84,11 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
     }
 
     public void testDateWithLocaleUK() throws Exception {
-
-        Map<String, Object> map = new HashMap<>();
         Locale locale = new Locale("en", "US");
-        map.put(ActionContext.LOCALE, locale);
+        Map<String, Object> context = createContextWithLocale(locale);
 
         String reference = "01/09/2009";
-        Object convertedObject = basicConverter.convertValue(map, null, null, null, reference, Date.class);
+        Object convertedObject = basicConverter.convertValue(context, null, null, null, reference, Date.class);
 
         assertNotNull(convertedObject);
 
@@ -133,9 +128,7 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
 
     public void testXW490ConvertStringToDouble() throws Exception {
         Locale locale = new Locale("DA"); // let's use a not common locale such as Denmark
-
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, locale);
+        Map<String, Object> context = createContextWithLocale(locale);
 
         // decimal seperator is , in Denmark so we should write 123,99 as input
         Double value = (Double) basicConverter.convertValue(context, null, null, null, "123,99", Double.class);
@@ -147,9 +140,7 @@ public class XWorkBasicConverterTest extends XWorkTestCase {
 
     public void testXW49ConvertDoubleToString() throws Exception {
         Locale locale = new Locale("DA"); // let's use a not common locale such as Denmark
-
-        Map<String, Object> context = new HashMap<>();
-        context.put(ActionContext.LOCALE, locale);
+        Map<String, Object> context = createContextWithLocale(locale);
 
         // decimal seperator is , in Denmark so we should write 123,99 as input
         String value = (String) basicConverter.convertValue(context, null, null, null, new Double("123.99"), String.class);
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 7bb42b6..3465737 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
@@ -317,7 +317,8 @@ public class XWorkConverterTest extends XWorkTestCase {
         Locale locale = Locale.GERMANY;
         DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
         String dateString = df.format(date);
-        context.put(ActionContext.LOCALE, locale);
+        context = ActionContext.of(context).withLocale(locale).getContextMap();
+
         assertEquals(dateString, converter.convertValue(context, null, null, null, date, String.class));
     }
 
@@ -553,7 +554,7 @@ public class XWorkConverterTest extends XWorkTestCase {
 
     public void testStringToInt() {
         assertEquals(123, converter.convertValue(context, null, null, null, "123", int.class));
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123.12", int.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", int.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", int.class));
@@ -562,7 +563,7 @@ public class XWorkConverterTest extends XWorkTestCase {
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1,234.12", int.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1.234", int.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1.234,12", int.class));
-        context.put(ActionContext.LOCALE, Locale.GERMANY);
+        context = ActionContext.of(context).withLocale(Locale.GERMANY).getContextMap();
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123.12", int.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", int.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", int.class));
@@ -576,7 +577,7 @@ public class XWorkConverterTest extends XWorkTestCase {
 
     public void testStringToInteger() {
         assertEquals(123, converter.convertValue(context, null, null, null, "123", Integer.class));
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123.12", Integer.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", Integer.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", Integer.class));
@@ -587,7 +588,7 @@ public class XWorkConverterTest extends XWorkTestCase {
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1.234", Integer.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1.234,12", Integer.class));
 
-        context.put(ActionContext.LOCALE, Locale.GERMANY);
+        context = ActionContext.of(context).withLocale(Locale.GERMANY).getContextMap();
         // WRONG: locale separator is wrongly placed
         assertEquals(12312, converter.convertValue(context, null, null, null, "123.12", Integer.class));
         assertEquals(1234, converter.convertValue(context, null, null, null, "1.234", Integer.class));
@@ -601,7 +602,7 @@ public class XWorkConverterTest extends XWorkTestCase {
 
     public void testStringToPrimitiveDouble() {
         assertEquals(123d, converter.convertValue(context, null, null, null, "123", double.class));
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
         assertEquals(123.12, converter.convertValue(context, null, null, null, "123.12", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", double.class));
@@ -611,7 +612,7 @@ public class XWorkConverterTest extends XWorkTestCase {
         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));
 
-        context.put(ActionContext.LOCALE, Locale.GERMANY);
+        context = ActionContext.of(context).withLocale(Locale.GERMANY).getContextMap();
         assertEquals(12312d, converter.convertValue(context, null, null, null, "123.12", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", double.class));
@@ -624,7 +625,7 @@ public class XWorkConverterTest extends XWorkTestCase {
 
     public void testStringToDouble() {
         assertEquals(123d, converter.convertValue(context, null, null, null, "123", Double.class));
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
         assertEquals(123.12, converter.convertValue(context, null, null, null, "123.12", Double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", Double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", Double.class));
@@ -635,7 +636,7 @@ public class XWorkConverterTest extends XWorkTestCase {
         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));
 
-        context.put(ActionContext.LOCALE, Locale.GERMANY);
+        context = ActionContext.of(context).withLocale(Locale.GERMANY).getContextMap();
         // WRONG: locale separator is wrongly placed
         assertEquals(12312d, converter.convertValue(context, null, null, null, "123.12", Double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", Double.class));
@@ -782,8 +783,7 @@ public class XWorkConverterTest extends XWorkTestCase {
 
         converter = container.getInstance(XWorkConverter.class);
 
-        ActionContext ac = ActionContext.getContext();
-        ac.setLocale(Locale.US);
+        ActionContext ac = ActionContext.getContext().withLocale(Locale.US);
         context = ac.getContextMap();
         stack = (OgnlValueStack) ac.getValueStack();
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
index 707b0e5..7641dcc 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
@@ -480,7 +480,7 @@ public class OgnlUtilTest extends XWorkTestCase {
         Map<String, Object> props = new HashMap<>();
         props.put("birthday", "02/12/1982");
         // US style test
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
         ognlUtil.setProperties(props, foo, context);
 
         Calendar cal = Calendar.getInstance(Locale.US);
@@ -519,7 +519,7 @@ public class OgnlUtilTest extends XWorkTestCase {
             .format(meetingTime);
         props.put("meeting", formatted);
 
-        context.put(ActionContext.LOCALE, Locale.UK);
+        context = ActionContext.of(context).withLocale(Locale.UK).getContextMap();
 
         ognlUtil.setProperties(props, foo, context);
 
@@ -529,7 +529,7 @@ public class OgnlUtilTest extends XWorkTestCase {
 
         //test RFC 3339 date format for JSON
         props.put("event", "1996-12-19T16:39:57Z");
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
         ognlUtil.setProperties(props, foo, context);
 
         cal = Calendar.getInstance(Locale.US);
@@ -545,7 +545,7 @@ public class OgnlUtilTest extends XWorkTestCase {
 
         //test setting a calendar property
         props.put("calendar", "1996-12-19T16:39:57Z");
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
         ognlUtil.setProperties(props, foo, context);
         assertEquals(cal, foo.getCalendar());
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/StrutsLocalizedTextProviderTest.java b/core/src/test/java/com/opensymphony/xwork2/util/StrutsLocalizedTextProviderTest.java
index 7efb8fd..251217a 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/StrutsLocalizedTextProviderTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/StrutsLocalizedTextProviderTest.java
@@ -327,7 +327,7 @@ public class StrutsLocalizedTextProviderTest extends XWorkTestCase {
 
         localizedTextProvider = container.getInstance(LocalizedTextProvider.class);
         
-        ActionContext.getContext().setLocale(Locale.US);
+        ActionContext.getContext().withLocale(Locale.US);
     }
 
     @Override
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java
index 4d6fddd..6ce0225 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java
@@ -336,7 +336,7 @@ public class AnnotationValidationConfigurationBuilderTest extends XWorkTestCase
         });
 
         // ActionContext is destroyed during rebuilding configuration
-        ActionContext.getContext().setLocale(locale);
+        ActionContext.getContext().withLocale(locale);
 
         ActionInvocation invocation = new DefaultActionInvocation(ActionContext.getContext().getContextMap(), true);
         container.inject(invocation);
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 709ba3c..c866ee4 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
@@ -124,8 +124,7 @@ public class SimpleActionValidationTest extends XWorkTestCase {
         try {
             ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.VALIDATION_ACTION_NAME, null, extraContext);
             ValueStack stack = ActionContext.getContext().getValueStack();
-            ActionContext actionContext = ActionContext.of(stack.getContext()).bind();
-            actionContext.setLocale(Locale.US);
+            stack.getActionContext().withLocale(Locale.US);
 
             proxy.execute();
             assertTrue(((ValidationAware) proxy.getAction()).hasFieldErrors());
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidatorTest.java
index 57e5475..de564c6 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidatorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidatorTest.java
@@ -44,7 +44,7 @@ public class DateRangeFieldValidatorTest extends XWorkTestCase {
         validator.validate(action);
 
         // then
-        assertTrue(context.getFieldErrors().size() == 0);
+        assertEquals(0, context.getFieldErrors().size());
     }
 
     public void testMinValidation() throws Exception {
@@ -53,11 +53,13 @@ public class DateRangeFieldValidatorTest extends XWorkTestCase {
         ValidatorContext context = new DummyValidatorContext(action, tpf);
         DateRangeFieldValidator validator = prepareValidator(action, context);
 
+        System.out.println(ActionContext.getContext().getLocale());
+
         // when
         validator.validate(action);
 
         // then
-        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals(1, context.getFieldErrors().size());
         assertEquals("Max is 12.12.13, min is 01.01.13 but value is 03.03.12", context.getFieldErrors().get("dateRange").get(0));
     }
 
@@ -71,7 +73,7 @@ public class DateRangeFieldValidatorTest extends XWorkTestCase {
         validator.validate(action);
 
         // then
-        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals(1, context.getFieldErrors().size());
         assertEquals("Max is 12.12.13, min is 01.01.13 but value is 04.04.14", context.getFieldErrors().get("dateRange").get(0));
     }
 
@@ -91,6 +93,7 @@ public class DateRangeFieldValidatorTest extends XWorkTestCase {
 
     private DateRangeFieldValidator prepareValidator(ValidationAction action, ValidatorContext context) {
         ValueStack valueStack = container.getInstance(ValueStackFactory.class).createValueStack();
+        valueStack.getActionContext().withLocale(new Locale("de"));
         valueStack.push(action);
 
         DateRangeFieldValidator validator = new DateRangeFieldValidator();
@@ -108,7 +111,6 @@ public class DateRangeFieldValidatorTest extends XWorkTestCase {
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        ActionContext.getContext().setLocale(new Locale("DE"));
         tpf = container.getInstance(TextProviderFactory.class);
     }
 
diff --git a/core/src/test/java/org/apache/struts2/components/ComponentTest.java b/core/src/test/java/org/apache/struts2/components/ComponentTest.java
index 70f9114..722f6be 100644
--- a/core/src/test/java/org/apache/struts2/components/ComponentTest.java
+++ b/core/src/test/java/org/apache/struts2/components/ComponentTest.java
@@ -430,7 +430,7 @@ public class ComponentTest extends AbstractTagTest {
 
 
     public void testI18nComponentDisposeItselfFromComponentStack() throws Exception {
-        stack.getContext().put(ActionContext.LOCALE, Locale.getDefault());
+        stack.getActionContext().withLocale(Locale.getDefault());
 
         TextFieldTag t = new TextFieldTag();
         t.setPageContext(pageContext);
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 3e621b1..b6a4101 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java
@@ -393,10 +393,10 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
         mai.setResultCode("success");
         mai.setInvocationContext(ActionContext.getContext());
         Map<String, Object> param = new HashMap<>();
-        ActionContext.getContext().setParameters(HttpParameters.create(param).build());
-        // set German locale
-        ActionContext.getContext().setLocale(Locale.GERMAN);
-        ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequest(req, 10));
+        ActionContext.getContext()
+            .withParameters(HttpParameters.create(param).build())
+            .withLocale(Locale.GERMAN)
+            .withServletRequest(createMultipartRequest(req, 10));
 
         interceptor.intercept(mai);
 
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 abb5d2d..99b9ffb 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
@@ -214,7 +214,7 @@ public class I18nInterceptorTest extends TestCase {
 
     public void testActionContextLocaleIsPreservedWhenNotOverridden() throws Exception {
         final Locale locale1 = Locale.TRADITIONAL_CHINESE;
-        mai.getInvocationContext().setLocale(locale1);
+        mai.getInvocationContext().withLocale(locale1);
         interceptor.intercept(mai);
 
         Locale locale = (Locale) session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE);
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java
index 75fb008..f31ccc4 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java
@@ -21,6 +21,7 @@ package org.apache.struts2.views.jsp;
 import java.io.File;
 import java.io.StringWriter;
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 
 import javax.servlet.http.HttpServletResponse;
@@ -118,10 +119,10 @@ public abstract class AbstractTagTest extends StrutsInternalTestCase {
                 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);
+        extraContext = ActionContext.of(extraContext).withLocale(null).getContextMap();
         stack.getContext().putAll(extraContext);
 
-        ActionContext actionContext = ActionContext.of(context)
+        ActionContext.of(context)
             .withServletRequest(request)
             .withServletResponse(response)
             .withServletContext(servletContext)
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 475e66f..6056a94 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
@@ -29,7 +29,7 @@ public class NumberTagTest extends AbstractTagTest {
 
     public void testSimpleFloatFormat() throws Exception {
         // given
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
 
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.0f);
@@ -48,7 +48,7 @@ public class NumberTagTest extends AbstractTagTest {
     
     public void testSimpleCurrencyUSFormat() throws Exception {
         // given
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
         
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.0f);
@@ -68,7 +68,7 @@ public class NumberTagTest extends AbstractTagTest {
     
     public void testSimpleCurrencyPLFormat() throws Exception {
         // given
-        context.put(ActionContext.LOCALE, new Locale("pl", "PL"));
+        context = ActionContext.of(context).withLocale(new Locale("pl", "PL")).getContextMap();
         
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.0f);
@@ -83,7 +83,8 @@ public class NumberTagTest extends AbstractTagTest {
         tag.doEndTag();
 
         // then
-        NumberFormat format = NumberFormat.getCurrencyInstance((Locale) context.get(ActionContext.LOCALE));
+        Locale locale = ActionContext.of(context).getLocale();
+        NumberFormat format = NumberFormat.getCurrencyInstance(locale);
         format.setRoundingMode(RoundingMode.CEILING);
         String expected = format.format(120.0f);
 
@@ -92,7 +93,7 @@ public class NumberTagTest extends AbstractTagTest {
 
     public void testSimpleRoundingCeiling() throws Exception {
         // given
-        context.put(ActionContext.LOCALE, Locale.US);
+        context = ActionContext.of(context).withLocale(Locale.US).getContextMap();
 
         TestAction testAction = (TestAction) action;
         testAction.setFloatNumber(120.45f);
@@ -107,7 +108,8 @@ public class NumberTagTest extends AbstractTagTest {
         tag.doEndTag();
 
         // then
-        NumberFormat format = NumberFormat.getInstance((Locale) context.get(ActionContext.LOCALE));
+        Locale locale = ActionContext.of(context).getLocale();
+        NumberFormat format = NumberFormat.getInstance(locale);
         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 684d262..29b5627 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
@@ -190,7 +190,7 @@ public class TextTagTest extends AbstractTagTest {
         Locale foreignLocale = getForeignLocale();
         assertNotSame(defaultLocale, foreignLocale);
 
-        ActionContext.getContext().setLocale(defaultLocale);
+        ActionContext.getContext().withLocale(defaultLocale);
         String key = "simpleKey";
         String value_default = getLocalizedMessage(defaultLocale);
         tag.setName(key);
@@ -204,7 +204,7 @@ public class TextTagTest extends AbstractTagTest {
         assertNotEquals(value_default, value_int);
         ValueStack newStack = container.getInstance(ValueStackFactory.class).createValueStack(stack);
         newStack.getActionContext().withLocale(foreignLocale).withContainer(container);
-        assertNotSame(newStack.getContext().get(ActionContext.LOCALE), ActionContext.getContext().getLocale());
+        assertNotSame(newStack.getActionContext().getLocale(), ActionContext.getContext().getLocale());
         request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, newStack);
         assertEquals(ActionContext.getContext().getValueStack().peek(), newStack.peek());
         tag.doStartTag();
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 c1b9c8e..7b6117d 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
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import javax.servlet.http.HttpSession;
@@ -553,7 +554,7 @@ public class URLTagTest extends AbstractUITagTest {
                 response);
         // let's not set the locale -- there is a test that checks if Dispatcher actually picks this up...
         // ... but generally we want to just use no locale (let it stay system default)
-        extraContext.remove(ActionContext.LOCALE);
+        extraContext = ActionContext.of(extraContext).withLocale(null).getContextMap();
         stack.getContext().putAll(extraContext);
 
         ActionContext actionContext = ActionContext.of(context)
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 321864f..0398ebf 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,8 +51,7 @@ public class JuneauXmlHandlerTest extends XWorkTestCase {
             "</object>";
         handler = new JuneauXmlHandler();
         ai = new MockActionInvocation();
-        ActionContext context = ActionContext.of(new HashMap<>()).bind();
-        context.setLocale(Locale.US);
+        ActionContext context = ActionContext.of(new HashMap<>()).withLocale(Locale.US);
         ((MockActionInvocation) ai).setInvocationContext(context);
     }