Write Precise Java Code With LOMBOK

Introduction

 
Have you ever thought of writing a small piece of Java code providing greater functionality? Yes, of course, you would like to do that. It may be a good framework or a good algorithm to do so. If you can write small Java code then it will increase the readability, portability and has fewer bugs and less maintenance. In this article, I present a great framework called "Lombok" that provides an efficient way to write smaller Java code to achieve greater functionality. Lombok is a framework that provides a boilerplate structure to minimize your code to perform more. Lombok provides certain annotations that help us to write better code and eliminates the burden of repetitive code in any project. Let us dive into the usage of the Lombok framework.
 

Technicalities

 
There are certain situations where developers complain about the vast code and find it difficult to make a walkthrough. It is the absolute reality that not all code can be minimized depending on the functionalities whether they are simple or complex. In modern days, new frameworks have evolved to make the developer's life easier. Lombok is one of the frameworks to help developers to write less code and avoid rewriting repetitious code. Think about a situation where you have a bean or POJO that contains fields like id, first name, last name, salary, designation and so on and you will have all the getter and setter methods for this. It is also true that modern developers never write getter and setter methods manually. It is only because of the benefit of the sophisticated style of the modern Java IDEs, developers generate getter and setter methods and some other generic methods also. However, the code finally looks vast. There may be a POJO or a bean that may contain 2 to 3 hundred lines of code. Now the simple POJO looks bulky. It may look complex for a novice Java developer. What if we simply write the fields and let all the relevant getter and setter methods be generated at runtime? That is the power and flexibility provided by Lombok. Lombok provides the following widely used annotations.
 
@NonNull,@Cleanup,@Getter/@Setter,@ToString,@EqualsAndHashCode,
@NoArgsConstructor,@RequiredArgsConstructor,@AllArgsConstructor,
@Data,@Value,@Slf4j,@Log4j
 
Let us discuss each annotation very precisely.
 

@NonNull

 
This annotation generates a NullPointerException for null checking. This annotation can be applied in the field of a class or at the method parameter level. Let us see the code below.
  1. package com.ddlab.rnd.lombok;  
  2. import lombok.NonNull;  
  3. /** 
  4.  * The Class NonNullCheck is used to provide an example on the generation of 
  5.  * NullPointerException with the help of Lombok @NonNull annotation. 
  6.  * 
  7.  * @author <a href="mailto:[email protected]">Debadatta Mishra</a> 
  8.  * @since 2013 
  9.  */  
  10. public class NonNullCheck  
  11. {  
  12.     /** The value. */  
  13.     @NonNull  
  14.     private String value;  
  15.     /** 
  16.     * Instantiates a new non null check.     
  17.     * @param value 
  18.     * the value 
  19.     */  
  20.     public NonNullCheck(@NonNull String value) {  
  21.     this.value = value;  
  22.     }  
  23.     /** 
  24.     * Show. 
  25.     */  
  26.      public void show()  
  27.      {  
  28.          System.out.println("Value--->" + value);  
  29.      }  
  30.       /** 
  31.       * The main method. 
  32.       * 
  33.       * @param args 
  34.       * the arguments 
  35.       */  
  36.       public static void main(String[] args)  
  37.       {  
  38.          NonNullCheck nc = new NonNullCheck(null);  
  39.          nc.show();  
  40.      }  
  41. }  
In the code above we are just providing @NonNull and we are not writing the code for NullPointerException.
 

@Cleanup

 
This is a very useful and handy annotation that saves our life. You have may have seen due to work pressure or for some other reason, developers forget to invoke the close method for file operations or database operation. If you provide this annotation then the code will automatically provide a close() method at runtime. It is also helpful while making code reviews so you can easily provide this annotation if the developer has forgotten to write it. Let us see the code below.
  1. package com.ddlab.rnd.lombok;  
  2. import java.io.File;  
  3. import java.io.FileInputStream;  
  4. import java.io.InputStream;  
  5. import lombok.Cleanup;  
  6. import lombok.NonNull;  
  7. /** 
  8.  * The Class FileReader is used as a utility to read a file by minimizing the 
  9.  * code. In this class @NonNull and @Cleanup annotations have been used for 
  10.  * null check and close operations respectively. 
  11.  * 
  12.  * @author <a href="mailto:[email protected]">Debadatta Mishra</a> 
  13.  * @since 2013 
  14.  */  
  15. public class FileReader {  
  16.     /** 
  17.     * Read file. 
  18.     * @NonNull annotation will generate a NullPointerException code at runtime 
  19.     * @Cleanup annotation will generate the close() method at run time 
  20.     * @param filePath 
  21.     * the file path 
  22.     * @throws Exception 
  23.     * the exception 
  24.     */  
  25.      public static void readFile(@NonNull String filePath) throws Exception {  
  26.      File file = new File(filePath);  
  27.      byte[] buffer = new byte[(int) file.length()];  
  28.      @Cleanup  
  29.      InputStream inStream = new FileInputStream(file);  
  30.      inStream.read(buffer);  
  31.      System.out.println("File Contents :\n" + new String(buffer));  
  32.      }  
  33.      /** 
  34.      * The main method. 
  35.      * @param args 
  36.      * the arguments 
  37.      */  
  38.      public static void main(String[] args) {  
  39.      try {  
  40.               FileReader.readFile("data/data.txt");  
  41.               //FileReader.readFile(null);  
  42.      } catch (Exception e) {  
  43.                    e.printStackTrace();  
  44.                    System.out.println("I got the exception ........");  
  45.       }  
  46.    }   
  47. }  
See the bold section of the code and you are saving your time by not writing a try and finally block and a close operation.
 

@Getter/@Setter

 
It is a common practice that whenever we write a POJO with some fields that we benefit from the intelligence of the Java IDE to generate the getter and setter methods. In this case, Lombok provides @Getter and @Setter annotations to generate the getter and setter methods at runtime. Let us look at the code below.
  1. package com.ddlab.rnd.lombok;  
  2. import lombok.Getter;  
  3. import lombok.Setter;  
  4. /** 
  5.  * The Class Employee is used as a POJO for the employee having id and name. Lombok 
  6.  * annotation will generate all the getter and setter methods for properties. 
  7.  * 
  8.  * @author <a href="mailto:[email protected]">Debadatta Mishra</a> 
  9.  * @since 2013 
  10.  */  
  11. public class Employee {  
  12.    /** 
  13.    * Specifies the id of the employee. 
  14.    * 
  15.    * @Getter annotation will generate all the getter method for id. 
  16.    * @Setter annotation will generate all the setter method for id. 
  17.    */  
  18.     @Getter  
  19.     @Setter  
  20.     private int id;  
  21.     /** 
  22.     * Specifies the name. 
  23.     * 
  24.     * @Getter annotation will generate all the getter method for name. 
  25.     * @Setter annotation will generate all the setter method for name. 
  26.     */  
  27.     @Getter  
  28.     @Setter  
  29.     private String name;  
  30. }  
Here the code looks very simple and precise.
 

@ToString and @EqualsAndHashCode

 
Sometimes it is necessary to provide toString(), equals() and hashcode() methods in a Java bean. In this case Lombok also provides the smart annotations like @ToString and @EqualsAndHashCode so that relevant code will be generated at runtime. Let us look at the code below.
  1. package com.ddlab.rnd.lombok;  
  2. import lombok.EqualsAndHashCode;  
  3. import lombok.Getter;  
  4. import lombok.Setter;  
  5. import lombok.ToString;  
  6. /** 
  7.  * The Class Student is used to provide the usage of Lombok annotation for the 
  8.  * methods toString() , equals() and hashcode(). 
  9.  * 
  10.  * @author <a href="mailto:[email protected]">Debadatta Mishra</a> 
  11.  * @since 2013 
  12.  */  
  13. @ToString  
  14. @EqualsAndHashCode  
  15. public class Student {  
  16.     /** Gets the roll no. */   
  17.     /** 
  18.     * Gets the roll no. 
  19.     * 
  20.     * @return the roll no 
  21.     */  
  22.     @Getter  
  23.     /** 
  24.     * Sets the roll no. 
  25.     * 
  26.     * @param rollNo the new roll no 
  27.     */  
  28.     /** 
  29.     * Sets the roll no. 
  30.     * 
  31.     * @param rollNo the new roll no 
  32.     */  
  33.     @Setter  
  34.     private int rollNo;  
  35.     /** Gets the name. */  
  36.      /** 
  37.      * Gets the name. 
  38.      * 
  39.      * @return the name 
  40.      */  
  41.      @Getter  
  42.      /** 
  43.      * Sets the name. 
  44.      * 
  45.      * @param name the new name 
  46.      */  
  47.      /** 
  48.      * Sets the name. 
  49.      * 
  50.      * @param name the new name 
  51.      */  
  52.      @Setter  
  53.      private String name;  
  54.      /** 
  55.      * Instantiates a new student. 
  56.      * 
  57.      * @param rollNo 
  58.      *            the roll no 
  59.      * @param name 
  60.      * the name 
  61.      */  
  62.      public Student(int rollNo, String name) {  
  63.               this.rollNo = rollNo;  
  64.               this.name = name;  
  65.      }  
  66. }  
In the code above I have used annotations like @Getter,@Setter,@ToString and @EqualsAndHashCode.
 

@Data and @Value

 
@Data is very handy and it is the replacement for @ToString, @EqualsAndHashCode, @Getter, @Setter on all non-final fields, and @RequiredArgsConstructor. Simply provide the @Data annotation for the class and let Lombok generate the code at runtime. Let us see the code below.
  1. package com.ddlab.rnd.lombok;  
  2. import lombok.Data;  
  3. /** 
  4.  * Instantiates a new person. This class provides the usage of @Data lombok 
  5.  * annotation to generate getter, setter, toString, hashcode and equals methods. 
  6.  * 
  7.  */  
  8. @Data  
  9. public class Person {  
  10.    /** The id. */  
  11.    private int id;  
  12.    /** The name. */  
  13.    private String name;  
  14. }  
@Value annotation helps us to define our class as immutable. You can easily make your class immutable with the annotation @Value but be cautious of java.util.Date class. This annotation does not handle Date object properly. Let us see the code below. 
  1. package com.ddlab.rnd.lombok;  
  2. import java.util.Date;  
  3. import lombok.Value;  
  4. /** 
  5.  * Instantiates a new immutable employee. * {@value} annotation is used to 
  6.  * convert the class into an immutable class. 
  7.  * 
  8.  * @param id 
  9.  *            the id 
  10.  * @param name 
  11.  *            the name 
  12.  * @param dateOfBirth 
  13.  *            the date of birth 
  14.  */  
  15. @Value  
  16. public class ImmutableEmployee {  
  17.       /** The id. */  
  18.       private int id;  
  19.       /** The name. */  
  20.       private String name;  
  21.       /** 
  22.        * Do not use Date type object, it will not give correct implementation of 
  23.        * immutable flavour, rather use date of birth as String type. 
  24.        */  
  25.       private Date dateOfBirth;  
  26. }  

val

 
The val keyword in Lombok is the replacement for final. It can be applied at the class level or the member inside a method. It is not so widely used. Let us see the code below.
  1. package com.ddlab.rnd.lombok;  
  2. import java.util.ArrayList;  
  3. import lombok.val;  
  4. /** 
  5.  * The Class UseOfVal is used to provide the usage of Lombok annotation val for 
  6.  * the final generic type. 
  7.  * 
  8.  * @author <a href="mailto:[email protected]">Debadatta Mishra</a> 
  9.  * @since 2013 
  10.  */  
  11. public class UseOfVal {  
  12.    /** 
  13.    * Populate names. 
  14.    * 
  15.    * @param names 
  16.    * the names 
  17.    */  
  18.    public void populateNames(String[] names){  
  19.        val nameList = new ArrayList<String>();  
  20.        for (String name : names)  
  21.          nameList.add(name);  
  22.          System.out.println("All Names : " + nameList);  
  23.    }   
  24. }  

@Slf4j and @Log4j

 
As you know in any application logging is an integral part and for that purpose we use the log4j or slf4j API. In this case Lombok provides @Slf4j and @Log4j annotations that can be applied in the class level. Let us see the code below.
  1. package com.ddlab.rnd.lombok.test;  
  2. import lombok.extern.log4j.Log4j;  
  3. /** 
  4.  * This class is used as demo for slf4j. 
  5.  * 
  6.  * @author Debadatta Mishra (PIKU) 
  7.  */  
  8. @Log4j  
  9. public class TestLog4jLogger {  
  10.     /** 
  11.     * This method is used to display the varous logger messages. 
  12.     */  
  13.     public static void logMessages() {  
  14.         log.debug("It is a debug statement ");  
  15.         log.info("It is an info statement ");  
  16.         log.error("It is an error statement ");  
  17.         log.warn("It is a warn statement ");  
  18.     }  
  19.     public static void main(String[] args) {  
  20.          logMessages();  
  21.     }  
  22. }  
This looks very easy and helps us to minimize our code. In the next section, we will learn about the configuration and use of Lombok.
 

Configuration

 
Lombok comes in the form of a JAR file that must be set in the classpath. Lombok can be downloaded from the following link.
 
 
If you want to use Lombok in the Eclipse IDE then just double-click the JAR file and provide the path of your Eclipse home/installation directory. You can refer to the following link for the installation. Installation of Lombok is not required for the deployable war or ear file. It is only required for the specified IDEs. You can download the relevant source that I have explained from the following link "https://www.dropbox.com/s/uh3ed72mhfvm79y/lombok1.zip". Configure the project in Eclipse and run the Java classes having main methods and you can also go through the javadocs. Lombok provides delombok to generate the original code also. I advise you to use a good decompiler to see the generated code. You can use the JD GUI and have a look into the class and see how the code has been generated and to what extent this framework is useful.
 

Conclusion

 
I hope you have enjoyed my small article about the usage of Lombok for Java objects. Download the complete project and go through the source code to understand the concept and its usage. Based on the complexity and design, you can decide whether to use this tool.
 
References