Java Top

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Introduction

In this tutorial, we'll talk about the configuration parameters of Lombok. We'll go over many different options as well as how to set up our configuration correctly.

2. Configuration Overview

Lombok is a library that helps us eliminate almost all standard boilerplates of our Java applications. We'll test many of the properties and configurations. The first thing is to add the Lombok dependency:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <scope>provided</scope>
</dependency>

The configuration system of Lombok offers us many valuable settings that frequently are the same across all the components of our project. However, it also lets us change or customize Lombok's behavior and sometimes even defines what can or cannot be used out of all the available features. For instance, we can tell Lombok to show a warning or an error if any experimental feature is used.

To start defining or customizing Lombok's behavior, we have to create a file called lombok.config. This file can leave at the root of our project, source code, or any package. Once created, all the source files in the child directories will inherit the configs defined in such a file. It's possible to have multiple config files. For example, we can define a config file in our root directory with general properties and create another one in a given package defining other properties.

The new configs will influence all classes of the given package and all children packages. Also, in the case of multiple definitions of the same property, the one closer to the class or member takes precedence.

3. Basic Configurations

One of the first things to mention is too many feature properties to discuss. For this reason, we'll see only the most common ones. To check the available options, let's go to Lombok's page, download the jar, and run the following command in the terminal:

java -jar lombok.jar config -g --verbose

As a result, we'll see a complete list of all properties and their possible values and a short description explaining its goal.

Now, let's see a typical lombok.config file:

config.stopBubbling = true
lombok.anyconstructor.addconstructorproperties = false
lombok.addLombokGeneratedAnnotation = true
lombok.experimental.flagUsage = WARNING

# ... more properties

The properties used in the file are for illustration purposes only. We'll discuss them later. But here, we can observe the format of the Lombok properties and their definition.

Let's begin with the config.stopBubbling property – this option tells the configuration system not to search for config files in the parent directories. It's a good practice to add this property to the root of your workspace or project. By default, its value is false.

4. Main Properties

4.1. Global Config Keys

Global config keys are configurations that may affect many of the configuration systems themselves. Next, we'll see some examples of such keys.

The first key we'll discuss is lombok.anyConstructor.addConstructorProperties. It adds the @java.beans.ConstructorProperties annotation to all constructors with arguments. Usually, frameworks that use reflection on constructors need this annotation to map properties and know the correct order of the params in the constructor. Here is the code in the Lombok version:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Account {
    private double balance;
    private String accountHolder;
}

And here is the generated code:

public class Account {
    private double balance;
    private String accountHolder;

    @ConstructorProperties({"balance", "accountHolder"})
    @Generated
    public Account(double balance, String accountHolder) {
        this.balance = balance;
        this.accountHolder = accountHolder;
    }
 
    @Generated
    public Account() {}

    // default generated getter and setters
}

In the code snippet above, we can see the generated class that contains the @ConstructorProperties annotation.

Next, we have the lombok.addLombokGeneratedAnnotation. If true, Lombok will mark all generated methods with the @lombok.Generated. That comes in handy when removing Lombok-generated methods from package scanning or code coverage tools.

Another helpful key is lombok.addNullAnnotations. This property supports many built-in options such as javax (JSR305), eclipse, JetBrains, NetBeans, Android, and more. It's also possible to use annotations defined by ourselves, like CUSTOM:com.example.NonNull:example.Nullable. Lombok will add the nullable or NotNull annotations whenever it makes sense.

Lastly, we have the lombok.addSuppressWarnings, that if false, Lombok stops adding the annotation @SuppressWarnings(“all”), which is the current default behavior. That is useful if we use static analyzers on the generated code.

4.2. Other Config Keys

Being the first feature-specific key lombok.accessors.chain, if true, changes the behavior of the setter methods. Instead of void return, those methods will return this. Allowing the chaining of the calls, as shown below:

@Test
void should_initialize_account() {
    Account myAccount = new Account()
      .setBalance(2000.00)
      .setAccountHolder("John Snow");

    assertEquals(2000.00, myAccount.getBalance());
    assertEquals("John Snow", myAccount.getAccountHolder());
}

Similar to the previous one, the lombok.accessors.fluent makes Lombok remove the prefix set and get from the accessors methods using only the property names to name them.

The lombok.log.fieldName key changes the name of the generated log field when configured by the user. By default, the lombok.log.fieldName key uses log to name the field, but in our example, we changed it to domainLog:

#Log name customization
lombok.log.fieldName = domainLog

We can then see it in action:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Log
public class Account {

    // same as defined previously

   public Account withdraw(double amount) {
        if (this.balance - abs(amount) < 0) {
            domainLog.log(Level.INFO, "Transaction denied for account holder: %s", this.accountHolder);
            throw new IllegalArgumentException(String.format("Not enough balance, you have %.2f", this.balance));
        }

        this.balance -= abs(amount);
        return this;
    }
}

The next is lombok.(featureName).flagUsage. This set of properties has warning, error, and allow as possible values. We can use them to control which Lombok features are permitted in our projects. For example, it is possible to use the word experimental and the value warning to output a message in the log if any experimental feature is used:

/home/dev/repository/git/tutorials/lombok/src/main/java/com/baeldung/lombok/configexamples/TransactionLog.java:9:
 warning: Use of any lombok.experimental feature is flagged according to lombok configuration.
@Accessors(prefix = {"op"})

4.3. Special Config Keys

Some keys are not common key-values properties, like lombok.copyableAnnotations. That property is different because it represents a list of fully qualified annotation types. When added to a field, Lombok will copy those annotations to constructors, getters, and setters related to the field. A typical use case for this feature is bean definitions with Spring, where the annotation @Qualifier and @Value frequently have to be copied to the constructor arguments. Other frameworks also leverage this feature.

To add annotations to the list, the user must use the following expression: lombok.copyableAnnotations += com.test.MyAnnotation. The library uses the mechanism to propagate the nullable annotation mentioned before:

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Log
public class Account {

    @NonNull
    private Double balance = 0.;
    @NonNull
    private String accountHolder = "";

    // other methods
}

Now, the code generated by Lombok:

public class Account {

    @Generated
    private static final Logger domainLog = Logger.getLogger(Account.class.getName());
    @NonNull
    private Double balance = 0.0D;
    @NonNull
    private String accountHolder = "";

    @ConstructorProperties({"balance", "accountHolder"})
    @Generated
    public Account(@NonNull Double balance, @NonNull String accountHolder) {
        if (balance == null) {
            throw new NullPointerException("balance is marked non-null but is null");
        } else if (accountHolder == null) {
            throw new NullPointerException("accountHolder is marked non-null but is null");
        } else {
            this.balance = balance;
            this.accountHolder = accountHolder;
        }
    }

    @NonNull
    @Generated
    public Double getBalance() {
        return this.balance;
    }

    @NonNull
    @Generated
    public String getAccountHolder() {
        return this.accountHolder;
    }

    // Rest of the class members...

}

And finally, we have a clear lombok.(anyConfigKey) directive. It restores any configuration key to its default value. If someone changed the value of the given key in any parent config file, it would now be ignored. We can use the directive clear, followed by any Lombok config key:

clear lombok.addNullAnnotations

4.4. File Directives

Now, we have a good idea of how Lombok's configuration system works and some of its features. Of course, this was not an extensive list of all available features, but from here, we must have a clear understanding of how to use it. Last but not least, let's see how to import configurations defined in another file inside our current configuration file.

For importing a config file inside another, the directives have to go on top of the file, and the path can be either relative or absolute:

##     relative or absolute path  
import lombok_feature.config

config.stopBubbling = true
lombok.anyconstructor.addconstructorproperties=false
lombok.addLombokGeneratedAnnotation = true
lombok.addSuppressWarnings = false

Just to illustrate, the imported file:

# lombok_feature.config file

lombok.experimental.flagUsage = warning

5. Conclusion

In this article, we looked at the configuration system from Lombok, its different properties, and how they affect its functioning. Although, as mentioned before, there are many more options available, we only looked at the most common ones. Feel free to check more on the Lombok page.

As usual, all code samples used in this article are available over on GitHub.

Java bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE
Generic footer banner
guest
0 Comments
Inline Feedbacks
View all comments