Monday, 10 June 2019

Java: Reload the classes dynamically


Using Java class loaders, you can load new code without redeploying the complete application. This is also called as hot deployment. Hot deployments don’t make the application down to deploy new changes.
We are going to develop an application, whenever user requests for reloading of classes, it reloads the classes from repository.

Step 1: Create a jar file ‘dependency.jar’.
Create ProductInfo.java by following below directory structure.

ProductInfo.java
package com.sample.app.model;

public class ProductInfo {

 private static final String VERSION = "1";

 static {
  System.out.println("Loading version " + VERSION + " of the class");
 }

 public String toString() {
  return "I am instantiated from version " + VERSION + " of class";
 }

}

$tree
.
└── com
    └── sample
        └── app
            └── model
                └── ProductInfo.java

4 directories, 1 file


Compile ProductInfo.java by executing below command.

javac com/sample/app/model/ProductInfo.java
$javac com/sample/app/model/ProductInfo.java 
$
$tree
.
└── com
    └── sample
        └── app
            └── model
                ├── ProductInfo.class
                └── ProductInfo.java

4 directories, 2 files


Create product.jar file by executing below command.
jar -cvf product.jar *
$jar -cvf product.jar *
added manifest
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/sample/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/model/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/model/ProductInfo.class(in = 638) (out= 407)(deflated 36%)
adding: com/sample/app/model/ProductInfo.java(in = 291) (out= 193)(deflated 33%)
$
$tree
.
├── com
│   └── sample
│       └── app
│           └── model
│               ├── ProductInfo.class
│               └── ProductInfo.java
└── product.jar

4 directories, 3 files


Step 2: Implement App.java like below.

App.java    
package com.sample.app;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLClassLoader;

public class App {

 private static Class productInfoClazz;

 private static final String REPOSIOTY_PATH = "file:/Users/krishna/Documents/TechnicalDocuments/Java/examples/classloading/product.jar";

 public static void main(String args[])
   throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {

  URL url1 = new URL(REPOSIOTY_PATH);
  URLClassLoader classLoader1 = new URLClassLoader(new URL[] { url1 });

  productInfoClazz = classLoader1.loadClass("com.sample.app.model.ProductInfo");

  Object obj1 = productInfoClazz.newInstance();

  System.out.println(obj1);

  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

  while (true) {
   System.out.println("\n*****************************");
   System.out.println("Choose an option from below");
   System.out.println("reload: To reload the class");
   System.out.println("quit: To quit the application ");
   System.out.println("*****************************");

   String input = br.readLine();

   switch (input) {
   case "reload":

    classLoader1 = new URLClassLoader(new URL[] { url1 });

    productInfoClazz = Class.forName("com.sample.app.model.ProductInfo", true, classLoader1);
    obj1 = productInfoClazz.newInstance();

    System.out.println(obj1);
    break;

   case "quit":
    System.exit(0);
   default:
    System.out.println("Invalid option");

   }

  }

 }
}
Run App.java.

You can see below messages in console.
Loading version 1 of the class
I am instantiated from version 1 of class

*****************************
Choose an option from below
reload: To reload the class
quit: To quit the application 
*****************************


Step 3: Update ProductInfo.java class like below.

ProductInfo.java
package com.sample.app.model;

public class ProductInfo {

 private static final String VERSION = "2";

 static {
  System.out.println("Loading version " + VERSION + " of the class");
 }

 public String toString() {
  return "I am instantiated from version " + VERSION + " of class";
 }

}


Recompile ProductInfo.java and regenerate product.jar file.

$javac com/sample/app/model/ProductInfo.java
$
$jar -cvf product.jar *
added manifest
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/sample/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/model/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/model/ProductInfo.class(in = 638) (out= 407)(deflated 36%)
adding: com/sample/app/model/ProductInfo.java(in = 291) (out= 194)(deflated 33%)

Now go to the console window of App.java application and given the option as ‘reload’.

reload
Loading version 2 of the class
I am instantiated from version 2 of class


Total console output of App.java is given below.

Loading version 1 of the class
I am instantiated from version 1 of class

*****************************
Choose an option from below
reload: To reload the class
quit: To quit the application 
*****************************
reload
Loading version 2 of the class
I am instantiated from version 2 of class

*****************************
Choose an option from below
reload: To reload the class
quit: To quit the application 
*****************************




Previous                                                 Next                                                 Home

No comments:

Post a Comment