A Minimalist Guide to Building Spring Boot Angular 5 Applications

Over the last year, I have worked with many teams using Spring Boot with Angular/React for developing Java web applications. I consider Spring Boot a pragmatic opinionated way to build Spring applications. Spring Boot makes it easy to build web applications in Java and provides a productive environment for development.
Continue reading “A Minimalist Guide to Building Spring Boot Angular 5 Applications”

Advertisements

Keeping Spring Boot Powered REST API Request and Response Objects Minimal

I am a big fan of Spring Boot. It is my preferred choice for building REST APIs in Java. It takes less than 5 minutes(given that you have Maven dependencies on your local machine) to get started with Spring Boot thanks to its auto configuration. In this blog, I will talk about a specific aspect of building REST API with Spring Boot. We will look at the request and response objects. The request object that you receive during the HTTP POST request and response object that you send in the response of HTTP GET request. I will discuss how you can keep these request and response objects to the bare minimum so that we can avoid writing and maintaining useless getters and setters.

Continue reading “Keeping Spring Boot Powered REST API Request and Response Objects Minimal”

JUnit Rule + Java 8 Repeatable Annotations == Clean Tests

Last couple of months I am spending most of my free time writing Docker Java REST API client using RxJava and OkHttp. I have been following TDD for developing this API. Some of the test cases in RxDockerClientTest have to first create a docker container and then they perform other operations. For example, shouldStartCreatedContainer test case will test that API can start a created container. Similarly, there are test cases that need a container. One common solution to achieve this is to use @Before setUp and @After tearDown methods that take care of creating a container before test case is executed and removing the container after test execution. The problem with this solution is that container will be created for every test case in the test class. I only wanted to create a container for test cases that need it. Continue reading “JUnit Rule + Java 8 Repeatable Annotations == Clean Tests”

Let’s master Java 8 Date Time API

So far in this series we have focussed on functional aspects of Java 8 and looked at how to design better API’s using Optional and default and static methods in Interfaces. In this blog, we will learn about another new API that will change the way we work with dates — Date Time API. Almost all Java developers will agree that date and time support prior to Java 8 is far from ideal and most of the time we had to use third party libraries like Joda-Time in our applications. The new Date Time API is heavily influenced by Joda-Time API and if you have used it then you will feel home.

Continue reading “Let’s master Java 8 Date Time API”

Write Infinite FizzBuzz Sequence in Java 8

One way to write FizzBuzz program in Java 8 using Stream API.

Write a program that prints the integers from 1 to 100. But for multiples of three print “Fizz” instead of the number, and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

import java.util.function.IntPredicate;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class FizzBuzz {

    public static void main(String[] args) {
        IntStream numbers = IntStream.iterate(1, el -> el + 1);

        IntPredicate divBy3 = number -> number % 3 == 0;
        IntPredicate divBy5 = number -> number % 5 == 0;
        IntPredicate divBy3And5 = divBy3.and(divBy5);

        Stream<String> fizzBuzzStream = numbers
                .mapToObj(String::valueOf)
                .map(number -> parse(number, divBy3And5, () -> "FizzBuzz"))
                .map(number -> parse(number, divBy3, () -> "Fizz"))
                .map(number -> parse(number, divBy5, () -> "Buzz"));

        fizzBuzzStream.limit(30).forEach(System.out::println);
    }

    private static String parse(String numberStr, IntPredicate predicate, Supplier<String> supplier) {
        try {
            int number = Integer.parseInt(numberStr);
            if (predicate.test(number)) {
                return supplier.get();
            }
            return String.valueOf(number);
        } catch (NumberFormatException e) {
            return numberStr;
        }
    }
}

The above program will run into integer overflow. You can use BigInteger to overcome that as shown below.

import java.math.BigInteger;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class FizzBuzzBigInteger {

    public static void main(String[] args) {
        BigInteger one = BigInteger.ONE;
        Stream<BigInteger> numbers = Stream.iterate(one, el -> el.add(one));

        Predicate<BigInteger> divBy3 = number -> number.remainder(BigInteger.valueOf(3)) == BigInteger.ZERO;
        Predicate<BigInteger> divBy5 = number -> number.remainder(BigInteger.valueOf(5)) == BigInteger.ZERO;
        Predicate<BigInteger> divBy3And5 = divBy3.and(divBy5);

        Stream<String> fizzBuzzStream = numbers
                .map(String::valueOf)
                .map(number -> parse(number, divBy3And5, () -> "FizzBuzz"))
                .map(number -> parse(number, divBy3, () -> "Fizz"))
                .map(number -> parse(number, divBy5, () -> "Buzz"));

        fizzBuzzStream.limit(100).forEach(System.out::println);
    }

    private static String parse(String numberStr, Predicate<BigInteger> predicate, Supplier<String> supplier) {
        try {
            BigInteger number = new BigInteger(numberStr);
            if (predicate.test(number)) {
                return supplier.get();
            }
            return numberStr;
        } catch (NumberFormatException e) {
            return numberStr;
        }
    }
}

The better and more functional approach suggested(in the comments) by Dominic is shown below.

import java.math.BigInteger;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class Fizzbuzz {

    public static void main(String[] args) {
        BigInteger one = BigInteger.ONE;

        Predicate<BigInteger> divBy3 = number -> Objects.equals(number.remainder(BigInteger.valueOf(3)), BigInteger.ZERO);
        Predicate<BigInteger> divBy5 = number -> Objects.equals(number.remainder(BigInteger.valueOf(5)), BigInteger.ZERO);
        Predicate<BigInteger> divBy3And5 = divBy3.and(divBy5);

        Stream<BigInteger> numbers = Stream.iterate(one, el -> el.add(one));

        Stream<String> fizzBuzzStream = numbers
                .map(FizzBuzzMatcher.matching(divBy3And5, () -> "FizzBuzz")
                        .otherwise(FizzBuzzMatcher.matching(divBy3, () -> "Fizz")
                                .otherwise(FizzBuzzMatcher.matching(divBy5, () -> "Buzz")
                                        .otherwise(BigInteger::toString))));

        fizzBuzzStream.limit(100).forEach(System.out::println);
    }
}

interface FizzBuzzMatcher extends Function<BigInteger, Optional<String>> {

    static FizzBuzzMatcher matching(Predicate<BigInteger> matcher, Supplier<String> resultMsgSupplier) {
        return number -> matcher.test(number) ? Optional.of(resultMsgSupplier.get()) : Optional.empty();
    }

    default Function<BigInteger, String> otherwise(Function<BigInteger, String> next) {
        return number -> apply(number).orElseGet(() -> next.apply(number));
    }
}

Word count example in Java 8

Following code snippet shows how you can write a word count program using Java 8 Stream API.

public class WordCountExample {

    public static void main(String[] args) throws IOException {
        Path path = Paths.get("src/main/resources/book.txt");
        Map<String, Integer> wordCount = Files.lines(path)
           .flatMap(line -> Arrays.stream(line.trim().split(" ")))
           .map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
           .filter(word -> word.length() > 0)
           .map(word -> new SimpleEntry<>(word, 1))
           .sorted((e1, e2) -> e1.getKey().compareTo(e2.getKey()))
            .reduce(new LinkedHashMap<>(), (acc, entry) -> {
               acc.put(entry.getKey(), acc.compute(entry.getKey(), (k, v) -> v == null ? 1 : v + 1));
               return acc;
            }, (m1, m2) -> m1);

        wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
    }
}

The better solution is using toMap collector as shown below.

public static void main(String[] args) throws IOException {
   Path path = Paths.get("src/main/resources/book.txt");
   Map<String, Integer> wordCount = Files.lines(path).flatMap(line -> Arrays.stream(line.trim().split("s")))
           .map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
           .filter(word -> word.length() > 0)
           .map(word -> new SimpleEntry<>(word, 1))
           .collect(toMap(e -> e.getKey(), e -> e.getValue(), (v1, v2) -> v1 + v2));

   wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
}

Even better version can be written using grouping and counting collector as shown below.

public static void main(String[] args) throws IOException {
    Path path = Paths.get("src/main/resources/book.txt");
    Map<String, Long> wordCount = Files.lines(path).flatMap(line -> Arrays.stream(line.trim().split("\s")))
            .map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
            .filter(word -> word.length() > 0)
            .map(word -> new SimpleEntry<>(word, 1))
            .collect(groupingBy(SimpleEntry::getKey, counting()));

    wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));

}