Declare final local variables in Java using Lombok

 Why we should mark local variables as final in Java?

In the cases where we do not want a local variable to change its value, it is a good practice to mark them as final

A final local variable serves as a warning when you “accidentally” try to modify a value and also provides information to the compiler that can lead to better optimization of the class file.

Some developers do not prefer this approach as it cutters the code with final keyword. This post is not debating whether to use final keyword or not, but explains an alternative, I stumbled upon, for making local variables as final.

Marking local variables as final using Lombok's val keyword.

Project Lombok provide a keyword val that can be used to mark local variables as final. Similar feature is available in Kotlin programming language, however in a more extensive way. Using Lombok's val keyword, might help us un-clutter the code.

See below examples:

Simple Java class with final local variables:

Java class using Lombok:

To add Lombok to your Maven project use this dependency:

Immutable Java class using Lombok

 We can generate an Immutable class in Java using @Value annotation of Lombok.

What is Immutable in Java?

An object is considered immutable if its state cannot change after it is constructed. We can create immutable class in Java by following below give steps:

  1. Declare the class as final so it can not be extended.
  2. Make all fields private so that direct access is not allowed.
  3. Don’t provide setter methods for fields.
  4. Make all mutable fields final so that its value can be assigned only once.
  5. Initialize all the fields via a constructor during instantiation of the class.
Below class shows an example of an Immutable class using core Java

Immutable class using @Value annotation of Lombok

Lombok is a Java library that auto generates lots of boiler plate code for Java classes. Lombok works at compile time and manipulates Java byte code to add additional features. Lombok uses annotations to specify what boiler plate code will be generates.

Lombok provides @Value annotation to create an immutable class. As per Lombok documentation:
@Value is the immutable variant of @Data; all fields are made private and final by default, and setters are not generated. The class itself is also made final by default, because immutability is not something that can be forced onto a subclass. Like @Data, useful toString(), equals() and hashCode() methods are also generated, each field gets a getter method, and a constructor that covers every argument (except final fields that are initialized in the field declaration) is also generated.

Add Lombok to your project. If you use Maven as build tool then following Lombok  dependency should be added.

Now simply annotate your class with @Value annotation to obtain an Immutable class. 

Auto generate constructors in Java object using Lombok

 What is Lombok?

Lombok is a Java library that auto generates lots of boiler plate code for Java classes. Lombok works at compile time and manipulates Java byte code to add additional features. Lombok uses annotations to specify what boiler plate code will be generates.

Using @AllArgsConstructor and @NoArgsConstructor annotations.

Lombok provides an @AllArgsConstructor annotation to auto generate a constructor containing all the fields defined in a Java object. @AllArgsConstructor can be applied to a Java class.

Lombok also provides a @NoArgsConstructor annotation that when applied to a class, with generate a default constructor without any parameters.

See below example on how to generate and use constructors using Lombok.

All the posts in this blog have a working example. Please visit our Github repository

Auto generate Setters and Getters in Java Objects using Lombok

 What is Lombok?

Lombok is a Java library that auto generates lots of boiler plate code for Java classes. Lombok works at compile time and manipulates Java byte code to add additional features. Lombok uses annotations to specify what boiler plate code will be generates.

Using @Setter and @Getter annotations

Lombok provides @Setter and @Getter annotations, that can be applied to any class to automatically generate Setter and Getter methods for all the variables in that class. @Setter annotation is smart enough, that it will not generate setter methods for final fields.

Below let's see an example of how to use @Setter and @Getter annotation to auto generate setter and getter methods for a Java object.

Define POJO class as below:

Now we can simple invoke setter and getter methods, without even defining them. You might need to add Lombok plugins to your IDEs to get this to work

All the posts in this blog have a working example. Please visit our Github repository

Trim all values in generated XML using Jaxb

In this post we will see how we can remove leading and trailing spaces from values while converting Java objects to XML using Jaxb. We will also replace empty String values with Null so that they are not exported to XML.

Implementation:

First of all, we need to create a custom adapter that will remove all leading and trailing spaces from a String value and if the resulting values is an empty String ("") then it will replace that with Null.

TrimStringToNullXmlAdapter.java

package com.blogspot.devnip.jaxb;

import javax.xml.bind.annotation.adapters.XmlAdapter;

import static java.util.Objects.isNull;

/**
 * Trim all string values while converting to XML, and replace empty Strings with Null.
 * Null values will be excluded from generated XML
 */
public class TrimStringToNullXmlAdapter extends XmlAdapter<String, String> {

    @Override
    public String unmarshal(String value) {
        return value;
    }

    @Override
    public String marshal(String value) {
        if (isNull(value)) {
            return null;
        }

        value = value.trim();

        if (value.length() == 0) {
            value = null;
        }

        return value;
    }
}

Now we need to add a `package-info.java` file in the package, which contains data objects.

package-info.java


@XmlJavaTypeAdapter(value = TrimStringToNullXmlAdapter.class, type = String.class)
package com.blogspot.devnip.jaxb;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

That's it, now if we use Jaxb to marshall objects in package defined above to XML, it will use the configured adapter and will trim all the String values to null.

XmlGenerator.java

package com.blogspot.devnip.jaxb;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.StringWriter;

/**
 * Handles XML conversion
 */
public class XmlGenerator {

    /**
     * Convert Java object to XML
     *
     * @param input
     * @return
     * @throws JAXBException
     */
    public static String serialize(Object input) throws JAXBException {
        JAXBContext contextObj = JAXBContext.newInstance(input.getClass());

        Marshaller marshallerObj = contextObj.createMarshaller();
        marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);

        StringWriter sw = new StringWriter();
        marshallerObj.marshal(input, sw);

        return sw.toString();
    }
}

Below is an example test.

XmlGeneratorTest.java

package com.blogspot.devnip.jaxb;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import javax.xml.bind.JAXBException;
import java.util.Collections;

class XmlGeneratorTest {

    private static final String TRIMMED_RESPONSE = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Document><Name>James Smith</Name><Code>123123</Code><EmailAddresses><Value>james@test.com</Value><Type>OFFICE</Type></EmailAddresses></Document>";

    @Test
    void test() throws JAXBException {
        XMLDocument xmlDocument = new XMLDocument();
        xmlDocument.setName(" James Smith ");
        xmlDocument.setCode(" 123123 ");

        XMLEmail xmlEmail = new XMLEmail();
        xmlEmail.setType(" OFFICE ");
        xmlEmail.setValue("    james@test.com");
        xmlDocument.setEmails(Collections.singletonList(xmlEmail));

        String result = XmlGenerator.serialize(xmlDocument);

        Assertions.assertEquals(TRIMMED_RESPONSE, result);
    }
}

All the posts in this blog have a working example. Please visit our Github repository

Trim all the String values in a Java object

 In this post we will see how we can remove leading and trailing spaces from all the String fields in a Java object.

We are going to use Jackson to serialize and deserialize a Java object, and while deserializing we will use a custom implementation to trim all the String fields to Null.

Implementation:

Let's create a custom deserializer for String values in Jackson:

TrimStringToNullDeserializer.java

package com.blogspot.devnip.jackson;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

import java.io.IOException;

import static java.util.Objects.isNull;

/**
 * Deserializer that will trim all the leading and trailing spaces from a String value.
 * If the final value us empty string ("") it will be returned as null.
 */
public class TrimStringToNullDeserializer extends JsonDeserializer {

    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException {
        String value = jsonParser.getValueAsString();

        if (isNull(value)) {
            return null;
        }

        value = value.trim();
        if (value.length() == 0) {
            value = null;
        }

        return value;
    }
}

Now, let's hook it up to Jackson's ObjectMapper as shown below.

TrimStringToNullConfiguration.java

package com.blogspot.devnip.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

import static java.util.Objects.isNull;

/**
 * This class shows, how Jackson can be used to trim all the string values in a Java object.
 */
public class TrimStringToNullConfiguration {

    private ObjectMapper objectMapper;

    public Client trimToNull(Client inputClient) throws JsonProcessingException {
        return getObjectMapper().readValue(getObjectMapper().writeValueAsString(inputClient), Client.class);
    }

    private ObjectMapper getObjectMapper() {
        if (isNull(objectMapper)) {
            objectMapper = new ObjectMapper();
            SimpleModule module = new SimpleModule();
            module.addDeserializer(String.class, new TrimStringToNullDeserializer());
            objectMapper.registerModule(module);
        }
        return objectMapper;
    }
}

That's it, you can call the `trimToNull()` function of above class to remove all the leading and trailing spaces from all the fields within a Java object.

Refer to below unit-test for how to use this method.

TrimStringToNullConfigurationTest.java

package com.blogspot.devnip.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

class TrimStringToNullConfigurationTest {

    private TrimStringToNullConfiguration configuration = new TrimStringToNullConfiguration();

    /**
     * Demonstrates trimming of all string values in a Java object.
     *
     * @throws JsonProcessingException
     */
    @Test
    void test() throws JsonProcessingException {
        Client testClient = new Client();
        testClient.setName("   James Smith ");      // String with spaces
        testClient.setSocialId(null);               // Null value
        testClient.setAge(23);                      // Non string value
        Address address = new Address();
        address.setCity("   New York");             // Demonstrates nested fields
        testClient.setOfficeAddress(address);

        Client result = configuration.trimToNull(testClient);

        Assertions.assertEquals("James Smith", result.getName());
        Assertions.assertEquals("New York", result.getOfficeAddress().getCity());
    }
}


All the posts in this blog have a working example. Please visit our Github repository

How to override Builder methods of Lombok in Java

What is Lombok?

Lombok is a Java library that auto generates lots of boiler plate code for Java classes. Lombok works at compile time and manipulates Java byte code to add additional features. Lombok uses annotations to specify what boiler plate code will be generates. Eg. @Getter annotation can be applied to any Java bean to auto generate Getter methods for all the fields in that bean.

In this article we will be looking at the Builder annotation of Lombok.

What is Builder annotation in Lombok?

Lombok can be used to generate Builder class for a Java bean, by annotating the bean class with @Builder annotation. 

Many times we might want to override some of the auto generated methods in our Builder class, to support specific functionality. For example, in below Pet class we are overriding the type() method in Builder so that it can accept String parameter instead of PetType parameter.

We are achieving this by providing implementation of portion of Builder class that we want to override, rest of the class is still generated by Lombok, for us.

Pet object class with overridden Builder annotation.

Usage of overridden Build in service class.

How to override methods of SuperBuilder of Lombok in Java

What is Lombok?

Lombok is a Java library that auto generates lots of boiler plate code for Java classes. Lombok works at compile time and manipulates Java byte code to add additional features. Lombok uses annotations to specify what boiler plate code will be generates. Eg. @Getter annotation can be applied to any Java bean to auto generate Getter methods for all the fields in that bean.

In this article we will be looking at SuperBuilder annotation of Lombok.

What is SuperBuilder in Lombok?

Lombok can be used to generate Builder class for a Java bean by annotating the bean class with @Builder annotation. In case of a class extending another class, a simple builder will not be able to set values in the parent class. For this case we use @SuperBuilder annotation.

@SuperBuilder annotation when applied on both parent and child classes, allows us to set values in both parent and child class field using the generated Builder class.

See below classes on how to generate SuperBuilder and use it.

The Parent class: Employee.java

package com.blogspot.devnip.lombok.superbuilder;

import lombok.Getter;
import lombok.experimental.SuperBuilder;

import java.time.LocalDate;

/**
 * Represents an employee in the company.
 */
@Getter
@SuperBuilder
public class Employee {

    /**
     * Id of the employee
     */
    private final String id;

    /**
     * Employees name
     */
    private final String name;

    /**
     * Date when employee joined the company
     */
    private final LocalDate joiningDate;
}
The extending Child class: Manager.java

package com.blogspot.devnip.lombok.superbuilder;

import lombok.Getter;
import lombok.experimental.SuperBuilder;

import java.time.LocalDate;
import java.util.List;

/**
 * Manager is a type of Employee
 */
@Getter
@SuperBuilder
public class Manager extends Employee {

    /**
     * Employees managed by the Manager
     */
    private final List<Employee> teamMembers;

    /**
     * Date on which this employee became Manager
     */
    private final LocalDate promotionDate;

    /**
     * Customizing builder methods. Rest of the builder code will be auto generated by Lombok.
     *
     * @param <C>
     * @param <B>
     */
    public static abstract class ManagerBuilder<C extends Manager, B extends ManagerBuilder<C, B>>
            extends EmployeeBuilder<C, B> {

        private LocalDate promotionDate;

        public B promotionDate(String dateStr) {
            this.promotionDate = LocalDate.parse(dateStr);
            return self();
        }
    }
}
Usage of Lombok generated builder methods: ManagerService.java


package com.blogspot.devnip.lombok.superbuilder;

/**
 * Provides operational methods on Manager entity.
 */
public class ManagerService {

    /**
     * Create a dummy Manager object for testing.
     *
     * @return
     */
    public Manager createDummyManager() {
        return Manager.builder()
                .id("001")
                .name("James Smith")
                .promotionDate("2010-07-18")
                .build();
    }
}


Customizing or overriding methods of SuperBuilder in Lombok.

The Manager class above also demonstrates how to customize the behaviour of Builder class. We simply need to provide our portion of code that we want to be customize and Lombok will generate the remaining code.

Compress a folder or directory to a zip file in Java

 Many times, for storage or transmission of files, we might be required to zip or compress a file. Compressing a file can reduce storage requirement and also transmission time and bandwidth.

Java provides a core library `java.util.zip` to make zipping and unzipping of files easy.

To zip an entire directory, we iterate through every files in the directory and add them to the output Zip file.

See below code on how to zip an entire directory or folder into a single zip file.

Compress and zip multiple files to a single Zip file in Java

 Many times, for storage or transmission of files, we might be required to zip or compress a file. Compressing a file can reduce storage requirement and also transmission time and bandwidth.

Java provides a core library `java.util.zip` to make zipping and unzipping of files easy.

Below code shows how to create create a zip file from multiple files.

How to zip a file in Java

Many times, for storage or transmission of files, we might be required to zip or compress a file. Compressing a file can reduce storage requirement and also transmission time and bandwidth.

Java provides a core library `java.util.zip` to make zipping and unzipping of files easy.

Below code shows how to create create a zip file from a single file.


Read QR code in Java using Google's ZXing libaray

 QR Code or Quick Response Code is a two dimensional barcode that can be read by modern smartphones and special QR Code scanner devices. Most QR Codes consist of black squares arranged in a square grid on a white backgroundThere are several types of QR codes depending on their symbol size, layout, encoding and structure.

QR Codes can contain data like - simple text, urls, phone numbers, sms, geolocation, email address etc.

How to read QR Code in Java?

Let's use following image as sample QR code.

We can easily read the above QR codes in Java using Google's ZXing library, as shown in below code.

ReadQRCodeZXing.java

package com.blogspot.devnip.qrcode;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;

import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;

/**
 * Read QR code from an image file using Google's ZXing library
 */
public class ReadQRCodeZXing {

    public static String readFile(File file) {
        try {
            BinaryBitmap bitmap = new BinaryBitmap(
                    new HybridBinarizer(
                            new BufferedImageLuminanceSource(ImageIO.read(file))));

            Result result = new MultiFormatReader().decode(bitmap);
            return result.getText();
        } catch (NotFoundException | IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

The results can be verified using below test.

ReadQRCodeZXingTest.java

package com.blogspot.devnip.qrcode;

import org.junit.jupiter.api.Test;

import java.io.File;
import java.net.URL;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

class ReadQRCodeZXingTest {

    @Test
    void test() {
        URL url = ReadQRCodeZXingTest.class.getResource("/qrcode/qrcode.png");
        assertNotNull(url);

        assertEquals("https://devnip.blogspot.com/", ReadQRCodeZXing.readFile(new File(url.getFile())));
    }
}

Generate QR Code in Java using ZXing library

 QR Code or Quick Response Code is a two dimensional barcode that can be read by modern smartphones and special QR Code scanner devices. Most QR Codes consist of black squares arranged in a square grid on a white backgroundThere are several types of QR codes depending on their symbol size, layout, encoding and structure.

QR Codes can contain data like - simple text, urls, phone numbers, sms, geolocation, email address etc.

How to generate QR Code in Java?

We can easily generate QR codes in Java using Google's ZXing library, as given in below code.

The above code will produce the following QR code image file in the base directory of the project.



Convert a list of objects to a map of key and list of objects in Java

 Many times we have a list of objects and we want to group them by a specific field of the object. For example, we have a group of Person objects and we want to find all Person residing in a particular country. 

The easiest way to do this is by converting the list of Person objects into a Map with country as the key and List of Person objects that reside in that country as value.

Java 8 stream comes in very handy to solving this problem.

Suppose we have person object as below.

We can use a very simple Java stream code to convert a List of objects to a Map of Lists.


Above code can be verified using below test:


Use Java streams to convert list of objects to a map

 Java 8 introduced the concept of Streams. Streams is an alternative way of iterating over a collection. Below sample code will show how to convert a list of objects to a key-value map.


Let's assume the objects to be:


Below code shows how to use streams to convert a List of Person objects to a Map with key as Id and values as Person object.


Above code can be verifies with below test.