I would like to implement a java application (server application) that can download a new version (.jar file) from a given url, and then update itself at runtime.
What is the best way to do this and is it possible?
I guess that the application can download a new .jar file and start it. But how should I do the handover, e.g. know when the new application is started and then exit. Or is there a better way to do this?
The basic structure of a solution is as follows:
There is a main loop responsible for repeatedly loading the latest version of the app (if required) and launching it.
The application does its thing, but periodically checks the download URL. If it detects a new version it exits back to the launcher.
There are a number of ways you could implement this. For example:
The launcher could be a wrapper script or binary application that starts a new JVM to run the application from a JAR file that gets replaced.
The launcher could be a Java application that creates a classloader for the new JAR, loads an entrypoint class and calls some method on it. If you do it this way, you have to watch for classloader storage leaks, but that's not difficult. (You just need to make sure that no objects with classes loaded from the JAR are reachable after you relaunch.)
The advantages of the external wrapper approach are:
you only need one JAR,
you can replace the entire Java app,
any secondary threads created by the app, etc will go away without special shutdown logic, and
you can also deal with recovery from application crashes, etc.
The second approach requires two JARs, but has the following advantages:
the solution is pure Java and portable,
the changeover will be quicker, and
you can more easily retain state across the restart (modulo leakage issues).
The "best" way depends on your specific requirements.
It should also be noted that:
There are security risks with auto-updating. In general, if the server that provides the updates is compromised, or if the mechanisms for providing the updates are susceptible to attack, then auto-updating can lead to a compromise of the client(s).
Pushing a update to a client that cause damage to the client could have legal risks, and risks to your business' reputation.
If you can find a way to avoid reinventing the wheel, that would be good. See the other answers for suggestions.
I am currently developing a JAVA Linux Daemon and also had the need to implement an auto-update mechanism. I wanted to limit my application to one jar file, and came up with a simple solution:
Pack the updater application in the update itself.
Application: When the application detects a newer version it does the following:
Download update (Zipfile)
Extract Application and ApplicationUpdater (all in the zipfile)
Run updater
ApplicationUpdater: When the updater runs it does the following:
Stop the Application (in my case a daemon via init.d)
Copy the downloaded jar file to overwrite current Application
Start the Application
Cleanup.
Hope it helps someone.
I've recently created update4j which is fully compatible with Java 9's module system.
It will seamlessly start the new version without a restart.
This is a known problem and I recommend against reinventing a wheel - don't write your own hack, just use what other people have already done.
Two situations you need to consider:
App needs to be self-updatable and keep running even during update (server app, embedded apps). Go with OSGi: Bundles or Equinox p2.
App is a desktop app and has an installer. There are many installers with update option. Check installers list.
I've written a Java application that can load plugins at runtime and start using them immediately, inspired by a similar mechanism in jEdit. jEdit is open source so you have the option of looking to see how it works.
The solution uses a custom ClassLoader to load files from the jar. Once they're loaded you can invoke some method from the new jar that will act as its main method. Then the tricky part is making sure you get rid of all references to the old code so that it can be garbage collected. I'm not quite an expert on that part, I've made it work but it wasn't easy.
First way: use tomcat and it's deploy facilities.
Second way: to split application on two parts (functional and update) and let update part replace function part.
Third way: In your server appliction just download new version, then old version releases bound port, then old version runs new version (starts process), then old version sends a request on application port to the new version to delete old version, old version terminates and new version deletes old version. Like this:
This isn't necessarily the best way, but it might work for you.
You can write a bootstrap application (ala the World of Warcraft launcher, if you've played WoW). That bootstrap is responsible for checking for updates.
If an update is available, it will offer it to the user, handle the download, installation, etc.
If the application is up to date, it will allow the user to launch the application
Optionally, you can allow the user to launch the application, even if it isn't up to date
This way you don't have to worry about forcing an exit of your application.
If your application is web based, and if it is important that they have an up to date client, then you can also do version checks while the application runs. You can do them at intervals, while performing normal communication with the server (some or all calls), or both.
For a product I recently worked on, we did version checks upon launch (without a boot strapper app, but before the main window appeared), and during calls to the server. When the client was out of date, we relied on the user to quit manually, but forbid any action against the server.
Please note that I don't know if Java can invoke UI code before you bring up your main window. We were using C#/WPF.
If you build your application using Equinox plugins, you can use the P2 Provisioning System to get a ready-made solution to this problem. This will require the server to restart itself after an update.
I see a security problem when downloading a new jar (etc.), e.g., a man in the middle attack. You always have to sign your downloadable update.
On JAX2015, Adam Bien told about using JGit for updating the binaries.
Sadly I could not find any tutorials.
Source in German.
Adam Bien created the updater see here
I forked it here with some javaFX frontend. I am also working on an automatic signing.
What I want to do is to have my main Java application to update another java application using Java Web Start and then run the second application "silently" upon user request.
I know Runtime.exec to call javaws and silently import the second application in the cache. I can do that when the first application runs and then I am sure I have an updated copy of the second application. My problem is how to run the second application without showing the Java Web start "Verifying application" window.
Doing some research I see no way to avoid that if I execute the .jnlp. I am wondering whether I can run the second application calling directly the downloaded jar files by passing Java Web Start.
Any Ideas?
Thanks
You have basically two possibilities here:
you can use the JNLP Api service and use the DownloadService;
or use the URLClassLoader and load the remote class.
I don't know if this what you want to do, may be for you it seems as a trick around, forgive me if so...
Why don't you run it as exe, by using process object?
Process process = new ProcessBuilder("C:\\...Desktop\\MyExe.exe").start();
And you can convert your app to exe easily by using jsmooth
Its possible to move my app hosted in appspot.com to another server.
If so what are the steps and requirements?
My app its done in eclipse using gae java
Thanks in advance!
It's not possible to take your code exactly as it is now, set it up in a different server and work. Even if your whole code is App Engine agnostic, your datastore models are probably not. Thus, first you need to define which is the development environment you want to move to, and then modify your code to properly work on that.
As far as your current data are concerned, you need to create a "migration tool" that will get the data from App Engine and import them to your new environment.
Hope this helps.
Google Appengine doesn't provide any controls over what host(s) your code runs on. If you've set up a paid app, you can change the memory/cpu profile on the Application Settings which could be assumed to require an instance of your app to run in a different virtual machine. You can also shutdown an instance (on the Instances page). If there are no instances running, a new one will be created on the next request, and is unlikely to run on the same virtual machine as the one that was running the app before.
I have an application which has a purpose to run when the user first runs their computer.
However, I'd like to make a check box on the app that enables/disables the application loading when the system is started. Is there any way to do this?
Thanks
I recommend you to create a service under windows. My suggestion is http://winrun4j.sourceforge.net/
This question has been discussed in SO time ago:
Code for Auto starting a java application on windows startup
Auto startup for java desktop application?
However, maybe the easier solution is to create a batch file,like suggested in the first link, to run your application as the user logs in.
If you want to enable/disable the startup through a checkbox, the first and simplest solution that comes to my mind is this: you can make a method, invoked by the checkbox listener, that edits the batch file and enables/disables the line used to run the application, in the batch file.
If you have Windows 7, read this tutorial.
I have a java application where I want to check to see if an application is running. If it is not running, I want to start it. If it is running, I want to kill it and then restart it.
Can someone tell me how to do this? I can start/stop the program easily enough, with the ProcessBuilder. But I cannot detect a process that is already running.
Thanks for your help!
John
Without the cooperation of the application (ideally have it listening on a network port), that may be impossible (your Java app might not have the rights to kill the app) and requires OS-specific code. On Linux, you'd uase the ps and kill commands.
Might sound silly, but you can create a file with a known name on application startup. Doesn't need to contain anything. To check if your application is running, check if that file exists.
Is the other application (the process you are monitoring) under your responsibility? If so, you can use a method I used in some high-availability system a few years back:
Open a connection to that other application and "ping" it. If the other application does not respond within a given timeout, it is either down or "hung", which is as bad (and something you can't detect through process monitoring.
Opening a connection can be done using sockets, or though more sophisticated protocols (SOAP?).
An alternative is to have the application send a "I'm alive" message every so often. If you haven't received it in some time - your application needs restarting.
In order to actually "kill" the other process, you can keep the Process instance you get from the exec() method, and destroy() it when you so choose.
Thanks for the replies. That was what I was afraid off. We are trying NOT to add more things to the application that I want to start up. We are basically trying to add a remote control web interface to a collection of applications.
The web server application that I am writing would basically start/stop 3 apps that all talk to each other to achieve a goal. If my web server starts and stops them, all is well. But if, for some reason they are already running when I try to start them bad things happen.
It is something I know I could handle with Visual Studio (C++/C#/etc). But this project has to be written in java due to a platform independence requirement.
Thanks for your help everyone!