Lombok builder override default constructor - java

I was setting the value of recordId from the child classes using the default constructor and was not using lombok #Builder initially. Eventually i decided to use the Builder here, but the problem now is lombok Builder overrides my default constructor internally hence the value is never set.
How can I put any hook too make lombok #Builder use my default constructor?
Parent class:
#Getter
#Setter
public abstract class Record {
private String recordId;
}
Child class:
#Getter
#Setter
#Builder
#ToString
#AllArgsConstructor
public class SRecord extends Record {
private static final String RECORD_ID = "REC001";
private String street;
private String city;
public SRecord() {
setRecordId(RECORD_ID); //value of recordId being set
}
}

Lombok's #Builder simply does not use the default constructor. It passes its values to an all-args constructor so that this constructor can fill the new instance with these values. #Builder does not use setters or direct access to the fields to do so. So your default constructor is simply ignored by #Builder.
What you can do is write your own all-args constructor. In it, you set your value for recordId and assign the rest of the fields from the parameters.

I think you should create a constructor in your base class:
#Getter
#Setter
public abstract class Record {
private String recordId;
public Record(String recordId) {
this.recordId = recordId;
}
}
Then use it in the constructor of the inherited class:
#Getter
#Setter
#Builder
public class SRecord extends Record {
private static final String RECORD_ID = "REC001";
private String street;
private String city;
public SRecord(String street, String city) {
super(RECORD_ID);
this.street = street;
this.city = city;
}
}
P.S. If you want to use Lombok Builder with inheritance you can use this technique.

Related

How can I make javax validation both of sub class and super class?

I'm using Spring framework,
and I faced the inheritance problem when I write Controller logic.
First of all,
this is my Controller code snippet
#PostMapping("/pay/detail")
public ResponseEntity<PayDetail.Response> getPayDetail(
#Valid PayDetail.Request payDetail
) {
... some code
}
and PayDetail class looks like this
public class PayDetail {
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public static class Request extends CommReqForm {
#NotNull(message = "Not null please")
private String work_type;
}
}
and CommReqForm
#Data
#AllArgsConstructor
#NoArgsConstructor
public class CommReqForm {
#NotEmpty(message = "servicecode not empty")
private String servicecode;
#NotEmpty(message = "reqtype not empty")
private String reqtype;
}
I wish that I can validate both of PayDetail.Request and CommReqForm classes but It makes validation just only PayDetail.Request class.
How can I solve this problem?
#Valid cannot validate super class. I want to make both of sub class and super class validation.

Change condition of object with out setters

I have object of following class:
#Jacksonized
#Builder
#Getter
public class Request {
private String id;
private String city_id;
private String country_id;
private List<String> product_id;
}
This class doesn't have setters, but does have #Builder. I don't want to build a new object. I need to replace following List with another List:
private List<String> product_id;
How can I change condition of the current object?
Should I use ReflectionUtils or is there something else better?

How to model constructors which use fewer arguments in lombok

How to model this in Lombok, constructors which take lesser arguments and supporting get/set for transient methods. How to tweak the following definitions
#NoArgsConstructor
#AllArgsConstructor
#Data
public class SalaryRange {
private Integer from;
private Integer to;
private transient String displayName;
private SalaryRange() {
}
private SalaryRange(Integer from) {
this(from, null);
}
private SalaryRange(Integer from, Integer to) {
this(from, to, null);
}
private SalaryRange(Integer from, Integer to, String displayName) {
this.from = from;
this.to = to;
this.displayName = displayName;
}
..
}
Just use a Builder and NoArgsConstructor
#NoArgsConstructor
#Builder
#Data
public class SalaryRange {
private Integer from;
private Integer to;
private transient String displayName;
}
and then
SalaryRange range = SalaryRange.builder().from(1).to(2).build();
Documentation:
Project Lombok Builder
One additional notice - when using #Builder do not static import Builder class - there is a bug that, as far as I know, is not fixed yet
static import not working in lombok builder in intelliJ
I don't think Lombok provide that much flexibility with constructor annotation. 2 approaches may help:
Use #RequiredArgsConstructor, which takes in all final variables.
#NoArgsConstructor
#AllArgsConstructor
#Data
public class SalaryRange {
private final Integer from;
private final Integer to;
private transient String displayName;
}
Use #Builder to achieve more flexibility. However, you may still need #NoArgsConstructor #AllArgsConstructor sometimes for serialization/deserialization by thirty party tools integration, e.g. spring rest, mybatis, etc. Just try it out and check logs.
Otherwise, just write constructor manually, intellij can generate constructor for you quickly by command + N
You may keep constructors from below, the other two are generated by #NoArgsConstructor and #AllArgsConstructor, constructors are meant to build objects
private SalaryRange(Integer from) {
this(from, null);
}
private SalaryRange(Integer from, Integer to) {
this(from, to, null);
}
Another approach might be to combine #Accessors (experimental feature) with #NoArgsConstructor and #AllArgsConstructor
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Accessors(chain = true)
public class SalaryRange {
private Integer from;
private Integer to;
private transient String displayName;
}
SalaryRange salaryRange1 = new SalaryRange().setFrom(1).setTo(2);
SalaryRange salaryRange2 = new SalaryRange(1, 2, "somename");
You may use #Accessors(chain = true, fluent = true) to have fluent accessors if you don't require the get & set prefix
SalaryRange salaryRange1 = new SalaryRange().from(1).to(2);
PD: Builder pattern has downsides that might lead to an Anti-Pattern and might hide a bad design, so be careful when you decide to use it. I think Builder pattern is overused in this scenario, we don't need to add extra complexity to build an object with three attributes.
https://www.baeldung.com/lombok-accessors
https://www.yegor256.com/2016/02/03/design-patterns-and-anti-patterns.html

Java Annotation for composite Range Keys in DDB

I have a my_table with a composite sort key made of two combined attributes id and model_name (i.e., id_model_name, similarly from what is done here here and here).
So I created this Java model:
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#DynamoDBTable(tableName = "my_table")
public class TableModel {
private static final String COMPOSITE_KEY_SEPARATOR = "_";
#DynamoDBAttribute(attributeName = "id")
private String id;
#DynamoDBAttribute(attributeName = "model_name")
private String modelName;
#DynamoDBRangeKey(attributeName = "id_model_name")
public String getIdModelName() {
return String.format("%s%s%s", id, COMPOSITE_KEY_SEPARATOR, modelName);
}
// more stuff...
}
However I'm getting:
DynamoDBMappingException: DRTFacet[id_model_name]; could not unconvert attribute
Notice that there is no String idModelName field, because it could mess up with #AllArgsConstructor and #Builder (since it's a derived field). Is it because this field is missing (together with a setter method?). How can I overcome this?
I found out that providing a dummy setter solved the problem:
public void setIdModelName(final String idModelName) {}

How to configure lombok to generate Getters/Setter for static members also when annotated on class

I have a class for all static members. The number of static members is more than 10 (which may increase with time).
I am using lombok and I want to generate Getters/Setters for all static members using single #Getter and #Setter annotations on class as we do for non-static members.
I know that
You can also put a #Getter and/or #Setter annotation on a class. In
that case, it's as if you annotate all the non-static fields in that
class with the annotation.
I also know that
We can annotate static fields individually using #Getter #Setter to generate Getters/Setters for static fields.
But this looks ugly and I want to make my class look as clean as possible.
Is there any way I can configure / Override #Getter and #Setter annotation so that I can annotate the class and it generate Getters and Setters for all members including static and non-static members, after all, what do those methods do is return the mentioned variable.
To be more precise, I want the following code snippet to generate Getters and Setters for all class variables-
#Getter
#Setter
public class myClass {
private static String d;
private static SomePojo c;
private String a;
private Integer b;
private SomeClass d;
}
Add #Getter to the static member itself and it should work.
#Getter
private static final String DEFAULT_VAL = "TEST";
For static fields you have to add #Getter to the specific field:
#Getter
#Setter
public class Task {
#Getter
private static int numberOfTasks;
#Getter
private static int taskId;
private String taskName;
private Integer executionTime;
}

Categories