Skip to content

Commit d70675a

Browse files
committed
Fix DynamoDB Enhanced Client immutable class introspection fails for is prefix fields issue
1 parent 6d791e0 commit d70675a

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Fix DynamoDB Enhanced Client immutable class introspection fails for \"is\" prefix fields. Fixes [#4446](https://github.com/aws/aws-sdk-java-v2/issues/4446)."
6+
}

services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/immutable/ImmutableIntrospector.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ private String normalizeSetterName(Method setter) {
180180
return Character.toLowerCase(setterName.charAt(3)) + setterName.substring(4);
181181
}
182182

183+
if (setterName.length() > 2
184+
&& Character.isUpperCase(setterName.charAt(2))
185+
&& setterName.startsWith(IS_PREFIX)
186+
&& isSetterMethodBoolean(setter)) {
187+
188+
return Character.toLowerCase(setterName.charAt(2)) + setterName.substring(3);
189+
}
190+
183191
return setterName;
184192
}
185193

@@ -208,6 +216,11 @@ private boolean isMethodBoolean(Method method) {
208216
return method.getReturnType() == boolean.class || method.getReturnType() == Boolean.class;
209217
}
210218

219+
private boolean isSetterMethodBoolean(Method setter) {
220+
return setter.getParameterCount() == 1 &&
221+
(setter.getParameterTypes()[0] == boolean.class || setter.getParameterTypes()[0] == Boolean.class);
222+
}
223+
211224
private Optional<Method> extractBuildMethod(Map<String, Method> indexedBuilderMethods, Class<?> immutableClass) {
212225
Method buildMethod = indexedBuilderMethods.get(BUILD_METHOD);
213226

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import org.junit.Test;
21+
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable;
22+
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
23+
24+
/**
25+
* Tests that TableSchema.fromImmutableClass() works correctly with immutable classes
26+
* that have boolean fields using "is" prefix.
27+
*/
28+
public class ImmutableBooleanIsPrefixTest {
29+
30+
@DynamoDbImmutable(builder = Car.Builder.class)
31+
public static final class Car {
32+
private final String licensePlate;
33+
private final boolean isRusty;
34+
private final boolean isImpounded;
35+
36+
private Car(Builder b) {
37+
this.licensePlate = b.licensePlate;
38+
this.isRusty = b.isRusty;
39+
this.isImpounded = b.isImpounded;
40+
}
41+
42+
@DynamoDbPartitionKey
43+
public String licensePlate() {
44+
return this.licensePlate;
45+
}
46+
47+
public boolean isRusty() {
48+
return this.isRusty;
49+
}
50+
51+
public boolean isImpounded() {
52+
return this.isImpounded;
53+
}
54+
55+
public static final class Builder {
56+
private String licensePlate;
57+
private boolean isRusty;
58+
private boolean isImpounded;
59+
60+
public Builder licensePlate(String licensePlate) {
61+
this.licensePlate = licensePlate;
62+
return this;
63+
}
64+
65+
public Builder isRusty(boolean isRusty) {
66+
this.isRusty = isRusty;
67+
return this;
68+
}
69+
70+
public Builder isImpounded(boolean isImpounded) {
71+
this.isImpounded = isImpounded;
72+
return this;
73+
}
74+
75+
public Car build() {
76+
return new Car(this);
77+
}
78+
}
79+
}
80+
81+
@Test
82+
public void fromImmutableClass_withIsPrefixBooleanSetters_shouldCreateSchemaSuccessfully() {
83+
// This should work without exception
84+
TableSchema<Car> schema = TableSchema.fromImmutableClass(Car.class);
85+
86+
// Verify the schema was created successfully without exception
87+
assertThat(schema).isNotNull();
88+
assertThat(schema.itemType().rawClass()).isEqualTo(Car.class);
89+
90+
// Verify all attributes are mapped correctly
91+
assertThat(schema.attributeNames()).containsExactlyInAnyOrder(
92+
"licensePlate", "rusty", "impounded"
93+
);
94+
}
95+
}

0 commit comments

Comments
 (0)