Pages

Sunday, April 10, 2022

How to convert Roman numbers to Integer ?



package java8.algorithemic;

import java.util.HashMap;
import java.util.Map;

public class RomanToInteger {

    private static Map<Character, Integer> romanIntegerMap = new HashMap<>(7);

    static {
        romanIntegerMap.put('I', 1);
        romanIntegerMap.put('V', 5);
        romanIntegerMap.put('X', 10);
        romanIntegerMap.put('L', 50);
        romanIntegerMap.put('C', 100);
        romanIntegerMap.put('D', 500);
        romanIntegerMap.put('M', 1000);
    }

    public int romanToInt(String s) {
        char[] charArray = s.toCharArray();
        int intValue = 0;
        char beforeChar = '\u0000';
        for(int i = 0; i < charArray.length; i++) {
            intValue += getBaseIntegerForRoman(beforeChar, charArray[i]);
            beforeChar = charArray[i];
        }
        return intValue;
    }

    public int getBaseIntegerForRoman(char beforeChar, char currentChar) {
        if (currentChar == 'V' && beforeChar == 'I') {
            return getCurrentValue(currentChar, beforeChar);
        } if (currentChar == 'X' && beforeChar == 'I') {
            return getCurrentValue(currentChar, beforeChar);
        } else if (currentChar == 'L' && beforeChar == 'X') {
            return getCurrentValue(currentChar, beforeChar);
        } else if (currentChar == 'C' && beforeChar == 'X') {
            return getCurrentValue(currentChar, beforeChar);
        } else if (currentChar == 'D'&& beforeChar == 'C') {
            return getCurrentValue(currentChar, beforeChar);
        } else if (currentChar == 'M' && beforeChar == 'C') {
            return getCurrentValue(currentChar, beforeChar);
        } else {
            int val = getBaseIntegerForRoman(currentChar);
            return val;
        }
    }

    public int getCurrentValue(char currentChar, char beforeChar) {
        int beforeVal  = getBaseIntegerForRoman(beforeChar);
        int currentVal = getBaseIntegerForRoman(currentChar) - beforeVal;
        return currentVal - beforeVal;
    }

    public int getBaseIntegerForRoman(char ch) {
        return this.romanIntegerMap.get(ch);
    }
}


Test class as follows.

package java8.algorithemic;

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

public class RomanToIntegerTest {
    @Test
    public void test() {
        RomanToInteger romanToInteger = new RomanToInteger();
        Assertions.assertEquals(4,romanToInteger.romanToInt("IV"));
        Assertions.assertEquals(9,romanToInteger.romanToInt("IX"));
        Assertions.assertEquals(13,romanToInteger.romanToInt("XIII"));
        Assertions.assertEquals(18,romanToInteger.romanToInt("XVIII"));
        Assertions.assertEquals(19,romanToInteger.romanToInt("XIX"));
        Assertions.assertEquals(4500,romanToInteger.romanToInt("MMMMD"));
        Assertions.assertEquals(90,romanToInteger.romanToInt("XC"));
        Assertions.assertEquals(80,romanToInteger.romanToInt("LXXX"));
    }
}

Saturday, April 2, 2022

How to use Java Optional

The most common and frequent exception which many Java developers encounter is NullPointerException.  Though this is very common exception and the fix is also straightforward for most of the developers. They simply put null check or nested null checks in order to avoid happening this exception. This actually increases the number of indentation level in your code and also reduces the readability too. Even if you avoid happening this exception in this way, the complete flow might not be consistence with all client codes. If you fix this exception with simple null check,  you need to make sure that the complete flow executes correctly as per business requirement without producing strange results from the application. 

And also, there are many situations where, you add this null check only after happening the NullPointerException at least a once only. Yes, some developers proactively check the presence and absence of a value of variable before it is accessed and write the complete flow which handles the absence of the value. 

Java 8 introduces java.util.Optional<T> to represent the absence of a value in a particular variable or a field of any type in more precise and safer manner. This enforces developers to specifically focus on the absence of the value of their reference, a variable or return type of a method.  So defining a method to accept an optional or a method to return an optional indicates that the value of that variable may not be presence. There is a possibility of absence of the value. Your peer developers or in future, if someone is going to modify the code or use those methods by different client code, they will know that the value of the reference can be absence and should write the client code according to that. 

Assume the following are two methods of a data access class for Employee entity.
    public Employee findEmployeeByName(String name) {
        Employee emp = null; // code get employee from DB or somewhere.
        return emp;
    }

    public Optional<Employee> findEmployeeOptionalByName(String name) {
        Employee emp = null; // code to get employee from DB or somewhere
        return Optional.ofNullable(emp);
    }

Both method is to find an employee for a given employee name. Let's say both scenario, system could not find an employee for the given name and both method returns value absence reference (null). The first method returns null. But the second method, in stead of returning null, it returns an empty optional which indicates all clients codes that, the return value in the returned variable may or may not presence and write your client code according to that. Let's look two client code for both above method.
 
    //Client code1
    Employee emp = employeeRepository.findEmployeeByName("David");
    System.out.print(emp.getName());

    //Client code2
    Optional<Employee> employeeOptional = employeeRepository.findEmployeeOptionalByName("David");
    System.out.println(employeeOptional.get().getName());	

In the above code, first client code end with NullPointerException and the second client code ends with NoSuchElementException. Off-course, in the first client code, developers may directly access 'emp' object without checking the absence of the value which results NullPointerException and then later on, they will add null check before accessing 'emp' object. This is the old practice that most developers were doing.

But, how about the second client code2 which is also not the best way to unwrap an optional. The 'findEmployeeOptionalByName()' method returns an Optional of Employee which indicates that the value may not be present. The developers should write the client code to handle the absent of the value in this case. It is a developer's responsibility and good practice too. 

How, optional is unwrapped in the above client code2 is not a best way of doing. If particular method returns an optional means, developers need to specifically focus on it and write the code appropriately. The above code does not leverage the purpose of Optional. 

There are several ways to unwrap an Optional. Using get() method of Optional is not a good idea every time, unless you know the the presence and absence of the value of the optional. For empty optional, this will return NoSuchElementException exception. The optional's ifPresent() method and also for default values, orElse() method are good choices in order to unwrap an optional and get the value. Look at the following code.

    //unwrap optional with isPresent() method
    if(employeeOptional.isPresent()) {
       System.out.println(employeeOptional.get().getName());
    }

    //unwrap optional with orElse() method
    String empName = employeeOptional.map(Employee::getName).orElse("Unknown");
    System.out.print(empName);
As in the above second approach, you can apply map() method to an optional in order to transform optional into a different type. In this case, Employee optional to a string. If optional is empty, it will execute default orElse() method. Further you have orElseGet() method which accepts a supplier than using orElse(). The orElseGet() is more efficient than orElse(), because the code within the supplier argument will be executed only if optional value is not present. Let's say, you have to do some expensive thing, if  optional value is not presence, orElseGet() method is best suited.
String empName = employeeOptional.map(Employee::getName).orElseGet(() -> "Unknnow"); System.out.println(empName);
If you want to throw an exception, in case of optional value is absence, you can use orElseThrow() method as follows. The advantage of using this method is, you can throw any exception type that you preferred.

      String empName = employeeOptional.map(Employee::getName).orElseThrow(() -> new RuntimeException("Unable to find employee"));
      System.out.print(empName);
You can apply map(), flatMap() and filter() methods to an optional similar as stream API.

Thursday, February 3, 2022

Java Function example use case

Java Function<T, R> is functional interface which accepts one type of argument and return a result. We can leverage java Function to write more maintainable codes. For example, let's say, we are going to develop an API or service method to place an order for the customer. After successful placement of order, the service method should send a notification to the customer. At this moment, we have two ways of sending notification, ie: SMS and  email.  But, we don't know, in future, we might need to add more notification methods. 
If we don't write this method in clear and maintainable manner, we have to modify this service method every time in order to add a new notification method. 

First, we will see, the solution for this using object oriented approach and then we will improve the code using Java Function in a functional way. 

As usual, let's define an interface as follows.

public interface Notifier {
    void notify(Order order);
}

Then we need two concrete classes for each type of notification method. As follows, we need to create a new concrete class for each notification method.

public class SmsNotifier implements Notifier {
    @Override
    public void notify(Order order) {
        //code to send sms notification
    }
}


public class EmailNotifier implements Notifier {
    @Override
    public void notify(Order order) {
        // Code to send email notification
    }
}

Let's write some sample client code in order to place an order
     
//OOP approch
//Assume we have an instanc eof order service
OrderService orderService = ...
//Assume we have the order object
Order order = ...
//Assume we have the customer object
Customer customer = ....

Notifier notifier = null;
if (customer.getNotificationPreference().equals("SMS")) {
    notifier = new SmsNotifier();
} else {
    notifier = new EmailNotifier();
}

orderService.placeOrder(order, notifier);
     
  
This disadvantage of above approch is, we have to create a concrete class for each new notification method. Let's see, how we can improve the code using java Function. Let's make 'Notifier' a functional interface. We simply add @FunctionalInterface annotation.

@FunctionalInterface
public interface Notifier {
    void notify(Order order);
}

The client code using java lambda expression is as follows.

// functional approach.
if (customer.getNotificationPreference().equals("SMS")) {
    orderService.placeOrder(order, (Order odr) -> {
      //code to send SMS
    });
} else {
    orderService.placeOrder(order, (Order odr) -> {
     //code toe send email
    });
}
With the functional programming approch, we don't want to create a new class for each new notification method. You need to decide which approch to use based on your use case or scope of different strategy. If it is small piece of code that you want to customize, you can go with functional approch using java lambda.

Sunday, January 30, 2022

How to group list of objects using java lambda

Let's consider the following POJO class.
public class Dish {

	private String name;
	private Boolean vegitarian;
	private Integer calories;
	private DishType type;

}

Java 8 stream API provides plenty of features to group objects into different buckets. Let's say, we want to group list of Dish objects based on the amount of calories. We will define an enum constant to declare different calory categories. 


public enum CaloryLevel {
    DIET,
    NORMAL,
    FAT;
}

The Calory level is not an attribute of Dish class. The calory level is defined by using the amount of calories from Dish class which is an attribute of Dish class, ie: 'calories'. If the amount of calory is less than 400, the calory level is 'DIET'. If the amount of calory is between 400 and 700, the calory level is 'NORMAL'. If the calory amount is above 700, the calary level is defined as 'FAT'. The legacy approch of grouping list of objects is as follows. It generally uses a map to put objects into different buckets.


public static void groupDishByCaloriAmountLegacyApproch(List<Dish> menu) {

	Map<CaloryLevel, List<Dish>> dishOverCaloryLevel = new HashMap<CaloryLevel, List<Dish>>();

	for(CaloryLevel caloryLevel : CaloryLevel.values()) {
		dishOverCaloryLevel.put(caloryLevel, new ArrayList<Dish>());
	}

	for(Dish dish : menu) {
		if (dish.getCalaries() <= 400) {
			dishOverCaloryLevel.get(CaloryLevel.DIET).add(dish);
		} else if (dish.getCalaries() <= 700) {
			dishOverCaloryLevel.get(CaloryLevel.NORMAL).add(dish);
		} else {
			dishOverCaloryLevel.get(CaloryLevel.FAT).add(dish);
		}
	}
}

Now, let's see, how we can improve the above code using Java 8 features. We can get the same output by using Java stream API provided methods. See the following code.

Map<CaloryLevel, List<Dish>> dishOverCaloryLevel = menu.stream().collect(Collectors.groupingBy((Dish d) -> {
	if (d.getCalaries() <= 400) {
		return CaloryLevel.DIET;
	} else if (d.getCalaries() <= 700) {
		return CaloryLevel.NORMAL;
	} else
		return CaloryLevel.FAT;
	}
));
Again, the calory level is not an attribute of Dish class. That attribute is external one which is defined by using the amount of calories. If we want to get the calory level by using the amount calories which is defined within the Dish class, we have to write boilaplate codes as in the above method. As a best coding practice, defining the calory level can be added into the Dish class itself as method. The new Dish class is as follows.

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Dish {

	private String name;
	private Boolean vegitarian;
	private Integer calaries;
	private DishType type;

	private CaloryLevel getCaloryLevel() {
		if (this.getCalaries() <= 400) {
			return CaloryLevel.DIET;
		} else if (this.getCalaries() <= 700) {
			return CaloryLevel.NORMAL;
		} else {
			return CaloryLevel.FAT;
		}
	}
}

The complete lambda expresion which was passed into the 'Collectors.groupingBy' method, now it is defined as a method inside the Dish class itself. We can now use Java 8's method referene to simply the code more as follows. Now the code to group list of Dish objects has narrowed down into a single like.

Map<CaloryLevel, List<Dish>> dishOverCaloryLevel1 = menu.stream().collect(Collectors.groupingBy(Dish::getCaloryLevel));

How to replace anonymous class with Java 8 lambda

Java lambda expression can be used to replace legacy anonymous class. For example, let's consider the following POJO class.

public class Dish {

	private String name;
	private Boolean vegitarian;
	private Integer calories;
	private DishType type;

}
Let's say, we have a list of objects from the above class and we want to sort them by name. The normal approch to sort this kind of custom object list is, using a comparator. So, we can write a comparator as follows.

Comparator<Dish> comparator = new Comparator<Dish>() {
         @Override
         public int compare(Dish o1, Dish o2) {
             return o1.getName().compareTo(o2.getName()); // ASC order
             //return o2.getName().compareTo(o1.getName()); // DESC order
         }
};

With Java's lambda, we can get rid of anonymous class comparator and reduce the code to a single like as follows.

Comparator<Dish> comparator = Comparator.comparing(Dish::getName);

And we can sort the list of Dish's as following.

Collections.sort(menu, comparator);

Wednesday, September 8, 2021

Java 8 Stream.collect() examples

Java 8 Stream interface provides a method called collect() which helps to perform various kind of manipulations of the elements in a Stream. These include

  • Combining all the elements of a Stream into a different data structures like List and Set.
  • Reducing and summarizing operations like count, max, min.
  • Grouping and partitioning.

The arguments passed into the collect() method are called collectors which are implementations of Collector interface.

In this tutorial, I am going to show you that, how to use these collectors under each category with examples. Very famous example, Employee and Department and the sample data set is as follows.

public class Employee {
 
    private String name;
 
    private Integer age;
 
    private String city;
 
    private Integer salary;
 
    private String sex;
 
    private Department department;
 
    public Employee(String name, Integer age, String city, Integer salary, String sex, Department department) {
        super();
        this.name = name;
        this.age = age;
        this.city = city;
        this.salary = salary;
        this.sex = sex;
        this.department = department;
    }

   // getters and setters
 
}


public class Department {

    private String departmentName;
 
    private Integer noOfEmployees;

    public Department(String departmentName, Integer noOfEmployees) {
         super();
         this.departmentName = departmentName;
         this.noOfEmployees = noOfEmployees;
    }
    // getters and setters
}


Sample data set :
Department account = new Department("Account", 75); 
Department hr = new Department("HR", 50);
Department ops = new Department("OP", 25);
Department tech = new Department("Tech", 150);
  
List<Employee> employeeList = Arrays.asList(new  Employee("David", 32, "Matara", 2000, "Male", account), 
    new  Employee("Brayan", 25, "Galle",  3000, "Male",hr),
    new  Employee("JoAnne", 45, "Negombo",  800, "Female", ops),
    new  Employee("Jake", 65, "Galle",  2500, "Male", hr),
    new  Employee("Brent", 55, "Matara",  8000, "Male", hr),
    new  Employee("Allice", 23, "Matara",  600, "Female", ops),
    new  Employee("Austin", 30, "Negombo",  9000, "Male", tech),
    new  Employee("Gerry", 29, "Matara",  2500, "Male", tech),
    new  Employee("Scote", 20, "Negombo",  2500, "Male", ops),
    new  Employee("Branden", 32, "Matara",  2500, "Male", account),
    new  Employee("Iflias", 31, "Galle",  2900, "Female", hr)); 



Combining Elements

The most straightforward and frequently used collector is toList() static method. By using this method, elements of a Stream can be combined to a List as follows.

List<Employee> employeeList = employeeList.stream().collect(Collectors.toList()); 

Similarly, if you want to convert Stream into a set, the toSet() static method can be used as follows.

Set<Employee> employeeSet = employeeList.stream().collect(Collectors.toSet());


Reducing and Summarizing


The collectors which are parameters to the Stream's collect() method can also be used to combine all the items in the stream into a single result like total, min, max and count.

Using Collectors.counting() :

If we want to find the number of employees in the list, Collectors.counting() method can be passed as an argument to collect() method as follows.
Long totalNumOfEmployees = employeeList.stream().collect(Collectors.counting());

Using Collectors.maxBy() and Collectors.minBy() :

If we want to find the maximum and the minimum value in a stream, we can use maxBy() and minBy() methods. These two collectors take a Comparator as an argument to compare the elements in the stream.

Let's try to find the employee who is getting the maximum and the minimum salary.

//Find max salary employee 
employeeList.stream() 
            .collect(Collectors.maxBy(Comparator.comparingInt(Employee::getSalary))) 
            .ifPresent(e -> System.out.println("Max salary employee :" + e.getName())); 

//Find min Salary 
employeeList.stream() 
            .collect(Collectors.minBy(Comparator.comparingInt(Employee::getSalary))) 
            .ifPresent(e -> System.out.println("Min salary employee :" + e.getName()));


Using Collectors.summingXXX() methods:


Collectors.summingInt(), Collectors.summingLong() and Collectors.summingDouble() are some collectors which can be used to get the summation of a particular properly of elements in a stream. These methods accept a property of corresponding type in order to perform the summing operation.

Let's say, we want to find the total salary of all the employees.

Integer totalSalary = employeeList.stream().collect(Collectors.summingInt(Employee::getSalary)); 



Using Collectors.averagingXXX() methods:

Collectors.averagingInt(), Collectors.averagingDouble() and Collectors.averagingLong() are the collectors that can be used to calculate the average value of some numeric fields. Let's say, we want to find the average salary of all the employees.

Double averageSalary = employeeList.stream().collect(Collectors.averagingInt(Employee::getSalary));

Using Collectors.summarizingXXX() methods:

Quite often, we might need to get the count, total, maximum, minimum and average by using a single operation. Collectors.summarizingInt(), Collectors.summarizingDouble() and Collectors.summarizingLong() collectors can be used to get above all statistics from a single operation. 

Let's try to get all above salary statistics from a single operation.

IntSummaryStatistics salalryStat = employeeList.stream().collect(Collectors.summarizingInt(Employee::getSalary));

IntSummaryStatistics class has many defined methods which returns the above statistic values separately. The string representation of above IntSummaryStatistics result will be as follows.

IntSummaryStatistics{count=11, sum=36300, min=600, average=3300.000000, max=9000}

Using Collectors.joining() method:

The joining() method can be used to concatenate String type property values into a single string from the elements of a stream. Note that the joining() method internally makes use of a StringBuilder to append the generated string into one.


Let's say, we want to get all the employee's names as comma separated single string.

String employeeNameStrings = employeeList.stream().map(Employee::getName).collect(Collectors.joining(", ")); 
System.out.println(employeeNameStrings);

Using Collectors.reducing() method:

The reducing() method is a generalization of all the collector methods. Using the reducing() method, we can perform many operations that were performed using specific collector methods. These operations include max, min, sum etc. 

The reducing() method takes three arguments.


  • The first argument is the starting value for reduction operation. This value will return in case empty stream. 
  • The second argument is usual transformation function. 
  • The third argument is a BinaryOperator that aggregates two arguments into a single one. 


Let's try to get the maximum and minimum salary of employees by using reducing() method too.

//Max salary
Integer maxSalary = employeeList.stream().collect(Collectors.reducing(0, Employee::getSalary, Integer::max)); 

Optional minSalary = employeeList.stream().collect(Collectors.reducing((e1, e2) -> e1.getSalary() < e2.getSalary() ? e1 :  e2));
System.out.println("Min salary " + minSalary.get().getSalary()); 

The reducing() method has a form of accepting single argument as in the above min operation.


Grouping

Groping of elements based on a one or more property is a very common database operation. The Collectors.groupingBy() factory method in Java 8 can be used to perform same kind of operations with collections of elements. The Collectors.groupingBy() method accepts a method reference as an argument which is used to classify the elements of the stream into different groups. 

Let's try to group list of employees by their department.

Map<Department, List<Employee>> employeesOverDepartment = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment));

We call the above Function a classification function, because it is used to classify the elements of the stream into different groups. But, it is not always possible to use a classification function, because we may wish to classify the elements using more complex criteria than a simple property reference. 

The Collectors.groupingBy() method accepts a lambda expression which allows us to group elements based on more complex criteria. 

Let's say, we want to group our employee list into two groups as "High Salary" and "Low Salary". This might not be a good example, but just to show you, how we can use more complex criteria to group elements.

Map<String, List<Employee>> map = employeeList.stream().collect(
                                        Collectors.groupingBy((Employee e) -> {
                                                if (e.getSalary() > 2000) {
                                                   return "High Salary";
                                                } else {
                                                    return "Low Salary";
                                                } 
                                        }));

The similar approach can be used to group employees by their department name.

Map<String, List<Employee>> employeesByDepartmentName = employeeList.stream()
                       .collect( Collectors.groupingBy((Employee e) -> { 
                                    return e.getDepartment().getDepartmentName();
                               }));


The Collectors.groupingBy() method has a version of accepting two argument which allows us to perform multilevel grouping. In the above example, we grouped employees by the department name. 

Let's say, we want to further group employees within a particular department by their sex.

Map<String, Map<String, List<Employee>>> employeesByDepartmentName = employeeList.stream()
                .collect( Collectors.groupingBy((Employee e) -> { return e.getDepartment().getDepartmentName(); },
                         Collectors.groupingBy((Employee e) -> { return e.getSex(); }) ) );


In the above example, two-argument version of Collectors.groupingBy() method, the second argument was a another groupingBy() method. But, it is not necessarily to be a groupingBy() method. But, more generally, the second collector passed to the first groupingBy() method can be any type of collector.

Let's say, we want to get the number of employees in each department.

Map<String, Long> noOfEmployeesInDepartment = employeeList.stream()
                       .collect(Collectors.groupingBy(
                                 (Employee e) -> { return e.getDepartment().getDepartmentName(); }, 
                                  Collectors.counting()));
Using a similar kind of approach, we can find the employee who gets the maximum salary for each department. See the following example.
Map<String, Employee> maxSalaryEmployeeOfDept = employeeList.stream()
                 .collect(Collectors.groupingBy((Employee e) -> {return e.getDepartment().getDepartmentName();}, 
                          Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Employee::getSalary)), 
                                                                        Optional::get) ) );




More generally, the collector passed as the second argument to the groupingBy() factory method will be used to perform a further reduction operation on all the elements in the stream classified into the same group. Let's say, we want to get the total salary for each department.
Map<String, Integer> totalSalaryOverDepartment = employeeList.stream() 
            .collect(Collectors.groupingBy(
                         (Employee e) -> {return e.getDepartment().getDepartmentName();}, 
                          Collectors.summingInt(Employee::getSalary)));

Partitioning

Sunday, July 15, 2018

Spring Boot Complete Example

This post provides a complete example of using spring boot to develop a loosely coupled REST service. Using spring boot, we can develop production ready java application which will run independently, as stand alone application with minimal dependencies and less coupling with other applications. Most of the time, spring boot application will provide a cohesive service and the boundaries of the service is clearly defined. Let's deep into the our example.

For this tutorial, I am going to use Spring Boot 2.0.3.RELEASE which requires the java 8 or 9 and Maven 3.2+, Eclipse as an IDE.

Creating Maven jar module

Since, we are going to bundle our application as a .jar file, we can use eclipse IDE support to generate maven jar module after integrating maven with Eclipse IDE. The recent version of Eclipse comes with integrated maven plugin. So you don't need to explicitly add maven plugin into eclipse. I am not going to explain, how to create maven jar module with eclipse within this post. If you want to know it, you can read my another post here which clearly explains about creating maven modules with eclipse. If you create a maven project by using 'quickstart' artifact, you will get a project structure similar to the following.



I have created a maven module called 'customer' with 'com.semika' as groupId and 'customer' as artifact id. You can choose what ever package structure, you want. Your inner package structure will change based on it.

App.java and AppTest.java files will be removed soon. Have a look on pom.xml file which contains information about the project and configuration details used by Maven to build the project. You can remove Junit dependency for now, since this tutorial does not cover unit testing features.

I want to highlight one important element here. 

<packaging>jar</packaging>

This is where, we tell maven to bundle our application as a .jar file for deployment. 


Adding spring boot features

Now, what we have is, typical maven jar module. How we are going to convert this into spring boot application? 

All spring boot dependencies are defined under org.springframework.boot group id within the maven repository. The spring-boot-starter-parent is a project which has some default settings and basic required configurations that we can use in order to quickly start using spring boot. We can inherits these default settings by adding following element into our pom.xml file.

<!-- Inherit defaults from Spring Boot --> 
<parent> 
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>2.0.3.RELEASE</version> 
</parent>

Connecting to a database

Now, let's see, how we can connect our spring boot application with a database or how we integrate a data source to our spring boot application. Spring framework provides a great support for accessing a database from direct JDBC access to ORM technologies like Hibernate. 

The javax.sql.DataSource interface provides standard methods in order to work with a database by creating data source with a connection pool. There are several implementation like BoneCP, Apache common DBCP2 and spring's default HikariCP.If We use the spring-boot-starter-jdbc or spring-boot-starter-data-jpa “starters”, we automatically get a dependency to HikariCP. We are going to use 'spring-boot-starter-data-jpa' for data access later on this tutorial. 

Now, time has come to add 'application.properties' file to our project. In spring boot application, this file contains all the configuration properties and the file should be available on classpath. I am going to delete 'App.java' and 'AppTest.java' file and create a new folder as 'resources' inside the 'main' folder, parallel to 'java' folder. When building modules by using maven, the files inside the 'resources' folder are made available to classpath. We don't need to do any extract things. 

Let's create a file as 'application.properties' inside the resources folder. I am going to connect my spring boot application to a MySql database. The minimal properties required to create a datasoruce for spring boot application, are as follows. 

spring.datasource.url=jdbc:mysql://localhost/springboot?useSSL=false
spring.datasource.username=root
spring.datasource.password=abc123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=false

Here property name convention was not selected randomly. Spring's datasource configuration properties should be prefix with spring.datasource.*. If you want to set up a specific data source implementation, the property names should be specify with respective prefix as spring.datasource.hikari.*, spring.datasource.tomcat.*, spring.datasource.dbcp2.*.

Since we are going to connect to MySql database, mysql-java connector maven dependency should be added to our pom.xml file as follows.

<dependency> 
     <groupId>mysql</groupId> 
     <artifactId>mysql-connector-java</artifactId> 
</dependency>

Adding Main Application class

Every spring boot application should have a main class with main() method defined. Generally this class is named as "Application.java" and should locate in the root package above the other classes. This class is normally annotated with few annotations. 

  • @EnableAutoConfiguration - This annotation enables auto-configuration for our spring boot application which attempts to automatically configure our Spring application based on the jar dependencies that we have added. 
  • @ComponentScan - This enables spring bean dependency injection feature by using @Autowired annotation. All of our application components which were annotated with @Component, @Service, @Repository or @Controller are automatically registered as Spring Beans. These beans can be injected by using @Autowired annotation. 
  • @Configuration - This enables Java based configurations for spring boot application. Usually the class that defines the main method is a good candidate to annotate with this annotation.

I am going go create a new class as "Application.java" inside the com.semika package, which is the root for my spring boot application.

package com.semika;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@EnableAutoConfiguration
@ComponentScan
@Configuration

public class Application {

    public static void main(String[] args) {
         SpringApplication app = new SpringApplication(Application.class);
         app.run(args); 
    }
}

In stead of using all three annotation, we can use only @SpringBootApplication annotation which is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan with their default attributes, as shown in the following example.

package com.semika;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class Application {
     public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        app.run(args); 
     }
}

Adding data access features with spring-data-JPA

Now, let's see, how we can integrate data access features to our spring boot applications. Data access classes are called 'Repositories' in spring boot application. JPA (Java Persistence API) is a standard technology that lets us “map” objects to relational databases. 

The spring-boot-starter-data-jpa starter project provides a quick way to get started with data access for spring boot application. It provides the following key dependencies: 
  • Using Hibernate to map objects with database tables. 
  • Spring Data JPA which can be used to write JPA-based repositories. 
  • Core ORM support from the Spring Framework.
In order to add data access features to our spring boot application, we should add the following maven dependency to our pom.xml file. After adding bellow dependency, we can use usual JPA annotations to map objects with relational database table. 

<dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-data-jpa</artifactId> 
</dependency>

Let's create a new package as 'customer' inside the root folder which is com.semika where the 'Application.java' class is located by now. Inside customer folder, new entity class is crated as 'Customer.java'. For now, my customer database table has three attributes as follows.











package com.semika.customer;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="customer") 
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    @Column(name="first_name")
    private String firstName;
 
    @Column(name="last_name")
    private String lastName;
 
    @Column(name="address")
    private String address;

    public Customer() {
       super();
    }

    // getters and setters
}

Spring data JPA repositories are interfaces that can be defined to access data. JPA queries are created automatically from the method names. For example, findAll() method in 'CustomerRepository.java' class fetches all the customers. The findByFirstName(String firstName) method will fetch all the customers for a given first name. 

The central interface in the Spring Data repository abstraction is Repository interface. It takes the domain class to manage as well as the ID type of the domain class as type arguments.The CrudRepository interface provides sophisticated CRUD functionality for the entity class that is being managed. Our repository interfaces should extend from CrudRepository interface.

Our 'CustomerRepository.java' interface will be as follows:

package com.semika.customer;

import org.springframework.data.repository.CrudRepository;

public interface CustomerRepository extends CrudRepository<Customer Long> {

}


You may find for the implementation class? Spring data JPA provides the implementation for most of the data access scenarios. We don't need to implement explicitly those methods. If you want to read more about spring data JPA, you can read the reference documentation here.

Further, I am going to add 'CustomerService.java' interface and it's implementation 'CustomerServiceImpl.java' class in order to keep our business logic in a separate layer.

package com.semika.customer;

public interface CustomerService {
    public Iterable<Customer> findAll(); 
}


package com.semika.customer;
package com.semika.customer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerRepository customerRepository;
 
    public Iterable<Customer> findAll() {
        return customerRepository.findAll(); 
    }
}

You can see that,CustomerRepository is injected to CustomerServiceImpl class using @Autowired annotation. We did enable this by adding @ComponentScan annotation via @SpringBootApplication to our 'Application.java' class early in this tutorial.

Adding web features

Now, it's time to build and test our application. Suppose, client makes HTTP requests to fetch all the customers data. So our spring boot application should response to HTTP requests. Spring MVC provides 'Controllers' which accepts HTTP requests and responses to those. Here, we are going to add some spring MVC features to our spring boot application. By using spring-boot-starter-web project, we can integrate some basic MVC features to our spring boot application so that we can write simple Controller class which responses client's HTTP requests.

We should add the following maven dependency to our project.

<dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-web</artifactId> 
</dependency>

package com.semika.customer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CustomerController {

    @Autowired
    private CustomerService  customerService;
 
    @RequestMapping("/customers") 
    @ResponseBody
    public Iterable<Customer> findAll() {
       Iterable<Customer> customers = customerService.findAll();
       return customers;
    }
}

@RestController is a stereotype annotation in Spring MVC which provides hints for people reading the code and for Spring that the class plays a specific role. That is, it contains the gates to enter into the application. In this case, our class is a web @Controller, so Spring considers it when handling incoming web requests. The @RestController annotation tells Spring to render the resulting string directly back to the caller.

The @RequestMapping annotation provides “routing” information. It tells Spring that any HTTP request with the '/customers' path should be mapped to the findAll() method.

These two annotations are spring MVC annotations. They are not specific to spring boot. We added this spring MVC web features in order to test our application by making some web requests. With the adding of 'spring-boot-starter-web' to a spring boot application, when running it, spring boot application starts up it's own web container and runs with in it.

So now, our project structure should be as follows.


Building application

Spring boot jar file is called a self-contained executable jar file that we can run directly in production environment. Executable jars are archives containing your compiled classes along with all of the jar dependencies that your code needs to run. In our example, since we used 'spring-boot-starter-web', when running the jar file, it starts internal web container in order to run the application. 

To create an executable jar, we need to add the spring-boot-maven-plugin to our pom.xml. To do so, insert the following lines just below the plugins section.

<plugins> 
     <plugin> 
          <groupId>org.springframework.boot</groupId> 
          <artifactId>spring-boot-maven-plugin</artifactId> 
     </plugin> 
</plugins>

You might notice that some of the configurations for above plugin is missing here. Since we are using 'spring-boot-starter-parent', we don't need to worry about those, because those are already included within the parent project. For example, parent project POM includes <executions> configuration to bind the repackage goal.

Let's look at our final pom.xml file now:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.semika.user</groupId>
  <artifactId>customer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  
  <!-- Inherit defaults from Spring Boot -->
  <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.0.3.RELEASE</version>
  </parent>

  <name>customer</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <!-- Building an executable jar file -->
  
  <build>
      <plugins>
         <plugin>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
  </build>

  <dependencies>
        <!-- Adding spring data jpa features -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
 
        <!-- Java MySQL connector -->
        <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
        </dependency>
 
        <!-- Integrating spring MVC features -->
        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
  </dependencies>
</project>


Let's build the application. Go the project root folder where pom.xml file is located and run the following command.

mvn package

Inside the target folder, you can see our executable jar file created as 'customer-0.0.1-SNAPSHOT.jar'.

Running the application:

From the same folder, run the following command to run the jar file. 

java -jar target/customer-0.0.1-SNAPSHOT.jar

If you analyze the logs when starting up the application, you can discover many important things. The console output at the server starting is as follows:


If you see the logs near the bottom, it starts the Tomcat server on port 8080. If you access the http://localhost:8080/customers URL from the browser, you will get JSON response of customers as the response.

If you want to start the application on different port than the default one, you can specify the port by suing --server.port option as follows.

java --server.port=9000 -jar target/customer-0.0.1-SNAPSHOT.jar

If you want to start the application with debug enabled, you can use the following command:

java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n -jar target/customer-0.0.1-SNAPSHOT.jar

To start the application with debug log enabled, you can use the following command

java -jar target/customer-0.0.1-SNAPSHOT.jar --debug

If you want to specify the sever running port in 'application.properties' file, you can include the following property into the file. 

server.port=${port:9000}

With above entry in 'application.properties' file, in stead of using --server.port option, you can simply user --port option with java -jar command in order to specify the port.

Most of the time, your configuration properties are different from environment to environment. For environment like, development, production and testing, you might need to keep different set of configuration properties. You can do this by keeping different configuration profiles for each environment. You should create the configuration properties file in the following format in order to achieve this.

application-${profile}.properties

Let's say you need to keep two configuration profiles for 'development' and 'production' environment separately. In this case, you should create two property files as 'application-development.properties' and 'application-production.properties'. When starting the application using java -jar command, you should specify the profile with -D parameter as follows: 

java -jar -Dspring.profiles.active=production customer-0.0.1-SNAPSHOT.jar

I hope this post will be helpful  specially for beginners who try to learn about spring boot application and Micro services.

References : Spring Boot Reference Guide

Thursday, July 5, 2018

Java 8 Stream examples

This post will help you to understand some of the important and frequently used Stream operations in Java 8 which makes your programming with Java easy.

Let's take our traditional example, Employee and Department.  

public class Employee {
 
 private String name;
 
 private Integer age;
 
 private String city;
 
 private Department department;
 
 public Employee(String name, Integer age, String city, Department department) {
    this.name = name;
    this.age = age;
    this.city = city;
    this.department = department;
 }

 // getters and setters.

}


public class Department {

 private String departmentName;
 
 private Integer noOfEmployees;

 public Department(String departmentName, Integer noOfEmployees) {
      this.departmentName = departmentName;
      this.noOfEmployees = noOfEmployees;
 }

        // getters and setters
}

I am going to have some sample data set as follows in order to show you some important functionalities of Java 8 Stream interface. We have four departments and set of employees from those departments.

      Department account = new Department("Account", 75); 
      Department hr = new Department("HR", 50);
      Department ops = new Department("OP", 25);
      Department tech = new Department("Tech", 150);          
  
      List<Employee> employeeList = Arrays.asList(new  Employee("David", 32, "Matara", account), 
                           new  Employee("Brayan", 25, "Galle", hr),
                           new  Employee("JoAnne", 45, "Negombo", ops),
                           new  Employee("Jake", 65, "Galle", hr),
                           new  Employee("Brent", 55, "Matara", hr),
                           new  Employee("Allice", 23, "Matara", ops),
                           new  Employee("Austin", 30, "Negombo", tech),
                           new  Employee("Gerry", 29, "Matara", tech),
                           new  Employee("Scote", 20, "Negombo", ops),
                           new  Employee("Branden", 32, "Matara", account),
                           new  Employee("Iflias", 31, "Galle", hr)); 

Find all employees who lives in 'Matara' city, sort them by their name and print the names of employees.

employeeList.stream()
     .filter(e -> e.getCity().equalsIgnoreCase("Matara"))
     .sorted(Comparator.comparing(Employee::getName))
     .forEach(e -> System.out.println(e.getName()));

Find distinct department names that employees work for.

employeeList.stream()
            .map(e -> e.getDepartment().getDepartmentName())
            .distinct()
            .forEach(System.out::println); 


Find the department names that these employees work for, where the number of employees in the department is over 50.

employeeList.stream()
            .map(Employee::getDepartment)
            .filter(d -> d.getNoOfEmployees() > 50)
            .distinct()
            .forEach(d -> System.out.println(d.getDepartmentName()));


Create a comma separate string of department names sorted alphabetically.

String s = employeeList.stream()
                       .map(e -> e.getDepartment().getDepartmentName())
                       .distinct()
                       .sorted()
                       .reduce("", (a, b) -> (a + "," + b)); 
System.out.println(s); 


Are there any employees from HR Department?

if (employeeList.stream()
                .anyMatch(e -> e.getDepartment().getDepartmentName().equalsIgnoreCase("HR"))) { 
    System.out.println("Found employees frm HR department"); 
}


Print all employee's name who are working for account department.

employeeList.stream()
            .filter(e -> e.getDepartment().getDepartmentName().equalsIgnoreCase("Account"))
            .map(Employee::getName)
            .forEach(System.out::println);


What is the highest number of of employees in all departments?

employeeList.stream()
            .map(e -> e.getDepartment().getNoOfEmployees())
            .reduce(Integer::max)
            .ifPresent(System.out::print);


Find the department which has the highest number of employees.

employeeList.stream()
            .map(Employee::getDepartment)
            .reduce( (d1, d2) -> d1.getNoOfEmployees() > d2.getNoOfEmployees() ? d1 : d2)
            .ifPresent(d -> System.out.println(d.getDepartmentName()));

The same thing can be done as follows using the max() method.

employeeList.stream()
            .map(Employee::getDepartment)
            .max(Comparator.comparing(Department::getNoOfEmployees))
            .ifPresent(d -> System.out.println(d.getDepartmentName()));


Find the total number of employees in all the departments.

employeeList.stream()
            .map(e -> e.getDepartment())
            .distinct()
            .map(e-> e.getNoOfEmployees())
            .reduce(Integer::sum).ifPresent(System.out::println);

Wednesday, July 4, 2018

Java 8 anyMatch(), allMatch(), noneMatch(), findAny() examples

Finding the existence of some elements among a collection of objects after matching with a specific property is common data processing idiom in programming. The Java 8 Streams API provides such facilities through the allMatch, anyMatch, noneMatch, findFirst, and findAny methods of a stream.

Let's take the following class to write example program for each of these methods. This class represents Dish of a menu.

public class Dish {

    private String name;
    private Boolean vegitarian;
    private Integer calaries;
    private Type type;
 
    public Dish(String name, Boolean vegitarian, Integer calaries, Type type) {
       super();
       this.name = name;
       this.vegitarian = vegitarian;
       this.calaries = calaries;
       this.type = type;
    }

    public String getName() {
       return name;
    }

    public void setName(String name) {
       this.name = name;
    }

    public Boolean getVegitarian() {
       return vegitarian;
    }

    public void setVegitarian(Boolean vegitarian) {
       this.vegitarian = vegitarian;
    }

    public Integer getCalaries() {
       return calaries;
    }

    public void setCalaries(Integer calaries) {
       this.calaries = calaries;
    }

    public Type getType() {
       return type;
    }

    public void setType(Type type) {
       this.type = type;
    }

    public enum Type { MEAT, FISH, OTHER };
}

Using anyMatch() method 

The anyMatch() method accepts a Predicate instance and checks for any matching elements in the stream. This method returns a boolean value, true, if it found a matching, otherwise falseThe anyMatch() method will traverse through the elements of the Stream until it finds a match.

Let's say, we have a  list of Dishes and want to find out if there is any vegetarian Dish among those. Just remind, how did you do this before Java 8. You had to at least write 5 or 6 lines of codes to do the above. In Java 8, you can do this by a single line.

List<Dish> menu = ....
if (menu.stream().anyMatch(Dish::getVegitarian)) {
    System.out.println("The menu is (somewhat) vegetarian friendly!!");
}

Using allMatch() method 

The allMatch() method also accepts a Predicate instance and works similar to anyMatch() method. This method will check to see if all the elements of the stream match the given predicate. For example, you can use it to find out whether the menu is healthy (that is, all dishes are below 1000 calories).

boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000);

The allMatch() method stops traversing the elements of the stream as soon as one element produces false output.

Using noneMatch() method

The opposite of allMatch() is noneMatch(). It ensures that no elements in the stream match the given predicate. For example, you could rewrite the previous example as follows using noneMatch.

List<Dish> menu = ....
boolean isHealthy = menu.stream().noneMatch(d -> d.getCalories() >= 1000);

Using findAny() method

The findAny() method returns an arbitrary element of the current stream. It can be used in conjunction with other stream operations. For example, you may wish to find a dish that’s vegetarian. You can combine the filter method and findAny to express this query.

List<Dish> menu = .....
Optional<Dish> dish = menu.stream().filter(Dish::isVegetarian).findAny();

The Optional<T> class (java.util.Optional) is a container class to represent the existence or absence of a value. In the previous code, it’s possible that findAny() doesn’t find any element. Instead of returning null, which is well known for being error prone, the Java 8 introduced Optional.

Optional interface has few important method as follows,

          isPresent() method which returns true if Optional contains a value, false otherwise.
          ifPresent(Consumer<T> block) executes the given block if a value is present.

if (dish.isPresent()) {
 ///........
}

dish.ifPresent(d->System.out.println(d.getName()); 

Java 8 map(), flatMap() examples

Using map() method

When programming, it is very common, processing data in order to collect some information from a collections of objects. Let's say, we wanted find out the cities from all the employees in a particular company. Our employee class will be as follows. 


public class Employee {
 
    private String name;
    private Integer age;
    private String city;
    private String state; 
    private Department department;
 
    public String getCity() {
         return city;
    }

    public void setCity(String city) {
         this.city = city;
    } 

    public String getState() {
         return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

I didn't include all the attributes for Employee class, but what I need 'city' attribute in this case. 

So now, we have a list of Employee objects and need to find out distinct cities. Let's see the approach before Java 8. Hopefully, you will write a code as follows in order to get distinct cities. 

List<Employee> employeeList = .....
Set<String> cities = new HashSet<String>();
for (Employee emp : employeeList) {
    cities.add(emp.getCity());
}

Java 8 Stream interface introduces map() method which takes a function as an argument. This function is applied to each element in the stream and returns new stream. The code will look like follows.

List<Employee> employeeList = new ArrayList<Employee>();
List<String> cities = employeeList.stream()
                                  .map(Employee::getCity)
                                  .distinct()
                                  .collect(Collectors.toList());

Using flatMap() method 

Java 8 Stream interface introduces flatMap() method which can be used to merge or flatten few streams into a single stream.

Let's take an example. Suppose, we wanted to filter out distinct words in a text file. Look at the following text file.


Sri Lanka is a beautiful country in Indian ocean.
It is totally surrounded by the sea.

In Java 8, we can read a text file using a single line and it will return a Stream of string. Each element of the stream will be a one line of the text file.

Stream<String> lineStream = Files.lines(Paths.get("data.txt"), Charset.defaultCharset());

If you see the out put of above code by printing 'lineStream' Stream, it will be the lines of the text file. 

Next, we can convert each element of the above Stream into a Stream of words. Then we can use flatMap() method to flatten all Streams of words into a single Stream. If we execute the following code for each element of the 'lineStream' Stream, we will get two Stream of words. See the following code.

line -> Arrays.stream(line.split(" "))

Two Streams of words will be as follows.

Stream 1 : [SriLanka][is][a][beautiful][country][in][Indian][ocean.]} 
Stream 2 : [It][is][totally][surrounded][by][the][sea.]

The flatMap() method can flatten these two into a single Stream of word as follows.

Stream<String> wordStream = lineStream.flatMap(line -> Arrays.stream(line.split(" ")));

If you print the elements of the above 'wordStream', it will be all the words of the text file. But still, you will see duplicate words. You can use distinct() method to avoid the duplicates. Here's the final code.

List<String> wordStream = lineStream.flatMap(line -> Arrays.stream(line.split(" ")))
                                    .distinct()
                                    .collect(Collectors.toList());

If you see closely, you can find the distinct words of a text file just by using two lines of code with Java 8.

Tuesday, July 3, 2018

How to use filter() method in Java 8

Java 8 Stream interface introduces filter() method which can be used to filter out some elements from object collection based on a particular condition. This condition should be specified as a predicate which the filter() method accepts as an argument.

The java.util.function.Predicate interface defines an abstract method named test() that accepts an object of generic type T and returns a boolean.

Let's do some coding to understand the filter method more clearly. Look at the following Dish class.

public class Dish {

     private String name;
     private Boolean vegitarian;
     private Integer calaries;
     private Type type;
 
     public Dish(String name, Boolean vegitarian, Integer calaries, Type type) {
          super();
          this.name = name;
          this.vegitarian = vegitarian;
          this.calaries = calaries;
          this.type = type;
     }

     public Boolean getVegitarian() {
         return vegitarian;
     }

     public void setVegitarian(Boolean vegitarian) {
         this.vegitarian = vegitarian;
     }

     public Type getType() {
         return type;
     }

     public void setType(Type type) {
         this.type = type;
     }

     public enum Type { MEAT, FISH, OTHER };
}


Let's think, we want to filter out only the vegetarian Dishes from a list of all Dishes. Following is the approach  before Java 8.

    List<Dish> vegetarianDishes = new ArrayList<Dish>(); 
    for(Dish d: menu) {
       if(d.getVegetarian()) { 
          vegetarianDishes.add(d);
       } 
    }

The above approach is called external iteration which we explicitly manage the iteration over the collection of data.

How this can be done with Java 8 ? It is just a matter of single line as follows.

List<Dish> menu = ....
List<Dish> vegitarianDishes = menu.stream()
                                    .filter(d -> d.getVegitarian())
                                    .collect(Collectors.toList());

We have passed a Predicate instance into the filter() method in a form of a Lambda expression.

Also, we can use java 8 method references to pass a Predicate instance to the filter() method as follows.
List<Dish> menu = ....
List<Dish> vegitarianDishes = menu.stream()
                                    .filter(Dish::getVegitarian)
                                    .collect(Collectors.toList());

Dish::getVegitarian is the syntax for Java 8 method references. It refers to the getVegitarian() method of Dish class. 

The filter() method returns a Stream of Dishes and the collect() method converts the Stream into a List. The 'collect' operation is called a terminal operation.

Now let's say, we want to get first three Dishes that have more than 300 calories. Streams support the limit(n) method, which returns another stream that’s no longer than a given size. The requested size is passed as argument to limit.

List<Dish> menu = ....
List<Dish> threeHighCalaricDish = menu.stream()
                                         .filter(d -> d.getCalaries() > 300)
                                         .limit(3)
                                         .collect(Collectors.toList());

Similarly, if we want to skip first 3 elements, streams support the skip(n) method to return a stream that discards the first n elements. If the stream has fewer elements than n, then an empty stream is returned. Note that limit(n) and skip(n) are complementary!

Now, an exercise for you ! How would you use streams to filter the first two meat dishes?
List<Dish> menu = ....
List<Dish> meatDishes = menu.stream()
                                  .filter(d -> d.getType() == Dish.Type.MEAT)
                                  .limit(2)
                                  .collect(Collectors.toList())

Saturday, June 9, 2018

Java 8 sorting examples

How many lines of code did you write to sort a collection of objects before Java 8 ? How many, you will need with Java 8 ?
You can do it with a single line in Java 8.

Let's see the following Employee class.

public class Employee {
 
     private String name;
 
     private Integer age;
 
     public Employee(String name, Integer age) {
         super();
         this.name = name;
         this.age = age;
     }

     public String getName() {
         return name;
     }

     public void setName(String name) {
         this.name = name;
     }

     public Integer getAge() {
         return age;
     }

     public void setAge(Integer age) {
        this.age = age;
     }

}

Using the Collection's sort() method, employee list can be sorted. The sort() method expects a Comparator as an argument in order to compare two Employee objects. So our first solution looks like as follows.


public class EmployeeComparotor implements Comparator {
    @Override
    public int compare(Employee e1, Employee e2) {
        return e1.getAge().compareTo(e2.getAge()); 
    }
}

employeeList.sort(new EmployeeComparotor());

Rather than implementing Comparator and instantiating a new instance of it, we can use an anonymous class to improve our program.

employeeList.sort(new Comparator() {
    @Override
    public int compare(Employee e1, Employee e2) {
        return e1.getAge().compareTo(e2.getAge()); 
    }
}); 

Now, let's see, how can we improve this code further in order to reduce the verbosity by using Java 8 features. Java 8 introduces lambda expressions which allows us to pass a code to a method. Lambda expression can be passed to a method where functional interface is expected. A functional interface is an interface defining only one abstract method. In Java 8, the Comparator is a functional interface. The Collection's sort() method expects a Comparator as an argument, which accepts a functional interface. In this case, the Comparator represents BiFunction's descriptor. The BiFunction is a functional interface in Java 8. So then, you can pass a lambda expression into the sort method as follows. In order to sort employee list by their age, you need a single line as follows.

employeeList.sort((Employee e1, Employee e2) -> e1.getAge().compareTo(e2.getAge()));

Java compiler can infer the types of parameters of a lambda expression by using the context in which the lambda appears. So you can remove the types of parameter and rewrite the code as follows.

employeeList.sort((e1, e2) -> e1.getAge().compareTo(e2.getAge()));

Let's try to further reduce the code. Java 8 Comparator has a static method called comparing() that accepts a Function as an argument. This Function should extract the sort key and produce a Comparator object. So the shortest code to sort a list of objects in Java 8 will be,

employeeList.sort(comparing((e) -> e1.getAge()));

In stead of using a lambda expression, we can use method references to make our code slightly less verbose.

employeeList.sort(comparing(Employee::getAge));

If you want to sort the employee list by descending order in age, you can use the reversed() default method of the interface.

employeeList.sort(comparing(Employee::getAge).reversed());

Now, let's see, you want to sort the employees in their age and then, similar age employees by their names. Just remind, how did you do this earlier version of Java. In Java 8, you can simply use thenComparing() method in order to do this.

employeeList.sort(comparing(Employee::getAge).thenComparing(Employee::getName));



Thursday, June 6, 2013

Online server console viewer with Ajax long polling.

This post will give you small web application which brings the real time server console to the browser.  I am going to explain you, how to run this web application as it is and also if you want to add more customization, how to build the project using the source.

The Comet concept

This application a demonstrative usage of the Comet concept introduced by  Alex Russell in 2006. Once you get the idea, you can develop innovative applications and make use of it with your web application. For example, Facebook, it shows new friend requests, inbox updates and notifications on time. That is one of the real time usage of Comet approach.

The Comet is a web application model which always keeps live  connection with the server and let the server push the data to the browser through that connection. The browser does not explicitly request specific data. It just keeps live connection with the server. What ever the data pushed (or published) by the server are carried to the browser through that open connection. Also this concept is know as Ajax-Push, Reverse-Ajax, Two-way-web, HTTP Streaming, HTTP-server push.

There are several  ways of implementing Comet model. The CometD is a java framework  developed by Dojo Foundation which implements the Comet concept with 'XMLHttpRequest long polling'. This works with all modern browsers which supports XHR. With XHR long polling, the browser makes an asynchronous request to the server and if there are data available at the server, the response will bring that data to the browser as XML or JSON. After processing the response at client side, browser makes another XHR to poll more available data from the server.

If you have frequent data changes on the server and want to update browsers, the comet approach will be a best fit, because this can be pretty network intensive, and you often make pointless requests, though nothing has happened on the server. For example, frequent stock market information can be published to many users as soon as latest information is available. 

How the application works?

This application keeps reading the specified server log file line by line and push collected chunk of lines to the browser as a one string. By default, the application reads the Tomcat's catalina.out file. Server runs a timer which is set to every one second and executes these log file reading function. It collects  all the lines read within a one second and push to the client. In the client side, application keeps appending new contents to HTML DIV element. The server function will always reads only the newly appending lines of the the log file.

How to run the application?

If you are using Tomcat, you can experiment this application without much worrying. You just need to download the 'console-viewer.war' file and deploy it in your Tomcat container. If you are testing this with your local configuration, point your browser to following URL.

http://localhost:8080/console-viewer

Click on 'Connect' button and keep looking while you are accessing some deployed application. You will see the Tomcat's console on your web browser. Keep in mind, by default, this application reads 'catalina.out' file. So you need to start the Tomcat with ./startup.sh command. If you are appending your application's logs into different log file or using different server, I will explain, how to customize the application for that later. 

How to build the project with source?

I have provided complete source to you so that you can download the source code and go one step further or to read different log file or run with different server other then Tomcat. You can build the project using maven. If you are not using maven, you can create your own simple web application and copy the required contents. If you want to get the set of .jar files, you can get it from console-viewer.war file.

Here are the steps to build the project using maven.

Download the source and extract it to some where in your local disk. 

1. Navigate to the location.

    cd /home/semika/console-viewer

2. Build the project with the following command.

    mvn clean install

You can see, it builds the project and copies the 'console-viewer.war' file into CATALINA_HOME/webapps folder.  

3. Start the Tomcat with the following command.

   ./startup.sh

If you want to read some other log file rather than default 'catalina.out' file, or you want to run this application to view different server's console, you have to provide required log file's absolute path as an initialization parameter of 'Initializer' servlet as follows and deploy the application on the server.

<servlet>
    <servlet-name>initializer</servlet-name>
    <servlet-class>com.semika.cometd.Initializer</servlet-class>
    <init-param>
         <param-name>logFilePath</param-name>
         <param-value>
             /home/semika/apache-tomcat-7.0.37/logs/catalina.out
         </param-value>
     </init-param>
     <load-on-startup>2</load-on-startup>
</servlet>

Download the application and source

Download console-viewer.war file.
Download source code. If you encounter some issues with this, please send me a mail. I am always ready to give help.

Friday, March 29, 2013

Don't use 'Query.list()' when you really need 'Query.uniqueResult()' in Hibernate.

I was motivated to discuss a little about this topic, since I am seeing a usage of hibernate which is capable of making server issues in your application. What I am going to discuss here, is very simple, but some developers are tend to do it in wrong way. Sometime, they are doing this intentionally for safe side.

When we are using hibernate Query to fetch a single instance, Query.uniqueResult() is being used except special scenarios. To use Query.uniqueResult(), we must make sure that query will return a single object. But some programmers are still used to do it with Query.list() method which can pull your application out into very inconsistency situation and issues which are very hard to discover the reason for failure. 

Just have a look into the following example.

public Account getAccountByAccountIdAndType(Long accountId, AccountType accountType) throws FetchAccountException {
 
    Account account = null;
    Query query = getSession().getNamedQuery("getAccountByAccountId");
    query.setLong("accountId", accountId); 
    query.setString("accountType", AccountType.SAVING.toString());
    List<Account> list = query.list();
    if (null != list && list.size() > 0) {
         account = list.get(0);
    }
    return account;
}

The above function is responsible to get Account instance for a given account number and type. Let's assume there can not be two accounts with the same type having same account number. 

If you carefully see the above code, the developer has applied many safe factors to minimize the exceptions. Some are even ambiguous. The above method will be functioning well until there is one Account with same type and account number and you expects that too. And also, it will execute well when there are more than one Account with same type and account number, which results wrong output and we don't actually need. 

What will happen, if there are more than one accounts with same type and same account number?

That will be a total failure of your application and you will have to compensate if banking system will be on this kind of state. Let's see how the above method will behave in this kind of situation. The above method will hide this critical exception and keeps application flow functioning. The function will get a list which is having the accounts and will return the first Account instance. Ultimately, this will result wrong outputs in your application. 

The programmer has added a safe factor to keep application flow functioning even with more than one accounts with same type and number. This is unnecessary and a kind of cheat programming. The programmer can survive for some time, the company who is working for, will have to compensate for loses. This is very poor programming. Some programmers do this intentionally as a safe factor, some are doing this as a quick fix for a defect. But this is very very dangerous.

Further the programmer has checked the "list" for NULL which is ambiguous, because hibernate does not return NULL list, instead it always returns empty list.

And other shortage of above method is, it may return NULL as the output which is not a good programming practice. Instead, you can throw an exception.

The getAccountByAccountIdAndType() method must return an exception in state. If the programmer used Query.uniqueResult() for this purpose, it returns the following exception keeping every one enlighten. We can take immediate action to get rid of this killer situation.

org.hibernate.NonUniqueResultException: query did not return a unique result: 2

We can improve the above function as follows.

public Account getAccountByAccountIdAndType(Long accountId, AccountType accountType) {
 
    Query query = getSession().getNamedQuery("getAccountByAccountId");
    query.setLong("accountId", accountId); 
    query.setString("accountType", AccountType.SAVING.toString());
    Account account = (Account)Query.uniqueResult();
    
    if (account == null) {
         throw new RuntimeException("Unable to find Account for account number :" + accountId);
    }
    return account;
}

Now the above method will return the exception when there are more than one account with same type and number.

If you want to send more specific error message rather than a hibernate exception message when you are having more than one account with same account number and type, you can put a try-catch block as follows.

public Account getAccountByAccountIdAndType(Long accountId, AccountType accountType) {
     
    Account account = null;
    try {
        Query query = getSession().getNamedQuery("getAccountByAccountId");
        query.setLong("accountId", accountId); 
        query.setString("accountType", AccountType.SAVING.toString());
        Account account = (Account)Query.uniqueResult();
    } catch(NonUniqueResultException) {
        throw new RuntimeException("Two account found with same account number and type : Acc No-" + accountId);
    }
    if (account == null) {
         throw new RuntimeException("Unable to find Account for account number :" + accountId);
    }
    return account;
}

As a conclusion, always use Query.uniqueResult() when you want to fetch a single object with hibernate Query and you should make sure your query will return a single object too.
Share

Widgets