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 <serega.mo...@gmail.com>
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 <garydgreg...@users.noreply.github.com>
---
 .../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());
 

Reply via email to