Java 8 – Builder pattern with Consumer interface

In this post, I am going to provide an example to show how we can implement the Builder pattern with Consumer interface.

With the use of Consumer interface, we can get rid of some boilerplate code in Java. Assume that you have a model class “Book” which contains a builder class inside of it. So to create an instance of “Book”, We can make use of this builder class. See the below example to know how we can do it in a normal way.


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Book {

    private String title;
    private List authors;
    private float price;

    public Book(Builder builder) {
        this.title = builder.title;
        this.authors = builder.authors;
        this.price = builder.price;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Builder{");
        sb.append("title='").append(title).append('\'');
        sb.append(", authors=").append(authors);
        sb.append(", price=").append(price);
        sb.append('}');
        return sb.toString();
    }

    public static class Builder {

        private String title;
        private List authors;
        private float price;

        public Builder withTitle(String title){
            this.title=title;
            return this;
        }
        public Builder withAuthors(List authors){
            this.authors=authors;
            return this;
        }
        public Builder withPrice(float price){
            this.price=price;
            return this;
        }
        public Book build() {
            return new Book(this);
        }
    }

    public static void main(String[] args) {
        Book book = new Builder().withTitle("Design Patterns: Elements of Reusable Object-Oriented Software").
                withAuthors(new ArrayList(Arrays.asList(new String[]{"Erich Gamma", "John Vlissides", "Ralph Johnson", "Richard Helm"}))).
                withPrice(16.98f).build();
        System.out.println(book);
    }
}

If you look at the above example, then you can understand there are two many setter methods available in the Builder class. We can avoid this with Java 8 Consumer interface. I have changed the above example class with Consumer interface.

Refer below the code.


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Book {

    private String title;
    private List authors;
    private float price;

    public Book(Builder builder) {
        this.title = builder.title;
        this.authors = builder.authors;
        this.price = builder.price;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Builder{");
        sb.append("title='").append(title).append('\'');
        sb.append(", authors=").append(authors);
        sb.append(", price=").append(price);
        sb.append('}');
        return sb.toString();
    }

    public static class Builder {

        public String title;
        private List authors;
        public float price;

        public Builder with(Consumer function) {
            function.accept(this);
            return this;
        }

        public Book build() {
            return new Book(this);
        }
    }

    public static void main(String[] args) {
        Book book = new Book.Builder().with(bookData -> {
            bookData.title = "Design Patterns: Elements of Reusable Object-Oriented Software";
            bookData.authors = new ArrayList(
                    Arrays.asList(new String[]{"Erich Gamma", "John Vlissides", "Ralph Johnson", "Richard Helm"}));
            bookData.price = 16.98f;
        }).build();
        System.out.println(book);
    }
}

In the above code, I have removed all the setter methods available in the Builder class and created only one method with() which takes the Consumer function as input.

Consumer is a functional interface in Java and it accepts a single input argument and does not return any value. Here we are going to pass a Consumer object with a value for each field(Builder class).

We can also update the reference name ‘bookData’ with any symbol. Refer the below example where I have used the symbol ‘$’ to make it simpler.


  public static void main(String[] args) {
        Book book = new Book.Builder().with($ -> {
            $.title = "Design Patterns: Elements of Reusable Object-Oriented Software";
            $.authors = new ArrayList(
                    Arrays.asList(new String[]{"Erich Gamma", "John Vlissides", "Ralph Johnson", "Richard Helm"}));
            $.price = 16.98f;
        }).build();
        System.out.println(book);
    } 

The one drawback of this approach is to update all the fields of the Builder class as public. But this should be fine as we are not going to modify the actual class (Book) here.

Advertisements

Java 8 – Optional class

Java 8 contains a new class called ‘Optional’ in the utils package which is used to represent a value is present or not.

This class is used to avoid the Null pointer exception. So we don’t need to do any null check in our code if we use Optional object along with our object.

Refer the below example to know how we can use the Optional class.


import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class OptionalMain {

    public static void main(String[] args) {

        OptionalMain optionalMain = new OptionalMain();
        optionalMain.testBasic();
        optionalMain.testFilter();
        optionalMain.testMap();
    }

    private void testBasic() {

        // Create the Optional object with a string object. Note the string is null.
        //This will create Optional.empty as the value is null
        Optional stringOptional = Optional.ofNullable(null);
        System.out.println("stringOptional:" + stringOptional);
        try {
            //If you pass null value to of method, then it will throw Null pointer exception
            System.out.println("ofNullable on Non-Empty Optional: " + Optional.of(null));
        }
        catch (NullPointerException npx) {
            npx.printStackTrace();
        }

        // Check whether the value is present in the Optional object
        System.out.println("stringOptional value is present: " + stringOptional.isPresent());

        // Get the value from the Optional object. If its null, then return the default value
        // passed to the orElse method
        System.out.println("stringOptional value " + stringOptional.orElse("EMPTY"));

        // Create the Optional object with a string object.
        Optional nameOptional = Optional.ofNullable("name");
        System.out.println("nameOptional name is present:" + nameOptional.isPresent());
        nameOptional.ifPresent(name -> System.out.println("Name is available"));

        try {
            // Get the value from the Optional object. If its null, then throw an exception
            System.out.println("stringOptional value " + stringOptional.orElseThrow(RuntimeException::new));
        }
        catch (RuntimeException ex) {
            ex.printStackTrace();
        }
    }

    private void testFilter() {
        Optional nameOptional = Optional.of("john");
        System.out.println("Filter Operation:" + nameOptional.filter(name -> name.equals("john")));
        Optional numOptional = Optional.of(100);
        System.out.println(numOptional.filter(value -> value > 10));
        System.out.println(numOptional.filter(value -> value > 100));
    }

    private void testMap() {

        List fruits = Arrays.asList("apple", "orange", "banana");
        Optional<List> fruitsOptional = Optional.ofNullable(fruits);
        System.out.println("Fruits" + fruitsOptional.get());
        System.out.println("Mapping the Fruits " + fruitsOptional.get().stream().map(String::toUpperCase)
                .collect(Collectors.toList()));

    }
}

Output:


stringOptional:Optional.empty
stringOptional value is present: false
stringOptional value EMPTY
nameOptional name is present:true
java.lang.NullPointerException
	at java.util.Objects.requireNonNull(Objects.java:203)
	at java.util.Optional.(Optional.java:96)
	at java.util.Optional.of(Optional.java:108)	
Name is available
java.lang.RuntimeException
	at java.util.Optional.orElseThrow(Optional.java:290)
Filter Operation:Optional[john]
Optional[100]
Optional.empty
Fruits[apple, orange, banana]
Mapping the Fruits [APPLE, ORANGE, BANANA]


Stackshare

If you want to know about the tools or application stack used in any major tech company, then you can visit this web site stackshare 

This is a crowd sourcing site and it acts as a software discovery platform and lets us search for the best software tools and which companies are using them.

 

How to use WireMock for stubbing web services

WireMock is a library for stubbing and mocking REST Web services. This will be a handy one if we want to test external web services. When we use this, it will start a mock http server on the given port number so it looks like we are connecting to the actual web services.

Lets see how we can use this for writing JUnit test cases. Consider that you have two web services. one if for creating the user and another one is for fetching it. We don’t worry about the actual services. Let’s see how we can stub these services with WireMock.

I am going to use JUnit Rule for this example. Add the below dependencies in the maven pom.xml file.

<dependencies>
        <dependency>
            <groupId>com.github.tomakehurst</groupId>
            <artifactId>wiremock</artifactId>
            <version>2.7.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>2.18</version>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-all</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

Now my test code is given below,


package com.wiremock;

import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.glassfish.jersey.client.JerseyClient;
import org.glassfish.jersey.client.JerseyClientBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import javax.ws.rs.core.Response;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.matching;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
import static javax.ws.rs.client.Entity.entity;
import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
import static org.junit.Assert.assertEquals;

public class WireMockTest {

    @Rule
    public WireMockRule rule = new WireMockRule(8080);

    private static String GET_USERS = "http://localhost:8080/users/12345";
    private static String POST_USER = "http://localhost:8080/users";
    private static String USER_CONTENT = "<users>
   <user>
      <id>12345</id>
      <name>bala</name>
   </user>
</users>";

    JerseyClient client;

    @Before
    public void setUp() {
        client = JerseyClientBuilder.createClient();
    }

    @After
    public void tearDowm() {
        rule.shutdown();
    }

    private void stubFor(){
      rule.stubFor(post(urlEqualTo("/users")).willReturn(aResponse().withStatus(200));
rule.stubFor(get(urlEqualTo("/users/12345")).willReturn(
                aResponse().withHeader("Content-Type", "application/xml")
                        .withBody(USER_CONTENT)));
    }

    @Test
    public void testAddUser() {
        stubFor();
        client.target(POST_USER).request().post(entity(USER_CONTENT, APPLICATION_XML_TYPE));
        rule.verify(postRequestedFor(urlMatching("/users"))
                            .withRequestBody(matching(USER_CONTENT))
                            .withHeader("Content-Type", matching("application/xml")));

    }

    @Test
    public void testGetUser() {
        stubFor();
        Response response = client.target(GET_USERS).request().get();
        String output = response.readEntity(String.class);
        System.out.println("output: "+output);
        assertEquals(200, response.getStatus());
        assertEquals(USER_CONTENT, output);
    }
}

Explanation:
The first step is to add the WireMockRule and pass the port number on which the mock server is going to be run. You can specify any port number. By default its 8080.

Now the next step is to add the stubFor for both services(getUser, addUser)
For adding user service, the method is POST and it will return the response status as 200. For getting the user service, the method is GET and it will the return the static user response XML.

The next step is to call the services with the REST client object.
The final step is to do the verification. We can do the same kind of verification as such verifying the actual response.

Refer the code @https://github.com/dkbalachandar/java-wiremock-tester

Java 8 – Lambda Predicates

Predicate is a functional interface in java 8. It’s used to hold the lambda expression and takes a value or an object and return a boolean value.

This is very handy if you want to do any validation or filtering anythig.

Refer the below example to know how to use the Predicate for validating the number whether it’s even or not and some more operations.


import java.util.function.Predicate;

public class PredicateMain {

    public static void main(String[] args) {
        // Validate whether the number is even or not.
        System.out.println("Predicates.isEven(2)::" + Predicates.isEven().test(2));
        // Validate whether the number is odd or not.
        System.out.println("Predicates.isOdd(3) ::" + Predicates.isOdd().test(3));
        // Validate whether the number is even and also greater than 100
        System.out.println("Predicates.isEven().and(Predicates.isGreaterThan100(100)) ::"
                + Predicates.isEven().and(Predicates.isGreaterThan100()).test(100));
        // Validate whether the number is even and also greater than 100
        System.out.println("Predicates.isEven().and(Predicates.isGreaterThan100(102)) ::"
                + Predicates.isEven().and(Predicates.isGreaterThan100()).test(102));
        // Validate whether the number is even or greater than 100
        System.out.println("Predicates.isEven().or(Predicates.isGreaterThan100(101)) ::"
                + Predicates.isEven().or(Predicates.isGreaterThan100()).test(101));
        // Validate whether the number is even and negate the result.
        System.out.println("Predicates.isEven().negate(11) ::" + Predicates.isEven().negate().test(11));
    }

    static class Predicates {

        public static Predicate isEven() {
            return number -> number % 2 == 0;
        }

        public static Predicate isOdd() {
            return number -> number % 2 != 0;
        }

        public static Predicate isGreaterThan100() {
            return number -> number > 100;
        }
    }
}


Output:



Predicates.isEven(2)::true
Predicates.isOdd(3) ::true
Predicates.isEven().and(Predicates.isGreaterThan100(100)) ::false
Predicates.isEven().and(Predicates.isGreaterThan100(102)) ::true
Predicates.isEven().or(Predicates.isGreaterThan100(101)) ::true
Predicates.isEven().negate(11) ::true


Refer the below example to know how we can use this for filtering


import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateCollections {

    public static void main(String[] args) {

        List users = Arrays.asList(new User("Bob", 51, 170), new User("john", 52, 80), new User("paul", 45 ,120), new User("alex", 46, 150), new User("scott", 56, 150));

        //All the users whose age are above 50
        List above50Users = filter(users, isAgeAbove50());
        System.out.println("The above 50 age users \n" + above50Users);

        //All the users whose age are below 50
        List below50Users = filter(users, isAgeBelow50());
        System.out.println("The below 50 age users \n"+ below50Users);

        //We can also use the negate expression. Lets see how we can do that
        above50Users = filter(users, isAgeBelow50().negate());
        System.out.println("The above 50 age users \n" + above50Users);

        below50Users = filter(users, isAgeAbove50().negate());
        System.out.println("The below 50 age users \n"+ below50Users);

        //Users whose age is above 50 and weight is more than 100
        List above50AndExcessWeightUsers = filter(users, isAgeAbove50().and(isWeightGtThan100()));
        System.out.println("The above 50 and excess weight users \n"+ above50AndExcessWeightUsers);
    }

    public static Predicate isAgeAbove50() {
        return user -> user.age > 50;
    }

    public static Predicate isAgeBelow50() {
        return user -> user.age < 50;
    }
    public static Predicate isWeightGtThan100() {
        return user -> user.weight > 100;
    }

    public static List filter(List users, Predicate p) {
        return users.stream().filter(p::test).collect(Collectors.toList());
    }

    static class User {

        String name;
        int age;
        int weight;

        User(String name, int age, int weight) {
            this.name = name;
            this.age = age;
            this.weight = weight;
        }

        @Override
        public String toString() {
            return "name:"+name +" age:"+age + " weight:"+weight;
        }
    }
}

Output:


The above 50 age users 
[name:Bob age:51 weight:170, name:john age:52 weight:80, name:scott age:56 weight:150]
The below 50 age users 
[name:paul age:45 weight:120, name:alex age:46 weight:150]
The above 50 age users 
[name:Bob age:51 weight:170, name:john age:52 weight:80, name:scott age:56 weight:150]
The below 50 age users 
[name:paul age:45 weight:120, name:alex age:46 weight:150]
The above 50 and excess weight users 
[name:Bob age:51 weight:170, name:scott age:56 weight:150]


Jersey REST service and Thread Local usage

In this exercise, I am going to provide an example to show how we can use the ThreadLocal with the Jersey REST service.

Consider that it’s a REST application and we need the user details in the application flow many places. The User details will be retrieved with the header information availbale in the HttpServletRequest.
One solution is to pass the HttpServletRequest object whereever its required. But its a tedious job.
So an another way is to use the ContainerRequestFilter and processes the request, then extract out the header and call the back end to get the User details and put into the ThreadLocal storage so that it can be accessible anywhere in that thread flow.

Refer the below sample code to know how to do that. We don’t use the Spring Framework here.

DataHolder:
This class holds the static ThreadLocal variable and it has getter and setter for User object. We will be setting the User Object from the ContainerRequestFilter


package com.utils;

public class DataHolder{

    private static final ThreadLocal userThreadLocal = new ThreadLocal();

    public static void setUser(User user) {
        userThreadLocal.set(user);
    }

    public static User getUser() {
        return userThreadLocal.get();
    }

    public static void remove() {
        userThreadLocal.remove();
    }
}

UserDataCaptureRequestFilter
This filter will intercept the request and extract out the header and retrieve the user details and put it into the ThreadLocal.



package com.filters;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class UserDataCaptureRequestFilter implements ContainerRequestFilter {
    @Context
    private HttpServletRequest httpRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        //Get the User data from the back end system with the request header/cookie. I have not given the getUser() method but assume it will get the user details 
        User user = getUser(httpRequest);
        DataHolder.setUser(user);
    }
}


Application
The ResourceConfig class where we can specify the packages to look into for the end points and context


public class Application extends ResourceConfig {
    public Application() {
        packages(true, "com.resource");
        packages(true, "com.filters");
    }
}

 
UserResource
This service returns the User details in JSON format. Here We have not retrived the User Details once again since we already retrieved the data in the filter itself. So the data would be available in the Thread scope. So we could use it


package com.resource;

import com.utils.DataHolder;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("user")
public class UserResource{

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUser() {
       
        return Response.ok().entity(DataHolder.getUser()).type(MediaType.APPLICATION_JSON).build();
    }
}

 

 

Finding the majority Element with Moore’s Voting Algorithm

Leetcode problem:

https://leetcode.com/problems/majority-element/description/

Problem Description:

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exists in the array.

Algorithm Link:

https://www.cs.utexas.edu/~moore/best-ideas/mjrty/index.html

moores-voting-algorithm

Solution:


public class Main {

    public static int majorityElement(int[] nums) {

        int currentElement = 0;
        int counter = 0;
        for (int num : nums) {
            if (counter == 0) {
                currentElement = num;
                counter = 1;
            }
            else {
                if (num == currentElement) {
                    counter++;
                }
                else {
                    counter--;
                }
            }
        }
        return currentElement;
    }

    public static void main(String[] args) {

        int[] nums = new int[] { 1, 3, 4, 5, 5, 1, 1 };
        System.out.println(majorityElement(nums));
    }
}