Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,6 @@ public class FluentPropertyBeanIntrospector implements BeanIntrospector {
/** The default prefix for write methods. */
public static final String DEFAULT_WRITE_METHOD_PREFIX = "set";

private static void clearDescriptorsCacheHierarchy(final Class<?> cls) {
if (cls != null && cls != Object.class) {
Introspector.flushFromCaches(cls);
clearDescriptorsCacheHierarchy(cls.getSuperclass());
}
}

/** The logger. */
private final Log log = LogFactory.getLog(getClass());

Expand Down Expand Up @@ -162,11 +155,13 @@ public void introspect(final IntrospectionContext icontext)
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) {
log.info("Error when creating PropertyDescriptor for " + m
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@

import static org.junit.Assert.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.beanutils.FluentPropertyBeanIntrospector;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.junit.Test;
Expand All @@ -42,6 +48,7 @@ public BaseType setField(final String objectName) {
return this;
}
}

public static class SubTypeA extends BaseType {

@Override
Expand All @@ -61,6 +68,29 @@ public static class SubTypeB extends BaseType {

@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 void testImpl() throws Exception {
final PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
propertyUtilsBean.addBeanIntrospector(new FluentPropertyBeanIntrospector());

Expand Down