Win a copy of Programmer's Guide to Java SE 8 Oracle Certified Associate (OCA) this week in the OCAJP forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

how to hot deploy jar files

 
chris liao
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am in trouble, and very painful! My boss want me to design hot deploy
for his application,which is a small java server and need hot-deploy jars
But,util now, i don't know about hot-deploy!

Hand-masters,please help me, What should i do ? write some classLoader or other? I hope you give me some very userful source code.
Thanks!
 
chris liao
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
for this, I wrote a classLoader, below is source code:

package org.jmin.bridge.loader;

import java.io.*;
import java.net.*;
import java.util.*;
import org.jmin.bridge.deploy.*;
import org.jmin.bridge.config.*;
import org.jmin.logger.Logger;

public class RuntimeLoader extends URLClassLoader{
private static Logger logger = Logger.getLogger(RuntimeLoader.class);
private static RuntimeLoader loader = null;
private static List urlList = new LinkedList();

public static RuntimeLoader getClassLoader(){
if(loader == null){
loader= new RuntimeLoader(AutoDetector.getInstance().getURLs(),
getSystemClassLoader());
} else {
URL[] urls = AutoDetector.getInstance().getURLs();
for(int i=0;i < urls.length;i++){
loader.addURL(urls[i]);
}
}
return loader;
}

public RuntimeLoader(URL[] urls) {
super(urls);
}

public Class loadClass(String clsname)
throws ClassNotFoundException {
return super.loadClass(clsname);
}

private List getList(){
if(urlList == null)
urlList = new LinkedList();
return urlList;
}

public RuntimeLoader(URL[] urls,ClassLoader parent) {
super(urls,parent);
}

public RuntimeLoader(URL[] urls, ClassLoader parent,
URLStreamHandlerFactory factory) {
super(urls,parent,factory);
}

public void addURL(URL url) {
if(!getList().contains(url)){
logger.debug("add url: " +url);
super.addURL(url);
getList().add(url);
}
}

protected void finalize() throws Throwable{
super.finalize();
}

private ClassLoader getParentClassLoader(){
if(loader == null)
return (OBClassLoader.class).getClassLoader();
else
return loader;
}

public static ClassLoader getSystemClassLoader(){
return (OBClassLoader.class).getClassLoader();
}
}
 
chris liao
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
and I wrote a Detector, source code is below:

package org.jmin.bridge.deploy;

import java.io.*;
import java.net.*;
import java.util.*;

import org.jmin.bridge.util.*;
import org.jmin.bridge.config.*;
import org.jmin.bridge.core.*;
import org.jmin.bridge.loader.*;
import org.jmin.bridge.common.*;
import org.jmin.bridge.server.*;
import org.jmin.logger.Logger;

public class AutoDetector extends Thread {
private static Logger logger = Logger.getLogger(AutoDetector.class);

private static String deployFolder = null;
private static String workFolder = null;
private static int PoolDetectTime =0;
private static AutoDetector deploy = null;

private File detectFolder = null;
private List currentFileList = null;
private List lastFileList = null;
private Map urlMap = null;

private Map fileServiceMap = null;
private Thread fatherThread = null;

static{
PoolDetectTime =
Config.getInstance().
getInt(ConfigKey.KEY_Thread_Pool_Detect_Time,
ConfigConstants.Thread_Pool_Detect_Time);

deployFolder = Config.getInstance().
getString(
ConfigKey.KEY_Deploy_Path);
workFolder = Config.getInstance().
getString(
ConfigKey.KEY_Work_Path);

deployFolder = "D:\\bridge\\deploy";// test
workFolder = "D:\\bridge\\work";//test

if(Util.isNull(deployFolder)&& CurrentRole.isServerRole()){
deployFolder = getDeployPath();
}

if(Util.isNull(workFolder)&& CurrentRole.isServerRole()){
workFolder = getWorkPath();
}

if(!Util.isNull(deployFolder) && !deployFolder.endsWith("\\")){
deployFolder = deployFolder +"\\";
}

if(!Util.isNull(workFolder) && !workFolder.endsWith("\\")){
workFolder = workFolder +"\\";
}
}

public static AutoDetector getInstance(){
if(deploy == null)
deploy = new AutoDetector();
return deploy;
}

public AutoDetector() {
this.prepare();
this.currentFileList = new LinkedList();
this.lastFileList = new LinkedList();
this.urlMap = new Hashtable();
this.fileServiceMap = new Hashtable();
this.fatherThread = Thread.currentThread();
if(!Util.isNull(workFolder) && !Util.isNull(workFolder)){
this.start();
}
}

private void prepare(){
detectFolder = new File(deployFolder);
if(!detectFolder.exists()&& CurrentRole.isServerRole()){
detectFolder.mkdirs();
}

File work = new File(workFolder);
if(!work.exists()&& CurrentRole.isServerRole()){
work.mkdirs();
}else{
File[] files = work.listFiles();
for(int i =0;i<files.length;i++)
files[i].delete();
}
}

public void run(){
ThreadPool.getInstance().push(fatherThread,this);
while(fatherThread.isAlive()){
this.getDeployFileList();
this.detectNewFile();
this.detectDelFile();
this.detectUpdateFile();
this.storeDeployFileList();
this.wait(PoolDetectTime);
}
}

private void wait(int time){
try{
Thread.sleep(time);
}catch(Exception e){
}
}

private void detectNewFile(){
for(int i =0;i< currentFileList.size();i++){
if(!lastFileList.contains(currentFileList.get(i))){
try{
FilePair file = (FilePair)currentFileList.get(i);
String filename = file.getFileName();
String wkFile = concludeWkPath(filename);
this.copyFile(file.getFile(),wkFile);
logger.debug("deploy file: " + filename);
Map map = XMLParser.parse(wkFile);
addNewService(filename,map);
addNewURL(filename,new File(wkFile).toURL());

}catch(Exception e){
e.printStackTrace();
}
}
}
}

private void addNewURL(String filename,URL ulr){
urlMap.put(filename,ulr);
}

private void removeURL(String filename){
urlMap.remove(filename);
}

private void detectDelFile(){
for(int i =0;i< lastFileList.size();i++){
if(!currentFileList.contains(lastFileList.get(i))){
FilePair file = (FilePair)lastFileList.get(i);
String filename = file.getFileName();
removeService(filename);
removeURL(filename);
logger.debug("undeploy file: " + filename);
}
}
}

private void detectUpdateFile(){
for(int i=0; i < lastFileList.size();i++){
try{
FilePair lastFile = (FilePair)lastFileList.get(i);
FilePair currentFile = getCurrentFile(lastFile);
if(currentFile != null && (currentFile.isModified(lastFile))){
String filename = currentFile.getFileName();
logger.debug("redeploy file: " + filename);
String wkFile = concludeWkPath(filename);
this.copyFile(currentFile.getFile(),wkFile);
Map map = XMLParser.parse(wkFile);
addNewService(filename,map);
addNewURL(filename,new File(wkFile).toURL());

}
}catch(Exception e){
}
}
}


private FilePair getCurrentFile(FilePair pair){
FilePair currentPair = null;
for(int i = 0;i < currentFileList.size();i++){
FilePair temp = (FilePair)currentFileList.get(i);
if(temp.equals(pair)){
currentPair = temp;
break;
}
}
return currentPair;
}

private synchronized void getDeployFileList(){
currentFileList.clear();
File[] files = detectFolder.listFiles();
for(int i = 0;i < files.length;i++){
if(files[i].getName().endsWith("jar") ||
files[i].getName().endsWith("zip")){
currentFileList.add(new FilePair(files[i]));
}
}
}

private void storeDeployFileList(){
this.lastFileList.clear();
this.lastFileList.addAll(currentFileList);
}

private String concludeWkPath(String shortname){
return workFolder + Counter.getValue()+ shortname;
}

private void copyFile(File deployJar, String file2)
throws IOException,FileNotFoundException{
FileInputStream deployjar = new FileInputStream(deployJar);
FileOutputStream workjar = new FileOutputStream(file2);
while(true){
int byteValue = deployjar.read();
if(byteValue == -1)
break;
workjar.write(byteValue);
}
workjar.close();
deployjar.close();
}

private static String getDeployPath(){
String path = CurrentRole.getAppPath();
if(!path.substring(path.length()).equals("\\")){
path = path + "\\";
}
path = path + "deploy";
File deployDict = new File(path);
if(!deployDict.exists()){
logger.debug("create folder: " + path);
deployDict.mkdirs();
}
return path;
}

private static String getWorkPath(){
String path = CurrentRole.getAppPath();
if(!path.substring(path.length()).equals("\\")){
path = path + "\\";
}
path = path + "work";
File workDict = new File(path);
if(!workDict.exists()){
logger.debug("create folder: " + path);
workDict.mkdirs();
}
return path;
}

private void addNewService(String file, Map newMap){
removeService(file);
fileServiceMap.put(file,newMap);
addServiceToManager(newMap);
}

private void removeService(String file){
Map oldMap = (Map)fileServiceMap.get(file);
if(oldMap != null){
removeServiceFromManager(oldMap);
fileServiceMap.remove(file);
}
}

private void addServiceToManager(Map map){
Iterator it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry entry = (Map.Entry)it.next();
String key = (String)entry.getKey();
String value = (String)entry.getValue();
ServiceManager.getInstance().addServiceClass(key,value);
}
}

private void removeServiceFromManager(Map map){
Iterator it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry entry = (Map.Entry)it.next();
String key = (String)entry.getKey();
ServiceManager.getInstance().remove(key);
}
}

private synchronized Collection getWorkFileList(){
return urlMap.values();
}

public URL[] getURLs(){
Collection col = getWorkFileList();
URL[] arry = new URL[col.size()];
Iterator it = col.iterator();
int i = 0;
while(it.hasNext()){
arry[i]=(URL)it.next();
}
return arry;
}
}

class Counter {
private static long value = 1;
public static long getValue(){
return value++;
}
}
 
chris liao
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
when load some class:

ClassNotFoundException is throwed.
 
Tony Morris
Ranch Hand
Posts: 1608
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I didn't go through your code, but "hot loading" (definition assumed) is really quite easy. The main point is that you must load classes with a new class loader each time you use the, since classes cannot be unloaded from class loaders, and so they cannot be redefined within the same class loader.
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Anyone know if you must write a custom class loader to do this? I dug through JUnit to find the one it uses and it is pretty simple, but I didn't try to figure out why they needed a custom one at all.

What's a common way to make a whole application start using a new class loader? If you're doing plain old "new Object()" all over the place you'll just keep using the loader that loaded the class you're in, right? Do you need a global loader or a factory that knows when laoders change?
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic