aws / aws/aws-sdk-java-v2

Fields with underscores work with @DynamoDbBean but not with @DynamoDbImmutable

Aperta
#5,589 4 commenti 0 reazioni 0 assegnatari Vedi su GitHub
bug dynamodb-enhanced p2 third-party
Lingua principale
Java
Stelle
2.6k
Fork
1k
Merge medio
2g 9h
PR unite (30g)
51

Descrizione

### Describe the bug

It is possible to declare a DynamoDB entity class with such a field:
```
private String __encryption_keyId;
```
... and use the entity when it's annotated `@DynamoDbBean` but it's not possible when it's annotated `@DynamoDbImmutable`.

### Expected Behavior

Consistent behavior for both `@DynamoDbBean` and `@DynamoDbImmutable` annotations. As it's already working for `@DynamoDbBean`, it should work for `@DynamoDbImmutable` too, rather than copying a restriction from `@DynamoDbImmutable` to `@DynamoDbBean`.

### Current Behavior

`TableSchema.fromClass(...)` throws an exception:
```
java.lang.IllegalArgumentException: A method was found on the immutable class that does not appear to have a matching setter on the builder class. Use the @DynamoDbIgnore annotation on the method if you do not want it to be included in the TableSchema introspection. [Method = "public java.lang.String com.example.UnderscoreFieldTest$Immutable.get__encryption_keyId()"]
at software.amazon.awssdk.enhanced.dynamodb.internal.immutable.ImmutableIntrospector.generateExceptionForMethod(ImmutableIntrospector.java:134)
at software.amazon.awssdk.enhanced.dynamodb.internal.immutable.ImmutableIntrospector.lambda$introspect$1(ImmutableIntrospector.java:87)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at software.amazon.awssdk.enhanced.dynamodb.internal.immutable.ImmutableIntrospector.lambda$introspect$2(ImmutableIntrospector.java:86)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at software.amazon.awssdk.enhanced.dynamodb.internal.immutable.ImmutableIntrospector.introspect(ImmutableIntrospector.java:93)
at software.amazon.awssdk.enhanced.dynamodb.internal.immutable.ImmutableIntrospector.getImmutableInfo(ImmutableIntrospector.java:65)
at software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema.createStaticImmutableTableSchema(ImmutableTableSchema.java:174)
at software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema.create(ImmutableTableSchema.java:145)
at software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema.lambda$create$0(ImmutableTableSchema.java:134)
at java.base/java.util.Map.computeIfAbsent(Map.java:1054)
at java.base/java.util.Collections$SynchronizedMap.computeIfAbsent(Collections.java:2760)
at software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema.create(ImmutableTableSchema.java:133)
at software.amazon.awssdk.enhanced.dynamodb.TableSchema.fromImmutableClass(TableSchema.java:141)
at software.amazon.awssdk.enhanced.dynamodb.TableSchema.fromClass(TableSchema.java:164)
```

### Reproduction Steps

Run the test:
```
package com.example;

import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.Value;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;

import static org.assertj.core.api.Assertions.assertThatCode;

class UnderscoreFieldTest {

@Test
void shouldResolveTableSchemaFromBean() {
assertThatCode(() -> TableSchema.fromClass(Bean.class)).doesNotThrowAnyException();
}

@Test
void shouldResolveTableSchemaFromImmutable() {
assertThatCode(() -> TableSchema.fromClass(Immutable.class)).doesNotThrowAnyException();
}

@Data
@DynamoDbBean
public static class Bean {

@Getter(onMethod_ = @DynamoDbPartitionKey)
private String id;

private String __encryption_keyId;
}

@Value
@Builder
@DynamoDbImmutable(builder = Immutable.ImmutableBuilder.class)
public static class Immutable {

@Getter(onMethod_ = @DynamoDbPartitionKey)
private String id;

private String __encryption_keyId;
}
}
```

Dependencies:
* `software.amazon.awssdk:dynamodb-enhanced` version `2.27.19`
* `org.springframework.boot:spring-boot-starter-test` version `3.3.3`
* `org.projectlombok:lombok` version `1.18.34`

### Possible Solution

Release restrictions for `@DynamoDbImmutable` annotation.

### Additional Information/Context

_No response_

### AWS Java SDK version used

2.27.19

### JDK version used

openjdk version "17.0.3" 2022-04-19

### Operating System and version

multiple (macOS 14.6.1, Ubuntu Linux 22.04 LTS)

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia con la riproduzione di UnderscoreFieldTest e con il percorso ImmutableIntrospector indicato nello stack trace, quindi segui il modo in cui TableSchema.fromClass gestisce il builder immutable. Verifica il comportamento sia per @DynamoDbBean sia per @DynamoDbImmutable e aggiungi o esegui un test di regressione che mostri che lo schema immutable viene risolto correttamente per __encryption_keyId.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
java
Ambito
databases
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.