Skip to content

Commit fda10f1

Browse files
iulianbudaudagnir
andauthored
issue #5039 - added support for fluent setters in dynamodb enhanced client (#5856)
Co-authored-by: Dongie Agnir <[email protected]>
1 parent 76d3d0b commit fda10f1

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "Amazon DynamoDB Enhanced Client",
4+
"contributor": "",
5+
"description": "Add support in BeanTableSchema for beans that use fluent setters."
6+
}

services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchema.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbIgnoreNulls;
6868
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable;
6969
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPreserveEmptyObject;
70+
import software.amazon.awssdk.utils.StringUtils;
7071

7172
/**
7273
* Implementation of {@link TableSchema} that builds a table schema based on properties and annotations of a bean
@@ -216,6 +217,7 @@ private static <T> StaticTableSchema<T> createStaticTableSchema(Class<T> beanCla
216217

217218
try {
218219
beanInfo = Introspector.getBeanInfo(beanClass);
220+
enhanceDescriptorsWithFluentSetters(beanClass, beanInfo);
219221
} catch (IntrospectionException e) {
220222
throw new IllegalArgumentException(e);
221223
}
@@ -260,6 +262,30 @@ private static <T> StaticTableSchema<T> createStaticTableSchema(Class<T> beanCla
260262
return builder.build();
261263
}
262264

265+
// Enhance beanInfo descriptors with fluent setter when the default set method is absent
266+
private static <T> void enhanceDescriptorsWithFluentSetters(Class<T> beanClass, BeanInfo beanInfo) {
267+
Arrays.stream(beanInfo.getPropertyDescriptors())
268+
.filter(descriptor -> descriptor.getWriteMethod() == null)
269+
.forEach(descriptor -> findFluentSetter(beanClass, descriptor.getName())
270+
.ifPresent(method -> {
271+
try {
272+
descriptor.setWriteMethod(method);
273+
} catch (IntrospectionException e) {
274+
throw new RuntimeException("Failed to set write method for " + descriptor.getName(), e);
275+
}
276+
}));
277+
}
278+
279+
private static Optional<Method> findFluentSetter(Class<?> beanClass, String propertyName) {
280+
String setterName = "set" + StringUtils.capitalize(propertyName);
281+
282+
return Arrays.stream(beanClass.getMethods())
283+
.filter(m -> m.getName().equals(setterName)
284+
&& m.getParameterCount() == 1
285+
&& m.getReturnType().equals(beanClass))
286+
.findFirst();
287+
}
288+
263289
private static AttributeConfiguration resolveAttributeConfiguration(PropertyDescriptor propertyDescriptor) {
264290
boolean shouldPreserveEmptyObject = getPropertyAnnotation(propertyDescriptor,
265291
DynamoDbPreserveEmptyObject.class) != null;

services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchemaTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.ExtendedBean;
5656
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.FlattenedBeanBean;
5757
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.FlattenedImmutableBean;
58+
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.FluentSetterBean;
5859
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.IgnoredAttributeBean;
5960
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.InvalidBean;
6061
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.ListBean;
@@ -1160,4 +1161,19 @@ public void emptyConverterProviderList_correct_whenAttributeConvertersAreSupplie
11601161
assertThat(reverse.getId(), is(equalTo("id-value-custom")));
11611162
assertThat(reverse.getIntegerAttribute(), is(equalTo(133)));
11621163
}
1164+
1165+
@Test
1166+
public void fluentSetterBean_correctlyMapsBeanAttributes() {
1167+
BeanTableSchema<FluentSetterBean> beanTableSchema =
1168+
BeanTableSchema.create(FluentSetterBean.class);
1169+
1170+
FluentSetterBean fluentSetterBean = new FluentSetterBean()
1171+
.setAttribute1(1)
1172+
.setAttribute2("testAttribute2")
1173+
.setAttribute3("testAttribute3");
1174+
1175+
Map<String, AttributeValue> itemMap = beanTableSchema.itemToMap(fluentSetterBean, false);
1176+
1177+
assertThat(beanTableSchema.mapToItem(itemMap), is(equalTo(fluentSetterBean)));
1178+
}
11631179
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans;
17+
18+
import java.util.Objects;
19+
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
20+
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
21+
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;
22+
23+
@DynamoDbBean
24+
public class FluentSetterBean {
25+
26+
private Integer attribute1;
27+
private String attribute2;
28+
private String attribute3;
29+
30+
@DynamoDbPartitionKey
31+
public Integer getAttribute1() {
32+
return attribute1;
33+
}
34+
35+
public FluentSetterBean setAttribute1(Integer attribute1) {
36+
this.attribute1 = attribute1;
37+
return this;
38+
}
39+
40+
@DynamoDbSortKey
41+
public String getAttribute2() {
42+
return attribute2;
43+
}
44+
45+
public FluentSetterBean setAttribute2(String attribute2) {
46+
this.attribute2 = attribute2;
47+
return this;
48+
}
49+
50+
public String getAttribute3() {
51+
return attribute3;
52+
}
53+
54+
public FluentSetterBean setAttribute3(String attribute3) {
55+
this.attribute3 = attribute3;
56+
return this;
57+
}
58+
59+
@Override
60+
public boolean equals(Object o) {
61+
if (this == o) return true;
62+
if (o == null || getClass() != o.getClass()) return false;
63+
FluentSetterBean fluentSetterBean = (FluentSetterBean) o;
64+
return Objects.equals(attribute1, fluentSetterBean.attribute1) &&
65+
Objects.equals(attribute2, fluentSetterBean.attribute2) &&
66+
Objects.equals(attribute3, fluentSetterBean.attribute3);
67+
}
68+
69+
@Override
70+
public int hashCode() {
71+
return Objects.hash(attribute1, attribute2, attribute3);
72+
}
73+
}

0 commit comments

Comments
 (0)