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)));

}

GSON tip: @JsonProperty equivalent

Jackson has a very useful annotation @JsonProperty that gives developer the option to provide a name that will be used to map data from JSON to the value object. This is very useful when REST API you are interacting with does not follow conventions like some fields are caps, some camel case, and other using underscore. Today, I had a similar need but I was working with GSON library instead of Jackson. The solution in Gson is a similar annotation called @SerializedName that you can use to provide names that match the source JSON. A simple example is shown below.

public class Message{
    @SerializedName("ID")
    private String id;
    @SerializedName("NFd")
    private int fileDescriptors;
}

Gson Tip: Using a different FieldNamingPolicy

Today, while write a client for a REST API I had the need to use a different field naming strategy than the default one. By default, when Gson tries to convert a JSON String to an object it expects field names in JSON to be same as field name in the converting object. For example, you can convert following JSON String to Message object as shown below.

{
"message": "hello world!"
}
public class Message{
private String message;
// setters and getters
}

To convert to message JSON to Message object you can use following code.

// String json
Message message = new Gson().fromJson(json, Message.class);

This will not work if JSON has different naming policy(first letter upper case) as shown below.

{
"Message": "hello world!"
}

To make it work, you can use GsonBuilder to create Gson with UPPER_CAMEL_CASE as field naming policy. This is shown below.

Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
Message message = gson.fromJson(json, Message.class);

Day 4 — Let’s write Null free Java code

Every Java developer whether beginner, novice, or seasoned has in his/her lifetime experienced NullPointerException. This is a true fact that no Java developer can deny. We all have wasted or spent many hours trying to fix bugs caused by NullPointerException. According to NullPointerException JavaDoc, NullPointerException is thrown when an application attempts to use null in a case where an object is required.. This means if we invoke a method or try to access a property on null reference then our code will explode and NullPointerException is thrown. You can follow the 7 Days with Java 8 series at https://shekhargulati.com/7-days-with-java-8/ Continue reading “Day 4 — Let’s write Null free Java code”

Day 2 — Let’s learn about Streams

On day 1, we learnt how lambdas can help us write clean concise code by allowing us to pass behavior without the need to create a class. Lambdas is a very simple language construct that helps developer express their intent on the fly by using functional interfaces. The real power of lambdas can be experienced when an API is designed keeping lambdas in mind i.e. a fluent API that makes use of Functional interfaces(we discussed them on day 1). Continue reading “Day 2 — Let’s learn about Streams”

Java EE7 Development and Hosting on OpenShift with Wildfly: Part 1

This is the first blog post in a series where I will cover how to build web applications in Java using Java EE 7. Java EE 7 is the latest release of the Java Enterprise Platform, with a focus on HTML 5 and developer productivity.

Java EE 7 introduced five new specifications covering WebSockets (JSR-356), JSON Processing (JSR-353), Batch Applications (JSR-352), Concurrency Utilities (JSR-236), and Caching (JSR-107). Apart from these new specifications, three existing specifications (JAX-RS 2.0JMS 2.0, and EL 3.0) have major updates and a few other specifications have minor updates. We will cover most of these specifications in detail in this blog post series.

Read full blog here https://www.openshift.com/blogs/java-ee7-development-and-hosting-on-openshift-with-wildfly-part-1

Developing Single Page Web Applications using Java 8, Spark, MongoDB, and AngularJS

In this post you will learn how to use a micro framework called Spark to build a RESTful backend. The RESTful backend is consumed by a single page web application using AngularJS and MongoDB for data storage. I’ll also show you how to run Java 8 on OpenShift. Read the full blog here https://www.openshift.com/blogs/developing-single-page-web-applications-using-java-8-spark-mongodb-and-angularjs

How to build Java WebSocket Applications Using the JSR 356 API

It is a well known fact that HTTP(Hypertext Transfer Protocol) is a stateless request-response protocol. This simple design of the HTTP protocol makes it very scalable but inefficient and unsuitable for highly interactive real-time web applications. HTTP was designed for document sharing and not for building today’s highly interactive web applications. HTTP is bit chatty in nature, as for each http request/response, a lot of headers need to be transmitted over the wire.

Before the HTTP 1.1 version, every request made to the server resulted in a new connection. This was improved in HTTP 1.1 with the introduction of HTTP persistence connections. Persistent connections allowed web browsers to reuse the same connection for fetching images, scripts, etc.

HTTP was designed to be half-duplex which means it allows transmission of data in just one direction at a time. A Walkie-talkie is an example of a half duplex device because only one person can speak at a time. Developers have created some workarounds or hacks to overcome this HTTP shortcoming. Some of these workarounds are polling, long polling, and streaming.

You can read full post at https://www.openshift.com/blogs/how-to-build-java-websocket-applications-using-the-jsr-356-api

Spring Test Failing with A ServletContext is required to configure default servlet handling

If you are getting exception shown below in your Spring test

Caused by: java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.(DefaultServletHandlerConfigurer.java:54)
at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:330)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$c733f512.CGLIB$defaultServletHandlerMapping$22()
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$c733f512$$FastClassByCGLIB$$b76778f9.invoke()
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:285)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$c733f512.defaultServletHandlerMapping()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:160)

Then to fix this error migrate to Spring 3.2 release. Change the maven dependency as shown below

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>3.2.0.RELEASE</version>
</dependency>

IBM DeveloperWorks Spring Roo Part 5 : Writing Advanced and Wrapper Addons

Today fifth part of my Spring Roo series got published at IBM DeveloperWorks. This article-cum-tutorial talks about how you can write advanced and wrapper Spring Roo add-ons. Checkout the article at http://www.ibm.com/developerworks/opensource/library/os-springroo5/index.html