How to Enable Color in Spring Boot Console Log

Spring boot supports color coding of logging output displayed on the console. This enables us to quickly identify any errors or warnings logged by spring boot system. On most systems color coding works automatically. However if you are using a Mac terminal, you will find that no color coding is applied to the spring boot console log output. Mac terminal does have support for color, but somehow spring boot is unable to detect it.

spring-boot-console-log-without-color

The solution is simple. Just add the following property in the application.properties located in src/main/resources folder of your spring boot project. The default value for the following attribute is "detect".

spring.output.ansi.enabled=always

Run the application again. Voila! Now you have the color coding enabled on your spring boot application console log.

spring-boot-console-log-with-color

How to Create a Fat Jar Using Maven

Maven is a popular build tool for Java projects. Using Maven it is possible specify all the third party dependencies of a project. During Java compilation, Maven adds these dependency library jars  automatically to the classpath. Maven can also be used to package a project as a distributable jar library. However when you package a project as a jar using maven, the dependent jars are not packaged. This means that in order to run the jar on a different machine, you need to provide all the dependent jars on the classpath.

The advantage of the above approach is that your distributable jars are small. However the downside is that the application won't run without providing the dependencies explicitly on the classpath. This is a problem with many cloud java runtime providers such as Amazon Web Services (AWS lambda) which expect the jar to be self contained with all dependencies.

Luckily Maven provides a plugin named Apache Maven Shade Plugin for creating a distributable jar with all the dependencies. Such a jar is know as a fat jar (also called uber jar) since it is substantially larger than the original. Maven Shade Plugin works by modifying the maven package task.

How to Create a Fat Jar Using Maven

To enable fat jar creation, just add the following xml snippet to your maven pom file. This will ensure that whenever you call the maven package task, all the dependent library code is also added to the generated fat jar.

<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
</build>

Following are the major features of Apache Maven Shade Plugin,

  • It is possible to relocate the dependent classes to avoid conflicts with the environment where the jar is running. Shade plugin rewrites the entire byte code under the relocated package. This ensures that a completely private copy of the dependency jar classes are added to the project!
  • It is possible to filter classes or resources from the dependency jars. This gives fine grained control over how the fat jar is created.
  • Apache maven shade plugin also contains a number of resource transformers for merging resources from several dependency jars. For example, ApacheLicenseResourceTransformer can be used to prevent duplicate license files.
  • Apache maven shade plugin also has support for creating executable jar files.

Example: Generating Fat/Uber Jar Using Shade Plugin

Following is  a simple project which uses Apache commons lang library for string comparison. Following is our main class which uses the third party class StringUtils.

package com.quickprogrammingtips.demo.shadedemo;

import java.util.Scanner;

import org.apache.commons.lang3.StringUtils;

public class App {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Please enter your name: ");
        String name = scanner.nextLine();

        if (StringUtils.isBlank(name)) {
            System.out.println("Sorry, cannot proceed without a name!");
        }else {
            System.out.println("Hello "+name);
        }

        scanner.close();
    }
}

Following is our original pom file for the project. Notice the dependency of commons-lang3 library.

<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.quickprogrammingtips.demo</groupId>
    <artifactId>shadedemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>
    </dependencies>
</project>

To create an ordinary jar, run the following command on the terminal. The jar file is created in the target subfolder.

mvn package

Now try to run our program from the terminal from the console (after switching to target folder),

java -cp shadedemo-0.0.1-SNAPSHOT.jar com.quickprogrammingtips.demo.shadedemo.App

Here is the output of the program,

Please enter your name: QPT

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils

    at com.quickprogrammingtips.demo.shadedemo.App.main(App.java:13)

Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.StringUtils

    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)

    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)

    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

    ... 1 more

Our program throws a runtime exception since it not able to load the commons-lang3 classes. Let us now modify our pom.xnl file to use the apache maven shade plugin,

<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.quickprogrammingtips.demo</groupId>
    <artifactId>shadedemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Run the following command on the terminal to create the distributable fat jar,

mvn package

Now the run program again with the following command. Now the application works without any runtime errors!

java -cp shadedemo-0.0.1-SNAPSHOT.jar com.quickprogrammingtips.demo.shadedemo.App

Please enter your name: QPT

Hello QPT

Apache maven shade plugin also supports executable jar files. Let us modify the pom.xml again to configure an executable jar file,

<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.quickprogrammingtips.demo</groupId>
    <artifactId>shadedemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                    <transformers>
                        <transformer
                            implementation= "org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.quickprogrammingtips.demo.shadedemo.App</mainClass>
                        </transformer>
                    </transformers>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Now you can directly run the jar file without specifying a class name,

java -jar shadedemo-0.0.1-SNAPSHOT.jar

To verify the inclusion of the dependent class files in the fat jar, you can extract the jar and inspect its contents.

contents-of-apache-shaded-jar

What is New in Spring Boot 2.0

Spring Boot 2 is a major upcoming release (scheduled for November 2017) with a number of dependency upgrades. Spring boot requires a more recent version of the following tools and frameworks.

  • Spring Boot 2 requires spring framework 5 or above. Spring framework 5 now requires Java 8 and Java EE 7 API. It also has full compatibility with JDK 9. Spring 5 also requires Tiles 3 and Hibernate 5 (older versions are no longer supported). Spring 5 also introduces a number of features for reactive programming model.
  • Spring Boot 2 requires JDK 8 or later. It won't work on JDK 6 and 7!
  • Spring Boot 2 requires Jetty 9.4 or above, Tomcat 8.5 or above, Hibernate 5.2 or above and Gradle 3.4 or above.

Following are some of the core changes in spring boot platform,

  • The spring security and spring session filters are now auto-configured with ASYNC, ERROR, and REQUEST dispatcher types. This is to align spring boot defaults with spring 5 defaults.
  • The @ConditionalOnBean now uses logical AND for combining conditions (this was OR in spring boot 1.x). This is an important change for spring boot 1.x to 2.x migration.
  • Spring boot 2.x removed support for the CRaSH remote shell since the CRaSH project itself is no longer actively supported.

If you are interested in the upcoming spring boot releases and spring boot roadmap, check out the official milestones page.

How to Generate all Permutations of a String in Java

The following Java program generates all the permutations of a string. It also eliminates any duplicate strings generated. This program can be used to generate anagrams. Note that the following program generates permutations in a case insensitive manner. Hence original case of the input string is not preserved in the permutations.

The following program uses a simple algorithm. We can find a subset of permutations by changing the first character of the string with each character in the string. Now for each of these permutations, we can find another subset by changing the second character of the string with each of the remaining characters. Now for each of these permutations, we can find another subset by changing the third character of the string with each of the remaining characters! We can continue this process until we run out of characters.

The above algorithm can be easily implemented using string operations and recursion. Each time we try to find the permutations of the remaining characters, we also pass the prefix (which includes previous characters and the current character). When we run out of characters, we know that the current prefix is a valid permutation. We simply add it to our unique set of permutations!

To ensure that we get only unique permutations, we are using the Set data structure (which doesn't allow duplicate entries). 

How to Generate All Permutations of a String: Java Source code

import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

// Java program to generate all permutations of a string
public class StringPermutationGenerator {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Please enter a string: ");
        String string = scanner.nextLine();

        Set<String> permutations = generatePermutations(string);

        System.out.println("Here are the unique permutations of " + string);
        System.out.println(Arrays.toString(permutations.toArray()));

        scanner.close();
    }

    // Generate all permutations of a string in Java
    private static Set<String> generatePermutations(String input) {
        input = input.toLowerCase();
        Set<String> result = new HashSet<>();
        permutations("", input, result);
        return result;
    }

    // Recursive function for generating permutations
    // Each call contains the left side of a valid permutation and remaining characters
    private static void permutations(String prefix, String letters, Set<String> result) {
        if (letters.length() == 0) {
            result.add(prefix);
        } else {
            for (int i = 0; i < letters.length(); i++) {
                String letter = letters.substring(i, i + 1);
                String otherLetters = letters.substring(0, i) + letters.substring(i + 1);
                permutations(prefix + letter, otherLetters, result);
            }
        }
    }
}

Here is the sample output from the above program,

Please enter a string: sun
Here are the unique permutations of sun
[usn, nsu, snu, uns, sun, nus]

To change the above program to use case insensitive permutations, comment out the line containing input.toLowerCase.

How to Change Log Level in Spring Boot

Spring boot has no mandatory dependency on any of the logging implementations. Spring boot only depends on commons logging API interface.  Commons logging API is a very thin bridge between logging clients and logging implementations. This enables application and framework writers to decouple application logging from actual logging implementations. Spring boot follows this approach and  uses the jcl-over-slf4j library for commons logging API interface. The enables backward compatibility to commons logging API but at the same time provides all the benefits of the new SLF4J API. This interface can be used to integrate any of the popular logging implementations such as Logback, Log4j2 or JDK logging.

If you are using any of the spring boot starter projects such as spring-boot-starter-web, it has a dependency on spring-boot-starter-logging. This starter library has a dependency on Logback logging library. The SLF4J API detects and configures Logback as the default logging implementation. Logback is considered to be successor to the popular log4j logging framework. Following are some of the benefits of Logback over log4J,

  • Logback is substantially faster than log4j and takes up less memory.
  • Logback has support for automatic reloading of configuration files.
  • With an exhaustive test suite, Logback is considered as a rock solid logging framework. This is very important since a logging framework is used across the application.
  • Logback-classic is a native implementation of the newer SLF4J API.
  • Built-in support for automatic removal of old logs and compression of the archival logs.
  • Built-in support for conditional processing of configuration files.

How to Change Log Level in Spring Boot Applications

The default out of the box logging configuration used by spring boot starter projects prints messages to the console. By default only ERROR, WARN and INFO messages are logged.

If you only want to change the log levels of various packages, you can configure it in the application.properties. For example, the following entries change the log level of all spring framework classes to ERROR and all the classes under the package com.quickprogrammingtips to DEBUG. We also sets the root logger to WARN.

# application.properties values
logging.level.root=WARN
logging.level.org.springframework=ERROR
logging.level.com.quickprogrammingtips=DEBUG

When you run with the above configuration, you will notice that very limited logging output is seen on the console.  This is because we have the root logger to WARN and spring framework classes to ERROR. Following is hierarchy of log levels in commons logging,

ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF

However for fine grained changes to Logback logging configuration, you can add a custom Logback configuration file (logback.xml) to the src/main/resources folder. It will be automatically picked up by spring boot. The following sample file shows how the logging levels can be set without using application.properties,

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<include resource="org/springframework/boot/logging/logback/base.xml" />
	<logger name="org.springframework" level="ERROR" />
	<logger name="root" level="WARN" />
	<logger name="com.quickprogrammingtips" level="DEBUG" />
</configuration>

If you want to use spring boot templating features in logback configuration, create a file named logback-spring.xml instead of logback.xml. Much more complex customization is possible using logback-spring.xml. See spring boot documentation for more details.

How to Use Logging in Spring Boot Application Code

The preferred interface for calling log methods in spring boot is SLF4J API. However you can also use commons logging API. The following classes show how each API can be used for logging. Note that the actual logging implementation is selected based on what is available on the classpath. As mentioned earlier, if you are using starter projects, Logback is default implementation (other options are Log4j2 and JDK logging).

Using SLF4J API for Logging in Spring Boot Application Classes

package com.quickprogrammingtips.springboot;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloWorldController {
    private static final Logger LOG = LoggerFactory.getLogger(HelloWorldController.class);

    @RequestMapping("/hello")
    @ResponseBody
    String home() {
        LOG.info("sending hello world response...");
        return "Hello World!";
    }
}

Using Commons Logging API in Spring Boot Application Classes

package com.quickprogrammingtips.springboot;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloWorld2Controller {
    private static final Log LOG = LogFactory.getLog(HelloWorldController.class);

    @RequestMapping("/hello2")
    @ResponseBody
    String home() {
        LOG.info("sending hello world 2 response...");
        return "Hello World!";
    }
}