well, the solution is almost perfect now. "almost" - because i have to completely duplicate the code of PropertyAccessImpl replacing 2 calls to Introspector.getBeanInfo buried inside private methods :)
here is a service override and final class public static void contributeServiceOverride(MappedConfiguration<Class, Object> configuration) { //Allow setters returning object itself to be detected configuration.add(PropertyAccess.class, new SpringPropertyAccessImpl()); } > package de.cgp.kunden.services; > > import > org.apache.tapestry5.ioc.internal.services.ClassPropertyAdapterImpl; > import org.apache.tapestry5.ioc.internal.util.CollectionFactory; > import org.apache.tapestry5.ioc.services.ClassPropertyAdapter; > import org.apache.tapestry5.ioc.services.PropertyAccess; > import org.springframework.beans.BeanUtils; > > import java.beans.IntrospectionException; > import java.beans.PropertyDescriptor; > import java.util.Arrays; > import java.util.LinkedList; > import java.util.List; > import java.util.Map; > > /** > * User: Pasha > * Date: 22.04.2010 > * Time: 11:49:43 > */ > public class SpringPropertyAccessImpl implements PropertyAccess { > > private final Map<Class, ClassPropertyAdapter> adapters = > CollectionFactory.newConcurrentMap(); > > @Override > public Object get(Object instance, String propertyName) { > return getAdapter(instance).get(instance, propertyName); > } > > @Override > public void set(Object instance, String propertyName, Object value) { > getAdapter(instance).set(instance, propertyName, value); > } > > /** > * Clears the cache of adapters and asks the Introspector to clear its > cache. > */ > @Override > public synchronized void clearCache() { > adapters.clear(); > } > > @Override > public ClassPropertyAdapter getAdapter(Object instance) { > return getAdapter(instance.getClass()); > } > > @Override > public ClassPropertyAdapter getAdapter(Class forClass) { > ClassPropertyAdapter result = adapters.get(forClass); > > if (result == null) { > result = buildAdapter(forClass); > adapters.put(forClass, result); > } > > return result; > } > > /** > * Builds a new adapter and updates the _adapters cache. This not only > guards access to the adapter cache, but also > * serializes access to the Java Beans Introspector, which is not > thread safe. In addition, handles the case where > * the class in question is an interface, accumulating properties > inherited from super-classes. > */ > private synchronized ClassPropertyAdapter buildAdapter(Class forClass) > { > // In some race conditions, we may hit this method for the same > class multiple times. > // We just let it happen, replacing the old ClassPropertyAdapter > with a new one. > > try { > > > List<PropertyDescriptor> descriptors = > CollectionFactory.newList(); > > addAll(descriptors, getPropertyDescriptors(forClass)); > > if (forClass.isInterface()) > addPropertiesFromExtendedInterfaces(forClass, descriptors); > > return new ClassPropertyAdapterImpl(forClass, descriptors); > } > catch (Throwable ex) { > throw new RuntimeException(ex); > } > } > > private PropertyDescriptor[] getPropertyDescriptors(Class forClass) { > return BeanUtils.getPropertyDescriptors(forClass); > } > > private <T> void addAll(List<T> list, T[] array) { > list.addAll(Arrays.asList(array)); > } > > private void addPropertiesFromExtendedInterfaces(Class forClass, > List<PropertyDescriptor> descriptors) { > LinkedList<Class> queue = CollectionFactory.newLinkedList(); > > // Seed the queue > addAll(queue, forClass.getInterfaces()); > > while (!queue.isEmpty()) { > Class c = queue.removeFirst(); > > > addAll(descriptors, getPropertyDescriptors(c)); > addAll(queue, c.getInterfaces()); > } > } > > > } > > -- View this message in context: http://old.nabble.com/T5.1-Setters-returning-value-tp28288048p28329198.html Sent from the Tapestry - User mailing list archive at Nabble.com. --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org