This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-beanutils.git
The following commit(s) were added to refs/heads/master by this push:
new a726f858 BEANUTILS-541 - FluentPropertyBeanIntrospector caches
corrupted writeMethod (parallel) (#234)
a726f858 is described below
commit a726f858e7ea8d5b45c00a1045a2ab995ee1d6d5
Author: Sergey Chernov <[email protected]>
AuthorDate: Sun Apr 14 22:27:16 2024 +0200
BEANUTILS-541 - FluentPropertyBeanIntrospector caches corrupted writeMethod
(parallel) (#234)
* BEANUTILS-541 - FluentPropertyBeanIntrospector caches corrupted
writeMethod (parallel)
* Fix import order (Checkstyle)
---------
Co-authored-by: Gary Gregory <[email protected]>
---
.../beanutils2/FluentPropertyBeanIntrospector.java | 17 +++++-------
.../commons/beanutils2/bugs/Jira541TestCase.java | 31 +++++++++++++++++++++-
2 files changed, 36 insertions(+), 12 deletions(-)
diff --git
a/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
b/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
index 21eb417d..e8bb593c 100644
---
a/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
+++
b/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
@@ -154,11 +154,13 @@ public class FluentPropertyBeanIntrospector implements
BeanIntrospector {
icontext.addPropertyDescriptor(createFluentPropertyDescritor(
m, propertyName));
} else if (pd.getWriteMethod() == null) {
- // We change statically cached PropertyDescriptor, it
may affect
- // other subclasses of targetClass supertype.
+ // We should not change statically cached
PropertyDescriptor as it can be from super-type,
+ // it may affect other subclasses of targetClass
supertype.
// See BEANUTILS-541 for more details.
-
clearDescriptorsCacheHierarchy(icontext.getTargetClass().getSuperclass());
- pd.setWriteMethod(m);
+ PropertyDescriptor fluentPropertyDescriptor = new
PropertyDescriptor(
+ pd.getName(), pd.getReadMethod(), m);
+ // replace existing (possibly inherited from
super-class) to one specific to current class
+
icontext.addPropertyDescriptor(fluentPropertyDescriptor);
}
} catch (final IntrospectionException e) {
if (log.isDebugEnabled()) {
@@ -170,13 +172,6 @@ public class FluentPropertyBeanIntrospector implements
BeanIntrospector {
}
}
- private static void clearDescriptorsCacheHierarchy(Class<?> cls) {
- if (cls != null && cls != Object.class) {
- Introspector.flushFromCaches(cls);
- clearDescriptorsCacheHierarchy(cls.getSuperclass());
- }
- }
-
/**
* Derives the name of a property from the given set method.
*
diff --git
a/src/test/java/org/apache/commons/beanutils2/bugs/Jira541TestCase.java
b/src/test/java/org/apache/commons/beanutils2/bugs/Jira541TestCase.java
index a8fac5d3..16edece0 100644
--- a/src/test/java/org/apache/commons/beanutils2/bugs/Jira541TestCase.java
+++ b/src/test/java/org/apache/commons/beanutils2/bugs/Jira541TestCase.java
@@ -16,7 +16,13 @@
*/
package org.apache.commons.beanutils2.bugs;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import org.apache.commons.beanutils2.FluentPropertyBeanIntrospector;
import org.apache.commons.beanutils2.PropertyUtilsBean;
@@ -34,6 +40,29 @@ public class Jira541TestCase {
@Test
public void testFluentBeanIntrospectorOnOverriddenSetter() throws
Exception {
+ testImpl();
+ }
+
+ @Test
+ public void testFluentBeanIntrospectorOnOverriddenSetterConcurrent()
throws Exception {
+ ExecutorService executionService = Executors.newFixedThreadPool(256);
+ try {
+ List<Future<?>> futures = new ArrayList<>();
+ for (int i = 0; i < 10000; i++) {
+ futures.add(executionService.submit(() -> {
+ testImpl();
+ return null;
+ }));
+ }
+ for (Future<?> future : futures) {
+ future.get();
+ }
+ } finally {
+ executionService.shutdown();
+ }
+ }
+
+ private static void testImpl() throws ReflectiveOperationException {
PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
propertyUtilsBean.addBeanIntrospector(new
FluentPropertyBeanIntrospector());