SGF-421 - Fix Spring Data GemFire's MappingPdxSerializer due to the package-private access modifier change on org.springframework.data.mapping.model.BeanWrapper.
(cherry picked from commit d5d2fd09b7a105c1eb1f8955f98127e550641ae6) Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,8 +26,8 @@ import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
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.BeanWrapper;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELContext;
|
||||
@@ -149,7 +149,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
|
||||
new PersistentEntityParameterValueProvider<GemfirePersistentProperty>(entity,
|
||||
new GemfirePropertyValueProvider(reader), null));
|
||||
|
||||
final BeanWrapper<Object> wrapper = BeanWrapper.create(instance, getConversionService());
|
||||
final PersistentPropertyAccessor wrapper = BeanPropertyAccessor.create(instance, getConversionService());
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
|
||||
@Override
|
||||
@@ -190,7 +190,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
|
||||
public boolean toData(Object value, final PdxWriter writer) {
|
||||
GemfirePersistentEntity<?> entity = getPersistentEntity(value.getClass());
|
||||
|
||||
final BeanWrapper<Object> wrapper = BeanWrapper.create(value, getConversionService());
|
||||
final PersistentPropertyAccessor wrapper = BeanPropertyAccessor.create(value, getConversionService());
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* 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<String> bean = new ExampleBean<String>();
|
||||
|
||||
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<String> bean = new ExampleBean<String>();
|
||||
|
||||
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<String> bean = new ExampleBean<String>();
|
||||
|
||||
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<String> bean = new ExampleBean<String>();
|
||||
|
||||
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<T> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,8 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.mapping;
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -44,12 +47,15 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MappingPdxSerializerUnitTests {
|
||||
|
||||
GemfireMappingContext context;
|
||||
ConversionService conversionService;
|
||||
|
||||
GemfireMappingContext context;
|
||||
|
||||
MappingPdxSerializer serializer;
|
||||
|
||||
@Mock
|
||||
EntityInstantiator instantiator;
|
||||
|
||||
@Mock
|
||||
PdxReader reader;
|
||||
|
||||
@@ -58,11 +64,12 @@ public class MappingPdxSerializerUnitTests {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
context = new GemfireMappingContext();
|
||||
conversionService = new GenericConversionService();
|
||||
context = new GemfireMappingContext();
|
||||
serializer = new MappingPdxSerializer(context, conversionService);
|
||||
|
||||
Map<Class<?>,PdxSerializer> customSerializers = new HashMap<Class<?>, PdxSerializer>();
|
||||
|
||||
customSerializers.put(Address.class, addressSerializer);
|
||||
serializer.setCustomSerializers(customSerializers);
|
||||
}
|
||||
@@ -71,17 +78,20 @@ public class MappingPdxSerializerUnitTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void usesRegisteredInstantiator() {
|
||||
Address address = new Address();
|
||||
address.zipCode = "01234";
|
||||
address.city = "London";
|
||||
address.zipCode = "01234";
|
||||
|
||||
Person person = new Person(1L, "Oliver", "Gierke");
|
||||
person.address = address;
|
||||
|
||||
ParameterValueProvider<GemfirePersistentProperty> provider = any(ParameterValueProvider.class);
|
||||
|
||||
GemfirePersistentEntity<?> entity = any(GemfirePersistentEntity.class);
|
||||
|
||||
ParameterValueProvider<GemfirePersistentProperty> provider = any(ParameterValueProvider.class);
|
||||
|
||||
when(instantiator.createInstance(entity, provider)).thenReturn(person);
|
||||
|
||||
Map<Class<?>, EntityInstantiator> instantiators = new HashMap<Class<?>, EntityInstantiator>();
|
||||
|
||||
instantiators.put(Person.class, instantiator);
|
||||
|
||||
serializer.setGemfireInstantiators(instantiators);
|
||||
@@ -91,4 +101,5 @@ public class MappingPdxSerializerUnitTests {
|
||||
any(ParameterValueProvider.class));
|
||||
verify(addressSerializer,times(1)).fromData(eq(Address.class), any(PdxReader.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user