Asked  4 Months ago    Answers:  5   Viewed   754 times

I'm using lombok in my project and generation Setters and Getters using @Setters and @Getters annotations on top of POJO class. I'm trying to override setters method of a property but it's not working

I want to check if JSON property is Empty or Null i want to set default value in Setter method

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ToString
public class DefaultModel {


private String name;
@Setter(AccessLevel.NONE)private String age;    

public void setAge(String age) {
     if(age==null||age.trim().isEmpty()||age.equals("null")) {
        this.age="10";
    }else {
        this.age=age;
    }
}

}

Working scenarios:

        {
"name":"some",
"age":null
     }

     {
"name":"some",
"age":"null"
     }

    {
"name":"some",
"age":"  "
     }

Failed Scenario :

    {
"name":"some"
    }

Output:

DefaultModel(name=some, age=null)

And i'm following this as reference also here, but no luck so far

 Answers

19

Either you just hit a bug I've never seen or you're testing it wrong.

An annotation like

@Setter(AccessLevel.NONE) private String age;

on the field level indeed stops the setter from being generated. But given that you're defining a setter, you don't even need it. An explicit @Setter stops the generation, too.

I've just tried your example using Eclipse 4.7.3a and Lombok 1.18.0 and your (buggy) setter gets called. I've been using Lombok a lot over a few years and never encountered such a bug.

Most probably the problem is that your JSON deserializer does not use setters at all. I guess, you're testing something like

DefaultModel defaultModel = deserialize("{"name":"some"}", DefaultModel.class);

instead of testing the setter directly. And that's the problem.

Monday, July 5, 2021
 
muaaz
answered 4 Months ago
84

Read the 'small print' section on the lombok page https://projectlombok.org/features/GetterSetter.html

For boolean fields that start with is immediately followed by a title-case letter, nothing is prefixed to generate the getter name.

So the behavior you experience is as specified.

Note that the behavior is different for boolean and Boolean:

@Getter
private boolean isGood; // => isGood()

@Getter
private boolean good; // => isGood()

@Getter
private Boolean isGood; // => getIsGood()
Friday, June 18, 2021
 
PandemoniumSyndicate
answered 4 Months ago
93

No that is not possible. There is a feature request to create a @SomeArgsConstructor where you can specify a list of involved fields.

Full disclosure: I am one of the core Project Lombok developers.

Saturday, July 17, 2021
 
christina
answered 3 Months ago
55

Be careful with your solution as it hides the original intent for A and B. That being said, your solution does work, even when casting to base classes.

Example:

D d = new D();
d.X = 2;
B b = d as B;

Assert.AreEqual(2, b.X);

If the base classes can be modified, I recommend using reflection.

Wednesday, August 4, 2021
 
Anand
answered 3 Months ago
78

Forget what you learned in OOP school!

We've come a ways in 3 years. We have much better languages now. Swift, Rust, Kotlin, Go, etc. We understand the difference between data/value types and the code that manipulates it. Proper enterprise CLEAN architecture advocates for this in the Java realm. But Java just doesn't provide language-level support for such patterns. The end result is heavy use of (still wonderful) things like RxJava, and annotation processors that do code generation, etc. But it's really hard to be happy dragging around Java's legacy these days. Kotlin tends to solve Java's problems in a way Java can't at a very very minimal price: loss of strict source compatibility (it's not Groovy).

Original answer, with update at the bottom.

There are two answers.

One:

Useless Boilerplate!

If the class represents some large data object it sounds like most the member variables are just containers for data. When something like this is the case it's less important to strictly follow the OOP convention of information hiding. People often confuse the purpose of this convention and end up abusing it. It is merely to prevent programmers from having to deal with complicated and unnecessary inner workings of an object. Rather than mask an entire object, just mask the parts that shouldn't be messed with. In a case where you are simply mapping information from a database or are acting as a storage container, code like:

import java.util.Date;

public class Article {

    protected int id;

    protected String guid;
    protected String title;
    protected String link;
    protected Date pubDate;
    protected String category;
    protected String description;
    protected String body;
    protected String comments;
    
    protected Article (String articleTitle, String articleBody) {
        title = articleTitle;
        body = articleBody;
    }
    
    protected Article (String guid, String articleTitle, String articleLink,
            long publicationDate, String category, String description,
            String articleBody, String commentsLink) {
        this(articleTitle, articleBody);
        this.guid = guid;
        this.link = articleLink;
        this.pubDate = new Date(publicationDate);
        this.category = category;
        this.description = description;
        this.comments = commentsLink;
    }
    
    protected Article (int id, String guid, String articleTitle, String articleLink,
            long publicationDate, String category, String description,
            String articleBody, String commentsLink) {
        this(guid, articleTitle, articleLink, publicationDate, 
                category, description, articleBody, commentsLink);
        this.id = id;
    }

    protected int getId() {
        return id;
    }
    
    protected String getTitle() {
        return title;
    }

    protected String getGuid() {
        return guid;
    }

    protected String getLink() {
        return link;
    }

    protected String getComments() {
        return comments;
    }

    protected String getCategory() {
        return category;
    }

    protected String getDescription() {
        return description;
    }

    protected String getBody() {
        return body;
    }

    protected void setId(int id) {
        this.id = id;
    }

    protected void setGuid(String guid) {
        this.guid = guid;
    }

    protected void setTitle(String title) {
        this.title = title;
    }

    protected void setLink(String link) {
        this.link = link;
    }

    protected void setPubDate(Date pubDate) {
        this.pubDate = pubDate;
    }

    protected void setCategory(String category) {
        this.category = category;
    }

    protected void setDescription(String description) {
        this.description = description;
    }

    protected void setBody(String body) {
        this.body = body;
    }

    protected void setComments(String comments) {
        this.comments = comments;
    }

}

.. is utterly abominable.

In a case like this there is really no reason to go through all the extra work just to access members of the data object. Especially if you're just using them in a few external lines of code:

public OtherClass {

    private Article article;

    public OtherClass(Article data) {
        article = data;
    }
    
    public String getArticleContents() {

        return (new StringBuilder())
        .append(article.getTitle())
        .append(article.getCategory())
        .append(dateToString(article.getPubDate())
        .append(article.getBody())
        .toString();
    }
}

Just access the members directly and save yourself hundreds of lines of code (like you've suggested you were trying to do).

This leads to the second answer to this question..

Two:

Design Stank..

Your code may be rotting. Chef Ramsey would be ashamed. Here's why:

Clearly the above OtherClass is entirely useless because its functionality could (and should) be placed in the Article class instead of contained in some other, useless, unwanted , file-system-littering OtherClass. If you do that you can forget about even needing the getters and setters and OtherClass because things interfacing with it may only need the article contents rather than the title, body, etc., separately. In this approach the Article class hides everything from the outside world and only provides the information that's absolutely needed.

Since these are two perfectly viable answers to your problem, there must be a solut j on.

Use Clojure

Modeling Objects

Although you can use closures to model objects, there are even better approaches. The interesting thing is that in a language that treats functions as first class citizens, you can model the traditional object oriented paradigm entirely using maps -- as you began to figure out in your refactoring of the 30-plus-member-field class system you were given.

Compare this to the original Article + OtherClass approach:

(defn Article []
  (let [id (atom nil)
        guid  (atom nil)
        title  (atom nil)
        link (atom nil)
        pubdate (atom nil)
        category (atom nil)
        description (atom nil)
        body (atom nil)
        comments (atom nil)

        set (fn [g t l p cg d b cm]
              (do (reset! guid g)
                  (reset! title t)
                  (reset! link l)
                  (reset! pubdate p)
                  (reset! category cg)
                  (reset! description d)
                  (reset! body b)
                  (reset! commments cm)))
        get (fn [] [@guid
                    @link
                    @description
                    @comments
                    :content (content)])

        content #(str title category pubdate body)]
    {:get get, :set set}))

This above examble is a system that takes points from both answers and combines them into one that hides unneeded members, incorporates logical functionality (the function to get the 'content'), and uses a language that doesn't need incredible amounts of shiny boilerplate code..

Replacing Class/Object System

While this is a nice example of how to model an object in a functional language, it's not entirely idiomatic to Clojure and functional programming in general. For even easier ways to do structured data, look at Clojure StructMaps and Records.

2017 Update

Just use Kotlin. It's curing Java sickness across the board. It has first class language support for all these things and the compiler will even help you get rid of useless boilerplate. It's been around for over 7 years and at a stable release for since February 2016. If I'd have known about it originally, I probably would not have included Closure.

Saturday, October 2, 2021
 
inVader
answered 2 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :