DATACMNS-820 - Allow setter invocations in projections backed by beans.
Invocations to setter methods are now passed to the backing bean. Original pull request: #155.
This commit is contained in:
committed by
Oliver Gierke
parent
1a97627196
commit
e868577def
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -30,6 +30,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* Method interceptor to forward a delegation to bean property accessor methods to the property of a given target.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 1.10
|
||||
*/
|
||||
class PropertyAccessingMethodInterceptor implements MethodInterceptor {
|
||||
@@ -66,6 +67,20 @@ class PropertyAccessingMethodInterceptor implements MethodInterceptor {
|
||||
throw new IllegalStateException("Invoked method is not a property accessor!");
|
||||
}
|
||||
|
||||
if (isSetterMethod(method, descriptor)) {
|
||||
if (invocation.getArguments().length != 1) {
|
||||
throw new IllegalStateException("Invoked setter method requires exactly one argument!");
|
||||
}
|
||||
|
||||
target.setPropertyValue(descriptor.getName(), invocation.getArguments()[0]);
|
||||
return null;
|
||||
}
|
||||
|
||||
return target.getPropertyValue(descriptor.getName());
|
||||
}
|
||||
|
||||
private boolean isSetterMethod(Method method, PropertyDescriptor descriptor) {
|
||||
return method.equals(descriptor.getWriteMethod());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.beans.NotReadablePropertyException;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PropertyAccessingMethodInterceptor}.
|
||||
@@ -62,6 +63,50 @@ public class PropertyAccessingMethodInterceptorUnitTests {
|
||||
new PropertyAccessingMethodInterceptor(new Source()).invoke(invocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-820
|
||||
*/
|
||||
@Test
|
||||
public void triggersWritePropertyAccessOnTarget() throws Throwable {
|
||||
|
||||
Source source = new Source();
|
||||
source.firstname = "Dave";
|
||||
|
||||
when(invocation.getMethod()).thenReturn(Projection.class.getMethod("setFirstname", String.class));
|
||||
when(invocation.getArguments()).thenReturn(new Object[] { "Carl" });
|
||||
MethodInterceptor interceptor = new PropertyAccessingMethodInterceptor(source);
|
||||
|
||||
interceptor.invoke(invocation);
|
||||
|
||||
assertThat(source.firstname, is((Object) "Carl"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-820
|
||||
*/
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void throwsAppropriateExceptionIfTheInvocationHasNoArguments() throws Throwable {
|
||||
|
||||
Source source = new Source();
|
||||
|
||||
when(invocation.getMethod()).thenReturn(Projection.class.getMethod("setFirstname", String.class));
|
||||
when(invocation.getArguments()).thenReturn(new Object[0]);
|
||||
MethodInterceptor interceptor = new PropertyAccessingMethodInterceptor(source);
|
||||
|
||||
interceptor.invoke(invocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-820
|
||||
*/
|
||||
@Test(expected = NotWritablePropertyException.class)
|
||||
public void throwsAppropriateExceptionIfThePropertyCannotWritten() throws Throwable {
|
||||
|
||||
when(invocation.getMethod()).thenReturn(Projection.class.getMethod("setGarbage", String.class));
|
||||
when(invocation.getArguments()).thenReturn(new Object[] { "Carl" });
|
||||
new PropertyAccessingMethodInterceptor(new Source()).invoke(invocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-221
|
||||
*/
|
||||
@@ -91,6 +136,10 @@ public class PropertyAccessingMethodInterceptorUnitTests {
|
||||
|
||||
String getFirstname();
|
||||
|
||||
void setFirstname(String firstname);
|
||||
|
||||
void setGarbage(String garbage);
|
||||
|
||||
String getLastname();
|
||||
|
||||
String someGarbage();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
/**
|
||||
@@ -29,6 +30,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class SpelAwareProxyProjectionFactoryUnitTests {
|
||||
|
||||
@@ -53,6 +55,42 @@ public class SpelAwareProxyProjectionFactoryUnitTests {
|
||||
assertThat(excerpt.getFullName(), is("Dave Matthews"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-820
|
||||
*/
|
||||
@Test
|
||||
public void setsValueUsingProjection() {
|
||||
|
||||
Customer customer = new Customer();
|
||||
customer.firstname = "Dave";
|
||||
|
||||
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class, customer);
|
||||
excerpt.setFirstname("Carl");
|
||||
|
||||
assertThat(customer.firstname, is("Carl"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-820
|
||||
*/
|
||||
@Test
|
||||
public void settingNotWriteablePropertyFails() {
|
||||
|
||||
Customer customer = new Customer();
|
||||
customer.firstname = "Dave";
|
||||
|
||||
ProjectionWithNotWriteableProperty projection = factory.createProjection(ProjectionWithNotWriteableProperty.class,
|
||||
customer);
|
||||
|
||||
try {
|
||||
projection.setFirstName("Carl");
|
||||
fail("Missing NotWritablePropertyException");
|
||||
} catch (NotWritablePropertyException e) {
|
||||
assertThat(e, instanceOf(NotWritablePropertyException.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-630
|
||||
*/
|
||||
@@ -87,5 +125,12 @@ public class SpelAwareProxyProjectionFactoryUnitTests {
|
||||
String getFullName();
|
||||
|
||||
String getFirstname();
|
||||
|
||||
void setFirstname(String firstname);
|
||||
}
|
||||
|
||||
interface ProjectionWithNotWriteableProperty {
|
||||
|
||||
void setFirstName(String firstname);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user