From 22d50d0189998250411f13e4373103ce4013c397 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 4 Aug 2015 09:56:47 +0200 Subject: [PATCH] SGF-421 - Switched to existing PropertyAccessor abstraction. Removed the custom BeanPropertyAccessor implementation that was introduced to compensate for the removal of BeanWrapper in Spring Data Commons. That removal however was already preceded by an alternative way to obtain a PropertyAccessor via the PersistentEntity, which is what we're now doing.(cherry picked from commit 85c333dfc582719229fee006e538ff77f569a242) Signed-off-by: John Blum --- .../gemfire/mapping/BeanPropertyAccessor.java | 103 -------- .../gemfire/mapping/MappingPdxSerializer.java | 18 +- .../mapping/BeanPropertyAccessorTest.java | 220 ------------------ 3 files changed, 11 insertions(+), 330 deletions(-) delete mode 100644 src/main/java/org/springframework/data/gemfire/mapping/BeanPropertyAccessor.java delete mode 100644 src/test/java/org/springframework/data/gemfire/mapping/BeanPropertyAccessorTest.java diff --git a/src/main/java/org/springframework/data/gemfire/mapping/BeanPropertyAccessor.java b/src/main/java/org/springframework/data/gemfire/mapping/BeanPropertyAccessor.java deleted file mode 100644 index 5356bb68..00000000 --- a/src/main/java/org/springframework/data/gemfire/mapping/BeanPropertyAccessor.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2010-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.data.gemfire.mapping; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -import org.springframework.core.convert.ConversionService; -import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.mapping.PersistentPropertyAccessor; -import org.springframework.data.mapping.model.ConvertingPropertyAccessor; -import org.springframework.data.mapping.model.MappingException; -import org.springframework.util.Assert; -import org.springframework.util.ReflectionUtils; - -/** - * The BeanPropertyAccessor class is an implementation of Spring Data Common's PersistentPropertyAccessor for accessing - * persistent properties on beans. - * - * @author John Blum - * @see java.lang.reflect.Field - * @see java.lang.reflect.Method - * @see org.springframework.data.mapping.PersistentProperty - * @see org.springframework.data.mapping.PersistentPropertyAccessor - * @see org.springframework.data.mapping.model.ConvertingPropertyAccessor - * @since 1.7.0 - */ -class BeanPropertyAccessor implements PersistentPropertyAccessor { - - private final Object bean; - - private BeanPropertyAccessor(final Object bean) { - Assert.notNull(bean, "Bean must not be null"); - this.bean = bean; - } - - public static PersistentPropertyAccessor create(Object bean) { - return new BeanPropertyAccessor(bean); - } - - public static PersistentPropertyAccessor create(Object bean, ConversionService conversionService) { - return new ConvertingPropertyAccessor(new BeanPropertyAccessor(bean), conversionService); - } - - @Override - public void setProperty(PersistentProperty property, Object value) { - try { - if (property.usePropertyAccess() && property.getSetter() != null) { - Method setter = property.getSetter(); - ReflectionUtils.makeAccessible(setter); - ReflectionUtils.invokeMethod(setter, getBean(), value); - } - else { - Field field = property.getField(); - ReflectionUtils.makeAccessible(field); - ReflectionUtils.setField(field, getBean(), value); - } - } - catch (Throwable t) { - throw new MappingException(String.format("Failed to set property (%1$s) to value (%2$s)!", - property, value), t); - } - } - - @Override - public Object getProperty(PersistentProperty property) { - try { - if (property.usePropertyAccess() && property.getGetter() != null) { - Method getter = property.getGetter(); - ReflectionUtils.makeAccessible(getter); - return ReflectionUtils.invokeMethod(getter, getBean()); - } - else { - Field field = property.getField(); - ReflectionUtils.makeAccessible(field); - return ReflectionUtils.getField(field, getBean()); - } - } - catch (Throwable t) { - throw new MappingException(String.format("Failed to get value of property (%1$s)!", property), t); - } - } - - @Override - public Object getBean() { - return bean; - } - -} diff --git a/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java b/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java index bfd6f431..94303c8f 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.PropertyHandler; +import org.springframework.data.mapping.model.ConvertingPropertyAccessor; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider; import org.springframework.data.mapping.model.SpELContext; @@ -149,7 +150,8 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw new PersistentEntityParameterValueProvider(entity, new GemfirePropertyValueProvider(reader), null)); - final PersistentPropertyAccessor wrapper = BeanPropertyAccessor.create(instance, getConversionService()); + final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance), + getConversionService()); entity.doWithProperties(new PropertyHandler() { @Override @@ -169,7 +171,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw } try { - wrapper.setProperty(persistentProperty, value); + accessor.setProperty(persistentProperty, value); } catch (Exception e) { throw new MappingException("Could not read value " + value.toString(), e); @@ -177,7 +179,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw } }); - return wrapper.getBean(); + return accessor.getBean(); } /* @@ -188,9 +190,11 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw */ @Override public boolean toData(Object value, final PdxWriter writer) { - GemfirePersistentEntity entity = getPersistentEntity(value.getClass()); - final PersistentPropertyAccessor wrapper = BeanPropertyAccessor.create(value, getConversionService()); + GemfirePersistentEntity entity = getPersistentEntity(value.getClass()); + + final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(value), + getConversionService()); entity.doWithProperties(new PropertyHandler() { @Override @@ -198,7 +202,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw public void doWithPersistentProperty(GemfirePersistentProperty persistentProperty) { try { - Object propertyValue = wrapper.getProperty(persistentProperty); + Object propertyValue = accessor.getProperty(persistentProperty); PdxSerializer customSerializer = getCustomSerializer(persistentProperty.getType()); diff --git a/src/test/java/org/springframework/data/gemfire/mapping/BeanPropertyAccessorTest.java b/src/test/java/org/springframework/data/gemfire/mapping/BeanPropertyAccessorTest.java deleted file mode 100644 index 212650de..00000000 --- a/src/test/java/org/springframework/data/gemfire/mapping/BeanPropertyAccessorTest.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2010-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.data.gemfire.mapping; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.hamcrest.Matchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.mapping.PersistentPropertyAccessor; -import org.springframework.data.mapping.model.MappingException; - -/** - * The BeanPropertyAccessorTest class is a test suite of test cases testing the contract and functionality - * of the BeanPropertyAccessor class. - * - * @author John Blum - * @see org.junit.Test - * @see org.mockito.Mockito - * @see org.springframework.data.gemfire.mapping.BeanPropertyAccessor - * @see org.springframework.data.mapping.PersistentProperty - * @see org.springframework.data.mapping.PersistentPropertyAccessor - * @since 1.7.0 - */ -public class BeanPropertyAccessorTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void createWithNullBean() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectCause(is(nullValue(Throwable.class))); - expectedException.expectMessage("Bean must not be null"); - BeanPropertyAccessor.create(null); - } - - @Test - public void setAndGetPropertyValueUsingFieldAccess() throws Exception { - ExampleBean bean = new ExampleBean(); - - PersistentProperty mockPersistentProperty = mock(PersistentProperty.class, "MockPersistentProperty"); - - when(mockPersistentProperty.usePropertyAccess()).thenReturn(false); - when(mockPersistentProperty.getField()).thenReturn(ExampleBean.class.getDeclaredField("value")); - when(mockPersistentProperty.getGetter()).thenReturn(null); - when(mockPersistentProperty.getSetter()).thenReturn(null); - - PersistentPropertyAccessor propertyAccessor = BeanPropertyAccessor.create(bean); - - assertSame(bean, propertyAccessor.getBean()); - assertThat(bean.getValue(), is(nullValue())); - - propertyAccessor.setProperty(mockPersistentProperty, "mock"); - - assertThat(bean.getValue(), is(equalTo("mock"))); - assertThat(String.valueOf(propertyAccessor.getProperty(mockPersistentProperty)), is(equalTo("mock"))); - - when(mockPersistentProperty.usePropertyAccess()).thenReturn(true); - propertyAccessor.setProperty(mockPersistentProperty, null); - - assertThat(bean.getValue(), is(nullValue())); - assertThat(propertyAccessor.getProperty(mockPersistentProperty), is(nullValue())); - - verify(mockPersistentProperty, times(4)).usePropertyAccess(); - verify(mockPersistentProperty, times(4)).getField(); - verify(mockPersistentProperty, times(1)).getGetter(); - verify(mockPersistentProperty, times(1)).getSetter(); - } - - @Test - @SuppressWarnings("unchecked") - public void setAndGetPropertyValueUsingPropertyAccess() throws Exception { - ExampleBean bean = new ExampleBean(); - - PersistentProperty mockPersistentProperty = mock(PersistentProperty.class, "MockPersistentProperty"); - - when(mockPersistentProperty.usePropertyAccess()).thenReturn(true); - when(mockPersistentProperty.getSetter()).thenReturn(ExampleBean.class.getMethod("setValue", Object.class)); - when(mockPersistentProperty.getGetter()).thenReturn(ExampleBean.class.getMethod("getValue")); - - PersistentPropertyAccessor propertyAccessor = BeanPropertyAccessor.create(bean); - - assertSame(bean, propertyAccessor.getBean()); - assertThat(bean.getValue(), is(nullValue())); - - propertyAccessor.setProperty(mockPersistentProperty, "test"); - - assertThat(bean.getValue(), is(equalTo("test"))); - assertThat(String.valueOf(propertyAccessor.getProperty(mockPersistentProperty)), is(equalTo("test"))); - - propertyAccessor.setProperty(mockPersistentProperty, null); - - assertThat(bean.getValue(), is(nullValue())); - assertThat(propertyAccessor.getProperty(mockPersistentProperty), is(nullValue())); - - verify(mockPersistentProperty, times(4)).usePropertyAccess(); - verify(mockPersistentProperty, never()).getField(); - verify(mockPersistentProperty, times(4)).getGetter(); - verify(mockPersistentProperty, times(4)).getSetter(); - } - - @Test - public void setPropertyWithNonExistingField() throws Exception { - ExampleBean bean = new ExampleBean(); - - PersistentProperty mockPersistentProperty = mock(PersistentProperty.class, "MockPersistentProperty"); - - when(mockPersistentProperty.usePropertyAccess()).thenReturn(false); - when(mockPersistentProperty.getField()).thenReturn(InvalidBean.class.getDeclaredField("temp")); - - PersistentPropertyAccessor propertyAccessor = BeanPropertyAccessor.create(bean); - - assertSame(bean, propertyAccessor.getBean()); - assertThat(bean.getValue(), is(nullValue())); - - expectedException.expect(MappingException.class); - expectedException.expectCause(is(notNullValue(Throwable.class))); - expectedException.expectMessage(Matchers.startsWith(String.format( - "Failed to get value of property (%1$s)!", mockPersistentProperty))); - - try { - propertyAccessor.getProperty(mockPersistentProperty); - } - finally { - verify(mockPersistentProperty, times(1)).usePropertyAccess(); - verify(mockPersistentProperty, times(1)).getField(); - verify(mockPersistentProperty, never()).getGetter(); - } - } - - @Test - public void setPropertyWithNonExistingSetterMethod() throws Exception { - ExampleBean bean = new ExampleBean(); - - PersistentProperty mockPersistentProperty = mock(PersistentProperty.class, "MockPersistentProperty"); - - when(mockPersistentProperty.usePropertyAccess()).thenReturn(true); - when(mockPersistentProperty.getSetter()).thenReturn(InvalidBean.class.getMethod("getTemp")); - - PersistentPropertyAccessor propertyAccessor = BeanPropertyAccessor.create(bean); - - assertSame(bean, propertyAccessor.getBean()); - assertThat(bean.getValue(), is(nullValue())); - - expectedException.expect(MappingException.class); - expectedException.expectCause(is(notNullValue(Throwable.class))); - expectedException.expectMessage(Matchers.startsWith(String.format( - "Failed to set property (%1$s) to value (test)!", mockPersistentProperty))); - - try { - propertyAccessor.setProperty(mockPersistentProperty, "test"); - } - finally { - assertThat(bean.getValue(), is(nullValue())); - verify(mockPersistentProperty, times(1)).usePropertyAccess(); - verify(mockPersistentProperty, never()).getField(); - verify(mockPersistentProperty, times(2)).getSetter(); - } - } - - public static class ExampleBean { - - private T value; - - public T getValue() { - return value; - } - - public void setValue(final T value) { - this.value = value; - } - - @Override - public String toString() { - return String.format("{ @type = %1$s, value = %2$s }", getClass().getName(), getValue()); - } - } - - @SuppressWarnings("unused") - public static class InvalidBean { - - Object temp; - - public Object getTemp() { - return temp; - } - - public void setTemp(final Object temp) { - this.temp = temp; - } - } - -}