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

lukaszlenart pushed a commit to branch release/struts-6-8-x
in repository https://gitbox.apache.org/repos/asf/struts.git


The following commit(s) were added to refs/heads/release/struts-6-8-x by this 
push:
     new 18d6e77bf WW-5514: Make ProxyUtil cache configurable via struts 
constants (#1573)
18d6e77bf is described below

commit 18d6e77bf2cb65816b09910483706695077b584d
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sat Feb 21 18:17:39 2026 +0100

    WW-5514: Make ProxyUtil cache configurable via struts constants (#1573)
    
    * fix(ognl): make ProxyUtil cache configurable via struts constants
    
    Makes the ProxyUtil cache type configurable through Struts constants,
    allowing applications to use BASIC cache type (default) without
    requiring Caffeine as a mandatory dependency.
    
    New configuration properties:
    - struts.proxy.cacheType: basic (default), lru, or wtlfu
    - struts.proxy.cacheMaxSize: 10000 (default)
    
    Fixes WW-5514
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-Authored-By: Claude <[email protected]>
    
    * refactor(ognl): use LazyRef for proxy caches and reset on factory change
    
    Extract lazy initialization into reusable LazyRef<T> utility with
    double-checked locking and reset support. ProxyUtil.setProxyCacheFactory()
    now resets both caches so they are recreated with the new factory,
    fixing the bug where caches were never refreshed after factory changes.
    Default proxy cache type changed from 'basic' to 'wtlfu' for consistency
    with expression and beanInfo caches. Fix @since version to 6.9.0.
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-Authored-By: Claude <[email protected]>
    
    ---------
    
    Co-authored-by: Claude <[email protected]>
---
 .../xwork2/config/impl/DefaultConfiguration.java   |  7 +++
 .../xwork2/ognl/ProxyCacheFactory.java             | 31 ++++++++++
 .../xwork2/ognl/StrutsProxyCacheFactory.java       | 44 ++++++++++++++
 .../java/com/opensymphony/xwork2/util/LazyRef.java | 71 ++++++++++++++++++++++
 .../com/opensymphony/xwork2/util/ProxyUtil.java    | 61 +++++++++++++++----
 .../xwork2/util/StrutsProxyCacheFactoryBean.java   | 38 ++++++++++++
 .../java/org/apache/struts2/StrutsConstants.java   | 14 +++++
 .../org/apache/struts2/default.properties          |  7 +++
 core/src/main/resources/struts-beans.xml           |  3 +
 9 files changed, 265 insertions(+), 11 deletions(-)

diff --git 
a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
 
b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
index 8990ba129..a2f73879d 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
@@ -82,6 +82,8 @@ import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory;
 import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
 import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
 import com.opensymphony.xwork2.ognl.ExpressionCacheFactory;
+import com.opensymphony.xwork2.ognl.ProxyCacheFactory;
+import com.opensymphony.xwork2.ognl.StrutsProxyCacheFactory;
 import com.opensymphony.xwork2.ognl.OgnlCacheFactory;
 import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
 import com.opensymphony.xwork2.ognl.OgnlUtil;
@@ -93,6 +95,7 @@ import 
com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor;
 import com.opensymphony.xwork2.util.OgnlTextParser;
 import com.opensymphony.xwork2.util.PatternMatcher;
 import com.opensymphony.xwork2.util.StrutsLocalizedTextProvider;
+import com.opensymphony.xwork2.util.StrutsProxyCacheFactoryBean;
 import com.opensymphony.xwork2.util.TextParser;
 import com.opensymphony.xwork2.util.ValueStack;
 import com.opensymphony.xwork2.util.ValueStackFactory;
@@ -143,6 +146,8 @@ public class DefaultConfiguration implements Configuration {
         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_PROXY_CACHE_TYPE, 
OgnlCacheFactory.CacheType.BASIC);
+        constants.put(StrutsConstants.STRUTS_PROXY_CACHE_MAXSIZE, 10000);
         constants.put(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, 
Boolean.FALSE);
         BOOTSTRAP_CONSTANTS = Collections.unmodifiableMap(constants);
     }
@@ -394,6 +399,8 @@ public class DefaultConfiguration implements Configuration {
 
                 .factory(ExpressionCacheFactory.class, 
DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON)
                 .factory(BeanInfoCacheFactory.class, 
DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON)
+                .factory(ProxyCacheFactory.class, 
StrutsProxyCacheFactory.class, Scope.SINGLETON)
+                .factory(StrutsProxyCacheFactoryBean.class, Scope.SINGLETON)
                 .factory(OgnlUtil.class, Scope.SINGLETON)
                 .factory(SecurityMemberAccess.class, Scope.PROTOTYPE)
                 .factory(OgnlGuard.class, StrutsOgnlGuard.class, 
Scope.SINGLETON)
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/ognl/ProxyCacheFactory.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/ProxyCacheFactory.java
new file mode 100644
index 000000000..4bb63453a
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/ProxyCacheFactory.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.opensymphony.xwork2.ognl;
+
+/**
+ * A factory interface for ProxyUtil cache to be used with Struts DI mechanism.
+ * This allows the proxy detection cache type to be configurable via Struts 
constants.
+ *
+ * @param <Key>   The type for the cache key entries
+ * @param <Value> The type for the cache value entries
+ * @since 6.9.0
+ */
+public interface ProxyCacheFactory<Key, Value> extends OgnlCacheFactory<Key, 
Value> {
+
+}
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/ognl/StrutsProxyCacheFactory.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/StrutsProxyCacheFactory.java
new file mode 100644
index 000000000..9f4571996
--- /dev/null
+++ 
b/core/src/main/java/com/opensymphony/xwork2/ognl/StrutsProxyCacheFactory.java
@@ -0,0 +1,44 @@
+/*
+ * 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 com.opensymphony.xwork2.ognl;
+
+import com.opensymphony.xwork2.inject.Inject;
+import org.apache.commons.lang3.EnumUtils;
+import org.apache.struts2.StrutsConstants;
+
+/**
+ * Struts Proxy Cache factory implementation for ProxyUtil caches.
+ * <p>
+ * This factory is used to create caches for proxy detection in ProxyUtil.
+ * The cache type and size can be configured via Struts constants.
+ *
+ * @param <Key>   The type for the cache key entries
+ * @param <Value> The type for the cache value entries
+ * @since 6.9.0
+ */
+public class StrutsProxyCacheFactory<Key, Value> extends 
DefaultOgnlCacheFactory<Key, Value>
+        implements ProxyCacheFactory<Key, Value> {
+
+    @Inject
+    public StrutsProxyCacheFactory(
+            @Inject(value = StrutsConstants.STRUTS_PROXY_CACHE_MAXSIZE) String 
cacheMaxSize,
+            @Inject(value = StrutsConstants.STRUTS_PROXY_CACHE_TYPE) String 
defaultCacheType) {
+        super(Integer.parseInt(cacheMaxSize), 
EnumUtils.getEnumIgnoreCase(CacheType.class, defaultCacheType));
+    }
+}
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/LazyRef.java 
b/core/src/main/java/com/opensymphony/xwork2/util/LazyRef.java
new file mode 100644
index 000000000..113ca6bc9
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/util/LazyRef.java
@@ -0,0 +1,71 @@
+/*
+ * 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 com.opensymphony.xwork2.util;
+
+import java.util.function.Supplier;
+
+/**
+ * A thread-safe lazy reference that computes its value on first access using
+ * double-checked locking. The cached value can be invalidated via {@link 
#reset()},
+ * causing the next {@link #get()} call to recompute the value.
+ *
+ * @param <T> the type of the lazily computed value
+ * @since 6.9.0
+ */
+public class LazyRef<T> implements Supplier<T> {
+
+    private final Supplier<T> factory;
+    private volatile T value;
+
+    /**
+     * Creates a new LazyRef with the given factory supplier.
+     *
+     * @param factory the supplier used to compute the value; must not be null
+     */
+    public LazyRef(Supplier<T> factory) {
+        this.factory = factory;
+    }
+
+    /**
+     * Returns the cached value, computing it on first access or after a 
{@link #reset()}.
+     *
+     * @return the computed value
+     */
+    @Override
+    public T get() {
+        T result = value;
+        if (result == null) {
+            synchronized (this) {
+                result = value;
+                if (result == null) {
+                    result = factory.get();
+                    value = result;
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Invalidates the cached value so the next {@link #get()} call recomputes 
it.
+     */
+    public void reset() {
+        value = null;
+    }
+}
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java 
b/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
index 22c344446..c3c4e1133 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
@@ -21,6 +21,7 @@ package com.opensymphony.xwork2.util;
 import com.opensymphony.xwork2.ognl.DefaultOgnlCacheFactory;
 import com.opensymphony.xwork2.ognl.OgnlCache;
 import com.opensymphony.xwork2.ognl.OgnlCacheFactory;
+import com.opensymphony.xwork2.ognl.ProxyCacheFactory;
 import org.apache.commons.lang3.reflect.ConstructorUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.apache.commons.lang3.reflect.MethodUtils;
@@ -41,7 +42,6 @@ import static java.lang.reflect.Modifier.isPublic;
  * <p>
  * Various utility methods dealing with proxies
  * </p>
- *
  */
 public class ProxyUtil {
     private static final String SPRING_ADVISED_CLASS_NAME = 
"org.springframework.aop.framework.Advised";
@@ -51,15 +51,45 @@ public class ProxyUtil {
     private static final String HIBERNATE_HIBERNATEPROXY_CLASS_NAME = 
"org.hibernate.proxy.HibernateProxy";
     private static final int CACHE_MAX_SIZE = 10000;
     private static final int CACHE_INITIAL_CAPACITY = 256;
-    private static final OgnlCache<Class<?>, Boolean> isProxyCache = new 
DefaultOgnlCacheFactory<Class<?>, Boolean>(
-            CACHE_MAX_SIZE, OgnlCacheFactory.CacheType.WTLFU, 
CACHE_INITIAL_CAPACITY).buildOgnlCache();
-    private static final OgnlCache<Member, Boolean> isProxyMemberCache = new 
DefaultOgnlCacheFactory<Member, Boolean>(
-            CACHE_MAX_SIZE, OgnlCacheFactory.CacheType.WTLFU, 
CACHE_INITIAL_CAPACITY).buildOgnlCache();
+
+    // Holder for the cache factory (set by container)
+    private static volatile ProxyCacheFactory<?, ?> cacheFactory;
+
+    // Lazy-initialized caches with reset support
+    private static final LazyRef<OgnlCache<Class<?>, Boolean>> isProxyCache =
+            new LazyRef<>(ProxyUtil::createCache);
+    private static final LazyRef<OgnlCache<Member, Boolean>> 
isProxyMemberCache =
+            new LazyRef<>(ProxyUtil::createCache);
+
+    /**
+     * Sets the cache factory. Called by the container during initialization.
+     * Resets existing caches so they are recreated with the new factory.
+     *
+     * @param factory the cache factory to use for creating proxy caches
+     * @since 6.9.0
+     */
+    public static void setProxyCacheFactory(ProxyCacheFactory<?, ?> factory) {
+        cacheFactory = factory;
+        isProxyCache.reset();
+        isProxyMemberCache.reset();
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <K, V> OgnlCache<K, V> createCache() {
+        if (cacheFactory != null) {
+            return ((ProxyCacheFactory<K, V>) cacheFactory).buildOgnlCache(
+                    CACHE_MAX_SIZE, CACHE_INITIAL_CAPACITY, 0.75f, 
cacheFactory.getDefaultCacheType());
+        }
+        // Fallback to BASIC if container hasn't initialized yet
+        return new DefaultOgnlCacheFactory<K, V>(
+                CACHE_MAX_SIZE, OgnlCacheFactory.CacheType.BASIC, 
CACHE_INITIAL_CAPACITY).buildOgnlCache();
+    }
 
     /**
      * Determine the ultimate target class of the given instance, traversing
      * not only a top-level proxy but any number of nested proxies as well 
&mdash;
      * as long as possible without side effects.
+     *
      * @param candidate the instance to check (might be a proxy)
      * @return the ultimate target class (or the plain class of the given
      * object as fallback; never {@code null})
@@ -78,24 +108,26 @@ public class ProxyUtil {
 
     /**
      * Check whether the given object is a proxy.
+     *
      * @param object the object to check
      */
     public static boolean isProxy(Object object) {
         if (object == null) return false;
         Class<?> clazz = object.getClass();
-        Boolean flag = isProxyCache.get(clazz);
+        Boolean flag = isProxyCache.get().get(clazz);
         if (flag != null) {
             return flag;
         }
 
         boolean isProxy = isSpringAopProxy(object) || isHibernateProxy(object);
 
-        isProxyCache.put(clazz, isProxy);
+        isProxyCache.get().put(clazz, isProxy);
         return isProxy;
     }
 
     /**
      * Check whether the given member is a proxy member of a proxy object or 
is a static proxy member.
+     *
      * @param member the member to check
      * @param object the object to check
      */
@@ -104,14 +136,14 @@ public class ProxyUtil {
             return false;
         }
 
-        Boolean flag = isProxyMemberCache.get(member);
+        Boolean flag = isProxyMemberCache.get().get(member);
         if (flag != null) {
             return flag;
         }
 
         boolean isProxyMember = isSpringProxyMember(member) || 
isHibernateProxyMember(member);
 
-        isProxyMemberCache.put(member, isProxyMember);
+        isProxyMemberCache.get().put(member, isProxyMember);
         return isProxyMember;
     }
 
@@ -147,6 +179,7 @@ public class ProxyUtil {
      * Determine the ultimate target class of the given spring bean instance, 
traversing
      * not only a top-level spring proxy but any number of nested spring 
proxies as well &mdash;
      * as long as possible without side effects, that is, just for singleton 
targets.
+     *
      * @param candidate the instance to check (might be a spring AOP proxy)
      * @return the ultimate target class (or the plain class of the given
      * object as fallback; never {@code null})
@@ -170,6 +203,7 @@ public class ProxyUtil {
 
     /**
      * Check whether the given object is a Spring proxy.
+     *
      * @param object the object to check
      */
     private static boolean isSpringAopProxy(Object object) {
@@ -180,6 +214,7 @@ public class ProxyUtil {
 
     /**
      * Check whether the given member is a member of a spring proxy.
+     *
      * @param member the member to check
      */
     private static boolean isSpringProxyMember(Member member) {
@@ -201,6 +236,7 @@ public class ProxyUtil {
 
     /**
      * Obtain the singleton target object behind the given spring proxy, if 
any.
+     *
      * @param candidate the (potential) spring proxy to check
      * @return the singleton target object, or {@code null} in any other case
      * (not a spring proxy, not an existing singleton target)
@@ -221,6 +257,7 @@ public class ProxyUtil {
 
     /**
      * Check whether the specified class is a CGLIB-generated class.
+     *
      * @param clazz the class to check
      */
     private static boolean isCglibProxyClass(Class<?> clazz) {
@@ -229,7 +266,8 @@ public class ProxyUtil {
 
     /**
      * Check whether the given class implements an interface with a given 
class name.
-     * @param clazz the class to check
+     *
+     * @param clazz          the class to check
      * @param ifaceClassName the interface class name to check
      */
     private static boolean implementsInterface(Class<?> clazz, String 
ifaceClassName) {
@@ -243,7 +281,8 @@ public class ProxyUtil {
 
     /**
      * Check whether the given class has a given member.
-     * @param clazz the class to check
+     *
+     * @param clazz  the class to check
      * @param member the member to check
      */
     private static boolean hasMember(Class<?> clazz, Member member) {
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/util/StrutsProxyCacheFactoryBean.java
 
b/core/src/main/java/com/opensymphony/xwork2/util/StrutsProxyCacheFactoryBean.java
new file mode 100644
index 000000000..1cd1d2d40
--- /dev/null
+++ 
b/core/src/main/java/com/opensymphony/xwork2/util/StrutsProxyCacheFactoryBean.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.opensymphony.xwork2.util;
+
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.ognl.ProxyCacheFactory;
+
+/**
+ * Bean that wires the ProxyCacheFactory to ProxyUtil during container 
initialization.
+ * <p>
+ * This bean is created by the container and receives the configured 
ProxyCacheFactory
+ * via dependency injection, then passes it to the static ProxyUtil class.
+ *
+ * @since 6.9.0
+ */
+public class StrutsProxyCacheFactoryBean {
+
+    @Inject
+    public StrutsProxyCacheFactoryBean(ProxyCacheFactory<?, ?> 
proxyCacheFactory) {
+        ProxyUtil.setProxyCacheFactory(proxyCacheFactory);
+    }
+}
diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java 
b/core/src/main/java/org/apache/struts2/StrutsConstants.java
index e666df61a..0ac751640 100644
--- a/core/src/main/java/org/apache/struts2/StrutsConstants.java
+++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java
@@ -517,4 +517,18 @@ public final class StrutsConstants {
      */
     public static final String STRUTS_CSP_NONCE_READER = 
"struts.csp.nonce.reader";
     public static final String STRUTS_CSP_NONCE_SOURCE = 
"struts.csp.nonce.source";
+
+    /**
+     * Specifies the type of cache to use for proxy detection in ProxyUtil.
+     * Valid values defined in {@link 
com.opensymphony.xwork2.ognl.OgnlCacheFactory.CacheType}.
+     * Default is 'basic' (no Caffeine dependency required).
+     * @since 6.8.0
+     */
+    public static final String STRUTS_PROXY_CACHE_TYPE = 
"struts.proxy.cacheType";
+
+    /**
+     * Specifies the maximum cache size for proxy detection caches in 
ProxyUtil.
+     * @since 6.8.0
+     */
+    public static final String STRUTS_PROXY_CACHE_MAXSIZE = 
"struts.proxy.cacheMaxSize";
 }
diff --git a/core/src/main/resources/org/apache/struts2/default.properties 
b/core/src/main/resources/org/apache/struts2/default.properties
index 7dd782ccb..3eedc2437 100644
--- a/core/src/main/resources/org/apache/struts2/default.properties
+++ b/core/src/main/resources/org/apache/struts2/default.properties
@@ -247,6 +247,13 @@ struts.ognl.beanInfoCacheType=wtlfu
 ### application-specific needs.
 struts.ognl.beanInfoCacheMaxSize=10000
 
+### Specifies the type of cache to use for proxy detection in ProxyUtil.
+### Valid values: basic, lru, wtlfu. Default is 'wtlfu'.
+struts.proxy.cacheType=wtlfu
+
+### Specifies the maximum cache size for proxy detection caches.
+struts.proxy.cacheMaxSize=10000
+
 ### Indicates if Dispatcher should handle unexpected exceptions by calling 
sendError()
 ### or simply rethrow it as a ServletException to allow future processing by 
other frameworks like Spring Security
 struts.handle.exception=true
diff --git a/core/src/main/resources/struts-beans.xml 
b/core/src/main/resources/struts-beans.xml
index be1838664..bb0ede480 100644
--- a/core/src/main/resources/struts-beans.xml
+++ b/core/src/main/resources/struts-beans.xml
@@ -255,6 +255,9 @@
           
class="com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory" 
scope="singleton"/>
     <bean type="com.opensymphony.xwork2.ognl.BeanInfoCacheFactory" 
name="struts"
           class="com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory" 
scope="singleton"/>
+    <bean type="com.opensymphony.xwork2.ognl.ProxyCacheFactory" name="struts"
+          class="com.opensymphony.xwork2.ognl.StrutsProxyCacheFactory" 
scope="singleton"/>
+    <bean class="com.opensymphony.xwork2.util.StrutsProxyCacheFactoryBean" 
scope="singleton"/>
 
     <bean type="org.apache.struts2.url.QueryStringBuilder" 
name="strutsQueryStringBuilder"
           class="org.apache.struts2.url.StrutsQueryStringBuilder" 
scope="singleton"/>

Reply via email to