'Update java desktop app
I am trying to develop a module that can update my running Java Desktop App. The problem is that I have to replace the actual running jar with another jar, all the while displaying an image and a progress bar with the remaining time of the update process.
One solution I thought about is that I can put a jar in my main jar, and when launching the update process, to extract that second jar which will display the image and the progess bar, and also which will replace the old main jar with a new main jar. My question is if this is possible and how can I do it. I do not have a lot of experience with java and java packaging so if you have any examples or links, it would be of great help for me.
Thank you very much. R.
Solution 1:[1]
Run this code when press UPDATE button ..
if(Desktop.isDesktopSupported()){
try {
Desktop.getDesktop().open(new File("update.jar"));
System.exit(0);
} catch (IOException ex) {
}
}
This will open update.jar and close main.jar. Now run this code from main class of update.jar
if(isUpdateVersionAvailable()) { //first check update from database
try{
Thread.sleep(5000);
} catch(Exception e){
e.printStackTrace();
}
if(copyMainJarFileFromServer()){ //copy newMain.jar from server and paste
new File("main.jar").delete();
rename(new File("newMain.jar"));
}
}
boolean isUpdateVersionAvailable() {
//todo
}
boolean copyMainJarFileFromServer() {
//todo
}
void rename(File file){
file.renameTo(new File("main.jar"));
}
Solution 2:[2]
You can have a starter jar that checks for updates and launches the app from the main jar.
It will show start logo, an image, that standard java can display at start-up. The start0er could also be used to restart the app in another interface language.
package starter;
...
public class StarterApp {
public static void main(String[] args) {
String workDir = System.getProperty("user.dir");
Path mainJar = Paths.get(workDir + "...");
Path nextMainJar = Paths.get(workDir + "...");
if (Files.exists(nextMainJar)) {
Files.copy(nextMainJar, mainJar, StandardCopyAction.REPLACE_EXISTING);
}
URLClassLoader classLoader = new URLClassLoader(new URL[] {mainJar.toURL()});
Class<?> appClass = classLoader.find("mainjar.MainApp");
... instantiate the app
}
As you see the main jar must not be loaded from too early, maybe not be on the class path entirely, and hence the use of a separate ClassLoader. The same might probably be done with the main jar on the class path of the starter app, and using Class.forName("mainjar.MainApp")
. The Class-Path can be specified in META-INF/MANIFEST.MF.
The secundary jars may reside in a lib/ directory.
For those readers wanting more modular, service oriented, updateable apps, one could make an OSGi application, a container for bundles (=jars), that provide exchangable services and life-time control.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Code Kadiya |
Solution 2 | Joop Eggen |