Generate MapStruct presence checker methods with Lombok - java

MapStruct is aware of source presence checking
and uses presence checker methods by default (if present of course) to verify if a field in a target object should be updated with a value in a source
object. Without presence checkers MapStruct by default updates only fields with non-null values.
I want to use DTO in a REST controller to implement partial update strategy using MapStruct's source presence checknig but since I use Lombok to generate getters and setters I also want to generate source presence checking methods.

There isn't any way to do that. SOURCE: Me. I'm a core lombok contributor.
However, there is a recent, and very long, feature request discussion on this very idea: Issue #2669: Generate hasXXX() method. It goes in multiple wrong directions, so I would suggest you start from the end, where some concrete plans on how to get there from here are listed. It's complicated.

In short I created a lombok extension which supports #PresenceChecker annotation and generates hasXXX() methods.
// Original code
#PresenceChecker
#Getter
#Setter
public class UserUpdateDto {
private String name;
}
//Generated code
public class UserUpdateDto {
private boolean hasName;
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
this.hasName = true;
}
public boolean hasName() {
return this.hasName;
}
}
More detailed answer can be found here

Related

How to generate getters for lombok Builder?

I have the following definition:
#Value
#Builder(toBuilder = true)
public class MyEntity {
String name;
}
When trying to use a getter on a builder, e.g. MyEntityBuilder.getName(), IDEA states that it "Cannot resolve method". Also, IDEA doesn't auto-complete it.
The only available method (except build()) is the setter: MyEntityBuilder name(String name);
Is there a way to generate getter on lombok generated builders? Thanks.
Using Lombok 1.8.16.
There seems to be no option to do it out of the box according to the Lombok docs or the source code.
If you want to inspect the contents of the builder, the best you can do, it seems, is to build the object and inspect the field from there.
You mentioned you were using IntelliJ IDEA as your IDE. It so happens that there is an IDEA plugin exactly for this:
https://plugins.jetbrains.com/plugin/6317-lombok
Once the plugin is installed, IDEA should recognize Lombok's annotation syntax.
Builders do not,
generally,
have getters.
The builder pattern is this:
Create the builder.
Set values in the builder.
Call build().
As answer from DwB suggests builder pattern does not need nor use getters.
You can have a getter for Lombok builder values but I think that it would not be very useful. You can customize builder this way:
#Value
#Builder(toBuilder = true)
public class MyEntity {
String name;
String name2; // just something to set also
// Customized builder
public static class MyEntityBuilder {
private String name;
public String getName() {
return this.name;
}
// This is not actually needed but just as an example howto
// customise a setter.
public MyEntityBuilder name(String name) {
this.name = name;
return this;
}
}
}
And to test it (Junit5):
#Test
void test() {
MyEntityBuilder meb = MyEntity.builder();
var myEntity = meb
// You need to set this first to access it later
.name("Name #1")
// The benefit having a getter ?
.name2(meb.getName())
.build();
assertEquals(myEntity.getName(), myEntity.getName2());
}

How to remove common code in similar Java String based Enums

I have a class that may have several enums within it.
Each enum is supposed to have a string value associated with each entry.
In order to achieve this, I have added a parametrized constructor,a supporting string class member and overridern the toString method.
However one can see that 50% of the code between my two enums are same. It's just the code to support mapping strings to the Enum values.
How can I move this code to a common place and avoid code duplication?
Edit: Use case is to easily obtain "New York" when I write America.STATES.NY.
Here's what I tried,
1) I tried using a common interface, but the constructors are different.
2) I tried using inheritance, but enums cannot be inherited
public class America {
public enum STATES {
NY("New York"), CA("California");
String displayName;
STATES(String displayName) {
this.displayName = displayName;
}
#Override
public String toString() {
return this.displayName;
}
}
public enum PROVINCES {
ON("Ontario"), QU("Qubec");
String displayName;
PROVINCES(String displayName) {
this.displayName = displayName;
}
#Override
public String toString() {
return this.displayName;
}
}
}
A typical phrase I like to use is "data isn't a part of behavior, and doesn't belong in the code". To be clear (and from my experience), it's much easier to adopt or translate a system that relies on the data for it being loaded from something rather than representing the data in hard-coded values.
public class Region {
private final String name;
public Region(String name) { this.name = name; }
public String getDisplayName() { return this.name; }
public String toString() { return getDisplayName(); }
}
public class Country {
//keeps a map/list of "regions", whether states or provinces or some other type
public Region getRegion(Object key); //lookup a region based on some key, I'll use strings here
}
Country america = /* a country supplied from somewhere */;
String name = america.getRegion("NY").getDisplayName(); //"New York"
This type of approach, while sub-optimal for hard-coded references in your code (like getRegion("NY")), is much more forgiving when you need to modify the data later or make a reference which is loaded from elsewheres (e.g. a user-supplied Region or lookup name). If you use a database, you can keep your code up-to-date without ever having to change the project, just the database itself. And in the end, since all of this data-related information is stored elsewheres, the overall amount of code to handle is vastly reduced.
You can also later add in something to support determining whether a given administrative region is a state or province or something else (which I think an enum is great for):
public enum RegionType {
STATE, PROVINCE, ADMIN_REGION, OTHER,
;
}
You can implement an EnumUtils class and add a static instance of it to every enum class. I implemented an example here: https://stackoverflow.com/a/48199147/7949301.

Determine which fields of a POJO are being accessed in a code

I have a huge (parent) POJO which is being used in some component. The POJO has individual fields as well as nested POJOs as well. Is it possible to determine what all fields/ nested fields from this POJO are being accessed in that component?
I was thinking about JUnits/ aspects but not sure if either would work. I've tried looking through SF/ and Google but could not find any relevant thread for this thing.
Say following is a sample POJO:
public class Student {
private String name;
private Date date;
private Subject subject;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
}
It has three fields name, date and subject, not all of which would be in use in my component. So I need to determine which are actually being used.
Edit:
Thanks Sharon for pointing out that the getter/setters were protected. I had just generated the class on the fly for the purpose of question and didn't notice the issue. Corrected now.
How the class is initialised: For the purpose of the component, objects will be created from Json/XML data and would have only getters being called.
As for static vs runtime analysis, I'd prefer to achieve it through static code analysis if that's possible otherwise runtime also is fine with me if that's easier.
As for using Decorator pattern, do we have anything without requiring existing code change? That's why I was thinking if JUnits could do this.
First of all, it is odd to see getter/setter methods that are protected. seems to me they need to be public?
Anyway, I would utilize the Decorator design pattern.
From the linked article:
The decorator design pattern allows us to dynamically add
functionality and behavior to an object without affecting the behavior
of other existing objects in the same class.
So, our decorated Student should inherit from the target class. All methods can log their usage and call super to invoke target operation. You didn't say how Student
is initialized, but anyway, you will want to modify that to create instances of LogUsageStudent
public class LogUsageStudent extends Student {
protected String getName() {
// log usage of getName()
return super.getName();
}
// etc
}

Can I use jackson mixIns to modify "getters" behavior?

I'm in the need of do some clean up of some invisible characters (\r\n) and html tags for specific getters on my entities.
I've been trying to use mixIns to modify what's returned from the entity but I'm not sure how can I reference the target class in my MixIn so I can add the clean up logic there. From the my tests seems that not even my method is called.
This is what I have so far, but it never gets called
public abstract class BookMixIn {
#JsonProperty
public String getTitle() {
return StringUtils.deleteWhitespace(getTitle());
}
}
public class Book {
private String title;
// getter/setters omitted...
}
And the ObjectMapper config:
mapper.getSerializationConfig().addMixInAnnotations(com.company.Book.class,
com.company.BookMixIn.class);
mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
String tmp = mapper.writeValueAsString(book);
log.info(tmp);
Can this be accomplished via MixIns?
Thanks
Jackson mix-ins are purely for associating annotations; they are not used for adding behavior (code).
So they would not help you here.
But the simple way that would work (possibly using mix-in too) is to add annotation for using custom serializer, which can use whatever filtering is needed:
#JsonSerialize(using=MyCoolSerializer.class) public String getTitle() { }
so either add that to POJO, if possible; but if not, associate it using mix-in.
If you are running Jackson 1.9, this works:
BookCleaner cleanBook = new BookCleaner(book);
mapper.getSerializationConfig().addMixInAnnotations(Book.class, BookMixIn.class);
mapper.writeValueAsString(cleanBook);
#JsonSerialize
class BookCleaner {
private Book book;
public BookCleaner(final Book book) { this.book = book; }
#JsonUnwrapped
public Book getBook() { return book; }
#JsonProperty("title")
public String getCleanTitle() { return cleanup(getBook().getTitle()); }
}
public interface BookMixIn {
#JsonIgnore public String getTitle();
}
I don't think it works like this; the class or interface is just used as a signature.
You could use AspectJ to modify the return value, but it might be easier to just create a decorator and serialize that instead of the underlying object.
Alternatively, you could create specific getters for the "safe" versions of things and use the #JsonProperty annotation to give it the name you need, and use #JsonIgnore on the "non-safe" getters.

Getters/setters in Java

I'm new to Java, but have some OOP experience with ActionScript 3, so I'm trying to migrate relying on stuff I know.
In ActionScript 3 you can create getters and setters using the get and set keywords, meaning you create a method in the class and access data through a property of an instance of that class. I might sound complicated, but it's not. Here's an example:
class Dummy{
private var _name:String;
public function Dummy(name:String=null){
this._name = name;
}
//getter
public function get name():String{
return _name;
}
//setter
public function set name(value:String):void{
//do some validation if necessary
_name = value;
}
}
And I would access name in an object as:
var dummy:Dummy = new Dummy("fred");
trace(dummy.name);//prints: fred
dummy.name = "lolo";//setter
trace(dummy.name);//getter
How would I do that in Java?
Just having some public fields is out of the question.
I've noticed that there is this convention of using get and set in front of methods, which I'm OK with.
For example,
class Dummy{
String _name;
public void Dummy(){}
public void Dummy(String name){
_name = name;
}
public String getName(){
return _name;
}
public void setName(String name){
_name = name;
}
}
Is there an equivalent of ActionScript 3 getter/setters in Java, as in
accessing a private field as a field from an instance of the class, but having a method for implementing that internally in the class?
Nope. AS3 getters and setters are an ECMAScript thing. In Java, you're stuck with the getVal() and setVal() style functions--there isn't any syntactic sugar to make things easy for you.
I think Eclipse can help auto-generating those types of things though...
Your Java code is fine, except that you would, want to make _name private.
There are no get and set keywords in Java as in your AS3 example. Sorry, it doesn't get better than what you're doing already.
Corrected code:
class Dummy {
private String _name;
public void Dummy() {}
public void Dummy(String name) {
setName(name);
}
public String getName() {
return _name;
}
public void setName(String value) {
_name = value;
}
}
Sadly, no, there isn't the equivalent language-level support in java.
The get* and set* patterns though are so established in java culture that you'll find strong IDE support for them (e.g., eclipse will make them for you automatically), and if you're working in something that uses the expression language first made for jsps (EL), then you'll be able to use the property notation to access getters and setters.
I would consider not having the getter or setter as they don't do anything in your case except make the code more complicated. Here is an example without getters or setters.
class Dummy {
public String name;
public Dummy(String name) { this.name = name; }
}
Dummy dummy = new Dummy("fred");
System.out.println(dummy.name);//getter, prints: fred
dummy.name = "lolo";//setter
System.out.println(dummy.name);//getter, prints: lolo
IMHO Don't make things more complicated than you need to. It so often the case that adding complexity will suffer from You-Aint-Gonna-Need-It
An IDE-independent way is to use Lombok, an annotation-based library that generates getters, setters, and even equals() and hashcode(). It does this for the compiler, but not in the source file, so you don't have to look at the methods, just use them.
In Java, the only option you have without exposing the internals of your object is to make your own getters and setters as you have in your example.
The convention is to prepend get or set in front of the field which is being altered. So, as in your example, the field name would have getName and setName methods as their corresponding getter and setter, respectively.
Also before adding setters and getters, it might be a good idea to ask yourself why are you exposing the internal data of the Object in question.
I suggests you read this article -
http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

Categories