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

kusal pushed a commit to branch 7.0.x/merge-master-2024-11-02
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 3bd473b2d398fbd7614275b02c31eb01b53a2ac1
Merge: 99434d99b 1908cbab8
Author: Kusal Kithul-Godage <g...@kusal.io>
AuthorDate: Sat Nov 2 14:11:48 2024 +1100

    Merge remote-tracking branch 'origin/master' into 
7.0.x/merge-master-2024-11-02

 core/src/main/java/org/apache/struts2/ActionContext.java   |  5 +++++
 core/src/main/java/org/apache/struts2/ModelDriven.java     |  3 +++
 .../org/apache/struts2/config/entities/ResultConfig.java   |  6 +++---
 .../apache/struts2/config/impl/DefaultConfiguration.java   |  4 ++--
 .../org/apache/struts2/factory/DefaultResultFactory.java   |  3 +++
 .../interceptor/parameter/ParametersInterceptor.java       |  1 +
 .../interceptor/ChainingInterceptorWithConfigTest.java     |  7 ++++---
 .../convention/PackageBasedActionConfigBuilderTest.java    |  4 ++--
 .../org/apache/struts2/rest/RestActionInvocationTest.java  | 14 ++++++--------
 9 files changed, 29 insertions(+), 18 deletions(-)

diff --cc core/src/main/java/org/apache/struts2/ActionContext.java
index 56163eacc,335c24e95..2f023bc51
--- a/core/src/main/java/org/apache/struts2/ActionContext.java
+++ b/core/src/main/java/org/apache/struts2/ActionContext.java
@@@ -543,9 -543,15 +543,14 @@@ public class ActionContext implements S
  
      @Override
      public final boolean equals(Object obj) {
 -        if (!(obj instanceof ActionContext)) {
 +        if (!(obj instanceof ActionContext other)) {
              return false;
          }
 -        ActionContext other = (ActionContext) obj;
          return Objects.equals(getContextMap(), other.getContextMap());
      }
+ 
+     @Override
+     public final int hashCode() {
+         return Objects.hash(getContextMap());
+     }
  }
diff --cc 
core/src/main/java/org/apache/struts2/config/entities/ResultConfig.java
index 5e2a1daae,000000000..40d20838e
mode 100644,000000..100644
--- a/core/src/main/java/org/apache/struts2/config/entities/ResultConfig.java
+++ b/core/src/main/java/org/apache/struts2/config/entities/ResultConfig.java
@@@ -1,163 -1,0 +1,163 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *  http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.struts2.config.entities;
 +
 +import org.apache.struts2.util.location.Located;
 +import org.apache.struts2.util.location.Location;
 +
 +import java.io.Serializable;
 +import java.util.Collections;
 +import java.util.LinkedHashMap;
 +import java.util.Map;
 +import java.util.Objects;
 +
 +
 +/**
 + * Configuration for Result.
 + *
 + * <p>
 + * In the xml configuration file this is defined as the <code>result</code> 
tag.
 + * </p>
 + *
 + * @author Mike
 + */
 +public class ResultConfig extends Located implements Serializable {
 +
-     protected Map<String,String> params;
++    protected Map<String, String> params;
 +    protected String className;
 +    protected String name;
 +
 +    protected ResultConfig(String name, String className) {
 +        this.name = name;
 +        this.className = className;
 +        params = new LinkedHashMap<>();
 +    }
 +
 +    protected ResultConfig(ResultConfig orig) {
 +        this.params = orig.params;
 +        this.name = orig.name;
 +        this.className = orig.className;
 +        this.location = orig.location;
 +    }
 +
 +    public String getClassName() {
 +        return className;
 +    }
 +
 +    public String getName() {
 +        return name;
 +    }
 +
-     public Map<String,String> getParams() {
++    public Map<String, String> getParams() {
 +        return params;
 +    }
 +
 +    @Override
 +    public boolean equals(Object o) {
 +        if (this == o) {
 +            return true;
 +        }
 +
 +        if (!(o instanceof ResultConfig resultConfig)) {
 +            return false;
 +        }
 +
 +        if (!Objects.equals(className, resultConfig.className)) {
 +            return false;
 +        }
 +
 +        if (!Objects.equals(name, resultConfig.name)) {
 +            return false;
 +        }
 +
 +        if (!Objects.equals(params, resultConfig.params)) {
 +            return false;
 +        }
 +
 +        return true;
 +    }
 +
 +    @Override
 +    public int hashCode() {
 +        int result;
 +        result = ((name != null) ? name.hashCode() : 0);
 +        result = (29 * result) + ((className != null) ? className.hashCode() 
: 0);
 +        result = (29 * result) + ((params != null) ? params.hashCode() : 0);
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public String toString() {
 +        return "ResultConfig: [" + name + "] => [" + className + "] with 
params " + params;
 +    }
 +
 +    /**
 +     * The builder for this object.  An instance of this object is the only 
way to construct a new instance.  The
 +     * purpose is to enforce the immutability of the object.  The methods are 
structured in a way to support chaining.
 +     * After setting any values you need, call the {@link #build()} method to 
create the object.
 +     */
 +    public static final class Builder {
 +        private ResultConfig target;
 +
 +        public Builder(String name, String className) {
 +            target = new ResultConfig(name, className);
 +        }
 +
 +        public Builder(ResultConfig orig) {
 +            target = new ResultConfig(orig);
 +        }
 +
 +        public Builder name(String name) {
 +            target.name = name;
 +            return this;
 +        }
 +
 +        public Builder className(String name) {
 +            target.className = name;
 +            return this;
 +        }
 +
 +         public Builder addParam(String name, String value) {
 +            target.params.put(name, value);
 +            return this;
 +        }
 +
-         public Builder addParams(Map<String,String> params) {
++        public Builder addParams(Map<String, String> params) {
 +            target.params.putAll(params);
 +            return this;
 +        }
 +
 +        public Builder location(Location loc) {
 +            target.location = loc;
 +            return this;
 +        }
 +
 +        public ResultConfig build() {
 +            embalmTarget();
 +            ResultConfig result = target;
 +            target = new ResultConfig(target);
 +            return result;
 +        }
 +
 +        private void embalmTarget() {
 +            target.params = Collections.unmodifiableMap(target.params);
 +        }
 +    }
 +}
diff --cc 
core/src/main/java/org/apache/struts2/config/impl/DefaultConfiguration.java
index b7bc93425,000000000..3ea854b21
mode 100644,000000..100644
--- 
a/core/src/main/java/org/apache/struts2/config/impl/DefaultConfiguration.java
+++ 
b/core/src/main/java/org/apache/struts2/config/impl/DefaultConfiguration.java
@@@ -1,674 -1,0 +1,674 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *  http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.struts2.config.impl;
 +
 +import org.apache.struts2.ActionContext;
 +import org.apache.struts2.DefaultLocaleProviderFactory;
 +import org.apache.struts2.DefaultTextProvider;
 +import org.apache.struts2.FileManager;
 +import org.apache.struts2.FileManagerFactory;
 +import org.apache.struts2.LocaleProviderFactory;
 +import org.apache.struts2.LocalizedTextProvider;
 +import org.apache.struts2.ObjectFactory;
 +import org.apache.struts2.StrutsTextProviderFactory;
 +import org.apache.struts2.TextProvider;
 +import org.apache.struts2.TextProviderFactory;
 +import org.apache.struts2.config.Configuration;
 +import org.apache.struts2.config.ConfigurationException;
 +import org.apache.struts2.config.ContainerProvider;
 +import org.apache.struts2.config.FileManagerFactoryProvider;
 +import org.apache.struts2.config.FileManagerProvider;
 +import org.apache.struts2.config.PackageProvider;
 +import org.apache.struts2.config.RuntimeConfiguration;
 +import org.apache.struts2.config.entities.ActionConfig;
 +import org.apache.struts2.config.entities.InterceptorMapping;
 +import org.apache.struts2.config.entities.PackageConfig;
 +import org.apache.struts2.config.entities.ResultConfig;
 +import org.apache.struts2.config.entities.ResultTypeConfig;
 +import org.apache.struts2.config.entities.UnknownHandlerConfig;
 +import org.apache.struts2.config.providers.EnvsValueSubstitutor;
 +import org.apache.struts2.config.providers.InterceptorBuilder;
 +import org.apache.struts2.config.providers.ValueSubstitutor;
 +import org.apache.struts2.conversion.ConversionAnnotationProcessor;
 +import org.apache.struts2.conversion.ConversionFileProcessor;
 +import org.apache.struts2.conversion.ConversionPropertiesProcessor;
 +import org.apache.struts2.conversion.ObjectTypeDeterminer;
 +import org.apache.struts2.conversion.TypeConverter;
 +import org.apache.struts2.conversion.TypeConverterCreator;
 +import org.apache.struts2.conversion.TypeConverterHolder;
 +import org.apache.struts2.conversion.impl.ArrayConverter;
 +import org.apache.struts2.conversion.impl.CollectionConverter;
 +import org.apache.struts2.conversion.impl.DateConverter;
 +import 
org.apache.struts2.conversion.impl.DefaultConversionAnnotationProcessor;
 +import org.apache.struts2.conversion.impl.DefaultConversionFileProcessor;
 +import org.apache.struts2.conversion.impl.DefaultObjectTypeDeterminer;
 +import org.apache.struts2.conversion.impl.NumberConverter;
 +import org.apache.struts2.conversion.impl.StringConverter;
 +import org.apache.struts2.conversion.impl.XWorkBasicConverter;
 +import org.apache.struts2.conversion.impl.XWorkConverter;
 +import org.apache.struts2.factory.ActionFactory;
 +import org.apache.struts2.factory.ConverterFactory;
 +import org.apache.struts2.factory.DefaultActionFactory;
 +import org.apache.struts2.factory.DefaultInterceptorFactory;
- import org.apache.struts2.factory.DefaultResultFactory;
 +import org.apache.struts2.factory.DefaultUnknownHandlerFactory;
 +import org.apache.struts2.factory.DefaultValidatorFactory;
 +import org.apache.struts2.factory.InterceptorFactory;
 +import org.apache.struts2.factory.ResultFactory;
 +import org.apache.struts2.factory.StrutsConverterFactory;
 +import org.apache.struts2.factory.UnknownHandlerFactory;
 +import org.apache.struts2.factory.ValidatorFactory;
 +import org.apache.struts2.inject.Container;
 +import org.apache.struts2.inject.ContainerBuilder;
 +import org.apache.struts2.inject.Context;
 +import org.apache.struts2.inject.Factory;
 +import org.apache.struts2.inject.Scope;
 +import org.apache.struts2.ognl.BeanInfoCacheFactory;
 +import org.apache.struts2.ognl.DefaultOgnlBeanInfoCacheFactory;
 +import org.apache.struts2.ognl.DefaultOgnlExpressionCacheFactory;
 +import org.apache.struts2.ognl.ExpressionCacheFactory;
 +import org.apache.struts2.ognl.OgnlCacheFactory;
 +import org.apache.struts2.ognl.OgnlReflectionProvider;
 +import org.apache.struts2.ognl.OgnlUtil;
 +import org.apache.struts2.ognl.OgnlValueStackFactory;
 +import org.apache.struts2.ognl.SecurityMemberAccess;
 +import org.apache.struts2.ognl.accessor.CompoundRootAccessor;
 +import org.apache.struts2.ognl.accessor.RootAccessor;
 +import org.apache.struts2.ognl.accessor.XWorkMethodAccessor;
 +import org.apache.struts2.util.OgnlTextParser;
 +import org.apache.struts2.util.PatternMatcher;
 +import org.apache.struts2.util.StrutsLocalizedTextProvider;
 +import org.apache.struts2.util.TextParser;
 +import org.apache.struts2.util.ValueStack;
 +import org.apache.struts2.util.ValueStackFactory;
 +import org.apache.struts2.util.fs.DefaultFileManager;
 +import org.apache.struts2.util.fs.DefaultFileManagerFactory;
 +import org.apache.struts2.util.location.LocatableProperties;
 +import org.apache.struts2.util.reflection.ReflectionProvider;
 +import ognl.MethodAccessor;
 +import org.apache.commons.lang3.StringUtils;
 +import org.apache.logging.log4j.LogManager;
 +import org.apache.logging.log4j.Logger;
 +import org.apache.struts2.StrutsConstants;
 +import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor;
 +import org.apache.struts2.conversion.StrutsTypeConverterCreator;
 +import org.apache.struts2.conversion.StrutsTypeConverterHolder;
++import org.apache.struts2.factory.StrutsResultFactory;
 +import org.apache.struts2.ognl.OgnlGuard;
 +import org.apache.struts2.ognl.ProviderAllowlist;
 +import org.apache.struts2.ognl.StrutsOgnlGuard;
 +import org.apache.struts2.ognl.ThreadAllowlist;
 +
 +import java.io.Serial;
 +import java.util.ArrayList;
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.LinkedHashMap;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Optional;
 +import java.util.Set;
 +import java.util.TreeMap;
 +import java.util.TreeSet;
 +
 +
 +/**
 + * DefaultConfiguration
 + *
 + * @author Jason Carreira
 + *         Created Feb 24, 2003 7:38:06 AM
 + */
 +public class DefaultConfiguration implements Configuration {
 +
 +    public static final Map<String, Object> BOOTSTRAP_CONSTANTS;
 +
 +    static {
 +        Map<String, Object> constants = new HashMap<>();
 +        constants.put(StrutsConstants.STRUTS_DEVMODE, Boolean.FALSE);
 +        constants.put(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, 
Boolean.FALSE);
 +        constants.put(StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS, 
Boolean.TRUE);
 +        constants.put(StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_TYPE, 
OgnlCacheFactory.CacheType.BASIC);
 +        constants.put(StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE, 
10000);
 +        constants.put(StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_TYPE, 
OgnlCacheFactory.CacheType.BASIC);
 +        constants.put(StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE, 
10000);
 +        
constants.put(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, 
Boolean.FALSE);
 +        BOOTSTRAP_CONSTANTS = Collections.unmodifiableMap(constants);
 +    }
 +
 +    protected static final Logger LOG = 
LogManager.getLogger(DefaultConfiguration.class);
 +
 +    // Programmatic Action Configurations
 +    protected Map<String, PackageConfig> packageContexts = new 
LinkedHashMap<>();
 +    protected RuntimeConfiguration runtimeConfiguration;
 +    protected Container container;
 +    protected String defaultFrameworkBeanName;
 +    protected Set<String> loadedFileNames = new TreeSet<>();
 +    protected List<UnknownHandlerConfig> unknownHandlerStack;
 +
 +
 +    ObjectFactory objectFactory;
 +
 +    public DefaultConfiguration() {
 +        this(Container.DEFAULT_NAME);
 +    }
 +
 +    public DefaultConfiguration(String defaultBeanName) {
 +        this.defaultFrameworkBeanName = defaultBeanName;
 +    }
 +
 +
 +    @Override
 +    public PackageConfig getPackageConfig(String name) {
 +        return packageContexts.get(name);
 +    }
 +
 +    @Override
 +    public List<UnknownHandlerConfig> getUnknownHandlerStack() {
 +        return unknownHandlerStack;
 +    }
 +
 +    @Override
 +    public void setUnknownHandlerStack(List<UnknownHandlerConfig> 
unknownHandlerStack) {
 +        this.unknownHandlerStack = unknownHandlerStack;
 +    }
 +
 +    @Override
 +    public Set<String> getPackageConfigNames() {
 +        return packageContexts.keySet();
 +    }
 +
 +    @Override
 +    public Map<String, PackageConfig> getPackageConfigs() {
 +        return packageContexts;
 +    }
 +
 +    @Override
 +    public Set<String> getLoadedFileNames() {
 +        return loadedFileNames;
 +    }
 +
 +    @Override
 +    public RuntimeConfiguration getRuntimeConfiguration() {
 +        return runtimeConfiguration;
 +    }
 +
 +    /**
 +     * @return the container
 +     */
 +    @Override
 +    public Container getContainer() {
 +        return container;
 +    }
 +
 +    @Override
 +    public void addPackageConfig(String name, PackageConfig packageContext) {
 +        PackageConfig check = packageContexts.get(name);
 +        if (check != null) {
 +            if (check.getLocation() != null && packageContext.getLocation() 
!= null
 +                    && 
check.getLocation().equals(packageContext.getLocation())) {
 +                LOG.debug("The package name '{}' is already been loaded by 
the same location and could be removed: {}",
 +                        name, packageContext.getLocation());
 +            } else {
 +                throw new ConfigurationException("The package name '" + name
 +                        + "' at location "+packageContext.getLocation()
 +                        + " is already been used by another package at 
location " + check.getLocation(),
 +                        packageContext);
 +            }
 +        }
 +        packageContexts.put(name, packageContext);
 +    }
 +
 +    @Override
 +    public PackageConfig removePackageConfig(String packageName) {
 +        return packageContexts.remove(packageName);
 +    }
 +
 +    /**
 +     * Allows the configuration to clean up any resources used
 +     */
 +    @Override
 +    public void destroy() {
 +        packageContexts.clear();
 +        loadedFileNames.clear();
 +    }
 +
 +    @Override
 +    public void rebuildRuntimeConfiguration() {
 +        runtimeConfiguration = buildRuntimeConfiguration();
 +    }
 +
 +    /**
 +     * Calls the ConfigurationProviderFactory.getConfig() to tell it to 
reload the configuration and then calls
 +     * buildRuntimeConfiguration().
 +     *
 +     * @param providers list of ContainerProvider
 +     * @return list of package providers
 +     *
 +     * @throws ConfigurationException in case of any configuration errors
 +     */
 +    @Override
 +    public synchronized List<PackageProvider> 
reloadContainer(List<ContainerProvider> providers) throws 
ConfigurationException {
 +        packageContexts.clear();
 +        loadedFileNames.clear();
 +        List<PackageProvider> packageProviders = new ArrayList<>();
 +
 +        ContainerProperties props = new ContainerProperties();
 +        ContainerBuilder builder = new ContainerBuilder();
 +        Container bootstrap = createBootstrapContainer(providers);
 +        for (final ContainerProvider containerProvider : providers)
 +        {
 +            bootstrap.inject(containerProvider);
 +            containerProvider.init(this);
 +            containerProvider.register(builder, props);
 +        }
 +        props.setConstants(builder);
 +
 +        builder.factory(Configuration.class, new Factory<Configuration>() {
 +            @Override
 +            public Configuration create(Context context) throws Exception {
 +                return DefaultConfiguration.this;
 +            }
 +
 +            @Override
 +            public Class<? extends Configuration> type() {
 +                return DefaultConfiguration.this.getClass();
 +            }
 +        });
 +
 +        ActionContext oldContext = ActionContext.getContext();
 +        try {
 +            // Set the bootstrap container for the purposes of factory 
creation
 +
 +            setContext(bootstrap);
 +            container = builder.create(false);
 +            setContext(container);
 +            objectFactory = container.getInstance(ObjectFactory.class);
 +
 +            // Process the configuration providers first
 +            for (final ContainerProvider containerProvider : providers)
 +            {
 +                if (containerProvider instanceof PackageProvider) {
 +                    container.inject(containerProvider);
 +                    ((PackageProvider)containerProvider).loadPackages();
 +                    packageProviders.add((PackageProvider)containerProvider);
 +                }
 +            }
 +
 +            // Then process any package providers from the plugins
 +            Set<String> packageProviderNames = 
container.getInstanceNames(PackageProvider.class);
 +            for (String name : packageProviderNames) {
 +                PackageProvider provider = 
container.getInstance(PackageProvider.class, name);
 +                provider.init(this);
 +                provider.loadPackages();
 +                packageProviders.add(provider);
 +            }
 +
 +            rebuildRuntimeConfiguration();
 +        } finally {
 +            if (oldContext == null) {
 +                ActionContext.clear();
 +            }
 +        }
 +        return packageProviders;
 +    }
 +
 +    protected ActionContext setContext(Container cont) {
 +        ValueStack vs = 
cont.getInstance(ValueStackFactory.class).createValueStack();
 +        return ActionContext.of(vs.getContext()).bind();
 +    }
 +
 +    protected Container createBootstrapContainer(List<ContainerProvider> 
providers) {
 +        ContainerBuilder builder = new ContainerBuilder();
 +        boolean fmFactoryRegistered = false;
 +        for (ContainerProvider provider : providers) {
 +            if (provider instanceof FileManagerProvider) {
 +                provider.register(builder, null);
 +            }
 +            if (provider instanceof FileManagerFactoryProvider) {
 +                provider.register(builder, null);
 +                fmFactoryRegistered = true;
 +            }
 +        }
 +
 +        bootstrapFactories(builder);
 +        bootstrapTypeConverters(builder);
 +
 +        if (!fmFactoryRegistered) {
 +            builder.factory(FileManagerFactory.class, 
DefaultFileManagerFactory.class, Scope.SINGLETON);
 +        }
 +
 +        for (Map.Entry<String, Object> entry : 
BOOTSTRAP_CONSTANTS.entrySet()) {
 +            builder.constant(entry.getKey(), 
String.valueOf(entry.getValue()));
 +        }
 +
 +        return builder.create(true);
 +    }
 +
 +    public static ContainerBuilder bootstrapFactories(ContainerBuilder 
builder) {
 +        return builder
 +                // TODO: SpringObjectFactoryTest fails when these are 
SINGLETON
 +                .factory(ObjectFactory.class, Scope.PROTOTYPE)
 +                .factory(ActionFactory.class, DefaultActionFactory.class, 
Scope.PROTOTYPE)
-                 .factory(ResultFactory.class, DefaultResultFactory.class, 
Scope.PROTOTYPE)
++                .factory(ResultFactory.class, StrutsResultFactory.class, 
Scope.PROTOTYPE)
 +                .factory(InterceptorFactory.class, 
DefaultInterceptorFactory.class, Scope.PROTOTYPE)
 +                .factory(ValidatorFactory.class, 
DefaultValidatorFactory.class, Scope.PROTOTYPE)
 +                .factory(ConverterFactory.class, 
StrutsConverterFactory.class, Scope.PROTOTYPE)
 +                .factory(UnknownHandlerFactory.class, 
DefaultUnknownHandlerFactory.class, Scope.PROTOTYPE)
 +
 +                .factory(FileManager.class, "system", 
DefaultFileManager.class, Scope.SINGLETON)
 +                .factory(ReflectionProvider.class, 
OgnlReflectionProvider.class, Scope.SINGLETON)
 +                .factory(ValueStackFactory.class, 
OgnlValueStackFactory.class, Scope.SINGLETON)
 +
 +                .factory(XWorkConverter.class, Scope.SINGLETON)
 +                .factory(XWorkBasicConverter.class, Scope.SINGLETON)
 +                .factory(ConversionPropertiesProcessor.class, 
StrutsConversionPropertiesProcessor.class, Scope.SINGLETON)
 +                .factory(ConversionFileProcessor.class, 
DefaultConversionFileProcessor.class, Scope.SINGLETON)
 +                .factory(ConversionAnnotationProcessor.class, 
DefaultConversionAnnotationProcessor.class, Scope.SINGLETON)
 +                .factory(TypeConverterCreator.class, 
StrutsTypeConverterCreator.class, Scope.SINGLETON)
 +                .factory(TypeConverterHolder.class, 
StrutsTypeConverterHolder.class, Scope.SINGLETON)
 +
 +                .factory(TextProvider.class, "system", 
DefaultTextProvider.class, Scope.SINGLETON)
 +                .factory(LocalizedTextProvider.class, 
StrutsLocalizedTextProvider.class, Scope.SINGLETON)
 +                .factory(TextProviderFactory.class, 
StrutsTextProviderFactory.class, Scope.SINGLETON)
 +                .factory(LocaleProviderFactory.class, 
DefaultLocaleProviderFactory.class, Scope.SINGLETON)
 +                .factory(TextParser.class, OgnlTextParser.class, 
Scope.SINGLETON)
 +
 +                .factory(ObjectTypeDeterminer.class, 
DefaultObjectTypeDeterminer.class, Scope.SINGLETON)
 +                .factory(RootAccessor.class, CompoundRootAccessor.class, 
Scope.SINGLETON)
 +                .factory(MethodAccessor.class, XWorkMethodAccessor.class, 
Scope.SINGLETON)
 +
 +                .factory(ExpressionCacheFactory.class, 
DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON)
 +                .factory(BeanInfoCacheFactory.class, 
DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON)
 +                .factory(OgnlUtil.class, Scope.SINGLETON)
 +                .factory(SecurityMemberAccess.class, Scope.PROTOTYPE)
 +                .factory(OgnlGuard.class, StrutsOgnlGuard.class, 
Scope.SINGLETON)
 +                .factory(ProviderAllowlist.class, Scope.SINGLETON)
 +                .factory(ThreadAllowlist.class, Scope.SINGLETON)
 +
 +                .factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, 
Scope.SINGLETON);
 +    }
 +
 +    public static ContainerBuilder bootstrapTypeConverters(ContainerBuilder 
builder) {
 +        return builder
 +                .factory(TypeConverter.class, 
StrutsConstants.STRUTS_CONVERTER_COLLECTION, CollectionConverter.class, 
Scope.SINGLETON)
 +                .factory(TypeConverter.class, 
StrutsConstants.STRUTS_CONVERTER_ARRAY, ArrayConverter.class, Scope.SINGLETON)
 +                .factory(TypeConverter.class, 
StrutsConstants.STRUTS_CONVERTER_DATE, DateConverter.class, Scope.SINGLETON)
 +                .factory(TypeConverter.class, 
StrutsConstants.STRUTS_CONVERTER_NUMBER, NumberConverter.class, Scope.SINGLETON)
 +                .factory(TypeConverter.class, 
StrutsConstants.STRUTS_CONVERTER_STRING, StringConverter.class, 
Scope.SINGLETON);
 +    }
 +
 +    /**
 +     * <p>
 +     * This builds the internal runtime configuration used by Xwork for 
finding and configuring Actions from the
 +     * programmatic configuration data structures. All of the old runtime 
configuration will be discarded and rebuilt.
 +     * </p>
 +     *
 +     * <p>
 +     * It basically flattens the data structures to make the information 
easier to access.  It will take
 +     * an {@link ActionConfig} and combine its data with all inherited dast.  
For example, if the {@link ActionConfig}
 +     * is in a package that contains a global result and it also contains a 
result, the resulting {@link ActionConfig}
 +     * will have two results.
 +     * </p>
 +     *
 +     * @return runtime configuration
 +     * @throws ConfigurationException in case of any configuration errors
 +     */
 +    protected synchronized RuntimeConfiguration buildRuntimeConfiguration() 
throws ConfigurationException {
 +        Map<String, Map<String, ActionConfig>> namespaceActionConfigs = new 
LinkedHashMap<>();
 +        Map<String, String> namespaceConfigs = new LinkedHashMap<>();
 +
 +        for (PackageConfig packageConfig : packageContexts.values()) {
 +
 +            if (!packageConfig.isAbstract()) {
 +                String namespace = packageConfig.getNamespace();
 +                Map<String, ActionConfig> configs = 
namespaceActionConfigs.get(namespace);
 +
 +                if (configs == null) {
 +                    configs = new LinkedHashMap<>();
 +                }
 +
 +                Map<String, ActionConfig> actionConfigs = 
packageConfig.getAllActionConfigs();
 +
 +                for (Object o : actionConfigs.keySet()) {
 +                    String actionName = (String) o;
 +                    ActionConfig baseConfig = actionConfigs.get(actionName);
 +                    configs.put(actionName, 
buildFullActionConfig(packageConfig, baseConfig));
 +                }
 +
 +                namespaceActionConfigs.put(namespace, configs);
 +                if (packageConfig.getFullDefaultActionRef() != null) {
 +                    namespaceConfigs.put(namespace, 
packageConfig.getFullDefaultActionRef());
 +                }
 +            }
 +        }
 +
 +        PatternMatcher<int[]> matcher = 
container.getInstance(PatternMatcher.class);
 +        boolean appendNamedParameters = Boolean.parseBoolean(
 +                container.getInstance(String.class, 
StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS)
 +        );
 +        boolean fallbackToEmptyNamespace = Boolean.parseBoolean(
 +                Optional.ofNullable(container.getInstance(String.class, 
StrutsConstants.STRUTS_ACTION_CONFIG_FALLBACK_TO_EMPTY_NAMESPACE)).orElse("true")
 +        );
 +
 +        return new 
RuntimeConfigurationImpl(Collections.unmodifiableMap(namespaceActionConfigs),
 +                Collections.unmodifiableMap(namespaceConfigs), matcher, 
appendNamedParameters, fallbackToEmptyNamespace);
 +    }
 +
 +    private void setDefaultResults(Map<String, ResultConfig> results, 
PackageConfig packageContext) {
 +        String defaultResult = packageContext.getFullDefaultResultType();
 +
 +        for (Map.Entry<String, ResultConfig> entry : results.entrySet()) {
 +
 +            if (entry.getValue() == null) {
 +                ResultTypeConfig resultTypeConfig = 
packageContext.getAllResultTypeConfigs().get(defaultResult);
 +                entry.setValue(new ResultConfig.Builder(null, 
resultTypeConfig.getClassName()).build());
 +            }
 +        }
 +    }
 +
 +    /**
 +     * Builds the full runtime actionconfig with all of the defaults and 
inheritance
 +     *
 +     * @param packageContext the PackageConfig which holds the base config 
we're building from
 +     * @param baseConfig     the ActionConfig which holds only the 
configuration specific to itself, without the defaults
 +     *                       and inheritance
 +     * @return a full ActionConfig for runtime configuration with all of the 
inherited and default params
 +     * @throws org.apache.struts2.config.ConfigurationException
 +     *
 +     */
 +    private ActionConfig buildFullActionConfig(PackageConfig packageContext, 
ActionConfig baseConfig) throws ConfigurationException {
 +        Map<String, String> params = new TreeMap<>(baseConfig.getParams());
 +        Map<String, ResultConfig> results = new TreeMap<>();
 +
 +        if (!baseConfig.getPackageName().equals(packageContext.getName()) && 
packageContexts.containsKey(baseConfig.getPackageName())) {
 +            
results.putAll(packageContexts.get(baseConfig.getPackageName()).getAllGlobalResults());
 +        } else {
 +            results.putAll(packageContext.getAllGlobalResults());
 +        }
 +
 +              results.putAll(baseConfig.getResults());
 +
 +        setDefaultResults(results, packageContext);
 +
 +        List<InterceptorMapping> interceptors = new 
ArrayList<>(baseConfig.getInterceptors());
 +
 +        if (interceptors.size() <= 0) {
 +            String defaultInterceptorRefName = 
packageContext.getFullDefaultInterceptorRef();
 +
 +            if (defaultInterceptorRefName != null) {
 +                
interceptors.addAll(InterceptorBuilder.constructInterceptorReference(new 
PackageConfig.Builder(packageContext), defaultInterceptorRefName,
 +                        new LinkedHashMap<String, String>(), 
packageContext.getLocation(), objectFactory));
 +            }
 +        }
 +
 +        String methodRegex = container.getInstance(String.class, 
StrutsConstants.STRUTS_SMI_METHOD_REGEX);
 +        if (methodRegex == null) {
 +            methodRegex = ActionConfig.DEFAULT_METHOD_REGEX;
 +        }
 +
 +        LOG.debug("Using pattern [{}] to match allowed methods when SMI is 
disabled!", methodRegex);
 +
 +        return new ActionConfig.Builder(baseConfig)
 +            .addParams(params)
 +            .addResultConfigs(results)
 +            .defaultClassName(packageContext.getDefaultClassRef())  // fill 
in default if non class has been provided
 +            .interceptors(interceptors)
 +            
.setStrictMethodInvocation(packageContext.isStrictMethodInvocation())
 +            .setDefaultMethodRegex(methodRegex)
 +            
.addExceptionMappings(packageContext.getAllExceptionMappingConfigs())
 +            .build();
 +    }
 +
 +
 +    private static class RuntimeConfigurationImpl implements 
RuntimeConfiguration {
 +
 +        private final Map<String, Map<String, ActionConfig>> 
namespaceActionConfigs;
 +        private final Map<String, ActionConfigMatcher> 
namespaceActionConfigMatchers;
 +        private final NamespaceMatcher namespaceMatcher;
 +        private final Map<String, String> namespaceConfigs;
 +        private final boolean fallbackToEmptyNamespace;
 +
 +        public RuntimeConfigurationImpl(Map<String, Map<String, 
ActionConfig>> namespaceActionConfigs,
 +                                        Map<String, String> namespaceConfigs,
 +                                        PatternMatcher<int[]> matcher,
 +                                        boolean appendNamedParameters,
 +                                        boolean fallbackToEmptyNamespace)
 +        {
 +            this.namespaceActionConfigs = namespaceActionConfigs;
 +            this.namespaceConfigs = namespaceConfigs;
 +            this.fallbackToEmptyNamespace = fallbackToEmptyNamespace;
 +
 +            this.namespaceActionConfigMatchers = new LinkedHashMap<>();
 +            this.namespaceMatcher = new NamespaceMatcher(matcher, 
namespaceActionConfigs.keySet(), appendNamedParameters);
 +
 +            for (Map.Entry<String, Map<String, ActionConfig>> entry : 
namespaceActionConfigs.entrySet()) {
 +                ActionConfigMatcher configMatcher = new 
ActionConfigMatcher(matcher, entry.getValue(), true, appendNamedParameters);
 +                namespaceActionConfigMatchers.put(entry.getKey(), 
configMatcher);
 +            }
 +        }
 +
 +
 +        /**
 +         * Gets the configuration information for an action name, or returns 
null if the
 +         * name is not recognized.
 +         *
 +         * @param name      the name of the action
 +         * @param namespace the namespace for the action or null for the 
empty namespace, ""
 +         * @return the configuration information for action requested
 +         */
 +        @Override
 +        public ActionConfig getActionConfig(String namespace, String name) {
 +            ActionConfig config = findActionConfigInNamespace(namespace, 
name);
 +
 +            // try wildcarded namespaces
 +            if (config == null) {
 +                NamespaceMatch match = namespaceMatcher.match(namespace);
 +                if (match != null) {
 +                    config = findActionConfigInNamespace(match.getPattern(), 
name);
 +
 +                    // If config found, place all the matches found in the 
namespace processing in the action's parameters
 +                    if (config != null) {
 +                        config = new ActionConfig.Builder(config)
 +                                .addParams(match.getVariables())
 +                                .build();
 +                    }
 +                }
 +            }
 +
 +            // fail over to empty namespace
 +            if (config == null && shouldFallbackToEmptyNamespace(namespace)) {
 +                config = findActionConfigInNamespace("", name);
 +            }
 +
 +            return config;
 +        }
 +
 +        private boolean shouldFallbackToEmptyNamespace(String namespace) {
 +            return StringUtils.isNotBlank(namespace) && 
("/".equals(namespace) || fallbackToEmptyNamespace);
 +        }
 +
 +        private ActionConfig findActionConfigInNamespace(String namespace, 
String name) {
 +            ActionConfig config = null;
 +            if (namespace == null) {
 +                namespace = "";
 +            }
 +            Map<String, ActionConfig> actions = 
namespaceActionConfigs.get(namespace);
 +            if (actions != null) {
 +                config = actions.get(name);
 +                // Check wildcards
 +                if (config == null) {
 +                    config = 
namespaceActionConfigMatchers.get(namespace).match(name);
 +                    // fail over to default action
 +                    if (config == null) {
 +                        String defaultActionRef = 
namespaceConfigs.get(namespace);
 +                        if (defaultActionRef != null) {
 +                            config = actions.get(defaultActionRef);
 +                        }
 +                    }
 +                }
 +            }
 +            return config;
 +        }
 +
 +        /**
 +         * Gets the configuration settings for every action.
 +         *
 +         * @return a Map of namespace - > Map of ActionConfig objects, with 
the key being the action name
 +         */
 +        @Override
 +        public Map<String, Map<String, ActionConfig>>  getActionConfigs() {
 +            return namespaceActionConfigs;
 +        }
 +
 +        @Override
 +        public String toString() {
 +            StringBuilder buff = new StringBuilder("RuntimeConfiguration - 
actions are\n");
 +
 +            for (Map.Entry<String, Map<String, ActionConfig>> entry : 
namespaceActionConfigs.entrySet()) {
 +                Map<String, ActionConfig> actionConfigs = entry.getValue();
 +
 +                for (String s : actionConfigs.keySet()) {
 +                    
buff.append(entry.getKey()).append("/").append(s).append("\n");
 +                }
 +            }
 +
 +            return buff.toString();
 +        }
 +    }
 +
 +    class ContainerProperties extends LocatableProperties {
 +        @Serial
 +        private static final long serialVersionUID = -7320625750836896089L;
 +
 +        @Override
 +        public Object setProperty(String key, String value) {
 +            String oldValue = getProperty(key);
 +            if (LOG.isInfoEnabled() && oldValue != null && 
!oldValue.equals(value) && !defaultFrameworkBeanName.equals(oldValue)) {
 +                LOG.info("Overriding property {} - old value: {} new value: 
{}", key, oldValue, value);
 +            }
 +            return super.setProperty(key, value);
 +        }
 +
 +        public void setConstants(ContainerBuilder builder) {
 +            for (Object keyobj : keySet()) {
 +                String key = (String)keyobj;
 +                builder.factory(String.class, key, new 
LocatableConstantFactory<>(getProperty(key), getPropertyLocation(key)));
 +            }
 +        }
 +    }
 +}
diff --cc 
core/src/main/java/org/apache/struts2/factory/DefaultResultFactory.java
index 202514ccd,000000000..54efb6972
mode 100644,000000..100644
--- a/core/src/main/java/org/apache/struts2/factory/DefaultResultFactory.java
+++ b/core/src/main/java/org/apache/struts2/factory/DefaultResultFactory.java
@@@ -1,78 -1,0 +1,81 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *  http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.struts2.factory;
 +
 +import org.apache.struts2.ObjectFactory;
 +import org.apache.struts2.Result;
 +import org.apache.struts2.config.ConfigurationException;
 +import org.apache.struts2.config.entities.ResultConfig;
 +import org.apache.struts2.inject.Inject;
 +import org.apache.struts2.util.reflection.ReflectionException;
 +import org.apache.struts2.util.reflection.ReflectionExceptionHandler;
 +import org.apache.struts2.util.reflection.ReflectionProvider;
 +
 +import java.util.Map;
 +
 +/**
 + * Default implementation
++ *
++ * @deprecated since 6.7.0, use {@link StrutsResultFactory} instead.
 + */
++@Deprecated
 +public class DefaultResultFactory implements ResultFactory {
 +
 +    private ObjectFactory objectFactory;
 +    private ReflectionProvider reflectionProvider;
 +
 +    @Inject
 +    public void setObjectFactory(ObjectFactory objectFactory) {
 +        this.objectFactory = objectFactory;
 +    }
 +
 +    @Inject
 +    public void setReflectionProvider(ReflectionProvider reflectionProvider) {
 +        this.reflectionProvider = reflectionProvider;
 +    }
 +
 +    public Result buildResult(ResultConfig resultConfig, Map<String, Object> 
extraContext) throws Exception {
 +        String resultClassName = resultConfig.getClassName();
 +        if (resultClassName == null) {
 +            return null;
 +        }
 +
 +        Object o = objectFactory.buildBean(resultClassName, extraContext);
 +
 +        if (!(o instanceof Result result)) {
 +            throw new ConfigurationException("Class [" + resultClassName + "] 
does not implement Result", resultConfig);
 +        }
 +
 +        Map<String, String> params = resultConfig.getParams();
 +        if (params != null) {
 +            for (Map.Entry<String, String> paramEntry : params.entrySet()) {
 +                try {
 +                    reflectionProvider.setProperty(paramEntry.getKey(), 
paramEntry.getValue(), result, extraContext, true);
 +                } catch (ReflectionException ex) {
 +                    if (result instanceof ReflectionExceptionHandler 
reflectionExceptionHandler) {
 +                        reflectionExceptionHandler.handle(ex);
 +                    }
 +                }
 +            }
 +        }
 +
 +        return result;
 +    }
 +
 +}
diff --cc 
core/src/test/java/org/apache/struts2/interceptor/ChainingInterceptorWithConfigTest.java
index 5d2e21dbc,000000000..211e7329b
mode 100644,000000..100644
--- 
a/core/src/test/java/org/apache/struts2/interceptor/ChainingInterceptorWithConfigTest.java
+++ 
b/core/src/test/java/org/apache/struts2/interceptor/ChainingInterceptorWithConfigTest.java
@@@ -1,127 -1,0 +1,128 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *  http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.struts2.interceptor;
 +
 +import org.apache.struts2.Action;
 +import org.apache.struts2.ActionChainResult;
 +import org.apache.struts2.ActionProxy;
 +import org.apache.struts2.ActionProxyFactory;
 +import org.apache.struts2.DefaultActionProxyFactory;
 +import org.apache.struts2.ObjectFactory;
 +import org.apache.struts2.SimpleAction;
 +import org.apache.struts2.XWorkTestCase;
 +import org.apache.struts2.config.Configuration;
 +import org.apache.struts2.config.ConfigurationException;
 +import org.apache.struts2.config.ConfigurationProvider;
 +import org.apache.struts2.config.entities.ActionConfig;
 +import org.apache.struts2.config.entities.InterceptorConfig;
 +import org.apache.struts2.config.entities.InterceptorMapping;
 +import org.apache.struts2.config.entities.PackageConfig;
 +import org.apache.struts2.config.entities.ResultConfig;
 +import org.apache.struts2.config.providers.XmlConfigurationProvider;
 +import org.apache.struts2.inject.ContainerBuilder;
 +import org.apache.struts2.util.location.LocatableProperties;
 +import org.apache.struts2.TestResult;
 +import org.apache.struts2.config.StrutsXmlConfigurationProvider;
 +
 +import java.util.Collections;
 +import java.util.HashMap;
++import java.util.Map;
 +
 +
 +/**
 + * Unit test for {@link ChainingInterceptor} with a configuration provider.
 + */
 +public class ChainingInterceptorWithConfigTest extends XWorkTestCase {
 +
 +    static String CHAINED_ACTION = "chainedAction";
 +    static String CHAINTO_ACTION = "chaintoAction";
 +    ObjectFactory objectFactory;
 +
 +    public void testTwoExcludesPropertiesChained() throws Exception {
 +        assertNotNull(objectFactory);
 +        ActionProxy proxy = actionProxyFactory.createActionProxy("", 
CHAINED_ACTION, null, null);
 +        SimpleAction chainedAction = (SimpleAction) proxy.getAction();
 +        chainedAction.setBar(1);
 +        chainedAction.setFoo(1);
 +        chainedAction.setBlah("WW-4528");
 +        proxy.execute();
 +    }
 +
 +    @Override
 +    protected void setUp() throws Exception {
 +        super.setUp();
 +        XmlConfigurationProvider provider = new 
StrutsXmlConfigurationProvider("xwork-default.xml");
 +        container.inject(provider);
 +        this.objectFactory = container.getInstance(ObjectFactory.class);
 +        loadConfigurationProviders(provider, new MockConfigurationProvider());
 +    }
 +
 +
 +    private class MockConfigurationProvider implements ConfigurationProvider {
 +        private Configuration config;
 +
 +        public void init(Configuration configuration) throws 
ConfigurationException {
 +            this.config = configuration;
 +        }
 +
 +        public boolean needsReload() {
 +            return false;
 +        }
 +
 +        public void destroy() {
 +        }
 +
 +
 +        public void register(ContainerBuilder builder, LocatableProperties 
props) throws ConfigurationException {
 +            if (!builder.contains(ObjectFactory.class)) {
 +                builder.factory(ObjectFactory.class);
 +            }
 +            if (!builder.contains(ActionProxyFactory.class)) {
 +                builder.factory(ActionProxyFactory.class, 
DefaultActionProxyFactory.class);
 +            }
 +        }
 +
 +        public void loadPackages() throws ConfigurationException {
 +            HashMap<String, String> interceptorParams = new HashMap<>();
 +            interceptorParams.put("excludes", "blah,bar");
 +
-             HashMap successParams1 = new HashMap();
++            Map<String, String> successParams1 = new HashMap<>();
 +            successParams1.put("propertyName", "baz");
-             successParams1.put("expectedValue", 1);
++            successParams1.put("expectedValue", "1");
 +
-             HashMap successParams2 = new HashMap();
++            Map<String, String> successParams2 = new HashMap<>();
 +            successParams2.put("propertyName", "blah");
 +            successParams2.put("expectedValue", null);
 +
 +            InterceptorConfig chainingInterceptorConfig = new 
InterceptorConfig.Builder("chainStack", 
ChainingInterceptor.class.getName()).build();
 +            PackageConfig packageConfig = new PackageConfig.Builder("default")
 +                .addActionConfig(CHAINED_ACTION, new 
ActionConfig.Builder("defaultPackage", CHAINED_ACTION, 
SimpleAction.class.getName())
 +                    .addResultConfig(new ResultConfig.Builder(Action.ERROR, 
ActionChainResult.class.getName()).addParam("actionName", 
CHAINTO_ACTION).build())
 +                    .build())
 +                .addActionConfig(CHAINTO_ACTION, new 
ActionConfig.Builder("defaultPackage", CHAINTO_ACTION, 
SimpleAction.class.getName())
 +                    .addInterceptors(Collections.singletonList(new 
InterceptorMapping("chainStack", 
objectFactory.buildInterceptor(chainingInterceptorConfig, interceptorParams))))
 +                    .addResultConfig(new ResultConfig.Builder(Action.SUCCESS, 
TestResult.class.getName()).addParams(successParams1).build())
 +                    .addResultConfig(new ResultConfig.Builder(Action.ERROR, 
TestResult.class.getName()).addParams(successParams2).build())
 +                    .build())
 +                .build();
 +            config.addPackageConfig("defaultPackage", packageConfig);
 +            config.addPackageConfig("default", new 
PackageConfig.Builder(packageConfig).name("default").build());
 +        }
 +    }
 +}
diff --cc 
plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
index fb80fae66,b6a9de4be..6aff13694
--- 
a/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
+++ 
b/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
@@@ -18,31 -18,30 +18,30 @@@
   */
  package org.apache.struts2.convention;
  
 -import com.opensymphony.xwork2.ActionChainResult;
 -import com.opensymphony.xwork2.ActionContext;
 -import com.opensymphony.xwork2.FileManager;
 -import com.opensymphony.xwork2.FileManagerFactory;
 -import com.opensymphony.xwork2.ObjectFactory;
 -import com.opensymphony.xwork2.Result;
 -import com.opensymphony.xwork2.config.Configuration;
 -import com.opensymphony.xwork2.config.entities.ActionConfig;
 -import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
 -import com.opensymphony.xwork2.config.entities.InterceptorConfig;
 -import com.opensymphony.xwork2.config.entities.InterceptorMapping;
 -import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
 -import com.opensymphony.xwork2.config.entities.PackageConfig;
 -import com.opensymphony.xwork2.config.entities.ResultConfig;
 -import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
 -import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
 -import com.opensymphony.xwork2.factory.DefaultInterceptorFactory;
 -import com.opensymphony.xwork2.inject.Container;
 -import com.opensymphony.xwork2.inject.Scope.Strategy;
 -import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
 -import com.opensymphony.xwork2.util.TextParseUtil;
 -import com.opensymphony.xwork2.util.fs.DefaultFileManager;
 -import com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory;
 -import com.opensymphony.xwork2.util.reflection.ReflectionException;
 +import org.apache.struts2.ActionChainResult;
 +import org.apache.struts2.ActionContext;
 +import org.apache.struts2.FileManager;
 +import org.apache.struts2.FileManagerFactory;
 +import org.apache.struts2.ObjectFactory;
 +import org.apache.struts2.Result;
 +import org.apache.struts2.config.Configuration;
 +import org.apache.struts2.config.entities.ActionConfig;
 +import org.apache.struts2.config.entities.ExceptionMappingConfig;
 +import org.apache.struts2.config.entities.InterceptorConfig;
 +import org.apache.struts2.config.entities.InterceptorMapping;
 +import org.apache.struts2.config.entities.InterceptorStackConfig;
 +import org.apache.struts2.config.entities.PackageConfig;
 +import org.apache.struts2.config.entities.ResultConfig;
 +import org.apache.struts2.config.entities.ResultTypeConfig;
 +import org.apache.struts2.config.impl.DefaultConfiguration;
 +import org.apache.struts2.factory.DefaultInterceptorFactory;
- import org.apache.struts2.factory.DefaultResultFactory;
 +import org.apache.struts2.inject.Container;
 +import org.apache.struts2.inject.Scope.Strategy;
 +import org.apache.struts2.ognl.OgnlReflectionProvider;
 +import org.apache.struts2.util.TextParseUtil;
 +import org.apache.struts2.util.fs.DefaultFileManager;
 +import org.apache.struts2.util.fs.DefaultFileManagerFactory;
 +import org.apache.struts2.util.reflection.ReflectionException;
  import junit.framework.TestCase;
  import org.apache.commons.lang3.StringUtils;
  import org.apache.struts2.convention.actions.DefaultResultPathAction;

Reply via email to