Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] @Builder.Exclude for a field in cases where @Builder/@SuperBuilder is on a type #3723

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

a1shadows
Copy link

@a1shadows a1shadows commented Aug 14, 2024

relates to #2307 , #3283 , #3713

Motivation

I know that #2307 has been closed but from the discussion thread I realized that many others were having the same issues I was: that some fields need not be part of a builder (or whatever creation pattern the class is using).

I understand that there is the option of creating a static method/constructor and annotating it with @Builder to achieve exclusion of field(s). However, I would argue that a similar argument could have been made for default values as well. Yet, we have a @Builder.Default which is a super useful feature to have!

My use cases specifically was with regards to JPA Entity classes where I wanted to hide certain non-insertable/non-updatable fields in a JPA Entity from users attempting to build an Entity object. While using @Setter, this was simple enough with @Setter(AccessLevel.PRIVATE), but I wanted to use @Builder since the entities were large and complex. There I had no options with regards to excluding these fields. Not excluding them would mislead the users since such fields are not persisted in the database even when initialized so I was forced to use Setters.

I did not want to badger the maintainers with excessive argumentation so I thought a "POC" might better demonstrate what such an idea would like and would take the discussion forward more constructively. I would greatly appreciate any and all feedback.

Implementation

The basic idea is that if the @Builder/@SuperBuilder annotation is on a type, no setter methods will be generated in the builder for the fields marked with @Builder.Exclude. This means that although the builder class will contain all the fields(so as not to break any existing logic of mapping the builder class to the annotated class through a constructor, generated for builder or maybe through @AllAgsConstructor). However, it will not be possible to set the value of the excluded field before calling the build() method.
It is somewhat similar in use(not implementation) to @Builder.Default:

@Builder
public class User {

    // field setter method will not be generated in builder
    @Builder.Exclude
    private int id;

    private String name;

}

The builder for this class will not contain a User.UserBuilder id(int id) method.

I've added a warning similar to the one for @Builder.Default for when the annotation is not on type. As is the case with @Builder.Default, the @Builder.Exclude annotation holds no meaning when used without a @Builder on the type. if the @Builder is on a constructor or a static method, the exclusion will not take place

I've added a few test cases to demonstrate its working.

I'll add more test cases to the PR if the direction looks promising!

@a1shadows a1shadows changed the title [POC] @Builder.Excludes for a field in cases where @Builder/@SuperBuilder is on a type [POC] @Builder.Exclude for a field in cases where @Builder/@SuperBuilder is on a type Aug 14, 2024
@a1shadows
Copy link
Author

@rspilker @rzwitserloot could you please take a look at this whenever possible?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants