How can I get another value like #Getter of lombok? - java

Is there any annotation to let us get another value if original value is null?
#Getter
#NoArgsConstructor
#AllArgsConstructor
#ToString
public class SomeDto extends BaseDto {
private BigDecimal a;
#GetOrAlternative(alternative = "a")
private BigDecimal b;
For example, I want to get value a if b is null on above code.
I want to use that like dto.getBOrAlternative().
Is that possible?
If that is not possible, how can I implement that?
I tried to make custom annotation and processor following this: https://www.happykoo.net/#happykoo/posts/256
However, it didn't work. I think it is because that is not a field level.

Related

way to change the jsonProperty name in only one use case

I have one model class which has approximately 100 property fields. I need to change the jsonProperty name's for one usage scenario but in all other cases where i'm using this class the property name should not be change. What would be the ideal way to handle this situation.
List<DebitTable> debitTableList = getListData();
Below is the DebitTable class.
#Validated
#Data
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#Builder
public class DebitTable {
#JsonProperty("debitId")
private Long debitId;
#JsonProperty("debitName")
#Pattern(regexp = "^[a-zA-Z0-9 ]*$")
#Size(max = 10)
private String debitName;
.....
}
In one of the usage which returns this List<DebitTable> , i want to change the jsonProperty name from debitId to "Debit Id" and "debitName" to "Debit Name"...Do i need to create another model class by changing the jsonProperty name,but that would be very difficult to set each and every field from one model DebitTable class to other new model class.

What is the class type of a #Builder object before calling build()?

I have done this before but forgot and couldn't find the answer easily online.
Let's say I have lombok on a POJO like
#Builder
#NoArgsConstructor
class Car {
private int gallons;
private int wheels;
private String name;
}
and I want to use the builder notation in some logic
public Car getCar(boolean isNew) {
<I dont know what type to put here> carBase = Car.builder().wheels(4);
if(!isNew) {
return carBase.gallons(10).build();
}
else {
return carBase.gallons(0).build();
}
}
What type should I use to fill in?
Okay, so I was actually running into this error Why is Lombok #Builder not compatible with this constructor? which was breaking my #Builder class.
Apparently lombok will generate a static nested class in the class annotated with #Builder called <classname>Builder, so to answer my original question there would be a valid class called Car.CarBuilder.

Lombok #SuperBuilder is not initializing my class objects

I have a parent class and a child class and I am using #SuperBuilder to build the child object, but seemingly it is not initializing at all.
My parent class looks like this:
#Getter
#Setter
#Component
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
#SuperBuilder
public class MessageResponse {
String responseMessage;
}
My child class looks like this:
#Getter
#Setter
#Component
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
#SuperBuilder
public class ListResponse extends MessageResponse {
List<Item> itemList;
int itemCount;
}
Where Item is a Serializable class.
Initially the ListResponse is
itemList = null
itemCount = 0
responseMessage = null
When I try to build ListResponse using builder, it does not change the ListResponse object at all. I am trying to build as
//listResponse is #Autowired from Spring and is initially as shown above.
List<Item> itemList = getItems(); // It returns a list of 15 items, i have checked in debugger, It does.
listResponse.builder()
.bucketList(itemList)
.responseMessage("Item List.")
.bucketCount(itemList.size())
.build();
Even after execution of .build() the contents of this listResponse object is still (null, 0 , null).
I tried to search other references regarding #SuperBuilder and #Builder but got no result. Can someone please point out what is going wrong here?
A builder always creates a new instance. This is the purpose of the builder pattern, and it is how builders work, whether you use Lombok's #SuperBuilder, #Builder, or a manual builder implementation.
You can see that the builder() method is a static method, so it has no access to the instance (typically your IDE should give you a warning here, advising to write ListResponse.builder() instead).
If you want to create a new instance using a builder that is pre-filled with the fields from an existing instance, you can use toBuilder = true as annotation parameter on #(Super)Builder. Then call listResponse.toBuilder().
If you want to modify an instance, the builder pattern is not the right choice. Use setters instead. Those can be generated by Lombok also in a fluent, chainable style; see #Accessors for details.

Spring Data MongoDB does not see accessor for private field from parent class

#Getter
#Setter
#Wither
class A {
protected final List<String> list;
//constructors
}
#Document
#Getter
#Setter
#Wither
class B extends A{
}
In this case, class B gets persisted but when I try to read the document from the Mongo database, i'm getting the following exception: "No accessor to set private final A list"
How to fix this?
Without masses of knowledge of Spring Data MongoDB, I would assume that the list field probably needs to be marked as protected rather than private for it to be visible to the subclass.
protected makes a field visible to its enclosing class's subclasses, whereas private means that only the class itself can see it.

Mapstruct Invoking implicitly other mapper with multiple parameter

Given the following classes and a mapper that takes mulitple source arguments
(I use lombok to keep source as short as possible.)
#Getter
#Setter
public class MySourceOne {
private String src1;
}
#Getter
#Setter
public class MySourceTwo {
private String src2;
}
#Getter
#Setter
public class MyTargetObject {
private String prop1;
private String prop2;
}
#Mapper
public interface MyTargetObjectMapper {
#Mapping(target="prop1", source="a")
#Mapping(target="prop2", source="b")
public MyTargetObject mapMyObject(String a, String b);
}
#Getter
#Setter
public class MyComplexTargetObject {
private MyTargetObject myTargetObject;
}
I am trying to create a mapper for MyComplexTargetObject that will invoke implicitly the MyTargetObjectMapper .
But the "source" won't allow to map multiple parameter like this
#Mapper(uses= {MyTargetObjectMapper.class})
public interface MyComplexTargetObjectMapper {
#Mapping(target="myTargetObject", source="one.src1, two.src2")
public MyComplexTargetObject convert(MySourceOne one, MySourceTwo two);
}
So I am trying to use an expression="..." instead of source, but nothing works so far.
Any thoughts a clean way to do this without calling the MyTargetObjectMapper in a concrete method?
MapStruct does not support selection of methods with multiple sources.
However: you can do target nesting to do this.
#Mapper
public interface MyComplexTargetObjectMapper {
#Mapping(target="myTargetObject.prop1", source="one.src1" )
#Mapping(target="myTargetObject.prop2", source="two.src2")
public MyComplexTargetObject convert(MySourceOne one, MySourceTwo two);
}
And let MapStruct take care of generating the mapper. Note: you can still use a MyComplexTargetObjectMapper to do single source to target to achieve this.

Categories

Resources