Skip to content

Instantly share code, notes, and snippets.

@krmahadevan
Last active September 23, 2017 16:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save krmahadevan/4649471 to your computer and use it in GitHub Desktop.
Save krmahadevan/4649471 to your computer and use it in GitHub Desktop.
This is a standalone java application that can continuously monitor a another JVM and if the JVM crashes or exits it can re-spawn it again.
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecuteResultHandler;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.exec.ShutdownHookProcessDestroyer;
/**
* This is a standalone class that essentially helps spawn a jar given via the commandline along with the
* arguments that are required by the jar.
*
*/
public class JarSpawner {
/**
* This class is internally used to save the absolute file path of a given jar and its command line arguments.
*
*/
static class JarFileAttributes {
public File getFilePath() {
return filePath;
}
public String getJarArgs() {
return jarArgs;
}
@Override
public String toString() {
return "JarFileAttributes [filePath=" + filePath.getAbsolutePath() + ", jarArgs=" + jarArgs + "]";
}
private File filePath;
private String jarArgs;
public JarFileAttributes(File filePath, String jarArgs) {
this.filePath = filePath;
this.jarArgs = jarArgs;
}
}
public static void main(String[] args) throws ExecuteException, IOException, InterruptedException {
JarFileAttributes attributes = getJarFile(args);
Properties properties = new Properties();
properties.load(JarSpawner.class.getResourceAsStream("/spawner.properties"));
long interval = Long.parseLong((String) properties.get("defaultInterval"));
while (true) {
continuouslyRestart(attributes, interval);
Thread.sleep(interval);
System.out.println("Application exited. Respawning the application again");
}
}
/**
* This method parses the commandline argument and extracts the jar file and its arguments.
* @param args - The command line arguments that needs to be parsed.
* @return - A {@link JarFileAttributes} object that represents the path of the jar file and its command line args.
*/
public static JarFileAttributes getJarFile(String[] args) {
File file = null;
boolean wasJarFound = false;
int jarArgsIndex = 0;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < args.length; i++) {
if (args[i].contains(".jar")) {
file = new File(args[i]);
wasJarFound = true;
jarArgsIndex = i + 1;
}
}
if (!wasJarFound) {
throw new RuntimeException("Please specify the jar file");
}
for (int i = jarArgsIndex; i < args.length; i++) {
sb.append(args[i]).append(" ");
}
return new JarFileAttributes(file, sb.toString());
}
/**
* This method spawns a jar, and waits for it to exit [either cleanly or forcibly]
*
* @param attributes - {@link JarFileAttributes} that represents the jar file path and its arguments.
* @param interval - How often should the application check if the jar is still running or if it exit.
* @throws ExecuteException
* @throws IOException
* @throws InterruptedException
*/
public static void continuouslyRestart(JarFileAttributes attributes, long interval)
throws ExecuteException, IOException, InterruptedException {
System.out.println("Spawning the application ");
CommandLine cmdLine = new CommandLine("java");
cmdLine.addArgument("-jar");
cmdLine.addArguments(attributes.getFilePath().getAbsolutePath() + " " + attributes.getJarArgs());
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(new PumpStreamHandler());
executor.setProcessDestroyer(new ShutdownHookProcessDestroyer());
DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
executor.execute(cmdLine, handler);
while (!handler.hasResult()) {
Thread.sleep(interval);
}
if (handler.hasResult()) {
ExecuteException e = handler.getException();
}
}
}
@krmahadevan
Copy link
Author

The properties file [spawner.properties] has just the below contents in it:

How often should the JVM spawner check to see if the client application is running or not.

By default we will check ONLY once in 10 minutes.

defaultInterval=600000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment