MYFACES-3252
diff --git a/api/src/main/java/javax/faces/component/UIComponent.java b/api/src/main/java/javax/faces/component/UIComponent.java
index 97e7189..d6d685f 100755
--- a/api/src/main/java/javax/faces/component/UIComponent.java
+++ b/api/src/main/java/javax/faces/component/UIComponent.java
@@ -629,9 +629,21 @@
 
             try
             {
+                ResourceBundle.Control bundleControl = (ResourceBundle.Control) context.getExternalContext()
+                        .getApplicationMap().get("org.apache.myfaces.RESOURCE_BUNDLE_CONTROL");
+
                 // looks for a ResourceBundle with a base name equal to the fully qualified class
                 // name of the current UIComponent this and Locale equal to the Locale of the current UIViewRoot.
-                _resourceBundleMap = new BundleMap(ResourceBundle.getBundle(getClass().getName(), locale, loader));
+                if (bundleControl == null)
+                {
+                    _resourceBundleMap = new BundleMap(
+                            ResourceBundle.getBundle(getClass().getName(), locale, loader));
+                }
+                else
+                {
+                    _resourceBundleMap = new BundleMap(
+                            ResourceBundle.getBundle(getClass().getName(), locale, loader, bundleControl));
+                }
             }
             catch (MissingResourceException e)
             {
diff --git a/api/src/main/java/javax/faces/component/_MessageUtils.java b/api/src/main/java/javax/faces/component/_MessageUtils.java
index 21fd8e1..558bcbf 100755
--- a/api/src/main/java/javax/faces/component/_MessageUtils.java
+++ b/api/src/main/java/javax/faces/component/_MessageUtils.java
@@ -158,30 +158,61 @@
                                             Locale locale,
                                             String bundleName)
     {
+        ResourceBundle.Control bundleControl = (ResourceBundle.Control) facesContext.getExternalContext()
+                .getApplicationMap().get("org.apache.myfaces.RESOURCE_BUNDLE_CONTROL");
+        
         try
         {
             //First we try the JSF implementation class loader
-            return ResourceBundle.getBundle(bundleName,
-                                            locale,
-                                            facesContext.getClass().getClassLoader());
+            if (bundleControl == null)
+            {
+                return ResourceBundle.getBundle(bundleName,
+                                                locale,
+                                                facesContext.getClass().getClassLoader());
+            }
+            else
+            {
+                return ResourceBundle.getBundle(bundleName,
+                                                locale,
+                                                facesContext.getClass().getClassLoader(), bundleControl);
+            }
         }
         catch (MissingResourceException ignore1)
         {
             try
             {
                 //Next we try the JSF API class loader
-                return ResourceBundle.getBundle(bundleName,
-                                                locale,
-                                                _MessageUtils.class.getClassLoader());
+                if (bundleControl == null)
+                {
+                    return ResourceBundle.getBundle(bundleName,
+                                                    locale,
+                                                    _MessageUtils.class.getClassLoader());
+                }
+                else
+                {
+                    //Next we try the JSF API class loader
+                    return ResourceBundle.getBundle(bundleName,
+                                                    locale,
+                                                    _MessageUtils.class.getClassLoader(), bundleControl);
+                }
             }
             catch (MissingResourceException ignore2)
             {
                 try
                 {
                     //Last resort is the context class loader
-                    return ResourceBundle.getBundle(bundleName,
-                                                    locale,
-                                                    _ClassUtils.getContextClassLoader());
+                    if (bundleControl == null)
+                    {
+                        return ResourceBundle.getBundle(bundleName,
+                                                        locale,
+                                                        _ClassUtils.getContextClassLoader());
+                    }
+                    else
+                    {
+                        return ResourceBundle.getBundle(bundleName,
+                                                        locale,
+                                                        _ClassUtils.getContextClassLoader(), bundleControl);
+                    }
                 }
                 catch (MissingResourceException damned)
                 {
diff --git a/api/src/main/java/javax/faces/component/html/_MessageUtils.java b/api/src/main/java/javax/faces/component/html/_MessageUtils.java
index 69a27d9..17fff27 100755
--- a/api/src/main/java/javax/faces/component/html/_MessageUtils.java
+++ b/api/src/main/java/javax/faces/component/html/_MessageUtils.java
@@ -159,30 +159,61 @@
                                             Locale locale,
                                             String bundleName)
     {
+        ResourceBundle.Control bundleControl = (ResourceBundle.Control) facesContext.getExternalContext()
+                .getApplicationMap().get("org.apache.myfaces.RESOURCE_BUNDLE_CONTROL");
+        
         try
         {
             //First we try the JSF implementation class loader
-            return ResourceBundle.getBundle(bundleName,
-                                            locale,
-                                            facesContext.getClass().getClassLoader());
+            if (bundleControl == null)
+            {
+                return ResourceBundle.getBundle(bundleName,
+                                                locale,
+                                                facesContext.getClass().getClassLoader());
+            }
+            else
+            {
+                return ResourceBundle.getBundle(bundleName,
+                                                locale,
+                                                facesContext.getClass().getClassLoader(), bundleControl);
+            }
         }
         catch (MissingResourceException ignore1)
         {
             try
             {
                 //Next we try the JSF API class loader
-                return ResourceBundle.getBundle(bundleName,
-                                                locale,
-                                                _MessageUtils.class.getClassLoader());
+                if (bundleControl == null)
+                {
+                    return ResourceBundle.getBundle(bundleName,
+                                                    locale,
+                                                    _MessageUtils.class.getClassLoader());
+                }
+                else
+                {
+                    //Next we try the JSF API class loader
+                    return ResourceBundle.getBundle(bundleName,
+                                                    locale,
+                                                    _MessageUtils.class.getClassLoader(), bundleControl);
+                }
             }
             catch (MissingResourceException ignore2)
             {
                 try
                 {
                     //Last resort is the context class loader
-                    return ResourceBundle.getBundle(bundleName,
-                                                    locale,
-                                                    _ClassUtils.getContextClassLoader());
+                    if (bundleControl == null)
+                    {
+                        return ResourceBundle.getBundle(bundleName,
+                                                        locale,
+                                                        _ClassUtils.getContextClassLoader());
+                    }
+                    else
+                    {
+                        return ResourceBundle.getBundle(bundleName,
+                                                        locale,
+                                                        _ClassUtils.getContextClassLoader(), bundleControl);
+                    }
                 }
                 catch (MissingResourceException damned)
                 {
diff --git a/api/src/main/java/javax/faces/convert/_MessageUtils.java b/api/src/main/java/javax/faces/convert/_MessageUtils.java
index d96f577..d999341 100755
--- a/api/src/main/java/javax/faces/convert/_MessageUtils.java
+++ b/api/src/main/java/javax/faces/convert/_MessageUtils.java
@@ -141,39 +141,67 @@
                                             Locale locale,
                                             String bundleName)
     {
+        ResourceBundle.Control bundleControl = (ResourceBundle.Control) facesContext.getExternalContext()
+                .getApplicationMap().get("org.apache.myfaces.RESOURCE_BUNDLE_CONTROL");
+        
         try
         {
             //First we try the JSF implementation class loader
-            return ResourceBundle.getBundle(bundleName,
-                                            locale,
-                                            facesContext.getClass().getClassLoader());
+            if (bundleControl == null)
+            {
+                return ResourceBundle.getBundle(bundleName,
+                                                locale,
+                                                facesContext.getClass().getClassLoader());
+            }
+            else
+            {
+                return ResourceBundle.getBundle(bundleName,
+                                                locale,
+                                                facesContext.getClass().getClassLoader(), bundleControl);
+            }
         }
         catch (MissingResourceException ignore1)
         {
             try
             {
                 //Next we try the JSF API class loader
-                return ResourceBundle.getBundle(bundleName,
-                                                locale,
-                                                _MessageUtils.class.getClassLoader());
+                if (bundleControl == null)
+                {
+                    return ResourceBundle.getBundle(bundleName,
+                                                    locale,
+                                                    _MessageUtils.class.getClassLoader());
+                }
+                else
+                {
+                    return ResourceBundle.getBundle(bundleName,
+                                                    locale,
+                                                    _MessageUtils.class.getClassLoader(), bundleControl);
+                }
             }
             catch (MissingResourceException ignore2)
             {
                 try
                 {
                     //Last resort is the context class loader
-                    if (System.getSecurityManager() != null)
+                    ClassLoader cl;
+                    if (System.getSecurityManager() == null)
                     {
-                        ClassLoader cl = (ClassLoader) AccessController.doPrivileged(
-                                (PrivilegedExceptionAction) () -> Thread.currentThread().getContextClassLoader());
-                        return ResourceBundle.getBundle(bundleName, locale, cl);
-
+                        cl = Thread.currentThread().getContextClassLoader();
                     }
                     else
                     {
-                        return ResourceBundle.getBundle(bundleName, locale,
-                                                        Thread.currentThread().getContextClassLoader());
-                    }                   
+                        cl = (ClassLoader) AccessController.doPrivileged(
+                                (PrivilegedExceptionAction) () -> Thread.currentThread().getContextClassLoader());
+                    }
+
+                    if (bundleControl == null)
+                    {
+                        return ResourceBundle.getBundle(bundleName, locale, cl);
+                    }
+                    else
+                    {
+                        return ResourceBundle.getBundle(bundleName, locale, cl, bundleControl);
+                    }
                 }
                 catch(PrivilegedActionException pae)
                 {
diff --git a/api/src/main/java/javax/faces/validator/_MessageUtils.java b/api/src/main/java/javax/faces/validator/_MessageUtils.java
index c78d9a2..e8693bf 100755
--- a/api/src/main/java/javax/faces/validator/_MessageUtils.java
+++ b/api/src/main/java/javax/faces/validator/_MessageUtils.java
@@ -146,41 +146,69 @@
                                             Locale locale,
                                             String bundleName)
     {
+        ResourceBundle.Control bundleControl = (ResourceBundle.Control) facesContext.getExternalContext()
+                .getApplicationMap().get("org.apache.myfaces.RESOURCE_BUNDLE_CONTROL");
+        
         try
         {
             //First we try the JSF implementation class loader
-            return ResourceBundle.getBundle(bundleName,
-                                            locale,
-                                            facesContext.getClass().getClassLoader());
+            if (bundleControl == null)
+            {
+                return ResourceBundle.getBundle(bundleName,
+                                                locale,
+                                                facesContext.getClass().getClassLoader());
+            }
+            else
+            {
+                return ResourceBundle.getBundle(bundleName,
+                                                locale,
+                                                facesContext.getClass().getClassLoader(), bundleControl);
+            }
         }
         catch (MissingResourceException ignore1)
         {
             try
             {
                 //Next we try the JSF API class loader
-                return ResourceBundle.getBundle(bundleName,
-                                                locale,
-                                                _MessageUtils.class.getClassLoader());
+                if (bundleControl == null)
+                {
+                    return ResourceBundle.getBundle(bundleName,
+                                                    locale,
+                                                    _MessageUtils.class.getClassLoader());
+                }
+                else
+                {
+                    return ResourceBundle.getBundle(bundleName,
+                                                    locale,
+                                                    _MessageUtils.class.getClassLoader(), bundleControl);
+                }
             }
             catch (MissingResourceException ignore2)
             {
                 try
                 {
                     //Last resort is the context class loader
-                    if (System.getSecurityManager() != null)
+                    ClassLoader cl;
+                    if (System.getSecurityManager() == null)
                     {
-                        ClassLoader cl = (ClassLoader) AccessController.doPrivileged(
-                                (PrivilegedExceptionAction) () -> Thread.currentThread().getContextClassLoader());
-                        return ResourceBundle.getBundle(bundleName, locale, cl);
-
+                        cl = Thread.currentThread().getContextClassLoader();
                     }
                     else
                     {
-                        return ResourceBundle.getBundle(bundleName,locale,
-                                                        Thread.currentThread().getContextClassLoader());
-                    }                   
+                        cl = (ClassLoader) AccessController.doPrivileged(
+                                (PrivilegedExceptionAction) () -> Thread.currentThread().getContextClassLoader());
+                    }
+
+                    if (bundleControl == null)
+                    {
+                        return ResourceBundle.getBundle(bundleName, locale, cl);
+                    }
+                    else
+                    {
+                        return ResourceBundle.getBundle(bundleName, locale, cl, bundleControl);
+                    }
                 }
-                catch (PrivilegedActionException pae)
+                catch(PrivilegedActionException pae)
                 {
                     throw new FacesException(pae);
                 }
diff --git a/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java b/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
index 0f39681..b0b7b3d 100755
--- a/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
@@ -406,6 +406,11 @@
     java.util.ResourceBundle getResourceBundle(final String name, final Locale locale, final ClassLoader loader)
             throws MissingResourceException
     {
+        if (_myfacesConfig.getResourceBundleControl() != null)
+        {
+            return java.util.ResourceBundle.getBundle(name, locale, loader,_myfacesConfig.getResourceBundleControl());
+        }
+
         return java.util.ResourceBundle.getBundle(name, locale, loader);
     }
 
diff --git a/impl/src/main/java/org/apache/myfaces/application/ResourceHandlerImpl.java b/impl/src/main/java/org/apache/myfaces/application/ResourceHandlerImpl.java
index 2d84a36..62f6440 100644
--- a/impl/src/main/java/org/apache/myfaces/application/ResourceHandlerImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/application/ResourceHandlerImpl.java
@@ -710,8 +710,19 @@
 
             try
             {
-                ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale,
-                        ClassUtils.getContextClassLoader());
+                ResourceBundle bundle;
+                ResourceBundle.Control bundleControl = MyfacesConfig.getCurrentInstance(context)
+                        .getResourceBundleControl();
+                if (bundleControl == null)
+                {
+                    bundle = ResourceBundle.getBundle(bundleName, locale, ClassUtils.getContextClassLoader());
+                }
+                else
+                {
+                    bundle = ResourceBundle.getBundle(bundleName, locale, ClassUtils.getContextClassLoader(),
+                            bundleControl);
+                }
+
                 if (bundle != null && bundle.containsKey(ResourceHandler.LOCALE_PREFIX))
                 {
                     localePrefix = bundle.getString(ResourceHandler.LOCALE_PREFIX);
diff --git a/impl/src/main/java/org/apache/myfaces/config/MyfacesConfig.java b/impl/src/main/java/org/apache/myfaces/config/MyfacesConfig.java
index df2535b..8e0bec6 100755
--- a/impl/src/main/java/org/apache/myfaces/config/MyfacesConfig.java
+++ b/impl/src/main/java/org/apache/myfaces/config/MyfacesConfig.java
@@ -19,6 +19,7 @@
 package org.apache.myfaces.config;
 
 import java.lang.invoke.MethodHandles;
+import java.util.ResourceBundle;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.faces.application.ProjectStage;
@@ -818,6 +819,13 @@
             "org.apache.myfaces.USE_METHOD_HANDLES";
     protected final static boolean USE_METHOD_HANDLES_DEFAULT = true;
     
+    /**
+     * Defines the {@link java.util.ResourceBundle.Control} to use for all
+     * {@link java.util.ResourceBundle#getBundle(java.lang.String)} calls.
+     */
+    @JSFWebConfigParam(since="2.3-next")
+    public static final String RESOURCE_BUNDLE_CONTROL = 
+            "org.apache.myfaces.RESOURCE_BUNDLE_CONTROL";
     
     // we need it, applicationImpl not ready probably
     private ProjectStage projectStage = ProjectStage.Production;
@@ -899,6 +907,8 @@
     private boolean renderClientBehaviorScriptsAsString = RENDER_CLIENTBEHAVIOR_SCRIPTS_AS_STRING_DEFAULT;
     private boolean alwaysForceSessionCreation = ALWAYS_FORCE_SESSION_CREATION_DEFAULT;
     private boolean useMethodHandles = USE_METHOD_HANDLES_DEFAULT;
+    private ResourceBundle.Control resourceBundleControl;
+    private boolean automaticExtensionlessMapping = AUTOMATIC_EXTENSIONLESS_MAPPING_DEFAULT;
     
     private static final boolean MYFACES_IMPL_AVAILABLE;
     private static final boolean RI_IMPL_AVAILABLE;
@@ -1343,6 +1353,15 @@
                 cfg.useMethodHandles = false;
             }
         }
+        
+        String resourceBundleControl = getString(extCtx, RESOURCE_BUNDLE_CONTROL, null);
+        if (StringUtils.isNotBlank(resourceBundleControl))
+        {
+            cfg.resourceBundleControl = (ResourceBundle.Control) ClassUtils.newInstance(resourceBundleControl);
+        }
+        
+        cfg.automaticExtensionlessMapping = getBoolean(extCtx, AUTOMATIC_EXTENSIONLESS_MAPPING,
+                AUTOMATIC_EXTENSIONLESS_MAPPING_DEFAULT);
 
         return cfg;
     }
@@ -1808,5 +1827,21 @@
     {
         return useMethodHandles;
     }
+    
+    public ProjectStage getProjectStage()
+    {
+        return projectStage;
+    }
+
+    public ResourceBundle.Control getResourceBundleControl()
+    {
+        return resourceBundleControl;
+    }
+
+    public boolean isAutomaticExtensionlessMapping()
+    {
+        return automaticExtensionlessMapping;
+    }
+
 }
 
diff --git a/impl/src/main/java/org/apache/myfaces/taglib/core/LoadBundleTag.java b/impl/src/main/java/org/apache/myfaces/taglib/core/LoadBundleTag.java
index eac521a..999e588 100755
--- a/impl/src/main/java/org/apache/myfaces/taglib/core/LoadBundleTag.java
+++ b/impl/src/main/java/org/apache/myfaces/taglib/core/LoadBundleTag.java
@@ -38,6 +38,7 @@
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspAttribute;
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspTag;
+import org.apache.myfaces.config.MyfacesConfig;
 import org.apache.myfaces.util.lang.ClassUtils;
 
 /**
@@ -125,20 +126,34 @@
             throw new NullPointerException("LoadBundle: 'basename' must not be null");
         }
 
+        ResourceBundle.Control bundleControl =
+                MyfacesConfig.getCurrentInstance(facesContext).getResourceBundleControl();
         ResourceBundle bundle;
         try
         {
-            bundle = ResourceBundle.getBundle(basename,
-                                              locale,
-                                              ClassUtils.getContextClassLoader());
+            if (bundleControl == null)
+            {
+                bundle = ResourceBundle.getBundle(basename, locale, ClassUtils.getContextClassLoader());
+            }
+            else
+            {
+                bundle = ResourceBundle.getBundle(basename, locale, ClassUtils.getContextClassLoader(),
+                        bundleControl);
+            }
         }
         catch (MissingResourceException e)
         {
             try
             {
-                bundle = ResourceBundle.getBundle(basename,
-                        locale,
-                        this.getClass().getClassLoader());
+                if (bundleControl == null)
+                {
+                    bundle = ResourceBundle.getBundle(basename, locale, this.getClass().getClassLoader());
+                }
+                else
+                {
+                    bundle = ResourceBundle.getBundle(basename, locale, this.getClass().getClassLoader(),
+                            bundleControl);
+                }
             }
             catch (MissingResourceException e1)
             {
diff --git a/impl/src/main/java/org/apache/myfaces/util/MessageUtils.java b/impl/src/main/java/org/apache/myfaces/util/MessageUtils.java
index dfe5790..a4ef03c 100755
--- a/impl/src/main/java/org/apache/myfaces/util/MessageUtils.java
+++ b/impl/src/main/java/org/apache/myfaces/util/MessageUtils.java
@@ -32,6 +32,7 @@
 import javax.faces.application.FacesMessage;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
+import org.apache.myfaces.config.MyfacesConfig;
 import org.apache.myfaces.util.lang.ClassUtils;
 
 /**
@@ -273,13 +274,23 @@
         String detail = null;
         String bundleName = getApplication().getMessageBundle();
         ResourceBundle bundle = null;
+        
+        ResourceBundle.Control bundleControl = MyfacesConfig.getCurrentInstance().getResourceBundleControl();
 
         if (bundleName != null)
         {
             try
             {
-                bundle = ResourceBundle.getBundle(bundleName, locale, 
-                        ClassUtils.getCurrentLoader(bundleName));
+                if (bundleControl == null)
+                {
+                    bundle = ResourceBundle.getBundle(bundleName, locale, ClassUtils.getCurrentLoader(bundleName));
+                }
+                else
+                {
+                    bundle = ResourceBundle.getBundle(bundleName, locale, ClassUtils.getCurrentLoader(bundleName),
+                            bundleControl);
+                }
+
                 if (bundle.containsKey(messageId))
                 {
                     summary = bundle.getString(messageId);
@@ -295,8 +306,17 @@
         {
             try
             {
-                bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, 
-                        ClassUtils.getCurrentLoader(DEFAULT_BUNDLE));
+                if (bundleControl == null)
+                {
+                    bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale,
+                            ClassUtils.getCurrentLoader(DEFAULT_BUNDLE));
+                }
+                else
+                {
+                    bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale,
+                            ClassUtils.getCurrentLoader(DEFAULT_BUNDLE), bundleControl);
+                }
+
                 if (bundle == null)
                 {
                     throw new NullPointerException();
@@ -347,8 +367,7 @@
             {
                 if (bundle.containsKey(detailMessageId))
                 {
-                    detail = substituteParams(locale,
-                        bundle.getString(detailMessageId), params);
+                    detail = substituteParams(locale, bundle.getString(detailMessageId), params);
                 }
             }
             catch(MissingResourceException e)
@@ -366,13 +385,23 @@
         String detail = null;
         String bundleName = context.getApplication().getMessageBundle();
         ResourceBundle bundle = null;
+        
+        ResourceBundle.Control bundleControl = MyfacesConfig.getCurrentInstance().getResourceBundleControl();
 
         if (bundleName != null)
         {
             try
             {
-                bundle = ResourceBundle.getBundle(bundleName, locale, 
-                        ClassUtils.getCurrentLoader(bundleName));
+                if (bundleControl == null)
+                {
+                    bundle = ResourceBundle.getBundle(bundleName, locale, ClassUtils.getCurrentLoader(bundleName));
+                }
+                else
+                {
+                    bundle = ResourceBundle.getBundle(bundleName, locale, ClassUtils.getCurrentLoader(bundleName),
+                            bundleControl);
+                }
+
                 if (bundle.containsKey(messageId))
                 {
                     summary = bundle.getString(messageId);
@@ -388,8 +417,17 @@
         {
             try
             {
-                bundle = ResourceBundle.getBundle(bundleBaseName, locale, 
-                        ClassUtils.getCurrentLoader(bundleBaseName));
+                if (bundleControl == null)
+                {
+                    bundle = ResourceBundle.getBundle(bundleBaseName, locale,
+                            ClassUtils.getCurrentLoader(bundleBaseName));
+                }
+                else
+                {
+                    bundle = ResourceBundle.getBundle(bundleBaseName, locale,
+                            ClassUtils.getCurrentLoader(bundleBaseName), bundleControl);
+                }
+
                 if (bundle == null)
                 {
                     throw new NullPointerException();
@@ -410,8 +448,17 @@
         {
             try
             {
-                bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, 
-                        ClassUtils.getCurrentLoader(DEFAULT_BUNDLE));
+                if (bundleControl == null)
+                {
+                    bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, 
+                            ClassUtils.getCurrentLoader(DEFAULT_BUNDLE));
+                }
+                else
+                {
+                    bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, 
+                            ClassUtils.getCurrentLoader(DEFAULT_BUNDLE), bundleControl);
+                }
+
                 if (bundle == null)
                 {
                     throw new NullPointerException();
@@ -462,8 +509,7 @@
             {
                 if (bundle.containsKey(detailMessageId))
                 {
-                    detail = substituteParams(locale,
-                        bundle.getString(detailMessageId), params);
+                    detail = substituteParams(locale, bundle.getString(detailMessageId), params);
                 }
             }
             catch(MissingResourceException e)
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/LoadBundleHandler.java b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/LoadBundleHandler.java
index 4474aff..31a2a56 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/LoadBundleHandler.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/LoadBundleHandler.java
@@ -40,6 +40,7 @@
 import javax.faces.view.facelets.TagHandler;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
+import org.apache.myfaces.config.MyfacesConfig;
 import org.apache.myfaces.util.lang.ClassUtils;
 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 
@@ -241,15 +242,21 @@
         ResourceBundle bundle = null;
         try
         {
+            ResourceBundle.Control bundleControl = MyfacesConfig.getCurrentInstance().getResourceBundleControl();
+            
             String name = this.basename.getValue(ctx);
             ClassLoader cl = ClassUtils.getContextClassLoader();
-            if (root != null && root.getLocale() != null)
+            Locale locale = root != null && root.getLocale() != null
+                    ? root.getLocale()
+                    : Locale.getDefault();
+
+            if (bundleControl == null)
             {
-                bundle = ResourceBundle.getBundle(name, root.getLocale(), cl);
+                bundle = ResourceBundle.getBundle(name, locale, cl);
             }
             else
             {
-                bundle = ResourceBundle.getBundle(name, Locale.getDefault(), cl);
+                bundle = ResourceBundle.getBundle(name, locale, cl, bundleControl);
             }
         }
         catch (Exception e)
diff --git a/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java b/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
index fdd2124..a1b7dba 100644
--- a/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
+++ b/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
@@ -52,6 +52,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.ResourceBundle;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.enterprise.inject.spi.BeanManager;
@@ -172,9 +173,8 @@
                     FacesFlowProviderFactory.getFacesFlowProviderFactory(externalContext);
             FacesFlowProvider facesFlowProvider = facesFlowProviderFactory.getFacesFlowProvider(externalContext);
             
-            MyFacesHttpSessionListener listener = (MyFacesHttpSessionListener)
-                externalContext.getApplicationMap().get(
-                    MyFacesHttpSessionListener.APPLICATION_MAP_KEY);
+            MyFacesHttpSessionListener listener = (MyFacesHttpSessionListener) externalContext.getApplicationMap()
+                    .get(MyFacesHttpSessionListener.APPLICATION_MAP_KEY);
             if (listener != null)
             {
                 listener.setViewScopeProvider(viewScopeProvider);
@@ -202,21 +202,24 @@
             }
 
             WebConfigParamsLogger.logWebContextParams(facesContext);
-
-            //Force output EL message
-            ExternalSpecifications.isBeanValidationAvailable();
             
             //Start ViewPoolProcessor if necessary
             ViewPoolProcessor.initialize(facesContext);
             
-            Boolean automaticExtensionlessMapping = WebConfigParamUtils.getBooleanInitParameter(externalContext,
-                    MyfacesConfig.AUTOMATIC_EXTENSIONLESS_MAPPING, 
-                    MyfacesConfig.AUTOMATIC_EXTENSIONLESS_MAPPING_DEFAULT);
-            if (Boolean.TRUE.equals(automaticExtensionlessMapping))
+            MyfacesConfig config = MyfacesConfig.getCurrentInstance(facesContext.getExternalContext());
+            if (config.isAutomaticExtensionlessMapping())
             {
                 initAutomaticExtensionlessMapping(facesContext, servletContext);
             }
 
+            // publish resourceBundleControl to applicationMap, to make it available to the API
+            ResourceBundle.Control resourceBundleControl = config.getResourceBundleControl();
+            if (resourceBundleControl != null)
+            {
+                facesContext.getExternalContext().getApplicationMap().put(
+                        MyfacesConfig.RESOURCE_BUNDLE_CONTROL, resourceBundleControl);
+            }
+ 
             // print out a very prominent log message if the project stage is != Production
             if (!facesContext.isProjectStage(ProjectStage.Production)
                     && !facesContext.isProjectStage(ProjectStage.UnitTest))
@@ -698,8 +701,7 @@
         }
     }
     
-    protected void initWebsocketIntegration(
-            ServletContext servletContext, ExternalContext externalContext)
+    protected void initWebsocketIntegration(ServletContext servletContext, ExternalContext externalContext)
     {
         Boolean b = WebConfigParamUtils.getBooleanInitParameter(externalContext, 
                 PushContext.ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME);
diff --git a/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java b/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java
index 90f2d68..2243893 100644
--- a/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java
+++ b/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java
@@ -96,7 +96,10 @@
             }

             finally

             {

-                facesContext.release();

+                if (facesContext != null)

+                {

+                    facesContext.release();

+                }

             }

         }

     }

diff --git a/impl/src/test/java/javax/faces/validator/_MessageUtilsTest.java b/impl/src/test/java/javax/faces/validator/_MessageUtilsTest.java
index 80affca..d9cb57c 100644
--- a/impl/src/test/java/javax/faces/validator/_MessageUtilsTest.java
+++ b/impl/src/test/java/javax/faces/validator/_MessageUtilsTest.java
@@ -18,6 +18,7 @@
  */
 package javax.faces.validator;
 
+import java.util.HashMap;
 import static org.easymock.EasyMock.expect;
 
 import java.util.Locale;
@@ -28,6 +29,7 @@
 import javax.faces.application.Application;
 import javax.faces.application.ViewHandler;
 import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
 import org.apache.myfaces.test.mock.MockFacesContext;
 
 import org.apache.myfaces.test.mock.MockFacesContext12;
@@ -52,16 +54,19 @@
         Application application = mocksControl.createMock(Application.class);
         ViewHandler viewHandler = mocksControl.createMock(ViewHandler.class);
         ELContext elContext = mocksControl.createMock(ELContext.class);
+        ExternalContext externalContext = mocksControl.createMock(ExternalContext.class);
         ExpressionFactory expressionFactory = mocksControl.createMock(ExpressionFactory.class);
         ValueExpression valueExpression = mocksControl.createMock(ValueExpression.class);
         facesContext.setApplication(application);
         facesContext.setViewRoot(root);
         facesContext.setELContext(elContext);
+        facesContext.setExternalContext(externalContext);
         
         expect(application.getViewHandler()).andReturn(viewHandler);
         expect(viewHandler.calculateLocale(facesContext)).andReturn(Locale.ENGLISH);
         expect(application.getMessageBundle()).andReturn("javax.faces.Messages");
         expect(application.getExpressionFactory()).andReturn(expressionFactory);
+        expect(externalContext.getApplicationMap()).andReturn(new HashMap<>());
         String s = "xxx: Validation Error: Value is greater than allowable maximum of ''xyz''";
         expect(expressionFactory.createValueExpression(elContext,s,String.class)).andReturn(valueExpression);
         expect(valueExpression.getValue(elContext)).andReturn(s);