Inheritance with lombok annotation get errors - java

In my project, lombok is used to avoid writing getters and setters for a class.
I have two classes Child extends Parent:
#Value
#Builder
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class Parent {
#Nonnull
#JsonProperty("personId")
private final String personId;
#JsonProperty("personTag")
private final String personTag;
...
}
And
#Value
#Builder
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class Child extends Parent {
#Nonnull
#JsonProperty("childId")
private final String childId;
...
}
But this doesn't seems work as no default constructor available in Parent. I'm not familiar with the lombok annotation. Is there any good way to extend the Base class and use the lombok annotation at the same time?

TL;DR: add #NonFinal annotation to your superclass
Details: #Value annotation makes the class final, so you cannot inherit from it. Experimental #NonFinal annotation should prevent this.
import lombok.Value;
import lombok.experimental.NonFinal;
#Value
#NonFinal
public class Parent {
REF: https://projectlombok.org/features/Value
NOTE: For performance reasons (if it matters) final (value) objects can be (theoretically) super fast. The optimizer can allocate them in the stack memory, or reuse the same stack block in cycles, so no GC overheads.
(This is similar to how .NET structure value objects are usually allocated by .NET framework)
By adding #NonFinal such an optimization opportunity disappears.

Class hierarchies + lombok doesn't work particularly well, in the sense that the lombok operations done on your Child class don't know anything about parent.
However, your specific question seems answerable:
The Parent class has a constructor that takes all fields, because you asked lombok to make this constructor via #AllArgsConstructor. Therefore, it does not have a no-args constructor. If you want both constructors (the one that takes all fields + a second one that takes no arguments, a.k.a. the default constructor), also add a #NoArgsConstructor annotation to tell lombok that you want that.
NB: #Builder does not work with hierarchy either, but the fresh new #SuperBuilder feature does. I'm pretty sure you want to replace #Builder with #SuperBuilder here. SuperBuilder requires that ALL classes in the hierarchy are annotated with #SuperBuilder and not #Builder.

Related

Is there any sense using java.beans.Transient with "non beans" methods?

I am currently checking some code and I've come across a class which uses java.beans.Transient annotation with some of its methods. The code looks like this:
import lombok.Data;
import java.beans.Transient;
#Data
public class SomeClass {
private OtherClass obj1;
private OtherClass obj2;
#Transient
public boolean isSthPossible(){
...
return retVal;
}
}
This is the first time I have contact with java.beans so I tried to read something more about it however there aren't that much materials on this topic. I was able to find some useful information but I wasn't able to fully understand it yet.
I understand that beans are classes that have private fields and getter/setter methods to access them. I also understand that the #Transient annotation is used to mark getters of a bean so that they are not used during serialization process. However I couldn't find any information on whether the annotation can have any effect on non-bean methods like this. I also couldn't deduce it from the code I am analyzing and I am not able to contact the author of the code.
My question is whether #Transient annotation makes any sense when applied to non-bean methods, like that described. Can it change anything and can it be used any other way than with bean getter methods for serialization purposes?

In Lombok, what is the difference between #AllArgsConstructor and #RequiredArgsConstructor?

Lombok offers a variety of annotations for java constructors, including but not limited to #AllArgsConstructor and #RequiredArgsConstructor. What is the difference between these two and when do you use one over the other? I found this documentation but the verbiage is a little convoluted and I'm having trouble following the basic differences between the two.
In short, use #AllArgsConstructor to generate a constructor for all of your class's fields and use #RequiredArgsConstructor to generate a constructor for all class's fields that are marked as final.
From the documentation,
#AllArgsConstructor generates a constructor with 1 parameter for each field in your class.
#RequiredArgsConstructor generates a constructor with 1 parameter for each field that requires special handling. All non-initialized final fields get a parameter, as well as any fields that are marked as #NonNull that aren't initialized where they are declared.

How to tell lombok that dont create getter and setter for a specific field [duplicate]

I want to use a data class in Lombok. Since it has about a dozen fields, I annotated it with #Data in order to generate all the setters and getter. However there is one special field for which I don't want to the accessors to be implemented.
How does Lombok omit this field?
You can pass an access level to the #Getter and #Setter annotations. This is useful to make getters or setters protected or private. It can also be used to override the default.
With #Data, you have public access to the accessors by default. You can now use the special access level NONE to completely omit the accessor, like this:
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private int mySecret;
According to #Data description you can use:
All generated getters and setters will be public. To override the
access level, annotate the field or class with an explicit #Setter
and/or #Getter annotation. You can also use this annotation (by
combining it with AccessLevel.NONE) to suppress generating a getter
and/or setter altogether.

Add rules when creating a POJO

I'm using lombok's annotation #Data when writing pojos because it automatically generates constructor, hashCode as well as other methods for me. It worked like a charm until I was trying to use #Data in such a pojo class.
#Data
public class MyPojo {
private final String name;
private final int from;
private final int to;
// other fields
}
What I need to do is to restrict values of from and to when creating this pojo so that to will always be greater than from, but it seems that in order to achieve this logic, I have to rewrite the constructor all by myself with lots of code similar to this.name = name.
PS: I think using super from inheritance could be a workaround, but it may make the program harder to be understood.
Is there any better way to satisfy this need?
#Data annotation is not providing any way to validate construction arguments. I feel you need to annotate your pojo with #Getter #Setter #ToString #EqualsAndHashCode annotations and write constructor on your own.
Looking at Lombok's website, I don't see any way to restrict constructor parameters to specific values, especially relative to another variable that may have not been initialized yet. You'll probably have to create a concrete constructor for this class.
but it may make the program harder to be understood
I really wouldn't worry about that as you're already using Lombok, which would make any big program very confusing when trying to track down a specific field/method.

How to generate getters en mass using aspectj

I have the following problem, I am wondering whether anyone knows a solution:
I would like to dynamically generate specially named getters for every private field in every subclass of a certain class using aspectj or some other similar bytecode manipulation tool.
I would like the names of the getters to be based on the corresponding field names, but I can settle for having one method taking a field name string and returning a value, as long as there is no reflection involved.
Have you looked into Lombok? If you have access to the source and are just trying to save typing, than its #Data annotation might be what you looking for.
As in Matt's answer, I suggest you Lombok.
Using the #Getter, #Setter annotations on the class level, corresponding getters/setters based on names of all the non-static fields will be generated at compilation.
Much better than annotating classes by hand is to use static crosscutting of AspectJ (page in the official documentation) to add those annotations globally.
Example for declaring #Getter and #Setter on each persistent Entity :
import javax.persistence.Entity;
import lombok.Getter;
import lombok.Setter;
public aspect EntityAspect {
declare #type: #Entity * : #Getter;
declare #type: #Entity * : #Setter;
}
It requires you either to have the source code, or to use compilation by aspectj on existing jar (instrumentation of an existing library).

Categories