Java Weekly Newsletter 1

Java Weekly Newsletter Issue 1

Hello and welcome to the very first  Java Weekly Newsletter Issue 1

 

1.  Blog Posts

In case you have missed any of my posts, here is the list of articles we published this week.

  1. Introduction to Java 9 REPL and JShell
  2. Introduction to Java 8 Optional API

 

2. Spring & Java Community

  1. javap Usage Unfolds: What’s Hidden Inside Your Java Class Files?
  2. JSF Applications with Spring Session
  3. JVM’s Automatic Resource Management
  4. 11 Mistakes Java Developers make when Using Exceptions
  5. Java’s Observer and Observable Are Deprecated in JDK 9
  6. Bootstrap a Simple Application using Spring Boot 
  7. Using Kotlin’s Apply Function for Dynamic SQL with jOOQ
  8. 10 Tips on How to be a Great Programmer

 

3. JPA / Persistence

I do not work very closely in JPA or Hibernate but following few of the blogs for some of the interesting insight into Persistence 

  1. The best way to use entity inheritance with JPA and Hibernate

4. Spring Releases

  1. Spring Data Release Train Kay M4 Released 
  2. Spring Framework 5.0 RC2 available now
  3. Spring Boot 1.5.4 Available Now

 

5. Presentations and Videos

  1. Real-World Java 9
  2. Getting Started with Spring Boot
  3. Core Design Principles for Software Developers

We will be back with our next week newsletter with some more insight details about Java and Spring community.

Happy Coding !!!!

 

If you haven’t Signup to our weekly newsletter, Signup Now

Java 9 REPL

Introduction to Java 9 REPL

In this post, we will explore Java 9 REPL (Read-Evaluate-Print-Loop) feature or shortly called as JShell. Many modern languages provide a tool (Mostly called as REPL or scripting tool) for real-time statement interpretation.

One of the benefits of such tool is that you can easily test your code without creating a complete class or project.Java 9 will be introducing REPL or JShell which can be used to quickly run your code and compare results. 

This post assumes that you already have Java 9 installed on your machine, if this is not the case, install Java 9 on your machine before moving forward. 

REPL Concept is not new and some of the modern languages have provided this feature, here is the list

  1. Groovy Console
  2. Beanshell
  3. Scala

If we want to run some programme in Java (Java 8 or lower version), We need to create a project and the main method to run that code and any change require a recompile and repeat this process.

1. What is Jshell

Jshell will be shipped as part of the Java 9 and will work as scripting shell to run your Java code without the need of creating project or class with the main method.

To run Jshell, run following command with -v to get information about the version


localhost:~ umesh$ jshell -v
|  Welcome to JShell -- Version 9-ea
|  For an introduction type: /help intro

jshell> 

If you have Java 9 configured correctly, Jshell will greet you with a Unix style welcome message.

2. What is Jshell

Jshell comes with a certain set of default import. This indicates you don’t have you do explicit import for these to run you programme, to list default imports run /import command in Jshell


jshell> /import
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*

jshell>

Jshell /import will give you a list of import for the current session, this means if you will add additional import and run this command again, those import will be added automatically by Jshell for the current session.

3. Simple Hello Word

Running and printing simple hello work using Jshell is quite simple and you don’t need to write a complete .java class for this.


jshell> System.out.println("Hello World from Jshell!!!");
Hello World from Jshell!!!

jshell>

Jshell is flexible in nature and you can even skip adding ; at the end of the statement and Jshell will handle it internally.


jshell> System.out.println("Hello World from Jshell!!!")
Hello World from Jshell!!!

jshell>

4. Creating and Running Method

Methods can be created and executed easily using Jshell


jshell> void helloWorld(){ System.out.println("Hello World!!");}
|  created method helloWorld()

jshell> helloWorld()
Hello World!!

jshell>

Jshell even allows you to modify your existing code, Let’s say we want to change “Hello World!!” to “Hello World from JShell”, you can easily change it.


jshell> void helloWorld(){ System.out.println("Hello World from JShell!!");}
|  modified method helloWorld()
|    update overwrote method helloWorld()

jshell> helloWorld()
Hello World from JShell!!

jshell>

5. Expressions

Jshell will accept any valid Java expression, Jshell will execute the expression, it will provide you information about the value, value type.


jshell> 3+7
$5 ==> 10
|  created scratch variable $5 : int

jshell> $5
$5 ==> 10
|  value of $5 : int

jshell>

Jshell provides you with a detailed information about the new variable ($5) it created and what is the value assigned to this new variable.You can even refer to this variable by just naming it $5

6. Variables

You can create variable and even name those variables using JShell, these variables will be visible in the current Jshell context and you can change/modify values as per your need.


jshell> int i=10
i ==> 10
|  created variable i : int

jshell> String blogName="Umesh Awasthi";
blogName ==> "Umesh Awasthi"
|  created variable blogName : String

jshell> blogName= blogName+" Java 9 REPL";
blogName ==> "Umesh Awasthi Java 9 REPL"
|  assigned to blogName : String

jshell> blogName
blogName ==> "Umesh Awasthi Java 9 REPL"
|  value of blogName : String

jshell>

7. Commands

Jshell provide number of build in command which can be used to get some insight on to the JShell, you can run these command on the JShell using forward slash (“\”) 


jshell> /vars
|    int $5 = 10
|    int i = 10
|    String blogName = "Umesh Awasthi Java 9 REPL"

jshell> /methods
|    void helloWorld()

jshell>

You can use /vars to list all variable in the current context, a similar way you can use /methods to list down all the method in the current context. Use /help to start Jshell help menu.

8. List

Jshell is quite powerful and it keeps trek of the activities happening in the current context, however, it’s not an IDE and you might want to get a list of all variables or methods or values being used in the context, Jshell provides /list method to give you all the information.


jshell> /list

   2 : helloWorld()
   3 : void helloWorld(){ System.out.println("Hello World from JShell!!");}
   4 : helloWorld()
   5 : 3+7
   6 : $5
   7 : int i=10;
   8 : String blogName="Umesh Awasthi";
   9 : blogName= blogName+" Java 9 REPL";
  10 : blogName

jshell> 

9. Save and Reload

Use /save method to save expression history, it will save a file in the same directory from which we are running the Jshell. To open saved file, we can use /open a command.


jshell> /save jshell.java
jshell> /open jshell.java

10. Forward reference

JShell provides a very good support for forward reference, this means we can refer to variable or methods which we are planning to introduce later in our code.

code class="language-vim">
jshell> double totalPendingAmount(int customerNumber){ return getCustomerPendingAmount(customerNumber);}
|  created method totalPendingAmount(int), however, it cannot be invoked until method getCustomerPendingAmount(int) is declared

jshell>

The interesting part is the output of above command, JShell indicating that we will not be able to use this method until getCustomerPendingAmount(int) is defined.

11. JShell API

Jshell also provides API which can be used by external parties to use Jshell capabilities. 

12. Why use Jshell

We are going to have a very natural question “Why use Jshell ??” , I will try to come up with some use cases where it will really be handy to use Jshell 

  1. JShell API provides a way to have a network connection, We can use it to connect to our remote server and may change few things remotely.
  2. We can even connect to DB and perform some operations.
  3. API can be used to hook into live JVM’s to get an insight of it.
  4. We can use JShell to determine and verify return type (Check video for detail)
  5. Rapid prototyping, You can quickly modify and run your programme without waiting for multiple rebuilds or redeploy.

13. Video Tutorials

It is always interesting to see things in action. Please watch this video to see Jshell in action.

Conclusion

Jshell is really interesting and powerful tool for rapid prototyping. I believe that Jshell will become a friendly tool for developers on a day to day life. Jshell has a lot of use cases but the best one for me is the ability to quickly test your code without getting into long build cycles.

Read Collection Factory Methods in Java 9  to learn how to create immutable collection in Java 9.

java 8 optional

Java 8 Optional

In this post, we will be talking about  Optional class introduced in Java 8. As a Java developer, You must have faced NullPointerException at least (I have faced it countless time 🙂 ).

NullPointerExceptions are a pain but the truth is you can not avoid it but can add certain checks to make sure we are ready for it when it happens.

A common (bad) practice is to return the null reference to indicate the absence of a given object and which can cause NullPointerException. The Optional class was introduced in Java8 to handle optional values instead of null reference.

1.  Introduction

To explain, Java 8 Optional feature, consider the following structure for a Car having a build in map (navigation) feature.

Car

public class Car {

    private GoogleMaps map;

    public GoogleMaps getMap() {
        return map;
    }

    public void setMap(GoogleMaps map) {
        this.map = map;
    }
}

Map

public class GoogleMaps {

    private String mapDetails;

    public String getMapDetails() {
        return mapDetails;
    }

    public void setMapDetails(String mapDetails) {
        this.mapDetails = mapDetails;
    }
}

Enable Map

Car car = new Car();
car.getMap().getMapDetails();

Above code looks good but as we know many cars (even new one) don’t have the build in map (navigation) system, so getMapDetails() will throw NullPointerException for all those cars which do not have a built-in navigation system.

As a standard practice is to return a null reference to indicate the absence of an object, for our case getMap() will return a null reference to indicate that Car does not have build in a navigation system. 

 

Let’s use Optional class to enrich the semantics of the above model

public class Car {

    private Option<GoogleMaps> map;

    public Option<GoogleMaps> getMap() {
        return map;
    }

    public void setMap(Option<GoogleMaps> map) {
        this.map = map;
    }
}

Based on the above change, Car refers to Optional<GoogleMap> which clearly indicate that GoogleMap is an optional feature for a car. API user of your domain model can easily understand what to expect out from the API.

How to we handle this use case?

2. Use Defensive Check to Handle Null 

In order to handle null pointer reference and to avoid NullPointerException, we will use standard null reference check in our code

public class OptionalTest {

    public static void main(String[] args) {

        Car car = new Car();
        car.getMap().getMapDetails();
    }

    public static String getMapDetails(final Car car) {
        if (car != null) {
            GoogleMaps map = car.getMap();
            if (map != null) {
                return map.getMapDetails();
            }
        }

        return "Unavailable";
    }
}

One of the major drawbacks of the above code is that it will become very unreadable due to nested check. All these checks are happening only to avoid NullPointerException and certainly not adding anything to the business logic.

I do not want to get into more details about the other drawbacks of the above code (what if you miss to check the null pointer for any other property).

To summarise, returning a null reference to indicate non-existence of an object or value is not a very good approach and definitely, need some other good alternate.

 

3. Java Optional Class

To handle the absence of object or value in a more graceful way than returning a null reference, java.util.Optional<T> was introduced as a new feature in Java 8.

Optional class provide a way to design better API in which consumer of the API has a better understanding as to what can be expected back from the API.

java.util.Optional<T> is like a container, either container have some object or it is empty (can not be null).In another term think of Optional as a wrapper, if the value is present, the Optional class will wrap that value else it will be empty.

 

4. How to Create Optional Class

There are multiple ways to create Optional objects. We can use empty() method to create empty Optional object

 

Optional With Empty Value
Optional<GoogleMaps> emptyOptional = Optional.empty();

Optional.empty() is a static factory method which returns Singleton object of the optional class (see java source for more details).

 

Optional With  Not Null Value
GoogleMaps googleMaps = new GoogleMaps();
Optional<GoogleMaps> optionalMap= Optional.of(googleMaps);

Keep in mind that argument passed to Optional.of() can not be null, above code will throw NullPointerException if GoogleMaps were null.If we use below code

Optional<GoogleMaps> optionalMap= Optional.of(null);

JRE will throw NPE

Exception in thread "main" java.lang.NullPointerException
    at java.util.Objects.requireNonNull(Objects.java:203)
    at java.util.Optional.<init>(Optional.java:96)
    at java.util.Optional.of(Optional.java:108)
    at com.umeshawasthi.tutorials.corejava.java8.optional.CreateOptionalObject.main(CreateOptionalObject.java:15)
 
Optional With  Not Null

To Create an Optional object for holding a null value, Optional class provide ofNullable() method.

Optional<GoogleMaps> nullGoogleMap = Optional.ofNullable(null);
System.out.println(nullGoogleMap.toString());

Output

Optional.empty

 

The difference between the null reference and empty Optional object is really significant, null reference will cause a NullPointerException whereas Optional.empty is a valid object and we can work on the object without worrying about NPE. 

 

5. Use Optional Value

Once We have an Optional object, we can work with methods provided by the optional object to handle presence or absence of given value.

We can use isPresent() method from Optional class to check if a value exists or not.

Optional<String> optional = Optional.of("umesh");
System.out.println(optional.isPresent());

Optional<String> nullValue= Optional.ofNullable(null);
System.out.println(nullValue.isPresent());

Output


true

false

6. Use get() method

The optional class provides get() method which can be used get value from the Optional object. Keep in mind that get() method will throw NoSuchElementException in case Optional is empty.

Optional<String> nullValue= Optional.ofNullable(null);
System.out.println(nullValue.get());

Output

Exception in thread "main" java.util.NoSuchElementException: No value present
    at java.util.Optional.get(Optional.java:135)
    at com.umeshawasthi.tutorials.corejava.java8.optional.CreateOptionalObject.useGet(CreateOptionalObject.java:45)
    at com.umeshawasthi.tutorials.corejava.java8.optional.CreateOptionalObject.main(CreateOptionalObject.java:18)

We can use isPresent() method with Optional.get() to handle above exception

Optional<String> nullValue= Optional.ofNullable(null);
if(nullValue.isPresent()) {
    System.out.println(nullValue.get());
}

Of the main issue with Optional.get() method is that it violate the main principle of Optional class to avoid or handle such issue (Exceptions). It is not recommended to use get() method and should be avoided in favour of other alternates.

 

7. Use Optional Value

ifPresent() method from Optional API can be used to perform conditional logic.

Optional<String> optional = Optional.of("umesh");
optional.ifPresent(System.out::println);

Optional<String> nullValue= Optional.ofNullable(null);
nullValue.ifPresent(System.out::println);

Without optional, we need to perform a null check before executing our logic, Optional make it easy to handle such use cases and provide a more clean API.

8. Default Value with orElse or orElseGet

A standard way to return default value in case result is null is by using ternary operator similar to 

GoogleMaps map = googleMap !=null ? googleMap : defaultMap;

Using Optional, we can use it’s orElse() method to return the default value in case the Optional object is null.

String name=null;
String value= Optional.ofNullable(name).orElse("Hello");
System.out.println(value);

 

Default value with orElseGet

orElseGet() is almost similar to the orElse() , orElseGet() method takes a Supplier functional interface. It Returns the value if present otherwise invokes other and return the result of that invocation. 

9. Difference Between orElse and orElseGet

To understand the difference, we will run following example.

public class OptionalElseGetExample {

    public static void main(String[] args) {

        Optional<String> testingOrElse = Optional.of("Testing orElse method");
        String finalOutput = testingOrElse.orElse(printHelloWorld());
        System.out.println("optional result:: " + finalOutput);

        Optional<String> testingOrElseGet = Optional.of("Testing orElse method");
        String finalOrElseOutput = testingOrElseGet.orElseGet(() -> printHelloWorld());
        System.out.println("optional result:: " + finalOrElseOutput);

    }

    public static String printHelloWorld() {
        System.out.println("Hello World");
        return "Say Hello";
    }
}

Output


Hello World
 orElse Test:: Testing orElse method
 orElseGet Test:: Testing orElse method
public class OptionalElseGetExample {

    public static void main(String[] args) {

        checkOrElseGet();
    }


    public static void checkOrElseGet() {

        Optional<String> testingOrElse = Optional.ofNullable(null);
        String finalOutput = testingOrElse.orElse(printHelloWorld());
        System.out.println("optional result:: " + finalOutput);

        Optional<String> testingOrElseGet = Optional.ofNullable(null);
        String finalOrElseOutput = testingOrElseGet.orElseGet(() -> printHelloWorld());
        System.out.println("optional result:: " + finalOrElseOutput);
    }

    public static String printHelloWorld() {
        System.out.println("Hello World");
        return "Say Hello";
    }
}

Output


Hello World
 optional result:: Say Hello
 Hello World
 optional result:: Say Hello

So orElseGet() will execute the function if Optional is empty, while for orElse() will execute function even if Optional is empty.Optional.orElse() can be used to assigning a literal value but we shouldn’t expect a control flow with it.

In above example, this difference might not be very visible but let’s say you are making an expensive DB call or connecting to an external web service, these small differences will make a lot of impacts.

Similarly, you can use the orElseThrow() method, which instead of providing a default value if Optional is empty, throws an exception.

 

10. Filtering Optional using filter method 

Most of the time, we need to call a method on an object and check some property, filter method provided by the Optional object can be used filter out values.

filter method takes a predicate as an argument if the Optional object is present and it matched the predicate, filter method will return the value else empty Optional object will be returned. 

Let’s take at following example, Let’s say we will give 10% off on a product to a customer if the product price is greater than $20 but not more than $50. 

public class Product {

    private Double productPrice;

    public Product(Double productPrice) {
        this.productPrice = productPrice;
    }

    public Double getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(Double productPrice) {
        
        this.productPrice = productPrice;
    }
}
public boolean checkIfEligibleForPromotion(Product product) {
    if (product != null && product.getProductPrice() != null
            && product.getProductPrice().doubleValue() > 20.00
            && product.getProductPrice().doubleValue() <= 50) {

        return true;
    }
    return false;
}

We need to write so much of code to accomplish this task, checking price range is part of the business workflow but other conditions are there just to avoid NullPointerException.

We will use Optional.filter() to handle above use case with more clean and better approach.

public boolean checkIfEligibleForPromotionByFilter(Product product) {
    return Optional.ofNullable(product).map(Product::getProductPrice)
            .filter(productPrice->productPrice >20)
            .filter(productPrice->productPrice <=50)
            .isPresent();
}

Map method of the Optional class transformed the value inside the Optional Object by the function passed as an argument.

Note following points in the map and filter method

  1. Even if we pass null object is passed, it will not throw any exception.
  2. Above code is cleaner as we just apply a filter to check if the product is eligible for promotion or not.
  3. API is cleaner and do not need an additional null check before executing business logic.

 

11. Transforming values using flatMap method 

Similar to map API, Optional also provides flatMap as another alternate for transforming values. map transforms values only when they are unwrapped whereas flatMap takes a wrapped value and unwraps it before transforming it.

Let’s go back to our original example of Car having Navigation System, in order to get Map from the navigation system, we will do something like

car.getMap().getMapDetails() 

To Summarise, above code extract one object from another object and map method is perfect candidate for it

myCar.map(Car::getMap)
        .map(GoogleMaps::getMapDetails)
        .orElse("Navigation Not Available");

 

Above code will not work, since map can only transform value when they are unwrapped, here are the details why above code will fail

  1. myCar is of type Optional<Car> and calling map on it will work, however, getMap will return an object of Optional<GoogleMap>.
  2. The result of above process will be of Optional<Optional<GoogleMap>> and getMapDetails() will not work (getMapDetails() is not valid for the outer Optional object)

In order to handle such use cases, Optional supports flatMap() which can take a wrapped value and unwraps it before transforming it.

myCar.flatMap(Car::getMap)
        .flatMap(GoogleMaps::getMapDetails)
        .orElse("Navigation Not Available");

 

12. Exceptions Vs Optional

Throwing an exception is a common pattern in Java API to return null in case a value is not present. Integet.parseInt(String) will throw NumberFormatException in case supplied argument is invalid. We can use Optional class to handle it in more interesting way (We no longer need to try catch block at each location where we need to parse String to Integer)

public static Optional<Integer> parseInt(String value) {

    try {
        return Optional.of(Integer.parseInt(value));
    } catch (NumberFormatException nfe) {
        return Optional.empty();
    }
}

Conclusion

In this post, we cover Java 8 Optional API in details along with some of the reasons as to why we should use it and how we can adapt it to our data model for the better API design. We learned how to use Optional class static factory methods like Optional.empty(), Optional.of() to create optional objects.

Do not try to replace every single null reference in your code with Optional as it might lead to other issues, I will use Optional to create better API which can clearly communicate to its user as what to expect from the API.

All the code of this article is available Over on Github. This is a Maven-based project.

References

Optional

Zipping and Unzipping in Java

Zipping and Unzipping in Java

In this post, we will learn Zipping and Unzipping in Java using java.util.zip API. We will also discuss some third party API to perform these tasks. 

1.  Zip a File

We will be performing a simple operation to zip a single file into an archive.

public class ZipSingleFile {

    public static void main(String[] args) throws IOException {

        String sourceFile = "/Users/umesh/personal/tutorials/source/index.html";
        String zipName="/Users/umesh/personal/tutorials/source/testzip.zip";

        File targetFile = new File(sourceFile);

        ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipName));
        zipOutputStream.putNextEntry(new ZipEntry(targetFile.getName()));
        FileInputStream inputStream = new FileInputStream(targetFile);

        final byte[] buffer = new byte[1024];
        int length;
        while((length = inputStream.read(buffer)) >= 0) {
            zipOutputStream.write(buffer, 0, length);
        }
        zipOutputStream.close();
        inputStream.close();
    }

}

2.  Zip Multiple Files / Directories Java8

Creating zip for a single file is not very interesting or real life solution, we will be improving our program with an option to zip entire directory using Files.walk method.

public class ZipDirectory {

    public static void main(String[] args) throws IOException {

        String sourceDirectoryPath = "/Users/umesh/personal/tutorials/source";
        String zipFilePath = "/Users/umesh/personal/tutorials/source.zip";

        zipDirectory(sourceDirectoryPath, zipFilePath);
    }

    public static void zipDirectory(String sourceDirectoryPath, String zipPath) throws IOException {
        Path zipFilePath = Files.createFile(Paths.get(zipPath));

        try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFilePath))) {
            Path sourceDirPath = Paths.get(sourceDirectoryPath);

            Files.walk(sourceDirPath).filter(path -> !Files.isDirectory(path))
                    .forEach(path -> {
                        ZipEntry zipEntry = new ZipEntry(sourceDirPath.relativize(path).toString());
                        try {
                            zipOutputStream.putNextEntry(zipEntry);
                            zipOutputStream.write(Files.readAllBytes(path));
                            zipOutputStream.closeEntry();
                        } catch (Exception e) {
                            System.err.println(e);
                        }
                    });
        }
    }
}

 

2.  Zip Multiple Files / Directories Java7

public class ZipDirectoryFilesWalk {

    public static void main(String[] args) throws IOException {

        Path sourceDirectoryPath = Paths.get("/Users/umesh/personal/tutorials/source");
        Path zipFilePath = Paths.get("/Users/umesh/personal/tutorials/source.zip");

        zipDirectory(sourceDirectoryPath, zipFilePath);
    }

    public static void zipDirectory(Path sourceDirectory, Path zipFilePath) throws IOException {

        try (FileOutputStream fileOutputStream = new FileOutputStream(zipFilePath.toFile());
             ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream)
        ) {
            Files.walkFileTree(sourceDirectory, new SimpleFileVisitor<Path>() {

                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                        throws IOException {
                    zipOutputStream.putNextEntry(new ZipEntry(sourceDirectory.relativize(file).toString()));
                    Files.copy(file, zipOutputStream);
                    zipOutputStream.closeEntry();
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                        throws IOException {
                    zipOutputStream.putNextEntry(new ZipEntry(sourceDirectory.relativize(dir).toString() + "/"));
                    zipOutputStream.closeEntry();
                    return FileVisitResult.CONTINUE;
                }

            });
        }
    }
}

In the above examples, we saw different options to Zipping Files and Directories in Java using Java7 and Java8.

3. Unzip  Directory

public class UnZipDirectory {

    public static void main(String[] args) throws IOException {

        String unzipLocation = "/Users/umesh/personal/tutorials/unzip";
        String zipFilePath = "/Users/umesh/personal/tutorials/source.zip";
        unzip(zipFilePath, unzipLocation);
    }

    public static void unzip(final String zipFilePath, final String unzipLocation) throws IOException {

        if (!(Files.exists(Paths.get(unzipLocation)))) {
            Files.createDirectories(Paths.get(unzipLocation));
        }
        try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath))) {
            ZipEntry entry = zipInputStream.getNextEntry();
            while (entry != null) {
                Path filePath = Paths.get(unzipLocation, entry.getName());
                if (!entry.isDirectory()) {
                    unzipFiles(zipInputStream, filePath);
                } else {
                    Files.createDirectories(filePath);
                }

                zipInputStream.closeEntry();
                entry = zipInputStream.getNextEntry();
            }
        }
    }

    public static void unzipFiles(final ZipInputStream zipInputStream, final Path unzipFilePath) throws IOException {

        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(unzipFilePath.toAbsolutePath().toString()))) {
            byte[] bytesIn = new byte[1024];
            int read = 0;
            while ((read = zipInputStream.read(bytesIn)) != -1) {
                bos.write(bytesIn, 0, read);
            }
        }

    }
}

In this post, we learned as to how to zip and unzip files or directory using core Java features. Read our articles List all files from a directory in Java to learn how to recursively transverse folders to zip multiple files.

If you want more sophisticated API to perform other operation on the zip files, you can check following open source libraries

  1. zt-zip
  2. zip4j

All the code of this article is available Over on Github. This is a Maven-based project.

Collection Factory Methods in Java 9

Collection Factory Methods in Java 9

In this post, we will explore Collection Factory Methods in Java 9. Java 9 introduced a new Convenience Factory Methods for Collections.

 

Introduction

Creating a new unmodifiable list in Java (before Java 9) is not very clean. Creating a small immutable collection in Java involves following steps

  1. Create collection.
  2. Add objects to Collection (e.g Map)
  3. Wrap it using unmodifiableXXX()  method provided under java.util.Collections class.

To create a unmodifiable map in Java8 

 

public class ImmutableCollection {

    public static void main(String[] args) {

        Set<String> set = new HashSet<String>();
        set.add("one");
        set.add("two");
        set.add("three");

        Set<String> immutableSet = Collections.unmodifiableSet(set);
    }
}


Above code is definitely not very clean and concise, another option to create unmodifiable set are

public class ImmutableMap {

    public static void main(String[] args) {
        
        Set<String> immutableSet = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("one", "two","three")));
    }
}

Above code is a little cleaner but have following issues

  1. We need to create List before creating Set (extra Overhead).

 

Double Brace Initialization

We have the option to use double brace initialization for creating unmodifiable collection (Set in our example)

public class ImmutableCollectionDoubleBrace {

    public static void main(String[] args) {

        Set<String> immutableSet = Collections.unmodifiableSet(new HashSet<>() {{
            add("one");
            add("two");
            add("three");
        }});
    }
}

Above option also have multiple issues

  1. It will create an extra class with each usage.
  2. It contains references to the enclosing instance.

 

Java8 Stream API

Java8 Stream API can also be used to create a unmodifiable collection.

public class ImmutableCollectionStream {

    public static void main(String[] args) {
        
        Set<String> unmodifiableSet= Collections.unmodifiableSet(Stream.of("one","two","three").collect(Collectors.toSet()));
        
    }
}

Java 8 Stream API also have some issue and not a very clean solution to create a unmodifiable collection, additionally stream API involve unnecessary object creation along with some extra calculations.

 

Unmodifiable Collections in Java 9

Collection Factory Methods are introduced in Java 9 like Scala (not same 🙂 ). Static methods have been provided by Java 9 on List, Set and Map interfaces which can easily returned unmodifiable collections by calling of() method of the respective interface.

 

List

public class Java9ImmutableList {

    public static void main(String[] args) {

        List<String> immutableList= List.of("1","2","3");
    }

}

Set

public class Java9ImmutableSet {

    public static void main(String[] args) {

        Set<String> immutableMap = Set.of("one","two","three");
    }
}

Map

public class Java9ImmutableMap {

    public static void main(String[] args) {

        Map<String, Integer> immutableMap = Map.of("one",1, "two", 2);
    }
}

Please note that Map.of() works with key and value pairs up to 10 entries. Beyond that, we need to use in a var-args of Entry instances and use Map.ofEntries()

public static void useMapEntries(){

    Map<String, Integer> map = Map.ofEntries(
            Map.entry("one", 1),
            Map.entry("two", 2),
            Map.entry("three", 3)
    );
}

Since every var-args method implicitly creates an array and to avoid performance issue, Java language team included 12 overloaded implementations for of factory method for each collection type.

static <E> Set<E> of() 
static <E> Set<E> of(E e1) 
static <E> Set<E> of(E e1, E e2) 
static <E> Set<E> of(E e1, E e2, E e3) 
.....

 

Null Element in Collection

Both List and Set will not allow adding a null element, Map does not allow null either as a key or value. If you will try to add a null element, JDK will throw NullPointerException.

public class NPEExample {

    public static void main(String[] args) {

        List<String> immutableList = List.of("one", null);
    }
}

 

Output

Exception in thread "main" java.lang.NullPointerException
 at java.base/java.util.Objects.requireNonNull(Objects.java:221)
 at java.base/java.util.ImmutableCollections$List2.<init>(ImmutableCollections.java:185)
 at java.base/java.util.List.of(List.java:822)
 at java/com.umeshawasthi.java9.example.NPEExample.main(NPEExample.java:9)

The introduction of Collection Factory Methods in Java 9 is one of the useful features and will be useful in day to day programming. I have covered feature of Collection Factory method along with some internal details. 

It is, of course, not nearly as convenient as Scala but I believe It’s a very welcome change in Java 9.

 

All the code of this article is available Over on Github. This is a Maven-based project.

References

JEP 269

Java nio2

Introduction to Java NIO2

This post is aiming to provide a high-level overview of the Java NIO2 API features. Java7 introduced a rich set of features to operators on the Files using Java NIO2 package.

In this post, we will learn about some of the basic features introduced by Java Nio2. The java.nio.file package provides a comprehensive support to work on the file IO. Files class is one of the main utility class provided by NIO package which provides a rich set of functionality to work on the underlying filesystem with help of Path class.

 

1.  Basics

In order to use Files or Path class, all we need to import java.io.file.* in our program, all major classes are defined within the java.io.file package.

Please read Java NIO Path to get understanding how Path class work in the new Java NIO2 package.

 

2. Checking a File or Directory

Java NIO package’s Files and Path API can be used to easily determine if a given path exists or not by utilising exists and notExists method provided by Files class.

public static void checkIfFileDirExist(final Path location){
    System.out.println(Files.exists(location));
}

public static void checkIfFileDirNotExist(final Path location){
    System.out.println(Files.notExists(location));
}

 

Please be aware Files.notExists work for both Files and Directories, so refer to both files and directory when I am talking about files in this post.  

 

3. Checking  File Accessibility

Java NIO2 package also provide way to check if given programme can access a file needed or do we have required permission to perform given file operation. Files utility class provide following method to check accessibility.

  1. isReadable(Path)
  2. isWritable(Path)
  3. isRegularFile (Path)
  4. isExecutable (Path)

 

   public static void checkIfReadable(final Path location)
    {
        System.out.println(Files.isReadable(location));
    }

   public static void checkIfWritable(final Path location)
    {
       System.out.println(Files.isWritable(location));
    }


 

A regular file is a file which is not special, in case file contains any symbolic links to similar properties, this will not be treated a regular file.

If you want to check if both Path objects are same or pointing to the same location, we can use isSameFile(Path path1, Path path2).

 

4. Creating Files

Files class provide an easy way to create the file using NIO. Please read How to write to file in Java for more details.

 

5. Creating Directory

Read How to create directory in Java to learn various options available under Java 7 NIO.

 

6.  Delete directory in Java

You can delete files, directories or links, please read Deleting Directory in Java to understand how we can use walkFileTree to recursively delete directories and files using Files NIO.

 

7.  Move Directory / Files  in Java

Java NIO provides an easy way to move files or directories using API’s move method. You can also copy files and directories recursively using the fileWalker method. Please read  How to Move a File in Java.

 

8. Copying a File or Directory

Copy a file or directory in Java is a common operation. Java NIO Files class provide a convenient copy method to copy file or directory. If you want to copy files from one directory to another in Java including subdirectories, you have to use Files.walkFileTree from NIO Java7 approach to recursively copy directory and all files to another location.

Please read Copy a File or Directory in Java to see how to use FileVisitor to recursively copy files and directories. 

 

In this post, we saw of the core features introduced as part of the Java NIO2 introduced with JDK7 along with some of the important operation being supported by NIO2 API.

 

All the code of this article is available Over on Github. This is a Maven-based project.

Java NIO Path

Java7 Introduced NIO2 as an enhancement to the current File API. Java NIO Path and especially Path class was one of the main entry points for NIO2 API.

Path class is a representation of the underlying platform file system.Path class will create a path based on the platform you are working on. (e.g. For Linux system Path class represents  path as /user/home while for window it will represent path as C:/home/my-folder).

Path class work very closely with the utility class Files introduced as part of the Java 7 NIO package and provide different utility methods to work on the file system.

Some of the common methods and information being returned by Path class are

  1. Creating Path to represent underlying platform path system.
  2. Access element of the Path.
  3. Comparing 2 paths
  4. Joining 2 paths

 

Keep in mind that all above operation using Path class operates on the path itself and not on the underlying file system. We need to use utility class Files in combination with Path class to access and work on the file system.

 

Path Operations

We will cover various operation performed on the Path class with information as to how to build a path to access the underlying file system.

 

1.  Creating Path 

Path is nothing but a representation or the location of the file or directory in your file system or on the system where you are planning to run this programme.Java NIO Path class provide a convenient way to create a path using Paths.get() method.

 

package com.umeshawasthi.tutorials.corejava.io.path;

import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * Created by umesh on 5/31/17.
 */
public class CreatePath {

    public static void main(String[] args) {

        Path path = Paths.get("/Users/umesh/personal/tutorials");
        
        Path path1 = Paths.get(URI.create("file:/Users/umesh/personal/tutorials"));
        
        Path path2= Paths.get(System.getProperty("user.home"),"personal", "tutorials");

        System.out.println(path2.toAbsolutePath());
        System.out.println(path1.toAbsolutePath());
        System.out.println(path.toAbsolutePath());
    }
}

 

Output

/Users/umesh/personal/tutorials 
/Users/umesh/personal/tutorials 
/Users/umesh/personal/tutorials

Paths is another utility class provided with Java NIO with a set of static methods for creating Path object for a given String or URI.

Paths.get() method will internally use FileSystems.getDefault().getPath() to get Path represnetation based on the platform.

FileSystems will be using code class=”language-java”>FileSystemProvider to get a concrete implementation file system provider based on the given platform (Windows will have different FileSystemProvider than Linux)

 

public class CreatePath {

    public static void main(String[] args) {

        Path path = Paths.get("/Users/umesh/personal/tutorials/source");
        pathMethod(path);
    }

    public static void pathMethod(Path path) {

        System.out.println("toString method :: " + path.toString());
        System.out.println("getFileName :: " + path.getFileName());
        System.out.println("getFileSystem :: " + path.getFileSystem());
        System.out.println("Get Root Name :: " + path.getRoot());
        System.out.println("Get Parent ::" + path.getParent());
        System.out.println("get count :: " + path.getNameCount());
    }
}

 

Output

toString method :: /Users/umesh/personal/tutorials/source
getFileName :: source
getFileSystem :: [email protected]
Get Root Name :: /
Get Parent ::/Users/umesh/personal/tutorials
get count :: 5

Pay close attention to the output of the getFileSystem, I am running this programme on MacOSX, so the MacOSXFileSystem is being returned as the underlying FileSystemProvider. If you run this programme on Windows, you will see a different output for this.

 

2.  Converting to Path 

Path Object provides different options to convert Path representation to String. We can use following options with Path

  1. Path.toURI ( For using it in the browser).
  2. Path.toAbsoultePath (For absolute path)
  3. Path.toRealPath (Getting real path including symbolic links)

 

public class DisplayPath {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("/Users/umesh/personal/tutorials/source");

        System.out.format("toURI: %s%n", path.toUri());
        System.out.format("toAbsolutePath: %s%n", path.toAbsolutePath());
        System.out.format("toRealPath: %s%n", path.toRealPath());
    }
}

 

Output


toURI: file:///Users/umesh/personal/tutorials/source/

toAbsolutePath: /Users/umesh/personal/tutorials/source

toRealPath: /Users/umesh/personal/tutorials/source

 

3.  Joining Path 

What is mean by joining path? Joining path means, you will combine root path with the partial path with the help of resolve method.

Read Copy a File or Directory in Java to get an understanding to use relativize and resolve methods.

 

4.  Comparing Two Paths

Path class provide support to compare two paths to check if both paths point to the same location. Keep in mind that Path.equals() method will be dependent upon the underlying file system.

public class PathEquality {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("/Users/umesh/personal/tutorials/source");
        Path path1 = Paths.get("/Users/umesh/personal/tutorials/source");

        System.out.println(path.equals(path1));
    }
}

 

If you want to check path for a specific name, you can use startsWith() and endsWith() methods.

There are a couple of interesting points about the Path class.

  1. Path class implement the Iterable interface which will help you to iterate over name element in the Path class.
  2. You can also compare two path object as Path class also implements the Comparable interface.

 

public class PathIterate {

    public static void main(String[] args) {

        Path paths= Paths.get("/Users/umesh/personal/tutorials/source/bootstrap",
                "/Users/umesh/personal/tutorials/source/build",
                "/Users/umesh/personal/tutorials/source/dist");

        for (Path path :paths){
            System.out.println(path.toAbsolutePath());
        }
    }
}

In this post, we get a basic understanding of the Java NIO Path class along with some of the methods and features being supported by it.

Good understanding of the Path class along with Files class is a good building block for understanding NIO and NIO2 introduced in Java7

 

All the code of this article is available Over on Github. This is a Maven-based project.

How to Move a File in Java

In this post, we will learn how to move a file in Java using Java7 NIO or Apache Commons IO. As part of the core java tutorials, we will be covering following options.

  1. Move a file or directory using NIO and JDK 7.
  2. Move files or directory using Apache Commons IO.

 

1. Using JDK7

NIO Package in JDK7 added a number of enhancements to file API in Java including Path and convenient Files class.

 

public class MoveFile {

    public static void main(String[] args) throws IOException {
        Path source = Paths.get("/Users/umesh/personal/tutorials/source/store.html");
        Path target = Paths.get("/Users/umesh/personal/tutorials/target");

        Files.move(source,target.resolve(source.getFileName()));

    }

 

Above code assume that both source and target directory already exists.In case target directory does nor exists, the method will throw code java.nio.file.NoSuchFileException.

You can also use above method to move the directory to the target location by changing the code a little.

public class MoveDirectory {

    public static void main(String[] args) throws IOException {
            Path source = Paths.get("/Users/umesh/personal/tutorials/source");
            Path target = Paths.get("/Users/umesh/personal/tutorials/target");

            Files.move(source,target.resolve(source.getFileName()));

        }
}

 

2. Using Apache Commons

Apache Commons provide easy options to move files/ directories.If you are already using Commons API in your project, there is nothing better than writing few lines to get your work done.

 

public class MoveDirectoryApache {

    public static void main(String[] args) throws IOException {

        File source =  FileUtils.getFile("/Users/umesh/personal/tutorials/source/bower.json");
        File target =  FileUtils.getFile("/Users/umesh/personal/tutorials/target/bower.json");

        FileUtils.moveFile(source, target);
    }
}

If you want API to create directory automatically, use moveFileToDirectory(File srcFile, File destDir, boolean createDestDir) and set createDestDir as true

 

2.1 Move Directory Using Apache Commons


public class MoveDirectoryApache {

    public static void main(String[] args) throws IOException {

        File source =  FileUtils.getFile("/Users/umesh/personal/tutorials/source");
        File target =  FileUtils.getFile("/Users/umesh/personal/tutorials/target");

        FileUtils.moveDirectory(source, target);
    }
}

In this post, we learn how to move a file in Java. With Java7 NIO moving file or directory is really easy and Apache Commons always have handy methods for these tasks.

 

All the code of this article is available Over on Github. This is a Maven-based project.

References

  1. Files.html#Move.
  2. Apache Commons IO

Copy a File or Directory in Java

Copy a File or Directory in Java

Copy a file or directory in Java is a common operation. In this post, we will go through different options to perform following operation.

  1. Copy a file from one location to another location.
  2. Copy all content of directory from one location to another.

We will be using Java 7+ and Apache Commons API for copying a file or directory in Java.

1.  Copy Directory Using Java

We will be using Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING) to copy files /directory from the source location to destination location.

 


public class CopyDirectory {

    public static void main(String[] args) throws IOException {

        Path sourceDirectory = Paths.get("/Users/personal/tutorials/source");
        Path targetDirectory = Paths.get("/Users/personal/tutorials/target");

        //copy source to target using Files Class
        Files.copy(sourceDirectory, targetDirectory);

    }

}

This will copy source directory to target location. We need to remember following points

  1. If target directory exists, the system will throw FileAlreadyExistsException.
  2. Use StandardCopyOption.REPLACE_EXISTING to replace target location with the source.
  3. Above method will only copy source directory but not files or subdirectories.
  4. To copy files and subdirectories, use Files.walkFileTree method.

 

2. Copy File Using Java

We will be using Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING) to copy files from source location to destination location.

 


public class CopyFIle {

    public static void main(String[] args) throws IOException {

        Path sourceDirectory = Paths.get("/Users/umesh/personal/tutorials/source/Variation_Relations.csv");
        Path targetDirectory = Paths.get("/Users/umesh/personal/tutorials/target/Variation_Relations.csv");

        //copy source to target using Files Class
        Files.copy(sourceDirectory, targetDirectory);

    }
}

Above assume that target folder already exists, if “target” directory does not exist, the system will throw NoSuchFileException.

This is not what we might want in many cases. Most of the time we want to Copy files from one directory to another in Java including sub directories.

We will be usingFiles.walkFileTree from NIO Java7 approach to recursively copy directory and all files to another location.

Custom Directory Walker


import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystemLoopException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

import static java.nio.file.FileVisitResult.CONTINUE;
import static java.nio.file.FileVisitResult.SKIP_SUBTREE;

/
public class CustomFileVisitor extends SimpleFileVisitor<Path> {

    final Path source;
    final Path target;

    public CustomFileVisitor(Path source, Path target) {
        this.source = source;
        this.target = target;
    }



    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
            throws IOException
    {
       
        Path newDirectory= target.resolve(source.relativize(dir));
        try{
            Files.copy(dir,newDirectory);
        }
        catch (FileAlreadyExistsException ioException){
            //log it and move
            return SKIP_SUBTREE; // skip processing
        }

        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {

       Path newFile = target.resolve(source.relativize(file));

        try{
            Files.copy(file,newFile);
        }
        catch (IOException ioException){
            //log it and move
        }

        return FileVisitResult.CONTINUE;

    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {

        
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        if (exc instanceof FileSystemLoopException) {
            //log error
        } else {
            //log error
        }
        return CONTINUE;
    }
}

Time to Use our CustomFileVisitor


public class CopyFilesRecursively {

    public static void main(String[] args) throws IOException {

        Path sourceLocation= Paths.get("/Users/umesh/personal/tutorials/source");
        Path targetLocation =Paths.get("/Users/umesh/personal/tutorials/target");

        CustomFileVisitor fileVisitor = new CustomFileVisitor(sourceLocation, targetLocation);
        //You can specify your own FileVisitOption
        Files.walkFileTree(sourceLocation, fileVisitor);
    }
}

If you want to permissions file permissions while copy directories/file using Files.copy(), look out for StandardCopyOption.html#COPY_ATTRIBUTES

2. Copy File Using Apache Commons

Apache Commons provides more easy and clean way to copy files/directories


public class CopyDirectoryApache {

    public static void main(String[] args) throws IOException {

        File sourceLocation= new File("/Users/umesh/personal/tutorials/source");
        File targetLocation = new File("/Users/umesh/personal/tutorials/target");

        FileUtils.copyDirectory(sourceLocation, targetLocation);
    }

In this post, we learned following ways Copy a File or Directory in Java

  1. Use Files.copy for simple operation.
  2. Use custom FileVisitor to recursively copy file or directories.
  3. Use Apache Commons IO.

 

Read our other post to learn How to create a directory in Java.

All the code of this article is available Over on Github. This is a Maven-based project.

References

  1. Files#copy
  2. StandardCopyOption#COPY_ATTRIBUTES
  3. Files#walkFileTree
  4. Apache Commons IO#FileUtils

List all files from a directory in Java

In this post, we will learn how to list all files from a directory in Java. We will be covering following techniques.

  1. Use Java8 Stream API.
  2. Using NIO Walk File Tree.
  3. File Walker.
  4. Apache Commons IO

At the end of this post, we will get a deep understanding of the performance for each of these methods and will discuss the best option to list all files recursively from a directory (subdirectories) in Java.

 

1. Using Java8 Steam API

public class ListFilesByStream {

    public static void main(String[] args) throws IOException {

        Path source = Paths.get("/Users/umesh/personal/tutorials/source");
        Files.walk(source).filter(Files::isRegularFile).forEach(System.out::println);
    }
}

Above method will return a Stream that is lazily populated with Path by walking the file tree rooted at a given starting file.

One of the main advantages of this method is Stream which provides flexibility to apply all different operations on returned stream (e.g. limit, grouping etc.).

 

If you want to list all files based on File Attributes or want to filter it, use Files.find() method by passing  BiPredicate.

 

2. Using FileVisitor walkFileTree

FileVisitor walkFileTree provides another convent way to recursively visit all the files in a file tree. We can use it to walk through the tree to perform any operation

  1. Read Files.
  2. Delete Files
  3. Move Files 

Please read  Deleting Directory in Java and Copy a File or Directory in Java to understand how to use FileVisitor to list all files from a directory in Java.

 

3. Using Apache Commons

public class ListFilesByApache {

    public static void main(String[] args) throws IOException {

        File source = new File("/Users/umesh/personal/tutorials/source");
        List<File> files = (List<File>) FileUtils.listFiles(source, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
        for (File file : files) {
            // work on the files
        }
    }
}

You can also use iterateFiles to iterate in the source directory. While using Apache Commons File Utils, keep in mind following points.

  1. You can use fileFilter and dirFilter to filter files and directories.
  2. Subdirectories will not be included in the search by default, We have used TrueFileFilter.INSTANCE to include all files and subdirectories.
  3. Use FileFilterUtils to filter specific files/ directories from the search.

 

Performance

Benchmarking tests of recursively iterating through the files and directories indicate that Java8 Stream API is the fastest and Apache Commons IO was the slowest.

In case you are ready using Java8 (Which you should), use Java8 Stream API, else use Java7 NIO Walk tree method.

 

All the code of this article is available Over on Github. This is a Maven-based project.

References

  1. FileUtils
  2. Files#walk
  3. Files#find
  4. BiPredicate
  5. FileFilterUtils