Saturday, October 14, 2017

Deploy Java Web Application on Heroku with Heroku CLI

This post will describe how to create and deploy a Java Web Application war to Heroku using Heroku CLI. You will need a basic understanding of Git and Maven, and have Git and Maven already installed on your system.
Pre-requisites
  • Install Java 8, Maven and Git. For this post, I used Java 8 and Maven 3.5.
  • Create a free account on heroku.com. This account will be used from Heroku CLI to login
  • Download and Install Heroku CLI from here.
Following are the high-level steps to follow
  1. Create a Simple Spring Web Application.
  2. Create an application on Heroku
  3. Create the Procfile
  4. Create app.json
  5. Update Maven pom.xml
  6. Push code to Heroku

Sunday, October 08, 2017

Jenkins Offline Install on Red Hat Enterprise Linux Server

In this post we will see how to do an offline install Jenkins and required plugins on a Red Hat Enterprise Linux Server release 7.3. This is likely the case when your server is behind a firewall. But you have access to internet from your workspace. The assumption here is that you have sudo access on the server to do the install. Follow these steps...

Build Git From Source Code on Red Hat Enterprise Linux Server

Redhat Enterprise Linux provides Redhat Developer Toolset, which allows you to install Git. However, it is usually an older version. If you want the latest version of Git on your Server, then building Git from sources is the easiest way. Follow these steps to install Git from sources on Red Hat Enterprise Linux Server release 7.3. On our server, the following commands were run by the root user.

Saturday, October 07, 2017

Weblogic Remote Deploy from Red Hat Enterprise Linux Server: Unknown object in LOCATE_REQUEST

Recently I was attempting to deploy to weblogic from a Jenkins installed on a Red Hat Enterprise Linux Server release 7.3, to a remote Weblogic 12.1.3 cluster. Which was failing with a org.omg.CORBA.OBJECT_NOT_EXIST. Eventually, I ended up trying to do a manual deploy using the ANT task wldeploy, with the following command
 ant -lib /apps/wls12130/wlserver/server/lib deploy -Dweblogic.user=adminuser -Dweblogic.password=adminpassword -Dadminurl=t3://admin-server:admin-port -Dweblogic.cluster=ClusterName
As you can see from the command, we are passing command-line arguments which specify the location and credentials for the remote cluster. On the Linux machine to with the [wldeploy] Caused by: javax.naming.NamingException: Couldn't connect to the specified host [Root exception is org.omg.CORBA.OBJECT_NOT_EXIST: Unknown object in LOCATE_REQUEST vmcid: 0x0 minor code: 0 completed: No] error. Following is the full stacktrace, followed by a cause and resolution to this problem...

Wednesday, October 04, 2017

Java 9: Reactive programming with Flow API

In a previous post about Reactive programming with Java 8, we looked into reactive programming support by Reactor. Java 9 introduced reactive programming in Java with the Flow API. In this post, we will look at how the various components in the Flow API work with a few examples.

Tuesday, October 03, 2017

Java 9 : Private interface methods

Java 8 introduced default and static methods, the previous post gives a few examples of Java 8 default and static methods. Java 9 builds on that foundation and adds support for private interface methods. In this post, we will see a simple example of how to use private methods to interfaces. In general,
  1. Like any private method, private interface methods are accessible from within the enclosing interface only.
  2. Private methods can be declared using the private keyword.
  3. Any private method has to be implemented in the interface as it cannot implemented in a sub-interface or implementing classes.

Java 8 Interfaces: default and static methods

Java 8 introduces default static methods that enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces. While both static and default methods allow to add method implementations to interfaces, the difference is that you cannot override static methods. Both default and static methods are "public", and there is no need to explicitly declare them as public.

Monday, October 02, 2017

Java 9 Date Time API Changes

Java 9 added a few enhancements to the new Date and Time API which was introduced in Java 8. We will go over a few of these additions to LocalDate and LocalTime in this post
  • Stream<LocalDate> datesUntil​(LocalDate endExclusive) // LocalDate
  • public Stream<LocalDate> datesUntil​(LocalDate endExclusive, Period step) //LocalDate
  • public long toEpochSecond​(LocalTime time, ZoneOffset offset) //LocalDate
  • toEpochSecond​(LocalDate date, ZoneOffset offset) //LocalTime

Friday, September 29, 2017

Java 8 Date Time API: LocalTime

With Java 8 Oracle introduced new Date and Time APIs which address the shortcomings of the existing java.util.Date and java.util.Calendar. In this article we will take a look at the Java 8 Date and Time API with few examples of the new LocalTime class introduced by Java 8.

Improvements to Existing Calendar and Date Classes

Thread Safety: The existing API was not designed with concurrency in mind. This meant developers had to come up with custom solutions to handle thread safety. The Java 8 Date/Time API ensures thread safety by making all the new classes immutable. Domain-driven design: The Java 8 date/time API has clear domain boundaries, and defines classes with specific use cases. Support for non-standard Calendars: The Java 8 Date/Time API provides support for non-standard calendaring systems (Japanese calendar for example) without affecting the standard calendar implementation.

Java 8 Date And Time API:Time Zones

In the previous three posts, we took a detailed look at the Java 8 Local Date and Time classes. In this post, we will take a look at the Java 8 provides ZonedDateTime and OffsetDateTime classes.

ZonedDateTime

ZonedDateTime uses ZoneId to represent different time zones. The following example shows how to create a ZoneId for Chicago
ZoneId zoneId = ZoneId.of("America/Chicago");
Following piece of code shows how to obtain a list of all zone ids.
Set zoneIdList = ZoneId.getAvailableZoneIds();
There are many ways to instantiate ZonedDateTime, most of them parallel LocalDateTime as shown in the previous post, with the addition of Zone Id.
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
ZonedDateTime.parse("2015-05-03T10:15:30+01:00[America/Los_Angeles]");
Truncate Time from ZonedDateTime
The truncateTo() method can be used to truncate the time fields. Any Time Unit lesser than the passed parameter will be marked to zero.
// Anything under days is set to zero. Works only for time.
System.out.println(zonedDateTime + " Truncated to  " + zonedDateTime.truncatedTo(ChronoUnit.HOURS));
Convert Time Zone
Converting time from one timezone to another is one of the common requirements. The method of ZonedDateTime can be used to convert a given ZonedDateTime to any timzone. The following example can be used to convert the current time in Chicago timezone to time in Los_Angeles
// Convert Time Zone
System.out.println(zonedDateTime + " in Los Angeles " + zonedDateTime.withZoneSameInstant(ZoneId.of("America/Los_Angeles")));
ZonedDateTime also offers many of the same utility methods offered by LocalDateTime. A few examples are shown below
System.out.println("3 days before today is : " + zonedDateTime.minus(3, ChronoUnit.DAYS));
System.out.println("3 decades before today is : " + zonedDateTime.minus(3, ChronoUnit.DECADES));
System.out.println("3 days after today is : " + zonedDateTime.plus(3, ChronoUnit.DAYS));
System.out.println("3 decades after today is : " + zonedDateTime.plus(3, ChronoUnit.DECADES));

System.out.println("The day of the week is : " + zonedDateTime.getDayOfWeek());
System.out.println("The day of the year is : " + zonedDateTime.getDayOfYear());

OffsetDateTime

OffsetDateTime class can be used to represent DateTime with an Offset. This class stores all date and time fields, to a precision of nanoseconds, as well as the offset from UTC/Greenwich. For example, the value "2nd October 2007 at 13:45.30.123456789 +02:00" can be stored in an OffsetDateTime. OffsetDateTime can be created in the following ways.
// Now
OffsetDateTime offsetDateTime = OffsetDateTime.now();
System.out.println("OffsetDateTime : " + offsetDateTime);

// Get LocalDateTime and apply Offset
LocalDateTime localDateTime = LocalDateTime.of(2017, Month.SEPTEMBER, 29, 5, 30);
ZoneOffset offset = ZoneOffset.of("+02:00");

OffsetDateTime offSetByTwo = OffsetDateTime.of(localDateTime, offset);
System.out.println(localDateTime + " Offset by two " + offSetByTwo);

Full code for this post

import java.time.LocalDateTime;
import java.time.Month;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

public class ZonedDateTimeExamples {

 public static void main(String[] args) {
  ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("America/Chicago"));
  System.out.println(zonedDateTime);

  // Convert Time Zone
  System.out
    .println(zonedDateTime + " in Los Angeles " + zonedDateTime.withZoneSameInstant(ZoneId.of("America/Los_Angeles")));

  // Anything under days is set to zero. Works only for time.
  System.out.println(zonedDateTime + " Truncated to  " + zonedDateTime.truncatedTo(ChronoUnit.HOURS));

  System.out.println("3 days before today is : " + zonedDateTime.minus(3, ChronoUnit.DAYS));
  System.out.println("3 decades before today is : " + zonedDateTime.minus(3, ChronoUnit.DECADES));
  System.out.println("3 days after today is : " + zonedDateTime.plus(3, ChronoUnit.DAYS));
  System.out.println("3 decades after today is : " + zonedDateTime.plus(3, ChronoUnit.DECADES));

  System.out.println("The day of the week is : " + zonedDateTime.getDayOfWeek());
  System.out.println("The day of the year is : " + zonedDateTime.getDayOfYear());

  // Now
  OffsetDateTime offsetDateTime = OffsetDateTime.now();
  System.out.println("OffsetDateTime : " + offsetDateTime);

  // Get LocalDateTime and apply Offset
  LocalDateTime localDateTime = LocalDateTime.of(2017, Month.SEPTEMBER, 29, 5, 30);
  ZoneOffset offset = ZoneOffset.of("+02:00");

  OffsetDateTime offSetByTwo = OffsetDateTime.of(localDateTime, offset);
  System.out.println(localDateTime + " Offset by two " + offSetByTwo);

 }

}

Java 8 Date And Time API: LocalDate

With Java 8 Oracle introduced new Date and Time APIs which address the shortcomings of the existing java.util.Date and java.util.Calendar. In this article we will take a look at the Java 8 Date and Time API with few examples of the new LocalDate class introduced by Java 8.

Improvements to Existing Calendar and Date Classes

Thread Safety: The existing API was not designed with concurrency in mind. This meant developers had to come up with custom solutions to handle thread safety. The Java 8 Date/Time API ensures thread safety by making all the new classes immutable. Domain-driven design: The Java 8 date/time API has clear domain boundaries, and defines classes with specific use cases. Support for non-standard Calendars: The Java 8 Date/Time API provides support for non-standard calendaring systems (Japanese calendar for example) without affecting the standard calendar implementation.

Java 8 Date Time API: LocalDateTime

With Java 8 Oracle introduced new Date and Time APIs which address the shortcomings of the existing java.util.Date and java.util.Calendar. In this article we will take a look at the Java 8 Date and Time API with few examples of the new LocalDateTime class introduced by Java 8.

Improvements to Existing Calendar and Date Classes

Thread Safety: The existing API was not designed with concurrency in mind. This meant developers had to come up with custom solutions to handle thread safety. The Java 8 Date/Time API ensures thread safety by making all the new classes immutable. Domain-driven design: The Java 8 date/time API has clear domain boundaries, and defines classes with specific use cases. Support for non-standard Calendars: The Java 8 Date/Time API provides support for non-standard calendaring systems (Japanese calendar for example) without affecting the standard calendar implementation.

Java 9 Streams : dropWhile()

In Java 9, comes with a few good additions to the Stream API. For more information on the Java 8 Streams, go to the Java 8 Page. The following new methods were added to the Java 9 Stream API.
  1. dropWhile
  2. dropWhile
  3. iterate
  4. ofNullable
In this post we will take a look at the dropWhile() method.

Thursday, September 28, 2017

Java 9 Streams: iterate() and ofNullable() methods

In Java 9, comes with a few good additions to the Stream API. For more information on the Java 8 Streams, go to the Java 8 Page. The following new methods were added to the Java 9 Stream API.
  1. dropWhile
  2. dropWhile
  3. iterate
  4. ofNullable
In this post we will take a look at the iterate() and ofNullable() methods.

Wednesday, September 27, 2017

Java 9 Streams : takeWhile() method

In Java 9, comes with a few good additions to the Stream API. For more information on the Java 8 Streams, go to the Java 8 Page. The following new methods were added to the Java 9 Stream API.
  1. takeWhile
  2. dropWhile
  3. iterate
  4. ofNullable
In this post we will take a look at the takeWhile() method.

Monday, September 25, 2017

Setup Java 9 in Eclipse Oxygen

This post gives the quick steps to setup Eclipse Oxygen with Java 9. This relies on Java™ 9 support for Eclipse JDT is available now. At this time, the it is not fully functional, and I have faced a couple of issues setting this up. Full support for Java 9 is expected on October 11, 2017 with Oxygen 1a release. Follow these steps to install the support for Java 9.

Sunday, September 24, 2017

Using Comparators with Java 8 Streams

This post gives a few examples of how to use Comparator with Java 8 streams to Sort and to find the Maximum and Minimum elements in a stream.

Comparing Simple types with Comparator.comparing* methods

The Comparator.comparingDouble, Comparator.comparingInt and Comparator.comparingLong etc. methods can be used to do sorting or finding max and min from stream. The following example uses the comparingDouble method to compare and sort a stream of doubles generated using the Stream.generate() method. The Stream.generate has been explained my earlier post "Java 8 Streams"
  // Sort a stream of Doubles
  Stream.generate(Math::random).limit(10).sorted(Comparator.comparingDouble(Double::valueOf)).forEach(System.out::println);

Monday, September 18, 2017

Auto-Restart Spring Boot Application On Code Change With Dev Tools

Spring Boot Dev Tools enables auto-restarting a Spring boot application whenever any class is changed in the class path. This is not comparable in speed with the hot swap functionality offered by Jrebel or Spring Loaded, but this is a very simple and easy way to implement and better than manual restart. In this post, I use a simple Spring boot rest echo service to demonstrate how spring boot dev tools can be used to auto restart the application when using Maven on an IDE or Gradle from command line. In either options, the main trigger for a restart is the change to a class file, which means that the change to a Java file has to be compiled either by the IDE in option 1 or by Gradle in option 2.

Monday, September 11, 2017

Passing System Properties and Arguments With Gradle

When using the Gradle application plugin, Gradle spawns a new JVM on the fly, and does not pass the System Properties or Command-line arguments to the new Java process. This post explains how to pass the System properties and command-line arguments when using Gradle application plugin.

Sunday, September 10, 2017

Load Environment Specific Properties Files Using Spring

One of the more common aspects of enterprise application development involves environment specific properties files. Some examples include Database configurations or external JMS resources etc. The common way to address this problem is to use multiple properties file an build the Application EAR/WAR/JAR at compile time. Although this works, this solution also means that we maintain different build scripts for different environments, or having some file renames etc. while building the application. Spring profiles address this problem in a more efficient way. Like any other property, using Spring profiles, we can inject the environment profile into Spring and Spring will handle the loading of the appropriate configuration files. In this post, I show how to load environment specific properties files using Spring.

Thursday, September 07, 2017

Merge and Paginate PDF files using iText 5

In this post we will see a way to merge multiple PDF files while adding page numbers at the bottom of each page in the format Page 1 of 10. The following steps give a brief description of the steps used to merge and add page number to the merged PDF.

Wednesday, September 06, 2017

Merge PDF files using iText 5

This is an example code for a simple PDF merge using iText 5. We use three InputStreams in a List as input and merged file is written to the file system.

Monday, September 04, 2017

WatchService to monitor Directories for changes

There a many scenarios where you would like to monitor a directory for new files, or changes to existing files or deleted files. Some of the use cases are
  • Files will be dropped into a directory by a third party which have to be processed by your application
  • A file editor which monitors the directory to make sure the files currently being edited are not modified by another concurrent user.
  • You want to start a build and deploy code whenever a source file is changed (In an enterprise application, this is usually done in a source control in conjunction with a tool like Jenkins).
Starting Java 7, the new java.nio.file.WatchService provides a scalable solution to monitor directory for any changes. In this post, we will go over the features of the WatchService service and a simple example for how to monitor a directory for changes and print the name of the file that was affected.

Friday, September 01, 2017

Directory Listing in Java

This post provides a examples of a few ways to list contents of a directory in Java. A couple of examples of how to recursively traverse a directory are also provided. Finally we will see the use of Files.walk() and Files.find() introduced in Java 8, which makes directory traversal even more simple.

Thursday, August 31, 2017

Java 8 Stream collect()

In Java 8 Streams, the collect() method is a terminal operation, which can be used collect elements of a stream into a list or group them into a Map etc. collect method takes java.util.stream.Collector as parameter. While you can create your own collector by implementing the java.util.stream.Collector interface, the more common way to instantiate a Collector is through the use of Collectors class. The following examples demonstrate a few ways to use the collect() method with different types of Collectors.

Wednesday, August 30, 2017

Java 8 Streams flatMap()

In Java 8 Stream API, flatMap() method is an intermediate functions for streams, in that, it will produce a final result but used to apply transformations on the elements of a Stream. It is possible to to chain multiple flatMap() while processing a single stream. Both map() and flatMap() both can be applied to a Stream<T> and return a Stream<R> or transformed elements, but the main difference is that map() produces one output element for each input element, whereas flatMap() produces any number (0-n) of output elements for each input element. Put simply, when using a map(), the resulting stream would have same number or elements as the input stream, where as it can be different in case of a flatMap(). The following example illustrates the differences the use of flatMap()

Monday, August 28, 2017

Java 8 Streams map()

In Java 8 Streams, map() is an intermediate function that can be used to apply a function to every element of a Stream. A few variations of map() include mapToInt(), mapToLong etc. which return streams of the corresponding types. The following examples show a few ways to use the map() function on streams.

Sunday, August 27, 2017

Java 8 Streams : map vs flatMap

In Java 8 Stream API, map and flatMap methods are provided as part of the java.util.stream.Stream Interface. Both methods are intermediate functions for streams, in that, they do not produce a final result but are used to apply transformations on the elements of a Stream. It is possible to to chain multiple map() and flatMap() while processing a single stream.

Saturday, August 26, 2017

Java 8 Streams

Java 8 Streams API provide a declarative way to process sequence of data elements. A stream can be a sequence of elements from a collection, a I/O channel or a generator function. To process a stream, a set of operations are composed into a pipeline. A stream pipeline consists of a Source (data stream), one or more intermediate operations (apply transformations on the stream) and a terminal operation that produces a result or a side-effect. The following example (from the Stream javadoc), has one source (widgets), two intermediate operations (filter and mapToInt) and a terminal operation (sum).
  int sum = widgets.stream() // Source
                    .filter(w -> w.getColor() == RED) // Intermediate operation
                    .mapToInt(w -> w.getWeight())  //Intermediate operation
                    .sum();  // Terminal operation, produces result
In this article, we will go over the basics of streams and how to create or initialize the source for a stream pipeline.

Sunday, July 23, 2017

Reactor: Reactive Programming Java 8

One of the more interesting features in the upcoming release of Java 9 is the support for Reactive Programming in Java. At a high-level Reactive programming deals with asynchronous data streams. Reactive streams provides a standard for asynchronous stream processing. Java 9 supports Reactive programming implementing the Reactive Streams specification through the Flow API. But before the release of Java 9, there are ways to implement Reactive programming in Java 8. Reactor and RxJava are a couple of APIs to implement Reactive streams in Java 8. Reactor is used internally by the Spring Framework to it's own Reactive support in version 5. In this post, we will look into Reactor library.

Monday, July 10, 2017

Mybatis Spring Integration

This post will give a quick introduction into integrating MyBatis and Spring with a very basic application. I will describe only the integration using XML based configuration. As always with MyBatis, this starts with setting up SqlSessionFactory from Spring. Instead of configuring the datasource and mapping in mybatis-config.xml, all configuration will be setup in Spring configuration. The only additional configuration will be the Mapper.xml file.

Sunday, July 09, 2017

Spring Standalone Application Setup with Gradle

This post is a continuation of the Spring Standalone Application post. In this post I will go over the application setup and the Gradle build file used for building the project. The assumption here is that Gradle is already installed on the machine and ready to use. For instructions on how to install Gradle please go the Gradle installation page.

Continue to full post ...

Application Setup

Following is the directory structure I had for this project. In case of the Annotation based approach, you don't need the resources folder.

+---SpringStandalone
    |   build.gradle
    |               
    \---src
        +---main
        |   \---java
        |       +---main
        |       |       SpringStandaloneTest.java
        |       |       
        |       \---service
        |               TestService.java
        |   \---resources
        |           applicationContext.xml
        |               
        \---test
            \---java

Gradle Build File: Gradle Application Plugin

The Gradle Application plugin is very useful for creating Standalone applications that can be run using gradle run. By default, the Gradle Application plugin applies the java plugin and Distribution plugin. You can configure the main class and any JVM arguments that you may want to pass to the application. To pass the main class name, you can use the mainClassName parameter like below

mainClassName = "main.SpringStandaloneTest"
And to pass any JVM arguments to the application, you can use applicationDefaultJvmArgs as shown below
applicationDefaultJvmArgs = ["-Dprop=val"]
And here is the full build.gradle file I used for the spring standalone application
apply plugin:'application'
mainClassName = "main.SpringStandaloneTest"
applicationName = 'SpringStandalone'

repositories {
    jcenter()
}

dependencies {
  compile group: 'org.springframework', name: 'spring-core', version: '4.3.9.RELEASE'
 compile group: 'org.springframework', name: 'spring-context', version: '4.3.9.RELEASE'
 compile group: 'org.springframework', name: 'spring-beans', version: '4.3.9.RELEASE'
 compile group: 'org.springframework', name: 'spring-tx', version: '4.3.9.RELEASE'
 compile group: 'org.springframework', name: 'spring-orm', version: '4.3.9.RELEASE'

    // Use JUnit test framework
    compile 'junit:junit:4.12'
}


applicationDefaultJvmArgs = ["-Dprop=val"]

Standalone Spring Application

Having a basic spring standalone application ready always helps when you want to do a quick POC or test of new libraries or tools you plan to use. This post shows a couple of ways in which you can setup a basic Spring standalone application.

  • Spring Standalone application with ApplicationContext XML Configuration file.
  • Spring Standalone application with Annotations

Continue to full post...

For this application I will use a simple service class TestService that has a single method echo(), which returns the Upper case version of any string passed as a parameter. The TestService class will be used a component to be injected into the main application class.

Spring Standalone application with ApplicationContext XML Configuration file

In this model we have 4 files

  1. SpringStandaloneTest.java
  2. TestService.java
  3. applicationContext.xml
  4. build.gradle (will go over the gradle build in the next post)
Following are the files used for this application

SpringStandaloneTest.java
package main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import service.TestService;

public class SpringStandaloneTest {

 public static void main(String[] args) {
  ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  SpringStandaloneTest test = ctx.getBean("springStandalone", SpringStandaloneTest.class);
  test.callService();

 }

 private TestService testService = null;

 private void callService() {
  System.out.println(testService.echo("Hello"));

 }

 public TestService getTestService() {
  return testService;
 }

 public void setTestService(TestService testService) {
  this.testService = testService;
 }

}
TestService.java
package service;

public class TestService {
 
 public String echo(String str) {
  return str.toUpperCase();
 }

}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

 <bean name="testService" class="service.TestService" />
 <bean name="springStandalone" class="main.SpringStandaloneTest">
  <property name="testService" ref="testService"></property>
 </bean>

</beans>

Spring Standalone application with Annotations

In this model, we will setup the standalone application with annotations instead of the applicationContext.xml file. The annotation @Component is used to define a class as a Spring component, so that Spring can detect it as a Spring bean. The @ComponentScan is used to direct Spring where to look for Components. It is similar to the directive when using Spring XML configuration. The following is the code used to implement the Standalone Spring application using annotations.

SpringStandaloneTest.java
package main;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import service.TestService;

@ComponentScan(basePackages= {"main", "service"})
public class SpringStandaloneTest {

 public static void main(String[] args) {
  ApplicationContext context = new AnnotationConfigApplicationContext(SpringStandaloneTest.class);

  SpringStandaloneTest test = context.getBean(SpringStandaloneTest.class);
  test.callService();
  
 }

 @Autowired
 private TestService service = null;

 private void callService() {
  System.out.println(service .echo("Hello"));

  
 }

}
TestService.java
package service;

import org.springframework.stereotype.Component;

@Component
public class TestService {
 
 public String echo(String str) {
  return str.toUpperCase();
 }

}
In the next post I will describe the Gradle build setup used for this standalone application.

Saturday, July 08, 2017

AsynchronousFileChannel

Java 7 AsynchronousFileChannel is an asynchronous channel for reading and writing to files asynchronously. In this post, we will look into a few operations on AsynchronousFileChannel.

  • Read from a file using Future
  • Read from File using CompletionHandler
  • Write to File using Future
  • Write to file using CompletionHandler
One thing common to all the operations will be the position within the file. Since we are working asynchronously, there is no current position, and the position where you want to read or write has to be sent with each call.

Continue to full post...

An AsynchronousFileChannel can be created using the open method. This static method takes the Path and the type of operations (READ, WRITE etc.) as paramters

Reading Data with Future

Following is the read() method that returns a Future.

Future operation = fileChannel.read(buffer, 0);
The data from the file is read into the ByteBuffer parameter starting at the beginning of the file. Since this is an asynchronous call, the read() method will return immediately, even if the read is not completed. To check if the read wheter the read operation completed, you can call the isDone() on the returned Future object.
In the following program, we try to read from a file and wait till the read is complete. Although this is not an ideal use case, it will demonstrate how to use the "Read with Future" feature.
package nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class AsyncFileChannelTest {
    public static void main(String[] args) {
        Path path = Paths.get("C:/test/data.csv");
        AsynchronousFileChannel fileChannel = null;
        try {
            fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            long position = 0;

            StringBuffer fileData = new StringBuffer();

            Future operation = fileChannel.read(buffer, position);
            // Future returns -1 if End of File is reached.
            while (operation.get() > 0) {
                while (!operation.isDone())
                    ;
                // Switch ByteBuffer from read to write mode
                buffer.flip();

                byte[] data = new byte[buffer.limit()];
                buffer.get(data);

                fileData.append(new String(data));

                buffer.clear();
                // Update to new read position.
                position = position + operation.get();
                operation = fileChannel.read(buffer, position);
            }
            System.out.println(fileData);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}


Reading with CompletionHandler

This version of the read() operation takes a CompletionHandler as a parameter.

package nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class AsyncFileChannelTest {
    public static class MyCompletionHandler 
            implements CompletionHandler {
        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            // TODO Auto-generated method stub

        }

        @Override
        public void completed(Integer result, ByteBuffer buffer) {
            System.out.println("result = " + result);
            bytesRead = result.intValue();
            if (bytesRead < 0)
                return;
            // Switch ByteBuffer from read to write mode
            buffer.flip();

            byte[] data = new byte[buffer.limit()];
            buffer.get(data);

            fileData.append(new String(data));

            buffer.clear();
            position = position + bytesRead;
            fileChannel.read(buffer, position, buffer, this);

        }

    }

    private static int bytesRead = 0;
    private static StringBuffer fileData = new StringBuffer();
    private static long position = 0;
    private static AsynchronousFileChannel fileChannel = null;

    public static void main(String[] args) {
        Path path = Paths.get("C:/test/data.csv");

        try {
            fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            MyCompletionHandler myCompletionHandler = new MyCompletionHandler();
            fileChannel.read(buffer, position, buffer, myCompletionHandler);
            // read() returns -1 if End of File is reached.
            while (bytesRead > 0) {

                // Update to new read position.
                position = position + bytesRead;
                fileChannel.read(buffer, position, buffer, myCompletionHandler);
            }

            // Main thread waits till the asynchronous operations are complete
            try {
                Thread.currentThread().sleep(10000);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
            System.out.println(fileData);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}
Once the read is finished the completed() method of CompletionHandler is called with the number of Bytes read as a paramter. The second parameter can be any object, and in our case, I passed the same ByteBuffer object as a parameter to help read the entire file. The failed() method is called if the read operation fails.

Writing Data using Future

Writing to a file with Future follows the same model as read. The differnces are that you open the channel in "WRITE" mode instead of "READ" and call the write() method. When the write is done, the number bytes written to the file will be set in the Future. As with read() we wait till the read is complete by calling isDone() method.

package nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class AsyncFileChannelTest {

    public static void main(String[] args) {
        Path path = Paths.get("C:/test/data.csv");
        AsynchronousFileChannel fileChannel = null;

        try {
            fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
            ByteBuffer buffer = ByteBuffer.allocate(100);

            buffer.put("Hello World".getBytes());
            buffer.flip();

            Future operation = fileChannel.write(buffer, 0);
            buffer.clear();

            while(!operation.isDone());

            System.out.println("Number of Bytes Written : " + operation.get());

            
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

       
    }

}

Writing with CompletionHandler

Writing to a file with CompletionHandler follows the same model as a read. The differnces are that you open the channel in "WRITE" mode instead of "READ" and call the write() method.

package nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class AsyncFileChannelTest {
    public static class MyCompletionHandler implements CompletionHandler {

        @Override
        public void completed(Integer result, ByteBuffer attachment) {
            System.out.println("Number of bytes written : " + result);

        }

        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            // TODO Auto-generated method stub

        }

    }

    public static void main(String[] args) {
        Path path = Paths.get("C:/test/data.csv");
        AsynchronousFileChannel fileChannel = null;

        try {
            fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
            ByteBuffer buffer = ByteBuffer.allocate(100);

            MyCompletionHandler myCompletionHandler = new MyCompletionHandler();

            buffer.put("Hello World".getBytes());
            buffer.flip();
            fileChannel.write(buffer, 0, buffer, myCompletionHandler);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Main thread waits till the asynchronous operations are complete
        try {
            Thread.currentThread().sleep(10000);
        } catch (InterruptedException e) {

            e.printStackTrace();
        }

    }

}

Popular Posts