Downloading JAR files at runtime in Java - java

I am wondering if it is possible to have a Java desktop application, on startup, look to some URL, to see if it needs an update, and if so download necessary JAR files, and add them to classpath for the running program.
If the old jars are there, they shouldn't have been loaded into the classloader yet, at this point should they? Is it possible to swap them out before they are loaded w/out restarting the application?

JNLP (Java Web Start) will do all of that for you.

It should be possible. The URLClassLoader is a place to start.

It's possible but prone to error.
A somewhat cleaner approach is to have a "launcher" application which does not rely on any of the updatable JARs do the above and then launch the actual app.
You may want to check out this question for more details on this topic.

Java Web Start is probably your best bet. The required jar files should be identified in the descriptor allowing your to manage the version control.
If you have a dynamic application that needs to discover and download classes dynamically at runtime, then you could look at Dynamic code downloading using RMI.

Java Web Start is a good choice but has some quirks. Notably:
Code which is updated must be downloaded before the program starts. A more modern approach would download updates and apply them at next start.
Default is inside a sandbox. If you need to go outside of that you must sign your code, which is rather cumbersome until you automate the deployment process (or use Netbeans which helps quite a bit).
Problems are not easy to debug - only tool is enabling full trace in the Java Console.
Caching of jars in the client is error prone. When you update, be sure that the URL is unique for each deployment component so the cache will not be used.
But WHEN it works it works pretty well. It is to my knowledge the easiest way to have a centralized version easily updateable of a given Java application.
--
EDIT: It appears that the "start program and transparently download updates if available" functionality is present in the latest Java 6. I have not tried it yet, but will soon.

Related

Self upgrading Java application running on Windows [duplicate]

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.

Implementing a JavaFX application auto update feature

I'm about to write a new cross platform application, and I choosed JavaFX, mainly because of its rich UI libraries (both standard and third party) and it native data binding feature. My application will be deployed via native packaging, both because the lack of PPAPI Java plugin (Chrome will discontinue NPAPI in Chrome 42, which is in beta now) that would prevent an user with Chrome to use WebStart, and because a more "classic" user experience, so WebStart and automatic updates are off the table.
The scenario would be the following:
Application starts and checks for updates
If updates are found, download them and put them in a temporary folder
At application shutdown, write the newly downloaded JAR files over the old ones
Automatically restart the updated application
However, a few question arises in my mind (initially these two, but I could be updating this question as soon as I have more):
Is it safe to do so? Am I risking that somehow the JVM gets crazy if I overwrite some of the JARs already used in the application lifecycle?
I'm struggling to find a way to automatically restart my JavaFX application. Is it even possible?
Thanks everyone for your help.
Take a look at GetDown or UpdateFX. It implements a bootstrap downloader that checks for updates, downloads them and starts your Application as soon it is updated
I've recently created update4j which works with Java 9's module system and meets your requirements.
Perhaps you can try install4j though it's paid. The main feature here that I love the most is the auto update and the way you can configure the installer in an easy way (create Linux - deb,rpm installer, Mac and window installer) and can even package the required jdk version to run your app (this means your users do not need to have that java version installed first before using your app)
Though, it might seem a bit overkill foe your needs

Packaging up a project for deployment - Java

I have a Java application (a quite large one with many external .jar dependencies as well as dependencies on images) and I need to package it up so that someone can double click to run, for example. Or something easy like that.
It uses Java Persistence, so it requires a sql connection which is specified in the Persistence.xml file in the Java Project.
How can I package this up? I was thinking:
the installation process should validate that the user has MySQL installed and if not, direct them to install it
the installation process could ask the user to enter credentials for any database and then I could update the Persistence.xml at run time
These were two ideas I had...but I wasn't sure if there was a known solution to this problem. Any help would be much appreciated!
I think you should take a look at embedded database solutions, like H2. Also, you can package your application using maven's shadowing or jar plugin, having the jar-with-dependencies profile activated.
This will nicely rid you of checking for database servers running on the client machine, and also will give you the proper means of bundling the application in one nice JAR, albeit a little large.
Maven is a build ecosystem and toolset especially designed for building Java applications and executing the code -- and generally doing whatever else you can imagine that's possible to do with and to your code.
It has a rich API for developing plugins and many developers have exploited this feature. There are numerous plugins for building -- and launching -- and packaging your application as well as helping you manage your applications dependencies.
Maven's shadowing comes in the form of maven-shade-plugin, available here. What it does is that it helps you create a single JAR file from all your dependencies. Also, there is the maven-jar-plugin which offers a profile jar-with-dependencies. It is also accessible from here.
H2, on the other hand is a full-fledged RDBMS. This is the website: http://www.h2database.com/html/main.html, and here is a tutorial.
You can find information on embedding the database here:
How to embed H2 database into jar file delivered to the client?
Embedding the Java h2 database programmatically
h2 (embedded mode ) database files problem
I would also suggest you use a combination of H2/Hibernate/Spring which is a very easy setup and provides you with really rich features and an easy-to-use API.
I hope this helps you :)
Building a sophisticated installer that checks lots of dependencies, and runs on lots of different platforms (which I assume you want) is complicated.
I suggest that you look at an installer generator; see What is the best installation tool for java?
Another alternative that I've seen in a few products is to write a (non-GUI) installer or configurer in a scripting language like Perl.
I wrote an installer using ANT, but has no GUI. Also, I used Iz Pack (good option), so I think that depends on how smart do you want it to be, if you are supposed to use it, or a non-technical person, etc.

How to maintain a group of apps with shared libraries that change often?

I have a lot of small-ish Java command-line apps that have to use a vendor set of jars to make their connection to the servers, and while writing these apps has been pretty easy, maintaining them is turning out not to be.
I built them using Maven and some templates that gave me a pretty quick turnaround on development time, but these are all standalone command-line apps so far.
The pain comes from the updates to the vendor servers. Whenever it happens, it forces me to recompile all of these applications with the new jars in play, otherwise I'd get SerialVersionUID Exceptions and borked apps.
What I'm considering
I was thinking that it would be possible to use Maven to generate the app and then throw it in an app server with the server providing a set of shared vendor .jars in whatever /shared classpath it provides. That way I could just update the .jars, restart the server, and everything will likely continue without error.
However, I'm not sure what is required to get that working. They aren't .war's, and most of these apps use other .jars besides my code that isn't usually shared.
Questions
What kinds of deployments work like this?
Are there other ways to do this that I'm missing?
Any tutorials, frameworks, etc., that would make this simpler?
I could just share from my experience. We have 3 ways of overcoming this at the moment. The first way, was our old way, which we still use.
Create a base project which we link to with all our external JARs. The user project when compiled/deployed checks for a newer tag of the base project than it is currently using, and if there's a newer tag, it will fail and force the user to check for the updates and recompile. The benefit of this is that at compile time you can check for new jars, and we get a list of what changed, and reload the jars. In our IDE we can quickly see if anything changed from the API - it has been known to happen, then we can fix and recompile. Also because we're aware of the changes, we can read the changelogs and see if any of the changes affect us, and we then retest parts of the application that depend on these libraries.
We use Maven, but instead of the public repositories, we maintain our own repository, where we only move a library into our local repo after it has been tested - so no surprises for us.
This method is unique to a Tomcat deployment, but we also load libraries via the Context using a classloader. It's not my favorite way to load external jars, but this one works without a deploy. Of course since the compiler isn't there to help you, the new jar can not be 100% compatible with your code, and you can end up with some runtime NoSuchMethodError or ClassNotFoundException expections.
I might be misunderstanding your situation, but if the interface you use in the vendor libraries does not change between versions, couldn't you just keep the jar-files in the classpath of your command-line applications and thereby just overwrite the vendor files when necessary? In that way you would only need to recompile when the interfaces change in a way to break your code?

What's the best way to add a self-update feature to a Java Swing application?

I'm trying to figure out a way to add a self-update feature to a Java/Swing application I'm working on.
Basically I've got a bunch of jar files with extra functionality to be re-deployed to the installed users when they change. Nothing complicated, just check if a new version has been released, download them over HTTP, and then optionally offer to restart the app to the user.
I had a look at webstart, and it could work. But this particular app does some funky stuff with classloading and GC memory settings that don't look like they are supported via webstart, or will at least complicate matters. (It's a tweaked build of JMeter)
I also went down the road of adding in this plugin handler http://swing-fx.blogspot.com/2008/06/add-auto-update-and-plugins-to-your.html, but it is very alpha, and tries to do too much with the usual bugs you get with alpha stuff.
I did the exact same thing. But that was long back so there are probably better tools today.
What I found out I needed was a loader. The loader main program did not have the app jars in classpath. It first downloaded an update if required and then created a custom classloader with the app jars in class path and invoked the main method of the application main class. It is not very complicated. IIRC I needed to do this because the jars could not be overwritten in windows if they were already in classpath.
Hope this helps.
we had a swing app 6 years ago that had self-update. like you suggested,
1)it downloaded the latest jars over http,
2) copied them to a folder.
3) since the swing app is launched using a .BAT file, after user said YES, we would shut down the swing app and look for any files in the update folder. if yes, launch another .BAT file to copy the NEW JARs to the required directory.
4) then re launch the swing app.
Updates, plugins, separation of concern etc. are exactly what OSGi is about - you might want to take a look at this. It won't come free (read: with a steep initial learning curve, especially when you are currently using classloading tricks) at least there are good open source implementations (felix - see felix.apache.org, equinox - see www.eclipse.org and others)
For these implementations autoupdaters are available - if you write your modules correctly it's possible to update at runtime without restarting.
I believe you should look again at Java WebStart, or at least detail the "funky classloading" which you think is going to cause problems (as it might also cause problems with any solution proposed here).
IIRC, you can set command line parameters using Java WebStart ( http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/syntax.html#resources ).
I would definitely first try out Webstart. We've had lots of success launching even the early Eclipse RCP apps using Webstart, and you can probably not get more funky classloading issues than with the OSGI framework (Eclipse Equinox).
Could you perhaps give some more detail in your question about you classloading approach?
Regarding the GC and other VM settings: these are easy to specify in your JNLP (Java Network Launching Protocol) files used by Webstart for launching apps.
The Java Web Start is good choice. The GC stuff is not important. Classloading could be problem. But when you got trusted by user you can grant AllPermisions and you will be able to do custom classloading. Maybe it will be good to reconsider funky stuff with classloading. It is really necessary? Or look at NetBeans. There should be found inspiration for auto-update.

Categories

Resources