Saturday, August 25, 2018

Running Spring Boot app as a service in unix


You should never run a Spring Boot application as root, so your application’s jar file should never be owned by root. Instead, create a specific user to run your application and use chown to make it the owner of the jar file

Creating executable Jar

We can always run Spring Boot applications by using java -jar <jarname> command, but it is also possible to make fully executable applications for Unix systems (centos, ubuntu, etc) that can be executed like any other executable binary and even registered with systemd. This makes it easy to install and manage Spring Boot applications in production environment.
Spring boot 1.x and 2.x have slightly different way of creating fully executable jars. We will explore both the options:

Spring Boot 1.x

The following configuration is required in build.gradlefile in Spring Boot 1.x projects.
build.gradle
1
2
3
4
5
6
7
8
9
10
jar {
    baseName = 'your-app'
    version = version
}

springBoot {
    buildInfo()
    executable = true   (1)
    mainClass = "com.shunya.App"
}
  1. This is required to make fully executable jar on unix system (Centos and Ubuntu)

Spring Boot 2.x

The following configuration in build.gradle will make a fully executable jar in Spring Boot 2.x project.
build.gradle
1
2
3
4
5
bootJar {
    launchScript()
    baseName = 'your-app'
    version =  '0.1.0'
}

Create a .conf file

If you want to configure custom JVM properties or Spring Boot application run arguments, then you can create a .conf file with the same name as the Spring Boot application name and place it parallel to jar file.
Considering that your-app.jar is the name of your Spring Boot application, then you can create the following file.
your-app.conf
JAVA_OPTS="-Xms64m -Xmx64m"
RUN_ARGS=--spring.profiles.active=prod
LOG_FOLDER=/custom/log/folder
This configuration will set 64 MB ram for the Spring Boot application and activate prod profile.

Create a new user in linux

For enhanced security we must create a specific user to run the Spring Boot application as a service.
Create a new user
sudo useradd -s /sbin/nologin springboot
On Ubuntu / Debian, modify the above command as follow:
sudo useradd -s /usr/sbin/nologin springboot
Set password
sudo passwd springboot
NOTE
To reduce the chances of the application’s user account being compromised, you should consider preventing it from using a login shell. For example, you can set the account’s shell to /usr/sbin/nologin, this will limit your system’s attack surface.
Make springboot owner of the executable file
chown springboot:springboot your-app.jar
Prevent the modification of jar file
chmod 500 your-app.jar
This will configure jar’s permissions so that it can not be written and can only be read or executed by its owner springboot.
TIP
Octal 500 = read + execute (r-x) for owner, group has 0 and world has zero permissions.
You can optionally make your jar file as immutable using the change attribute (chattr) command.
sudo chattr +i your-app.jar
NOTE
chattr +i sets the immutable filesystem attribute on the file. It differs from access control rules. Access controls are file attributes, immutable is a filesystem extended file attribute (may not be available). Only user with root privileges can set or unset this attribute.
Appropriate permissions should be set for the corresponding .conf file as well. .conf requires just read access (Octal 400) instead of read + execute (Octal 500) access
chmod 400 your-app.conf

Create Systemd service

/etc/systemd/system/your-app.service
1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=Your app description
After=syslog.target

[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Automatically restart process if it gets killed by OS

Append the below two attributes (Restart and RestartSec) to automatically restart the process on failure.
/etc/systemd/system/your-app.service
[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143
Restart=always
RestartSec=30
The change will make Spring Boot application restart in case of failure with a delay of 30 seconds. If you stop the service using systemctl command then restart will not happen.

Schedule service at system startup

To flag the application to start automatically on system boot, use the following command:
Enable Spring Boot application at system startup
sudo systemctl enable your-app.service

Start an Stop the Service

systemctl can be used in Ubuntu 16.04 LTS and 18.04 LTS to start and stop the process.
Start the process
sudo systemctl start your-app
Stop the process
sudo systemctl stop your-app

For more such questions, you can get my ebook

Cracking Spring Microservices Interviews PDF updated on April 2018
Buy from Shunya (DRM Free PDF download with updates) Buy from Pothi.com

Recursion, Dynamic Programming in Java and Kotlin

Introduction to Dynamic Programming in Java and Kotlin

Before starting Dynamic Programming, we must get familiar with recursion first.

Recursion

In recursion, we simply a complex problem by breaking it down into simpler sub-problems in a recursive manner. If a problem can be composed off sub-problems, then it could be a good candidate for recursion.
Few examples of recursive problems are:
  1. Calculation of Fibonacci number
  2. Calculating factorial of a given number
General structure of recursive solution
if (base condition) {// base condition with iterative solution
    return <some simple iterative expression>
}
else {// recursive case
     some work before call()
     recursive call()
     some work after call()
}
Solution to a recursive problem is built using solution to its sub-problems. Recursive solutions can be broadly divided into two categories:
Bottom-up recursion
Here we start with knowing how to solve the problem for the simple case, like with only 1 element for factorial and then for 2 elements. Basically we build the solution for one case off of the previous case.
Top-down recursion
We start with dividing the problem for case N into sub-problems till we achieve the solution.
Notes:
  1. Recursion is helpful in writing complex algorithms in easy to understand manner.
  2. Normally iterative solutions provide better efficiency compared to recursive one because of so much overhead involved in executing recursive steps.

Calculating Fibonacci using Recursion

For example, we would use the following code to calculate the Fibonacci series using recursion
Fibonacci - Kotlin version
fun fibonacci(n: Int): Long {
    if (n == 0) return 0
    if (n == 1) return 1
    return fibonacci(n - 1) + fibonacci(n - 2)
}
Fibonacci - Java version
public class Fibonacci {
    public int fib(int n) {
        if (n <= 1) { (1)
            return n;
        } else { (2)
            return fib(n - 1) + fib(n - 2);
        }
    }
}
  1. base condition
  2. recursive condition
Time Complexity
Computing the nth Fibonacci number depends on the solution of previous n-1 numbers, also each call invokes two recursive calls. This means that the Time complexity of above fibonacci program is Big O (2n) i.e. exponential. That’s because the algorithm’s growth doubles with each addition to the data set.
TIP
Exponential runtime complexity
Time complexity of an algorithm is Big O (2n) i.e. exponential when its growth doubles with each addition to the input data set. It is exactly opposite to Big O (log n) where problem size is reduced to half on each successive iteration.

Dynamic Programming

Dynamic Programming is a powerful optimization technique, where a recursive problem can be solved in O (n2) or O (n3) where a naive approach would take exponential time O (2n)
The optimization in Dynamic Programming is achieved by caching the intermediate results for the future calls.
If we run the previous fibonacci program, input of 50 will take around 1 minute on a average modern hardware.
Now, we will write the same fibonacci program using Dynamic Programming:
Fibonacci - Optimized Kotlin version using Dynamic Programming
class Fibonacci {
    private val cache: MutableMap<Int, Long> = HashMap()

    fun cal(n: Int): Long {
        if (n == 0) return 0
        if (n == 1) return 1

        return when {
            cache.containsKey(n) -> cache[n]!!
            else -> {
                cache[n] = cal(n - 1) + cal(n - 2)
                cache[n]!!
            }
        }
    }
}
Fibonacci - Optimized Java version using Dynamic Programming
public class Fibonacci {
    final int max = 10000;
    int[] fib = new int[max];

    int fibonacci(int num) {
        if (num == 0) return 0;
        if (num == 1) return 1;

        if (fib[num] != 0) {
            return fib[num];    (1)
        }
        fib[num] = fibonacci(num - 1) + fibonacci(num - 2);  (2)
        return fib[num];
    }
}
  1. return the cached result, if already available.
  2. cache the result of computation for future use.
You can try to run the above example on your machine, even 1000th Fibonacci number will be calculated in a fraction of millisecond.
In nutshell, Dynamic Programming is an optimized recursive technique where you cache the results for use in future calls. You can always start with a normal recursive approach first and then add the caching part later on.

Monday, August 20, 2018

What is difference between sleep() and wait() method in Java?

wait() and notify() are used in multi-threading programming for inter-thread communication, while sleep is used to control execution time of current thread.

Summary of difference sleep and wait

  1. sleep() method is part of java.lang.Thread class
    private void sleepExample()
      throws InterruptedException {
        Thread.sleep(1000);
      }
    wait() is method of Object class, though Thread class also has wait() method since it inherits from Object too, but wait() is called on the synchronized object.
    Object lock = new Object();
    synchronized (lock) {
        lock.wait();
    }
  2. sleep() may be called from anywhere. wait() method must be called from synchronized context (i.e. synchronized method or block), otherwise it will throw IllegalMonitorStateException
  3. sleep() does not release the lock acquired by thread on current object. wait() releases the lock on object waiting for a condition to be fulfilled, in the meantime another thread can acquire the lock on this object.
  4. sleeping thread can not be woken up (except by calling Thread.interrupt()). A wait can be "woken up" by another thread calling notify() or notifyAll()on the monitor which is being waited. If more than one thread are waiting on the given object, only one of them will be able to grab the lock.
    synchronized (lock) {
        lock.notifyAll();
    }
  5. spurious wakeups (waiting thread wakes up for no apparent reason) can happen on wait(), so you should always call wait() inside a while loop on some condition.
    synchronized (lock) {
        while (!condition) {
         lock.wait();
        }
        //Take action
    }
    Such wakeups never happen in sleep().
  6. Thread goes from Runnable to TIMED_WAITINGstate. Thread goes from Runnable to WAITINGstate, if no timeout is specified
The below example of CustomSemaphore illustrates use of wait() and notify() method on a object monitor in synchronized context.
Custom Semaphore using wait() and notify()
public class CustomSemaphore {
    private final Object monitor = new Object();
    private int permits;

    CustomSemaphore(int initialPermits) {
        synchronized (monitor) {
            permits = initialPermits;
        }
    }

    /**
     * Blocks until permitsAvailable (permit > 0)
     */
    public void acquire() throws InterruptedException {
        synchronized (monitor) {
            while (permits <= 0)
                monitor.wait();
            --permits;
        }
    }

    /**
     * Release a single permit and notifies threads waiting on permitsAvailable Condition
     */
    public void release() {
        synchronized (monitor) {
            ++permits;
            monitor.notifyAll();
        }
    }
}
In general, we should use sleep() for controlling execution time of one thread and wait() & notify() for multi-thread synchronization.

For more such questions, you can get my ebook