You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by ya...@apache.org on 2019/09/07 10:02:08 UTC
[struts] branch struts-2-5-x updated: Proposed WW-5035 enhancement:
- Provide cache clearing methods for OgnlUtil (expression cache,
BeanInfo cache). - Provide methods to check the cache sizes (entry number
for expression cache,
BeanInfo cache). - Provide static method to clear the OgnlRuntime cache
(convenience method).
This is an automated email from the ASF dual-hosted git repository.
yasserzamani pushed a commit to branch struts-2-5-x
in repository https://gitbox.apache.org/repos/asf/struts.git
The following commit(s) were added to refs/heads/struts-2-5-x by this push:
new 9216e8e Proposed WW-5035 enhancement: - Provide cache clearing methods for OgnlUtil (expression cache, BeanInfo cache). - Provide methods to check the cache sizes (entry number for expression cache, BeanInfo cache). - Provide static method to clear the OgnlRuntime cache (convenience method).
new 4ae1a6a Merge pull request #361 from JCgH4164838Gh792C124B5/localS2_25x_OgnlCachecontrol
9216e8e is described below
commit 9216e8e22c67393f29665186dd25ac5c4bf753e4
Author: JCgH4164838Gh792C124B5 <43...@users.noreply.github.com>
AuthorDate: Sat Jun 15 11:40:58 2019 -0400
Proposed WW-5035 enhancement:
- Provide cache clearing methods for OgnlUtil (expression cache, BeanInfo
cache).
- Provide methods to check the cache sizes (entry number for expression
cache, BeanInfo cache).
- Provide static method to clear the OgnlRuntime cache (convenience
method).
---
.../com/opensymphony/xwork2/ognl/OgnlUtil.java | 70 +++++++++++++
.../com/opensymphony/xwork2/ognl/OgnlUtilTest.java | 112 +++++++++++++++++++++
2 files changed, 182 insertions(+)
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
index 20be3dc..071ed71 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
@@ -189,6 +189,76 @@ public class OgnlUtil {
}
/**
+ * Convenience mechanism to clear the OGNL Runtime Cache via OgnlUtil. May be utilized
+ * by applications that generate many unique OGNL expressions over time.
+ *
+ * Note: This call affects the global OGNL cache, see ({@link ognl.OgnlRuntime#clearCache()} for details.
+ *
+ * Warning: Frequent calling if this method may negatively impact performance, but may be required
+ * to avoid memory exhaustion (resource leak) with too many OGNL expressions being cached.
+ *
+ * @since 2.5.21
+ */
+ public static void clearRuntimeCache() {
+ OgnlRuntime.clearCache();
+ }
+
+ /**
+ * Provide a mechanism to clear the OGNL expression cache. May be utilized by applications
+ * that generate many unique OGNL expressions over time.
+ *
+ * Note: This call affects the current OgnlUtil instance. For Struts this is often a Singleton
+ * instance so it can be "effectively global".
+ *
+ * Warning: Frequent calling if this method may negatively impact performance, but may be required
+ * to avoid memory exhaustion (resource leak) with too many OGNL expressions being cached.
+ *
+ * @since 2.5.21
+ */
+ public void clearExpressionCache() {
+ expressions.clear();
+ }
+
+ /**
+ * Check the size of the expression cache (current number of elements).
+ *
+ * @return current number of elements in the expression cache.
+ *
+ * @since 2.5.21
+ */
+ public int expressionCacheSize() {
+ return expressions.size();
+ }
+
+ /**
+ * Provide a mechanism to clear the BeanInfo cache. May be utilized by applications
+ * that request BeanInfo and/or PropertyDescriptors for many unique classes or objects over time
+ * (especially dynamic objects).
+ *
+ * Note: This call affects the current OgnlUtil instance. For Struts this is often a Singleton
+ * instance so it can be "effectively global".
+ *
+ * Warning: Frequent calling if this method may negatively impact performance, but may be required
+ * to avoid memory exhaustion (resource leak) with too many BeanInfo elements being cached.
+ *
+ * @since 2.5.21
+ */
+ public void clearBeanInfoCache() {
+ beanInfoCache.clear();
+ }
+
+ /**
+ * Check the size of the BeanInfo cache (current number of elements).
+ *
+ * @return current number of elements in the BeanInfo cache.
+ *
+ * @since 2.5.21
+ */
+ public int beanInfoCacheSize() {
+ return beanInfoCache.size();
+ }
+
+ /**
* Sets the object's properties using the default type converter, defaulting to not throw
* exceptions for problems setting the properties.
*
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
index 9c5e59b..5f1a5a5 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
@@ -31,6 +31,7 @@ import com.opensymphony.xwork2.test.User;
import com.opensymphony.xwork2.util.*;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
+import java.beans.IntrospectionException;
import ognl.*;
import org.apache.struts2.StrutsConstants;
@@ -113,6 +114,84 @@ public class OgnlUtilTest extends XWorkTestCase {
assertSame(expr0, expr2);
}
+ public void testClearExpressionCache() throws OgnlException {
+ ognlUtil.setEnableExpressionCache("true");
+ // Test that the expression cache is functioning as expected.
+ Object expr0 = ognlUtil.compile("test");
+ Object expr1 = ognlUtil.compile("test");
+ Object expr2 = ognlUtil.compile("test");
+ // Cache in effect, so expr0, expr1, expr2 should be the same.
+ assertSame(expr0, expr1);
+ assertSame(expr0, expr2);
+ assertTrue("Expression cache empty before clear ?", ognlUtil.expressionCacheSize() > 0);
+ // Clear the Epxression cache and confirm subsequent requests are new.
+ ognlUtil.clearExpressionCache();
+ assertTrue("Expression cache not empty after clear ?", ognlUtil.expressionCacheSize() == 0);
+ Object expr3 = ognlUtil.compile("test");
+ Object expr4 = ognlUtil.compile("test");
+ Object expr5 = ognlUtil.compile("test");
+ // Cache cleared, expr3 should be a new instance.
+ assertNotSame(expr0, expr3);
+ // Cache still in effect, so expr3, expr4, expr5 should be the same.
+ assertSame(expr3, expr4);
+ assertSame(expr3, expr5);
+ assertTrue("Expression cache empty after usage ?", ognlUtil.expressionCacheSize() > 0);
+ }
+
+ public void testClearBeanInfoCache() throws IntrospectionException {
+ final TestBean1 testBean1 = new TestBean1();
+ final TestBean2 testBean2 = new TestBean2();
+ // Test that the BeanInfo cache is functioning as expected.
+ Object beanInfo1_1 = ognlUtil.getBeanInfo(testBean1);
+ Object beanInfo1_2 = ognlUtil.getBeanInfo(testBean1);
+ Object beanInfo1_3 = ognlUtil.getBeanInfo(testBean1);
+ // Cache in effect, so beanInfo1_1, beanInfo1_2, beanInfo1_3 should be the same.
+ assertSame(beanInfo1_1, beanInfo1_2);
+ assertSame(beanInfo1_1, beanInfo1_3);
+ Object beanInfo2_1 = ognlUtil.getBeanInfo(testBean2);
+ Object beanInfo2_2 = ognlUtil.getBeanInfo(testBean2);
+ Object beanInfo2_3 = ognlUtil.getBeanInfo(testBean2);
+ // Cache in effect, so beanInfo2_1, beanInfo2_2, beanInfo2_3 should be the same.
+ assertSame(beanInfo2_1, beanInfo2_2);
+ assertSame(beanInfo2_1, beanInfo2_3);
+ // BeanInfo for TestBean1 and TestBean2 should always be different.
+ assertNotSame(beanInfo1_1, beanInfo2_1);
+ assertTrue("BeanInfo cache empty before clear ?", ognlUtil.beanInfoCacheSize() > 0);
+ // Clear the BeanInfo cache and confirm subsequent requests are new.
+ ognlUtil.clearBeanInfoCache();
+ assertTrue("BeanInfo cache not empty after clear ?", ognlUtil.beanInfoCacheSize() == 0);
+ Object beanInfo1_4 = ognlUtil.getBeanInfo(testBean1);
+ Object beanInfo1_5 = ognlUtil.getBeanInfo(testBean1);
+ Object beanInfo1_6 = ognlUtil.getBeanInfo(testBean1);
+ // Cache in effect, so beanInfo1_4, beanInfo1_5, beanInfo1_6 should be the same.
+ assertSame(beanInfo1_4, beanInfo1_5);
+ assertSame(beanInfo1_4, beanInfo1_6);
+ // Cache was cleared in-between, so beanInfo1_1/beanInfo1_2/beanInfo1_3 should differ
+ // from beanInfo1_4/beanInfo1_5/beanInfo1_6.
+ assertNotSame(beanInfo1_1, beanInfo1_4);
+ assertNotSame(beanInfo1_2, beanInfo1_5);
+ assertNotSame(beanInfo1_3, beanInfo1_6);
+ Object beanInfo2_4 = ognlUtil.getBeanInfo(testBean2);
+ Object beanInfo2_5 = ognlUtil.getBeanInfo(testBean2);
+ Object beanInfo2_6 = ognlUtil.getBeanInfo(testBean2);
+ // Cache in effect, so beanInfo2_4, beanInfo2_5, beanInfo2_6 should be the same.
+ assertSame(beanInfo2_4, beanInfo2_5);
+ assertSame(beanInfo2_4, beanInfo2_6);
+ // Cache was cleared in-between, so beanInfo2_1/beanInfo2_2/beanInfo2_3 should differ
+ // from beanInfo2_4/beanInfo2_5/beanInfo2_6.
+ assertNotSame(beanInfo2_1, beanInfo2_4);
+ assertNotSame(beanInfo2_2, beanInfo2_5);
+ assertNotSame(beanInfo2_3, beanInfo2_6);
+ // BeanInfo for TestBean1 and TestBean2 should always be different.
+ assertNotSame(beanInfo1_4, beanInfo2_4);
+ assertTrue("BeanInfo cache empty after usage ?", ognlUtil.beanInfoCacheSize() > 0);
+ }
+
+ public void testClearRuntimeCache() {
+ // Confirm that no exceptions or failures arise when calling the convenience global clear method.
+ OgnlUtil.clearRuntimeCache();
+ }
+
public void testCacheDisabled() throws OgnlException {
ognlUtil.setEnableExpressionCache("false");
Object expr0 = ognlUtil.compile("test");
@@ -1333,4 +1412,37 @@ public class OgnlUtilTest extends XWorkTestCase {
}
}
+
+ class TestBean1 {
+ private String testBeanProperty;
+
+ public TestBean1() {
+ testBeanProperty = "defaultTestBean1Property";
+ }
+
+ public String getTestBeanProperty() {
+ return testBeanProperty;
+ }
+
+ public void setTestBeanProperty(String testBeanProperty) {
+ this.testBeanProperty = testBeanProperty;
+ }
+ }
+
+ class TestBean2 {
+ private String testBeanProperty;
+
+ public TestBean2() {
+ testBeanProperty = "defaultTestBean2Property";
+ }
+
+ public String getTestBeanProperty() {
+ return testBeanProperty;
+ }
+
+ public void setTestBeanProperty(String testBeanProperty) {
+ this.testBeanProperty = testBeanProperty;
+ }
+ }
+
}