aws / aws/aws-sdk-java-v2

Customizing immutable data class methods

Open
#2,603 1 comment 0 reactions 0 assignees View on GitHub
dynamodb-enhanced feature-request p3
Dominant language
Java
Stars
2.6k
Forks
1k
Avg merge
2d 9h
Merged PRs (30d)
51

Description

Currently, methods belonging to a class that is annotated with @DynamoDbImmutable are constrained as follows:

1. Getters must be the attribute value that is stored in the table
2. The static Builder factory method must be called `builder()`
3. Builder setters must match the class getters

This restricts the user to how these methods can be named. For example, class getters cannot be prepended with the conventional `get`, builder setters cannot be prepended with `set` or `with`, and the static Builder factory method cannot be prepended with `new`.

These restrictions can be seen in the [README](https://github.com/aws/aws-sdk-java-v2/tree/master/services-custom/dynamodb-enhanced#working-with-immutable-data-classes).

## Describe the Feature
Allow users to customize class getters, builder setters, and the Builder factory method, similar to how [Immutables allows users to customize the style of generated code](https://immutables.github.io/style.html).

## Is your Feature Request related to a problem?
The problem is only stylistic and does not affect the actual functionality.

## Proposed Solution
The following is a partial implementation of the class included in the README that follows the current constraints.

```
@DynamoDbImmutable(builder = Customer.Builder.class)
public class Customer {
private final String accountId;
private final String name;

private Customer(Builder b) {
this.accountId = b.accountId;
this.name = b.name;
}

public static Builder builder() { return new Builder(); }

@DynamoDbPartitionKey
public String accountId() { return this.accountId; }

@DynamoDbSecondaryPartitionKey(indexNames = "customers_by_name")
public String name() { return this.name; }

public static final class Builder {
private String accountId;
private String name;

private Builder() {}

public Builder accountId(String accountId) { this.accountId = accountId; return this; }
public Builder name(String name) { this.name = name; return this; }
public Customer build() { return new Customer(this); }
```

Now, the same class but with a flexible @DynamoDbImmutable annotation that can recognize getters, setters, and the Builder factory method.

```
@DynamoDbImmutable(
get = {"is*", "get*"},
init = "set*",
builderFactory = "newBuilder",
builder = Customer.Builder.class)
public class Customer {
private final String accountId;
private final String name;

private Customer(Builder b) {
this.accountId = b.accountId;
this.name = b.name;
}

public static Builder newBuilder() { return new Builder(); }

@DynamoDbPartitionKey
public String getAccountId() { return this.accountId; }

@DynamoDbSecondaryPartitionKey(indexNames = "customers_by_name")
public String getName() { return this.name; }

public static final class Builder {
private String accountId;
private String name;

private Builder() {}

public Builder setAccountId(String accountId) { this.accountId = accountId; return this; }
public Builder setName(String name) { this.name = name; return this; }
public Customer build() { return new Customer(this); }
```

## Describe alternatives you've considered
None

## Additional Context
The restrictions of the current implementation are frustrating because it forces users to name their classes in a specific way.

- [x] I may be able to implement this feature request

## Your Environment
* AWS Java SDK version used: v2
* JDK version used: 11
* Operating System and version: Microsoft Windows 10 Home (10.0.19042 Build 19042)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.