edvin / fxlauncher Goto Github PK
View Code? Open in Web Editor NEWAuto updating launcher for JavaFX Applications
License: Apache License 2.0
Auto updating launcher for JavaFX Applications
License: Apache License 2.0
Hi Edvin
Thanks for your work
I have a little question
When i try to run :
java -jar target/app/fxlauncher.jar
janv. 28, 2017 5:12:19 PM fxlauncher.Launcher lambda$start$0
INFOS: Using cache dir ${app.cacheDir}
janv. 28, 2017 5:12:19 PM fxlauncher.Launcher lambda$start$0
AVERTISSEMENT: Error during File Synchronization phase
java.io.FileNotFoundException: http://www.myfowo.com/rondoclient-1.0.0.jar
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLCo
nnection.java:1872)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLCon
nection.java:1474)
at fxlauncher.Launcher.syncFiles(Launcher.java:159)
at fxlauncher.Launcher.lambda$start$0(Launcher.java:78)
at java.lang.Thread.run(Thread.java:745)
I should miss something but can't find the fix
Could you help me ?
Thanks
Quite often the end user doesn't have JRE supported by the app, e.g. user has 1.6 and we need a 1.8.
Therefore it would be handy if FXLauncher could download packaged JRE along with the application jars. This would make user experience even more seamless without asking users to update their Java or investigating why application uses the wrong version of JRE (if multiple are installed) or why JRE installation is broken. Unfortunately this happens quite often.
I couldn't really figure out how to use fxlauncher in a Gradle project containing multiple modules. I added the needed gradle code to the build.gradle file of the parent project but it doesn't copy the build files from the modules to the output directory. Could you help me out please?
P.S.: I am relatively new to Java and coding in general. Sorry if this question is stupid.
As of now we only have a build system plugin for Gradle, but one is sorely needed for Maven as well. I would like to create a common core for all the functionality and have the Gradle/Maven plugins call the core functionality instead of reinventing the wheel for every build system. This would make it even easier to support Leiningen, Kobalt etc as well.
I'm having issues configuring the fxlauncher to download files into the directory where launcher is started from. I tried messing with the cache-dir
setting, and while that worked great, having no cache-dir
argument results into downloading everything to /home/val
. As I understand it from the documentation, not definining cache-dir
should download every file into the current directory, but it does not appear to do that.
Edit: I should specify that I'm using Maven for this project.
FYI, in the README.md file, section "A slimmer alternative", you have a typo, "wether", should be "whether/either".
As discussed in #15, reworking the architecture of fxlauncher would allow to bring new features to it such as:
All of those changes would result in a small native executable (exe, app, etc.) that would download all needed dependencies on the first launch. The native stub wouldn't be bigger than 1 MB for sure, meaning that the launcher would function as a 'web installer'.
Hi,
next idea: it would be cool if the updater would automatically update the manifest file so if we update a dependency library or other files that they could be included via a regular update and the application must not be installed completely new.
Hi,
I am using tornadofx and built a small helloworld app and I know I wish to create a native installer (I am on Linux MINT Kde), I am using gradle. So I found fxlauncher that seems to do more than I originally wanted. I tried running the generateNativeInstaller but i get the following errors
:embedApplicationManifest
:generateNativeInstaller FAILEDFAILURE: Build failed with an exception.
- What went wrong:
Execution failed for task ':generateNativeInstaller'.java.io.IOException: Cannot run program "javapackager": error=2, No such file or directory
- Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.BUILD FAILED
Total time: 12.873 secs
error=2, No such file or directory
2:53:53 AM: External task execution finished 'generateNativeInstaller'.
I did the following to my gradle file, placing it here for transparency.
buildscript {
ext.kotlin_version = '1.0.4'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'no.tornado:fxlauncher-gradle-plugin:1.0.14'
}
}
apply plugin: "kotlin"
apply plugin: 'no.tornado.fxlauncher'
fxlauncher {
applicationVendor 'My Company'
applicationUrl 'http://soemthing/'
applicationMainClass 'com.example.demo.app.MyApp'
acceptDowngrade false
deployTarget '[email protected]:fxldemo'
}
repositories {
mavenLocal()
mavenCentral()
}
apply plugin: 'application'
dependencies {
compile 'no.tornado:tornadofx:1.5.7'
testCompile 'junit:junit:4.12'
}
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'com.example.demo.app.MyApp'
)
}
from configurations.compile.collect { entry -> zipTree(entry) }
}
Can anyone help, I must admit when it comes to java / gradle I wouldn't consider myself a complete expert :-) Although I love Kotlin!
It's a little thing but it would be nice if the slash was added if not there.
I'm mac user and I'm testing you great FXLauncher. I see that FXLauncher downloads jar files into user.home variable and It would be great to set the target folder. In OS X it would be download into the .app folder in fact, because if you drop the icon app to trash, you don't uninstall all the app because all the jars it's outside. If you want to get the dir to save the jars on OS X the code is:
final URL myURL = Client.class.getProtectionDomain().getCodeSource().getLocation();
java.net.URI myURI = null;
try {
myURI = myURL.toURI();
final String dir = java.nio.file.Paths.get(myURI).toFile().toString();
} catch (final URISyntaxException e){
}
Thank you and keep the great job
Hi seems I am missing some thing - getting following error
[INFO] --- exec-maven-plugin:1.4.0:exec (embed-manifest-in-launcher) @ Turn ---
java.io.FileNotFoundException: fxlauncher.jar (The system cannot find the file specified)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.(FileInputStream.java:138)
at sun.tools.jar.Main.run(Main.java:261)
at sun.tools.jar.Main.main(Main.java:1288)
[INFO] ------------------------------------------------------------------------
help requested..
I tried to setup an update repository for my app with github pages. The url (folder) that contains all files is http://sirwindfield.github.io/taskflow/application-support
. I added it in the manifest as app.url
. But resolving the url for the first artifact, guide.jar, doesn't work as I would have expected it. The launcher checks the location http://sirwindfield.github.io/guice.jar
.
I understand that it resolves it correctly (from a programmer's view) but specifying a URL should allow people to be able to use other locations and not only the base url location.
I could not find anything in the fxlauncher docs about changing the icon of either the installer or the installed program. Is there a way?
Hi,
first i think this is a realy cool project because it is easy to use and seems extremly stable.
Maybe this could also be a part of #16, but we found a problem, our customer wanted to have complete installation-bundles to test the application before our update-server was present, we also implemented some new features, and shipped them with the installer and not on the server, but if the new version now checks for an update and client version is newer than the version on the update server if does something wrong, throws errors and afterwards it is not possible to start the application online or offline. would be realy cool, also a possibility for downgrade and updates for the jre would be very good.
regards
børge
https://github.com/edvin/fxlauncher#try-a-native-installer
links to
http://fxsamples.tornado.no/CRMApplication-1.0.exe
which returns a 404.
Downloaded and ran the demo installer on Windows 10. Result is:
java.lang.NullPointerException
at no.tornado.FxlDemo.start(FxlDemo.java:31)
at fxlauncher.Launcher.lambda$launchAppFromManifest$2(Launcher.java:104)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
Hey Edvin,
could you think of any way to make it possible updating the build in jre too?
Besides customizing the updater ui (which was mentioned in another issue) and passing in some jmv arguments, it's the one thing left on my list :)
I thought about using your fxlauncher not just for FX stuff, but also for plain java installations. e.g. running headless as windows service.
Having a headless mode of fxlauncher could also allow such a java service update itself.
In fact, I have it already running on my machine, but it requires some additional efforts to avoid code duplications.
I thought about refactoring Launcher into
Because this leads to a bigger pull request I wanted to ask if you are interested in such a thing at all - or is this out of scope of your library?
Is it somehow possible to notify the user that a new update is available? Like a small Alert in the main application?
I ran into two separate problems where the error shown to the end-user is unfriendly and/or inaccurate.
In both cases, the reported error was a ClassNotFoundException. The download failure was apparently ignored and fxlauncher attempted to run the program even though it had been unable to download the resources.
The desired outcome would be to tell the end-user that the update had failed (unable to get manifest or unable to get required resources) and perhaps mention the HTTP status 403 code when that is the culprit. A stacktrace is, IMO, unfriendly to the end user. Being unable to reach the server at all, as one might get when running offline, should be acceptable if all the resources are present to run the app.
Even when the update succeeds, if the target app terminates abnormally, a stacktrace should not be shown to the end user - they should simply be told that there was a failure and directed to the diagnostic log...and possibly an application-specific URL for getting help from the app developer.
Hey there!
I've been trying to pass an application parameter into my application on several ways now but it kinda ends like I don't find the right way to do it.
I tried passing it via
jvmProperties=--myOption=myValue and
userJvmOptions=--myOption=myValue
also tried appending an paramfile via
-paramfile file
Would you be so kind to help me out here?
thanks so much for this project by the way!!
best regards
patrick
Hello Edvin,
I'm wondering if it's possible to customize the loading and updating scenes.
This is the default loading scene:
and this is the updating scene:
I think right now is possible to do some customization to the "updating" scene via app.xml. Would be awesome if we can provide both custom scenes or something like that.
Again, thanks.
Hi!
I had hard times to get fxlauncher working with my app which uses custom URLStreamHandler which could not be loaded by my app if started using fxlauncher.
It came down to the java.net.URL class which uses Class.forName() which uses the classloader of the callee (which is the URL class). But this classloader is not aware of the URLClassLoader created by fxlauncher and thus is not able to instantiate my URLStreamHandler.
I was able to workaround that by setting my own URLStreamHandlerFactory. But, well, it looks a bit of a hack (see below), because I have to handle a recursive case where (after setting up the URLStreamHandlerFactory) java has to load all the handlers again, even the builtin for file/jar/http/etc ...
And then, who knows which other java classes are using Class.forName .
Long story short, I think we need to create a system class loader and set that up using the startup parameter (-Djava.system.class.loader=myClassLoader) which allows us to add the additional classpath entries directly to this classloader instead of creating a new one.
Basically a URLClassLoader where we unprotect addURL()
What do you think?
`
// old solution: System.setProperty("java.protocol.handler.pkgs", "my.base.class");
URL.setURLStreamHandlerFactory(protocol ->
{
if (recursiveUrlHandler)
{
return null;
}
try
{
recursiveUrlHandler = true;
URLStreamHandler handler = (URLStreamHandler) Utils.forName("my.base.class." + protocol + ".Handler").newInstance();
return handler;
}
catch (Throwable e)
{
return null;
}
finally
{
recursiveUrlHandler = false;
}
});
`
it would be good to enable optional http authentification for the update-server
Basic auth is not working properly for subdirectories, i.e. if the files are stored in: host.de/subdirectory
Maven App URL configuration;
<app.url>http://user:[email protected]/subdirectory</app.url>
=> With this configuration, an exception occurs: FileNotFoundException: http://user:[email protected]/someJar.jar
It seems that the subdirectory is ignored.
I´ve found out that there is a workaround by extending the maven <app.url> configuration
<app.url>http://user:[email protected]/subdirectory/**any_string_workaround**</app.url>
=> Now the path host.de/subdirectory seems to be resolved correctly
Hi!
I wonder if the Windows path construction in FXManifest for the USERLIB is fully correct.
Shouldn't there be a Local/LocalLow or Roaming in the path?
I'd prefer "Local" for now.
`
case win:
replacement = Paths.get(System.getProperty("user.home"))
.resolve("AppData")
.resolve("Local")
.resolve(cacheDir.substring(8))
.toString();
break;
`
What do you think?
I think that this test
if (!Files.isDirectory(file) && file.toString().endsWith(".jar") && !file.getFileName().toString().startsWith("fxlauncher"))
into CreateManifest class is not correct if you have any war as dependency.
In my case, I have a app that runs a embedded jetty with a war (that it's a dependency of the project).
What do you think? Could you create a dependencyExtension param and by default it's only ".jar"?
I'm updating all my projects to use this amazing lib and removing from jnlp, so thank you so much :)
it would be cool to be able to manually add files to the manifest that would be updated during the regular allplication start
Not using the complete url as href fails, when downloading JNLP file and double click it. More and more browsers are not supporting java and webstart directly.
When double clicking the jnlp file, webstart tries to find the dependencies locally, where no fxlauncher.jar exists, when loaded from webserver.
As you have the url in the settings, you could easily add them to the JNLP file, like
<jnlp ... href="**http://javafx.ninja/smartcsv/**SmartCSV.fx.jnlp">
I can give you access to the code if you want, as this code is not public (yet)
ron@frankenstein ~/src/keepassjava $ java -jar target/app/fxlauncher.jar
Sep 17, 2016 10:24:06 AM fxlauncher.Launcher lambda$start$0
INFO: Using cache dir /tmp
Sep 17, 2016 10:24:06 AM fxlauncher.Launcher lambda$start$0
WARNING: Error during File Synchronization phase
java.io.FileNotFoundException: http://ronsmits.org/ron/slf4j-simple.jar
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1836)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at java.net.URL.openStream(URL.java:1045)
at fxlauncher.Launcher.syncFiles(Launcher.java:146)
at fxlauncher.Launcher.lambda$start$0(Launcher.java:64)
at java.lang.Thread.run(Thread.java:745)
Sep 17, 2016 10:24:06 AM fxlauncher.Launcher reportError
WARNING: Error during Create Application phase
java.lang.ClassNotFoundException: org.ronsmits.keepassswing.KeepassJava
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at fxlauncher.Launcher.createApplication(Launcher.java:171)
at fxlauncher.Launcher.lambda$start$0(Launcher.java:70)
at java.lang.Thread.run(Thread.java:745)
ron@frankenstein ~/src/keepassjava $
Allthough the app.cachedir is optional, if you dont have it the directory is created as ${app.cachedir}:
ron@frankenstein ~/src/keepassjava $ ls
${app.cacheDir} keepassJava.iml openkeepass pom.xml README.md sequences src target USERDIR
ron@frankenstein ~/src/keepassjava $
When running from a native installer, the end-user won't see anything logged to stdout. Requiring users to run the program from the command-line to capture the output is not a good end-user experience. It would be great if the launcher would redirect all of its output to a log file that can be easily located by the end-user...perhaps even showing giving them the opportunity to view it or save it to the desktop when an error occurs.
Alter manifest.ts to use a more human-readable timestamp.
Alt 1: a la Maven: Integer: yyyymmddhhmmss
Alt 2: java.sql.Timestamp (ISO-format): String: "yyyy-mm-dd hh:mm:ss"
Question: Is millisecond resolution needed/useful?
Once I had dug into the FxLauncher code a little working on the icon issue I raised, I thought it might be easy to add support for multiple release channels. I really wanted this so I could fully test my app without disturbing my current users. So I dug in and got it working pretty quick.
It uses two setting files - one contains a list of release channels (which would be downloaded from a configured URL) and the other only contains a setting for which channel should be used at launch. The app URLs are different for each channel. The app.xml manifest for each channel specifies a different cacheDir folder, so the downloaded files for the channels are maintained separately. The files are consulted prior to launch to decide which app.xml URL (and thus which cacheDir) to use for launching. Switching channels requires editing the second settings file, but with the addition of a UI component in my app, the user could switch easily between release channels by making a selection in the UI and then restarting.
The implementation currently sits in a layer between the native launcher and FxLauncher. But it would be pretty easy for me to move that into FxLauncher.
Would you be interested in including this feature in FxLauncher?
I'm bumping into an issue running the deployApp task in Gradle from my Windows dev box
What went wrong:
Execution failed for task ':deployApp'.
java.io.IOException: Cannot run program "scp": CreateProcess error=2, The system cannot find the file specified
I've grabbed Putty's pscp, renamed it to scp and have it on my Path. I can manually scp the files from command line, but unsure why Java can't see the binary.
Anyone had any luck with this build task in Windows?
I'm having trouble with the update step when I startup my app. I didn't find any debugging information on the readme....so not sure how to diagnose the problem. Note that the very first time I ran the installer, it updated fine. Since then, the results have not been as good.
Problem 1: My app has 87 jars (most are 3rd-party). When it gets to one of MY jars, it stops updating and tries to run the app. This results in a ClassNotFound error instead of reporting the real problem (which is that the download failed for some reason). I don't understand what is different about my jars.
Problem 2: When I copy MY jars in, it hangs on some of the other 3rd party jars, but in this case, the update hangs. The progress bar goes back and forth (instead of filling in). If I manually copy in the remaining jars from the fxlauncher, then the app starts.
I can't tell if this is some odd network problem, a checksum problem, or something else. Is there a way to turn on some verbose debugging?
Also, how is the checksum in the manifest computed? I tried computing using md5sum and cksum - neither matches the value I see in the manifest.
Thanks!
Chris
It would be really nice if you could pass the URL of the remote app.xml to the Launcher. This would be much easier than trying to replace the app.xml in the fxlauncher.jar file.
Starting the application with webstart without cacheDir information leads into the follwing NPE (you could test it with http://javafx.ninja/smartcsv/SmartCSV.fx.html
java.lang.NullPointerException
at fxlauncher.Launcher.createApplication(Launcher.java:165)
at fxlauncher.Launcher.lambda$start$0(Launcher.java:70)
How could I set the parameter? As argument in the jnlp file has not worked out.
Thanks for your help!
Kindest regards,
Andi
Hi, I'm trying to integrate Fxlauncher with Griffon. Until now, no luck. Seems there is some issues with threading. Any ideas?.
Thanks.
The cache dir option will override the directory the downloaded artifacts are placed in. By default, artifacts are placed in the current working directory. The program parameter --cache-dir
or the manifest entry cacheDir
can be specified to override this.
If the cache dir parameter starts with the magical string USERLIB/
this string will be replaced with an OS specific path. Consider the following parameter value:
fxlauncher.jar --cache-dir=USERLIB/MyApp
The result will be:
OS | Location |
---|---|
Windows | ~/AppData/MyApp |
Mac | ~/Library/Application Support/MyApp |
Linux | ~/.MyApp |
This feature can be helpful in several circumstances:
The program parameter will override any configured value in the manifest, and the default will still be "the current working directory".
If I want parameters passed to the launched application, I can pass them to fxlauncher.Launcher but it doesn't pass them through.
I solved this by adding this line before the app.start(primaryStage); in Launcher.java:
ParametersImpl.registerParameters(app, getParameters());
I know this uses a com.sun class but I didn't see any other way to do it.
Curious to know if you have a plan for future enhancements for this project? Or do you consider it "done"?
There are a couple of features that come immediately to mind when I consider using this in my project:
Thanks!
Chris
I was wondering if it's possible to adjust the plugin so it just updates the main fat jar (made with Shade plugin) instead of copying every possible dependency.
When running copyAppDependencies from the Gradle plugin, I'm bumping into an issue where the local jar dependencies I've defined are not being copied to the fxlauncher folder, and have no entry in app.xml
So in my build.gradle I'll use either 'fileTree' or 'files' to compile my local dependencies (I've tried testing both)
dependencies {
compile fileTree(dir: 'lib', include: '*.jar')
compile files('lib/example1.jar', 'lib/example2.jar')
}
I'm fairly new to Gradle so not sure if I'm missing something obvious.
Cheers.
Hi,
I tried to get the gradle plugin work with my project, but it seems that the project jar isn't build and included. Only the dependencies are so I always get a ClassNotFoundException.
My gradle build file can be found here: https://github.com/frosch95/SmartCSV.fx/blob/fxlauncher/build.gradle
Thanks for your help.
Best regards,
Andi
Steps to reproduce:
I used the example app https://github.com/edvin/fxlauncher#try-a-native-installer
Stack trace:
java.net.UnknownHostException: fxsamples.tornado.no
at java.net.InetAddress.getAllByName0(InetAddress.java:1280)
at java.net.InetAddress.getAllByName(InetAddress.java:1192)
at java.net.InetAddress.getAllByName(InetAddress.java:1126)
at org.apache.http.impl.conn.SystemDefaultDnsResolver.resolve(SystemDefaultDnsResolver.java:45)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:111)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:71)
at tornadofx.Rest.execute(Rest.kt:142)
at tornadofx.Rest.execute$default(Rest.kt:128)
at tornadofx.Rest.get(Rest.kt:96)
at tornadofx.Rest.get$default(Rest.kt:96)
at controller.ContactController.listContacts(ContactController.kt:13)
at view.ContactList$1.invoke(ContactList.kt:23)
at view.ContactList$1.invoke(ContactList.kt:13)
at tornadofx.Component$background$1.call(Component.kt:53)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:745)
Hi Edvin,
I noticed that the link to the Window's Native Installer won't work. Are you able to fix this?
http://fxsamples.tornado.no/CRMApplication-1.0.exe
Thank you for your hard work,
Mike
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.