Building Reactive Systems

In today’s world, we are always striving for building applications which can adapt to constantly changing needs. We want our systems to flexible, resilient, scalable and withstand end user’s high expectations.

Considering these needs, a Reactive Manifesto was put together, with best practices which will help us build robust applications. Following four pillars makes a strong base of reactive application.

1. Responsive
2. Resilient
3. Elastic
4. Message Driven

You can see none of these concepts are new in nature, and you might be already implementing them in the applications you build. Reactive Manifesto brings them under one umbrella and emphasizes their importance. Let’s take a look at these pillars one by one and see what all well-known patterns we can use to implement each of them.

Responsive: An application is responsive if it responds to the user in a timely manner. A very simple example is you clicked on a button or link in a web application, it does not give you a feedback that button was clicked and the action gets completed after few seconds. Such an application is non-responsive as the user is left guessing if he is performing the right action.

Some of the well-known practices and design patterns which help us make sure if the application is responsive
– Asynchronous communication
– Caching
– Fanout and quickest reply pattern
– Fail-fast pattern

Resilience: An application is called resilient if it can handle failure conditions in a graceful manner.

Some of the patterns that help maintain resilience
– Circuit breaker pattern
– Failure handling pattern
– Bounded Queue Pattern
– Bulkhead Pattern

Elasticity: An application is called elastic if it can stand increase or decrease in load without any major impact on overall working and performance.

Some of the practices and patterns to implement elasticity
– Single responsibility
– Statelessness
– Autoscaling
– Self-containment

Message Driven: An application which uses message driven communication makes sure we are implementing various components and services in a loosely coupled manner. This helps us keep our components scalable and makes failure handling easy.

Practices used to implement Message driven communicaiton
– Event driven
– Publisher Subscriber pattern
– Idempotency pattern

I have covered some of these patterns in details in my book on Design Patterns and Best Practices.

Design before you code

Somehow, with the penetration of agile development practices, I have been observing that less and less time is spent on designing the solution. Engineers treat Agile as a license to develop without design.

What is the problem with developing without designing or architecting the system first? I still remember when I was in college, my professor drew a parallel between architecting a building and architecting a software. Would you start building a house without thinking about design? you will not just start placing bricks without considering how many rooms you need? Where all these rooms go? How large should be every room? Where will the kitchen and bathroom be? Where all the wiring and plumbing will go? You will come up with the design, put in on a paper or a software and then calculate the feasibility.

Think of the complications that can happen if you build your house without thinking about design first. One room might be so big that there is very little space for the others. Or you are not left with any space to create a bathroom. These mistakes are costly. And that brings me to the other important factor which is causes ignoring of design in software. The manager thinks that change at a later state is going to be easy. At the end it is code, we can just change it. Well, changing the code is definitely possible, but never easy or cheap. It comes with its own cost.

More than often, where developers need to make changes at a later stage, they would be more inclined to apply quick fixes or hacks rather than making a bigger correct change. Of course, you have a tried and tested code in hand, why would you make too many changes to it, even if you know that is the right thing. And then there is developer ego, I mean, let’s admit it, it is not easy to accept one’s fault, especially if that means you would need to put in extra hours to fix that. More than ego, it is actually denial at times. People would try to stick to the solution they developed initially even though it is realized at a later stage that there could have been a better solution. Reason being, you have already invested too much.

This situation can be avoided if we think about design first. We can make sure our design covers all the possible requirements. It will not be possible to anticipate all the changes that are going to come at a later stage, but we can try to keep our design flexible. The idea is, set the ground rules, understand what all component and services we are required to create? What all data needs to be persisted and how are we going to do that? How security and error handling will be done? We need not get into implementation details, but the high-level design is a good start. We can fill in the details as and when requirements are clearer and we start actual work on the given piece of requirement.

In the end, all I would like to highlight is, if you think you are saving time by not thinking about the design of the application before you start to code, you are going to end up spending more time applying patches and fixes at the end.

Getting started with Spring Boot

This is a short tutorial about creating a simple REST webservice with spring boot. This assumes you have basic knowledge of Spring and Java.

To get started we will create a Spring project. The simplest way to do this is to go to http://start.spring.io/ and create a project.

This will give us a blank project on which we can build upon. Import the project as Maven project to Eclipse or any other ID. By default, it will provide a class which will look like

@SpringBootApplication
public class NewtestApplication {

	public static void main(String[] args) {
		SpringApplication.run(NewtestApplication.class, args);
	}
}

As you can see this is the main class and all the execution starts here. Also, note the @SpringBootApplication annotation. Spring documentation states that

“The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan with their default attributes”

For this example, we will keep it simple and introduce a controller

@RestController
public class HelloController {
	
	@GetMapping("/sayhello")
	public String sayHello() {
		return("Hello");
	}
}

Finally, Run the main class as a normal Java application, it will automatically start the Spring Boot server at 8080.

We can now access our application at http://localhost:8080/sayhello

Updating Java version in Linux

Recently I upgraded my Java version from 9 to 10 on a Linux machine. I was able to set JAVA_Home in .bashrc file properly but version did not get updated when checked java -version on shell.

Following commands helped to change the system’s Java version

sudo update-alternatives --install "/usr/bin/java" "java" "/path/to/jdk-10.0.1/bin/java" 1

And then

sudo update-alternatives --config java

This showed all the Java versions available and I was able to choose correct version i.e. 10.
Similary executed same commands for java compiler.

sudo update-alternatives --install "/usr/bin/java" "java" "/path/to/jdk-10.0.1/bin/javac" 1
sudo update-alternatives --config javac

Designing a Solution with AWS

When one goes for a Cloud based solution with solution provider like Amazon AWS, there are 2 things which are important. One, you need to have a clarity on what you are trying to achieve, and second is understanding of the services being provided by the provider.

Both the aspects are equally important. AWS provides plethora of services which can amuse at the same time confuse one. You might be tempted to use services which might not be required for your project and unnecessarily adds to the cost. At the same time if services not used with proper understanding, can backfire in terms of output and cost. For example, in one of my projects, incorrect implementation of autoscaling ended up running unused servers adding to cost instead of saving it.

Additionally, one need to be aware of all the capabilities of the service provider, for example, what all database and backup services we can use, can we use caching services, monitoring services provided by the service provider. Otherwise you will end up putting in unnecessary effort in rebuilding the wheel.

Here is a good starting point for AWS usage –

Features in Java 9

Java 9 might not be adding major changes like Java 8 which had features like Lambda or Streams or Interface modification, but it does have some good additions.

JShell: If you have worked in python or ruby, you might be aware of shell features these languages provide to quickly run and analyze commands and snippets. Java has come up with similar shell as JShell in Java 9 where you can evaluate the system.

Java Modules/ Jigsaw: Java has taken further step towards modularization. You can define your application in forms of modules and tell JVM what all modules will be used by current module, and what all modules will be exposed which can be used by others.

Private Methods in Interfaces: Java 8 gave us liberty to add method definitions in form of static and default implementations. With Java 9, one can add private methods to help us with organising our code better.

Additional Reads

http://www.baeldung.com/new-java-9
https://www.pluralsight.com/blog/software-development/java-9-new-features

AWS CloudFormation

When you are setting up an environment on AWS cloud, you need to go through many steps, like creation of IAM roles, Security groups, Databases, EC2 instances, load balancers etc. Often one resource is dependent on other and hence you have to create components one by one which can be time consuming. With Cloudformation scripts one can easily get the deployment steps automated. And most importantly, the script is reusable any number of times. So if I want to replicate a stage setup on production or another setup in another region, it is easily possible.

One can create template in JSON or YML formats. The template is submitted to cloud formation which executes the template and create the stack which is actual environment with all the mentioned components.

Another important thing is that you can not only create infrastructure, but also do required settings. For example, I needed to get setup for application done on EC2, which I was easily able to do with UserData section.

Here is an example

Resources: 
    AppNode1: 
        Type: AWS::EC2::Instance
        Properties:
            InstanceType: XXXXX # type here
            ImageId: ami-XXXX # any ami here
            KeyName: XXXX # name of the key if already exising or create a new one
            IamInstanceProfile: !Ref InstanceProfile
            NetworkInterfaces:
            - AssociatePublicIpAddress: true
              DeleteOnTermination: true
              Description: ENI for bastion host
              DeviceIndex: '0'
              SubnetId: subnet-XXXXX
              GroupSet:
              - !Ref AppNodeSG
            UserData:  
              "Fn::Base64":
                "Fn::Sub": |
                  #!/bin/bash
                  cd /root/
                  apt-get update
                  apt-get -y install awscli
                  aws s3 cp s3://XXXX/XXXX.XXX ~/some location
                  #One can install servers, download wars and deploy at runtime
    AppNode2: 
        Type: AWS::EC2::Instance
        Properties:
            # create another instance
    AppNodeSG: 
        # Security group to give access to ssh and port 80
        Type: AWS::EC2::SecurityGroup
        Properties: 
            GroupDescription: SecurityGroup for new AppNode
            VpcId: vpc-XXXXX
            SecurityGroupIngress:
            - IpProtocol: tcp
              FromPort: 80
              ToPort: 80
              CidrIp: 0.0.0.0/0
            - IpProtocol: tcp
              FromPort: 22
              ToPort: 22
              CidrIp: 0.0.0.0/0
    InstanceProfile:
        Type: AWS::IAM::InstanceProfile
        Properties: 
            Path: /
            Roles: [S3FullAccess] # S3FullAccess Role created Manually, so that my EC2 instance can access S3.

Features added in Java 8

I have already talked about 2 most important features added in Java 8 in my last posts, i.e. Lambda and Streams. Apart from these there were few interesting additions.

Method definition in interfaces: For long time, Java has avoided multiple inheritance due to dreaded diamond problem. They had given us interfaces which did not had method definition, which could have been implemented by a class in multiple numbers. Now, Java has relieved the restriction a bit by allowing static and default methods definition in interfaces.
What about multiple inheritance diamond problem? Well if compiler cannot decide which implementation to use it will thrown an exception.

ForEach: For Collections like Lists, instead of creating an explicit iterator one can use forEach.

Optional: There can be a situation when a method can return null, in such situations the value can be saved in optional class.

Good reads: https://www.journaldev.com/2389/java-8-features-with-examples
http://www.baeldung.com/java-8-new-features

Lambda expressions in Java

Lambda expressions in java is a way to implement functional interfaces. Functional interface is the one which only has single unimplemented method. This gives us freedom from creating a class or anonymous class. In addition Lambdas can be used with streams.

Here is an example. Download the code here

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Jaba8Lambda {

	interface Operations{
		public int operate(int a, int b);
	}
	
	public static void main(String s[]) {
		System.out.println("Welcome to Lambdas");
		
		// A simplest form of lambda, same interface, multiple implementations without a class
		Operations sum = (int a, int b)->a+b;
		Operations multiple = (int a, int b)->a*b;
		
		//Java8Lambda obj= new Jaba8Lambda();
		int mysum = sum.operate(2, 3);
		System.out.println(mysum);
		int myproduct = multiple.operate(2, 3);
		System.out.println(myproduct);
		
		// Another example using Thread Runnable
		// Earlier you would create a Runnable
		
		Runnable myrun = new Runnable() {
			
			@Override
			public void run() {
				System.out.println("starting:"+Thread.currentThread().getName());
			}
		};
		
		new Thread(myrun).start();
		
		// With Labdas we can do away with anonymous classes
		Runnable myrunLambda = ()->{
			System.out.println("starting:"+Thread.currentThread().getName());
		};
		new Thread(myrunLambda).start();
		
		// Lambdas can be used with streams as well
		List intlist= new ArrayList();
		intlist.add(2);
		intlist.add(7);
		intlist.add(12);
		intlist.add(17);
		Stream stream = intlist.stream(); 
		stream.forEach(i->{
			if(i%2==0) {
				System.out.println(i+" is even.");
			}
		});

	}
}