Tuesday 26 May 2020

Java 14 Features with examples

Java 14, another non-LTS version has been released on March 17, 2020. Let's discuss it's feature with examples.

Here’s the list of Java 14 features:

  • Pattern Matching for instanceof (Preview) – JEP 305
  • Switch Expressions (Standard) – JEP 361
  • Helpful NullPointerExceptions – JEP 358
  • Records (Preview) – JEP 359
  • Text Blocks (Second Preview) – JEP 368
  • Packaging Tool (Incubator) – JEP 343
  • NUMA-Aware Memory Allocation for G1 – JEP 345
  • JFR Event Streaming – JEP 349
  • Non-Volatile Mapped Byte Buffers – JEP 352
  • ZGC on macOS – JEP 364
  • ZGC on Windows – JEP 365
  • Foreign-Memory Access API (Incubator) – JEP 370
1. Pattern Matching for instanceof (Preview) : Before Java 14, we use instanceof and cast to check the object’s type and cast to a variable. For example.

if (obj instanceof String) { // instanceof
      String str = (String) obj; // cast after type check
      if("test".equals(str)){
      }
} else {
     System.out.println("value is not a string");
}

Now using Java 14, we can refactor above code like this.if obj is an instance of String, then it is cast to String and assigned to the binding variable str.

if (obj instanceof String str) { // instanceof, cast and bind the variable
    if("test".equals(str)){
    }
} else {
    System.out.println("value is not a string");
}

2.  Switch Expressions (Standard) – JEP 361 : The switch expression was a preview feature in Java 12 and Java 13; now it is officially JDK standard feature, it means from Java 14 and onward, we can return value via switch expressions (we can use yield or label rules).

private int getSwitchValueViaYield(String mode) {
        int result = switch (mode) {
            case "Developer", "Tester":
                yield 10;
            case "Lead":
                yield 20;
            case "CTO", "CEO", "Director":
System.out.println("Supports multi line block!");
                yield 30;
            default:
                yield -1;
        };
        return result;
 }

3. Helpful NullPointerExceptions – JEP 358 : Improved the description of NullPointerExceptions by telling which variable was null. Add -XX:+ShowCodeDetailsInExceptionMessages option to enable this feature.

public class NullPointerExample {

    public static void main(String[] args) {
        String input = null;
        String result = showLowerCase(input); 
        System.out.println(result);
    }

    public static String showLowerCase(String str){
        return str.toLowerCase();
    }
}

Before JAVA 14 :

D:\Learning\JAVA 14\src>java com/blogspot/edgydebug/NullPointerExample.java
Exception in thread "main" java.lang.NullPointerException
        at com.blogspot.edgydebug.NullPointerExample.showLowerCase(NullPointerExample.java:12)

        at com.blogspot.edgydebug.NullPointerExample.main(NullPointerExample.java:7)



With JAVA 14 (-XX:+ShowCodeDetailsInExceptionMessages) :

D:\Learning\JAVA 14\src>java -XX:+ShowCodeDetailsInExceptionMessages com/blogspot/edgydebug/NullPointerExample.java
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.toLowerCase()" because "<parameter1>" is null
at com.blogspot.edgydebug.NullPointerExample.showLowerCase(NullPointerExample.java:12)
at com.blogspot.edgydebug.NullPointerExample.main(NullPointerExample.java:7)




4. Records (Preview) – JEP 359 : This feature is introduced to simplify the process of custom class creation. With a record you need to simply define a class in the following way.
Student.java :

package com.blogspot.edgydebug;
public record Student(String name, String id) {}

RecordExample.java :

package com.blogspot.edgydebug;

public class RecordExample {

     public static void main(String[] args) {
          Student student = new Student("John","12AWS34");
          System.out.println(student.name() + " "+student.id());
     }

}

D:\Learning\JAVA 14\src>javac --enable-preview --source 14 com\blogspot\edgydebug\Student.java
Note: com\blogspot\edgydebug\Student.java uses preview language features.
Note: Recompile with -Xlint:preview for details.

D:\Learning\JAVA 14\src>java --enable-preview --source 14 com\blogspot\edgydebug\RecordExample.java
Note: com\blogspot\edgydebug\RecordExample.java uses preview language features.
Note: Recompile with -Xlint:preview for details.
John 12AWS34

  • The Java compiler will generate a constructor, private final fields, accessors, equals/hashCode and toString methods automatically.
  • Points related to record class :
  • Records cannot be abstract
  • A record can neither extend a class nor it can be extended by another class. It’s a final class.
  • Records cannot extend any other class and cannot define instance fields inside the body. Instance fields must be defined in the state description only
  • The body of a record allows static fields and methods
  • Declared fields are private and final

5. Text Blocks (Second Preview) – JEP 368 : Text Blocks were introduced as a preview feature in Java 13. The text block helps easy creation of multiline string literals. It’s useful in easily creating HTML and JSON or SQL query strings.
For example :
package com.blogspot.edgydebug;
public class TextBlockExample {
      public static void main(String[] args) {
                String text = """
                                    <html>
                                   <body>\
                                   <p>Hello, '\s' World</p>\
                                  </body>
                                  </html>
                                  """;
               System.out.println(text);
   }
}


Output :
D:\Learning\JAVA 14\src>java --enable-preview --source 14 com\blogspot\edgydebug\TextBlockExample.java
Note: com\blogspot\edgydebug\TextBlockExample.java uses preview language features.
Note: Recompile with -Xlint:preview for details.
<html>
<body> <p>Hello, ' ' World</p> </body>
</html>

6. Packaging Tool (Incubator) – JEP 343 :

New jpackage tool to package a Java application into a platform-specific package.
Linux: deb and rpm
macOS: pkg and dmg
Windows: msi and exe (package the JAR file into an exe file on Windows)


7. NUMA-Aware Memory Allocation for G1 – JEP 345 : New NUMA-aware memory allocation mode, improves the G1 performance on large machines.Add +XX:+UseNUMA option to enable it.

8. JFR Event Streaming – JEP 349 : Improved the existing JFR (JDK Flight Recorder) to support event streaming, it means now we can stream the JFR events in real-time, without the need to dump the recorded events to disk and parse it manually.

9. Non-Volatile Mapped Byte Buffers – JEP 352 : Improved FileChannel API to create MappedByteBuffer that access to non-volatile memory (NVM)  a memory that can retrieve stored data even after having been power cycled. For example, this feature ensures that any changes which might still be in the cache are written back to memory.

10. ZGC on macOS – JEP 364 : Java 11 – JEP 333 introduced the Z Garbage Collector (ZGC) on Linux, and now it ports to macOS.

11. ZGC on Windows – JEP 365 : Java 11 – JEP 333 introduced the Z Garbage Collector (ZGC) on Linux, and now it ports to Windows version >= 1803.

12. Foreign-Memory Access API (Incubator) – JEP 370 : Introduce an API to allow Java programs to safely and efficiently access foreign memory outside of the Java heap.

Friday 22 May 2020

Containerizing Angular application using Docker

Let's containerize angular application using Docker.

Pre-requisites for exercise:


  1. Install Docker for Desktop
  2. Install Node js
  3. Install Angular CLI (make sure you have the latest version of Angular CLI installed).

You must have an Angular application to containerize it. If you already have the application, then you can skip Angular Application creation step.

Create Angular Application


1. Create an folder/directory on your machine, let's say HelloWorldApp.
2. Open command-line and navigate to this directory.
3. Create Angular application using ng new HelloWorldAngular command.

Angular Application Creation



4. Navigate to created project folder cd HelloWorldAngular
5. To make sure app is running. run ng serve command here, then navigate to https://locahost:4200 in your browser.
6. Feel free to make any changes (add new components/modify existing components.

Creating Docker file


To create a docker image we must create the docker file and specify the required steps to build the image.
1. Create the Dockerfile (name of the file must be Dockerfile) without any extension in the root of your project.
2. Let's update our empty Dockerfile.

Note : Here we are going to use multistage build to create an optimized image.


Below is the detail of Dockerfile instructions.

FROM node:latest As builder

This line will tell the docker to pull the node image with tag latest if the images don't exist. We are also giving a friendly name (alias) builder to this image so we can refer it later.

WORKDIR /usr/src/app

This WORKDIR command will create the working directory in our docker image. going forward any command will be run in the context of this directory.

COPY package.json package-lock.json ./

This COPY command will copy package.json and package-lock.json from our current directory to the root of our working directory inside a container which is /usr/src/app.

RUN npm install

This RUN command will restore node_modules define in our package.json

COPY . .
This COPY command copies all the files from our current directory to the container working directory. this will copy all our source files.

RUN npm run build --prod

This command will build our angular project in production mode and create production ready files in dist/HelloWorldAngular folder.

FROM nginx:latest

This line will create a second stage nginx container where we will copy the compiled output from our build stage.

COPY --from=builder /usr/src/app/dist/HelloWorldAngular/ /usr/share/nginx/html

This is the final command of our docker file. This will copy the compiled angular app from builder stage path /usr/src/app/dist/HelloWorldAngular/ to nginx container. 

Complete Dockerfile


Complete Dockerfile

Building a docker image


Navigate to the project folder in command prompt and run the below command to build the image.


docker build . -t  jagdevsingh2020/helloworldappimage

This command will look for a docker file in the current directory and create the image. The  default convention is <DockerHubUsername>/<ImageName> e.g. jagdevsingh2020/helloworldappimage. jagdevsingh2020 is my docker hub username and helloworldappimage is the image name.
Run docker images command to verify above image. This will list all the Docker images on your machine.

Running a container


You can run the docker image using the below command.

docker run -p 4000:80 
 jagdevsingh2020/helloworldappimage

Here -p flag publishes all exposed ports to the host interfaces. we are publishing container port 80 to host 4000 port.

Navigate to your browser with http://localhost:4000 to verify your application.

Happy Learning !!