https://kotlinlang.org logo
r

ron

03/27/2017, 9:51 AM
[Fxlauncher][1] is a auto updating launcher for javafx programs. Download a small jar (around 18Kb), start it and it will download the actual application and run it. Every time you start the small jar it will check if there is a newer version and download it automatically. So fxlauncher is a fun project and it will make keeping a desktop application uptodate easy. Setting up fxlauncher from Maven was not so easy. A plugin was needed. ## requirements The plugin needs to do the following: 1. create the
app.xml
that is used to describe the application, its dependencies and several settings. 2. update
fxlauncher.jar
with app.xml 3. copy all the dependencies to a directory from where it can later be uploaded to a webserver 4. upload to a webserver. All these tasks can be done without writing a plugin for it and was how it was done untill now, this means several calls using the
maven-exec-plugin
. The setup was huge. I will not go into details about all of them, but I do want to highlight some interesting things I found while writing this. ## Maven plugin documentation is bad Subject says it all. I did not expect the documentation to be this bad. In the end I analyzed several well known plugins (the dependency plugin, the shade plugin and the jgitflow plugin) to see how a maven-plugin project is supposed to be setup. There is an archetype for it but I could not get that one to work. See [pom.xml][2] for how I set it. ## java.nio.file.FileSystem is cool To manipulate the fxlauncher.jar I decided to use the [FileSystem][3] that was introduced in Java7. This makes it very easy to add or delete files to, in this case, a jar file. ~~~java void addtoLauncher(String fileToAdd) throws MojoExecutionException { getLog().info(String.format("placing %s in fxlauncher", fileToAdd)); Path path = Paths.get(String.format("%s/fxlauncher.jar", buildDir)); Map<String, String> props = new HashMap<>(); props.put("create", "false"); URI uri = URI.create("jar:" + path.toUri().toASCIIString()); try (FileSystem jarFile = FileSystems.newFileSystem(uri, props)) { Path source = Paths.get(fileToAdd); Path target = jarFile.getPath(String.valueOf(source.getFileName())); Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { throw new MojoExecutionException("error in adding file to jar", e); } } ~ The heavy lifting is done in the
try
block. There are several types of files you can open this way. ## [mojo-executor][4] is cool too Normally when you want to copy dependencies to a certain place you will setup the maven-dependency-plugin to do the heavy lifting for you. You would configure it in your pom.xml and tie it to a phase. I wanted however to be able to call the maven-dependency-plugin from another plugin. Luckily this is possible with the mojo-executor: ~~~java void copyDependencies() throws MojoExecutionException, IOException { getLog().info("copying to " + buildDir); executeMojo( plugin(groupId("org.apache.maven.plugins"), artifactId("maven-dependency-plugin"), version("2.0") ), goal("copy-dependencies"), configuration( element(name("outputDirectory"), buildDir) ), executionEnvironment( project, session, buildPluginManager )); } ~ It doesn't get much easier then this. I like the fluent like api. [1]: https://github.com/edvin/fxlauncher [2]: https://github.com/ronsmits/fxlauncher-maven-plugin/blob/master/pom.xml [3]: https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html [4]: http://timmoore.github.io/mojo-executor/