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

[FEATURE] lombok.noArgsConstructor.extraProtected in lombok.config, which is necessary for proxy generation by libraries #3773

Open
Vyacheslav-Lapin opened this issue Oct 31, 2024 · 0 comments

Comments

@Vyacheslav-Lapin
Copy link

Vyacheslav-Lapin commented Oct 31, 2024

Lombok already has a setting lombok.noArgsConstructor.extraPrivate in lombok.config which, without conflicting with constructors generated in response to annotations, creates a private noArgConstructor in classes.

This feature would be handy for libraries like Hibernate/JPA that need a robust programmatic mechanism for creating objects from certain classes (entities) along with convenient programmer-friendly constructors with arguments (which would be generated using Lombok annotations like @AllArgsConstructor and @RequiredArgsConstructor or implicitly introduced by the @Data annotation).

As a result, if we set “lombok.noArgsConstructor.extraPrivate = true” (also “lombok.fieldDefaults.defaultPrivate = true” for brevity and "lombok.toString.doNotUseGetters = true" for correct debug, because debugger calls toString, but getters in Hibernate proxy is lazy) in lombok.config we would get in the result of class compilation:

@Data
@Entity
public class MyEntity {
  @Id 
  @GeneratedValue
  @Column(updatable = false, nullable = false)
  UUID id;
  
  @NonNull String businessField1; // ... and other fields

  // Explicit Hibernate-specific equals and hashCode - so that Lombok
  // doesn't generate its own, which Hibernate won't work with.
}

It's more elegant than what we have to do for entities now:

@Data
@Entity
@NoArgsConstructor(access = PROTECTED)
@RequiredArgsConstructor // even though this annotation is included in @Data above, we have to write it explicitly because of the conflict with NoArgsConstructor...
public class MyEntity { /*...*/]

Using this setting to elegantly solve this problem of providing such a constructor is unfortunately not possible in real-world conditions, since Hibernate not only instantiates objects, but also creates proxies from them. The latest version of the documentation records without explanation:

“An entity must: be a non-final class, with a non-private constructor with no parameters.”,

, but in earlier version it was explained:

”All persistent classes must have a default constructor (which can be non-public) so that Hibernate can instantiate them using java.lang.reflect.Constructor.newInstance(). It is recommended that this constructor be defined with at least package visibility in order for runtime proxy generation to work properly.

I.e. when generating a proxy from a class you need at least a protected constructor, and one private constructor is not enough :((( And this is not only a problem of Hibernate, but probably a problem of all libraries that use proxy.

In addition, it would be convenient for programmers to inherit their classes (because the private constructor essentially forbids inheritance).

I suggest creating a similar to setting lombok.noArgsConstructor.extraPrivate in a pair —lombok.noArgsConstructor.extraProtected to form a protected no-arg constructor generation.

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

No branches or pull requests

1 participant