Function composition using Java 8

The objective of this blog post is to give you a basic idea of functional composition in Java 8. We will look at 2 methods, andThen and compose which are part of the functional interface, Function.  We will then build on it further to show how we can apply a stream to a variable number of functions to combine all the functions.

Let us take a very simple example of 2 functions, one function adds 0.2 to an incoming value and another one adds 0.5 to an input value. So the input is a double and the output is also a double. This can represented as a Function<Double,Double>. Function is the functional interface introduced in Java 8.

Function<Double, Double> func1  =  d -> d + 0.2;
Function<Double, Double> func2  = d -> d + 0.5;

Both andThen and compose are default methods.

The andThen method:

To compose these 2 functions together , we can use andThen method from the Function interface. What do we get now ?

func1.andThen(func2)

Let us start with an initial value, 1.0.

Hence :

func1.andThen(func2).apply(1.0)

This gives us an output of 1.7.

How ?

  1. The call to the andThen method first applies the func1 to 1.0 which is the input. This gives us an output of 1.2 as behavior of func1 is d -> d+0.2, here d = 1.0
  2. The output from above , 1.2 , serves as an input to func2 and hence we get 1.2+0.5 = 1.7.

The compose method:

To understand this let us slightly modify the 2 functions:

Function<Double, Double> func1 = d -> d + 0.2;
Function<Double, Double> func2 = d -> d * 10.0;

The second function multiplies the incoming value by 10.

If we were to do:

func1.compose(func2).apply(1.0)

The output is 10.2

How?

  1. The call to the compose method first applies the func2 to 1.0 which is the input. This gives us an output of 10.0 as behavior of func2 is d -> d * 10.0, here d = 1.0
  2. The output from above , 10.0 , serves as an input to func1 and hence we get 10.0 + 0.2 = 10.2

What if we applied andThen to the above?  Well, the output is 12.0 . Surprised ?

Why?

  1. The call to the andThen method first applies the func1 to 1.0 which is the input. This gives us an output of 1.2 as behavior of func1 is d -> d+0.2, here d = 1.0
  2. The output from above , 1.2 , serves as an input to func2 and hence we get 1.2 * 10.0 = 12.0.

Remember:

The andThen method applies the first function, func1 to the input, that is the parameter to the apply method but the compose method operates by applying func2 to the value in the apply and then passes the value to func1.

andThen:

func1.andThen(func2).apply(1.0)

compose:

func1.compose(func2).apply(1.0)

More fun with functional composition:

Let us go back to :

Function<Double, Double> func1 = d -> d + 0.2;
Function<Double, Double> func2 = d -> d + 0.5;

When we did the following, we got the output as 1.7 :

func1.andThen(func2).apply(1.0)

Let us apply a Stream.of to func1 and func2.


Function<Double,Double> combined = Stream.of(func1,func2)
.reduce(Function.identity(), Function::andThen);
combined.apply(1.0);

The output from this is also 1.7

The Stream.of(…) returns a stream of Function<Double,Double>. The reduce method takes a Function.identity(), this is just saying, hey whatever is the next element in the stream, return it to me as it is. The Function::andThen specifies that combine each element in the stream with  andThen(). So <element_from_the stream>.andThen<next_element_from_stream>. The combination of stream and reduce method combines or chains all the functions together and gives us a single Function<Double,Double> which is a chain of functions.

Now how is this useful ? We can create a function which accepts  a variable number of functions and then they can all be chained in one place.


import java.util.function.Function;
import java.util.stream.Stream;
public class FunctionalChaining {
public static void main(String[] args)
{
Function<Double, Double> func1 = d -> d + 0.2;
Function<Double, Double> func2 = d -> d + 0.5;
// Simple chaining
System.out.println(func1.andThen(func2).apply(1.0));
// Chaining using Stream.of
Function<Double, Double> combined = Stream.of(func1, func2)
.reduce(Function.identity(), Function::andThen);
System.out.println(combined.apply(1.0));
// Pass it to a function which can accept variable number of functions.
System.out.println(combineFunctions(func1, func2));
}
private static Double combineFunctions(Function<Double, Double>… combineFunctions)
{
Function<Double, Double> chainedFunction = Stream.of(combineFunctions)
.reduce(function -> function,Function::andThen);
return chainedFunction.apply(1.0);
}
}

Output from all 3 types:

1.7
1.7
1.7

We used a very simple Function<Double,Double> which just added a double value but we could easily pass and chain functions which do a lot more.Function composition is a powerful mechanism which can be used to solve a variety of problems.Think about the decorator pattern or how consecutive filters are applied , can’t we use functional composition instead ?

How I met Spring Boot…

The title of this blog is inspired from the famous sitcom “How I met your Mother”. Well, this is a short story of How I met Spring Boot.

We are a team of 5 developers among whom there is a so-called “Software Architect”. In this part of the world that I live, the 2 words, “software architect” really mean different things to different people. More on that later.

There was a new requirement to rewrite a system currently maintained using mainframe to a more modern AngularJS/RESTful based application.The back-end would have REST based services which would communicate with an Oracle database using JPA . On the server side, the first task was really to set up the basic back end application and then the developers on the team would start with their use cases. Our architect decided to take up the responsibility of setting up the basic back end and mentioned that it was a tough task. By basic I mean, just the bare bones with all the basic dependencies, configuration against an in memory database to begin with, simple rest service to help the team get up and running.

When the scrum master asked him an estimate , he said he would take around 2 weeks to set up the basic backend code.

Well during the daily stand up meeting, the architect would say that he is still setting up the project and that went on for 2 weeks.At the end of 2 weeks when he checked in the code, what I saw was really shocking. What I saw was strange dependencies, outdated versions of jars, unused code,dependencies. I realized later that he had copy pasted the basic setup from another project.

Well, I said to myself, “Is setting up a project that hard ? I do remember shying away from trying a few things on my own assuming it would be complicated to bring in all the right dependencies, set up the right Spring configuration.I remember I wanted to integrate Spring with Hibernate and never really understood spring-orm library and everything else that came along with it. I have sometimes wondered how to get all configuration right and well sometimes been a little lazy.

But this time,  I decided to investigate this further and decided to set up the project  and of course nobody in the team knew this. This is when I discovered Spring Boot.

Well, as I was browsing through the official Spring framework website, I read something about bootstrapping your Spring Boot application and this is when I stumbled upon the Spring Initializr. I switched to the full version there and chose the following:

  1. Maven project
  2. Java 1.8
  3. Left the group and artifact id as it is as I was playing around.
  4. JPA support
  5. H2 as in memory database and finally
  6. Full stack web development with Tomcat and Spring MVC

And well on clicking the Generate Project button,  I had a full-fledged maven project. That took a few days…Correction – seconds!

I then wrote the following simple classes, one end point for the rest service, one for the repository layer, one JPA entity and finally the class which starts everything.

EmployeeRestController.java


package com.example;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmployeeRestController {
private EmployeeRepository employeeRepository;
@Autowired
public EmployeeRestController(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
@RequestMapping("/employees")
public List<Employee> employees() {
return employeeRepository.findAll();
}
}

EmployeeRepository.java


package com.example;
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}

Employee.java


package com.example;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
public Employee() {
}
public Employee(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Employee [firstName=" + firstName + ", lastName=" + lastName + "]";
}
}

view raw

Employee.java

hosted with ❤ by GitHub

DemoApplication.java


package com.example;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
// Use constructor injection.
@Autowired
private EmployeeRepository employeeRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
// Initialization to add data to h2 db.
@Override
public void run(Stringargs) throws Exception {
List<Employee> employees = getAllEmployees();
employees.forEach(employee -> employeeRepository.save(employee));
}
private List<Employee> getAllEmployees() {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("Barney", "Stinson"));
employees.add(new Employee("Alex", "Hitch"));
employees.add(new Employee("Douglas", "Ramsey"));
return employees;
}
}

Snapshot of the pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<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.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/> <!– lookup parent from repository –>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

view raw

pom.xml

hosted with ❤ by GitHub

Then I did the following:

  1. Ran mvn clean install
  2. java -jar ./target\demo-0.0.1-SNAPSHOT.jar ( Yes, that is right, a jar file)

That’s it, the application was up and running ! When I hit the URL :

http://localhost:8080/employees

I got the following output:

[{"firstName":"Barney","lastName":"Stinson"},{"firstName":"Alex","lastName":"Hitch"},{"firstName":"Douglas","lastName":"Ramsey"}]

Note The DemoApplication implements a CommandLineRunner and hence the run method. This is being done only to populate some mock data into the H2 database which the rest service can access .

The entire thing took me only a few minutes. We were able to set up and run a Spring REST, JPA based maven project in a matter of few minutes ! Not just that , we were able to get an executable jar file which ran in an embedded server. Now, how cool is that !

Well, I wonder what the architect did during those 2 weeks what we could do in a few minutes! Not just that, we were able to configure the project with all the latest and relevant dependencies without worrying about compatibility and version related issues.

We did not write a single configuration file, there are no xml’s,  there is absolutely no code generation behind the scenes !

But what really happened ?

This is all handled by Spring Boot ! The starter pom that we added brings in the required jars to the classpath. As an example ,with the spring-boot-starter-parent and spring-boot-starter-data-jpa dependency , Sprint Boot will bring all the latest versions of the jars(Spring data, Hibernate). In our case  it pulls in version 5.0.9 of Hibernate.

Then through the usage of the @SpringBootApplication annotation (see DemoApplication.java)  Spring Boot configures  some defaults.

Some of the defaults in this case:

  1. Spring Boot configures an embedded Tomcat server if we haven’t configured it to run on anything else. This is done since we added the spring-boot-starter-web in  then pom.xml
  2. As we did not specify any other database specific parameters, Sprint boot decided to use an in memory H2 database which we added in the pom.xml
  3. Spring boot configured JPA with Hibernate for us as we added the spring-boot-starter-data-jpa dependency

Of course we can add other specific configurations that we want and in that case Spring Boot will honor that and move out of the way or if we wanted to bring an older version of Hibernate, we just need to modify the pom.xml and add the following:

<hibernate.version>Required_Version</hibernate.version>

We were able to run the application using the java -jar command. This is enabled through the spring-boot-maven-plugin dependency we added in the pom.xml.

We have only scratched the surface of how simple it is get a project up and running with a rest based service along with JPA but Spring Boot can do a lot more for us. Not only did we manage to get it up and running quickly but with all the right dependencies and the setup looks clean !

We can integrate spring boot with a nosql database, jms , apache camel, jersey, cloud foundry, service discovery and even use it to monitor the application in production. Take a look at Spring Initializr for all the cool things it can do.

This article was only meant to introduce you to Spring Boot. Well, Spring Boot is just perfect for a lazy developer like me.

Well Barney Stinson from the sitcom “How I met your mother” always wore a suit and one of his famous quote is “Suit Up”.  Having met Spring Boot, I must say that we must all Boot up…Spring Boot Up !