Maven + Build Native with javafx-maven-plugin without JRE - java

I have a simple JavaFX application and I want to create an installer for Windows machines. The javafx-maven-plugin works and create an executable file of the application along with a Windows installer, but the problem is that, it creates a Windows installer with the JavaFX application inside and the complete JRE too.
So, how can I make to build the native files for Windows with the javafx-maven-plugin without carrying the complete Java framework in it. Perhaps it should create only a depedency to the Java Framework. This bloats the installer from 1.5MB to 200MB of disk space.
With Maven I use the command mvn clean compile jfx:build-jar jfx:native to get the native files in Windows and here is the POM file I am using:
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-javafx-maven-example</artifactId>
<name>JavaFX Example Maven Project</name>
<organization>
<name>Jaa Demo</name>
</organization>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>8.1.3</version>
<configuration>
<mainClass>com.demo.helloWorld</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

I'm the maintainer of that javafx-maven-plugin.
When creating your installer, it is "by design" that the JRE is bundled within your application. I myself stumbled upon this too, but in despite of the current documentation of oracle, I found it not possible to run my generated files (using JDK 1.8u40 and above, Windows) without having that JRE aside of my native launcher. The packager.dll seems to require it to be there. But to make it clear: this may be just a problem for me, not verified it nor did I investigate this.
To answer your question: you can remove the JRE by passing some bundleArguments:
<bundleArguments>
<runtime />
</bundleArguments>
I'm doing this myself, mostly to speed up test-projects, like here:
https://github.com/javafx-maven-plugin/javafx-maven-plugin/blob/master/src/it/03-cli-jfx-native/pom.xml#L31
EDIT: please consider of upgrading to plugin-version 8.1.5 since there are some bugs fixed including a (IMHO) serious workaround for native launchers on linux-systems. Also there is support for creating bundles while normal maven-lifecycle: https://github.com/javafx-maven-plugin/javafx-maven-plugin/blob/master/src/it/07-lifecycle-build-jfx-native/pom.xml

Related

Dynamically package JAR to specific directory for any given Java project using Maven and IntelliJ IDEA

I'm making Minecraft server (Spigot) plugins using IntelliJ IDEA and Maven. I want a button which works on all my Spigot projects (not necessarily automatically determining these projects, though that would also be useful) which packages my plugin directly to my testing server's 'plugins' folder then starts the server.
There are two methods I've thought of to accomplish this, but neither of them work due to limitations with IntelliJ and Maven.
My first idea was to write a batch file which takes the path to the packaged JAR as a parameter, copies the JAR from that path to the 'plugins' folder then starts the testing server.
move "%*" "C:\path\to\my\spigotTestingServer\plugins"
call "C:\path\to\my\spigotTestingServer\startServer.bat"
Then, in the 'Script parameters' for my run configuration, I would reference Maven properties (${project.build.directory}\${project.artifactId}-${project.version}) to obtain this path. However, IntelliJ doesn't seem to allow you to reference Maven properties in any run configuration settings.
My second idea was to modify the package directory directly inside my POM using Maven plugins. However, this means I'd still have to copy this code between projects and it would pollute my Git commits with a path only effective with my filesystem.
Now, I found out Maven has 'build profiles' which could potentially be a solution to this, so I wrote this 'settings.xml'
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
<profiles>
<profile>
<id>spigotTestingServer</id>
<build>
<finalName>${project.name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<outputDirectory>C:/path/to/my/spigotTestingServer/plugins/</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</settings>
I could then use this for all my Spigot projects by adding '-P spigotTestingServer' to the run configuration.
However, Maven doesn't allow profiles defined in settings.xml to include anything under 'build' including build plugins, which is exactly what I need to modify the package directory.
So, at this point, I'm stuck. Is there any way to get around the issues I've faced so far or are there any alternative solutions to packaging my JAR directly to my Spigot testing server's 'plugins' folder?

How to resolve dependencies on JNLP with Maven

I'm working on a Slick 2D project, with JDK 15, using Eclipse 09-2020, and I am resolving my dependencies via Maven. When I add Slick2D to pom.xml, it shows an error in the IDE at xsi:schemaLocation, saying "Missing artifact javax.jnlp:jnlp-api:jar:5.0"
I've tried re-downloading Java, resetting my JAVA_HOME variable, but to no avail. The other problems that I've come across reference "javaw.jar" in the lib directory, but that is not present in my JDK. How do I solve this?
Here's my pom.xml, if it helps:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.newproject</groupId>
<artifactId>newapi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Slick Based API</name>
<dependencies>
<dependency>
<groupId>org.slick2d</groupId>
<artifactId>slick2d-core</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
Just a general note: The slick project seems dead. The official source repo has been taken offline. I would probably not use it for a completely new project.
But now to your question:
Java Webstart has been removed starting from Java11 since oracle did not opensource it. So what can you do?
You downgrade to Java 9/10
You use https://openwebstart.com (some adaptions might be necessary)
You remove JNLP from the project (since there are other means to start it)
Some other guy seems to have taken up the project. You can find it on github. In one of the forks JNLP has been removed, too.

Convert java plugin into maven project with eclipse-plugin packaging

I am quite experienced with java but i'm using maven for the first time.
i have installed Eclipse Kepler (Eclipse for RCP and RAP Developers), I have installed Tychus as well with the "add new software" button.
There is an Internet of things project that I cloned and built called OM2M.
I followed the install wiki step by step and everything work until then.
cloning wiki here
I want to develop my own OSGI module so I went to the 'developer' section of the wiki and once again and created a new plugin project.
When i try to convert this plugin project into a maven project ( link to the step i'm talking about ) I don't have to "eclipse-plugin" packaging type for my pom wiki screenshot here.
I looked it up on the web and apparently it has something to do with Tychus that needs configuration, I tried typing it in the box but obviously I have problems when i try to build, I tried editing the main pom.xml with stuff I found but none of them work and I really don't know what to do to make it work.
Do you guys have an idea ?
Thanks
Edit : i forgot to mention that i read this thread but I don't understand the the answers, I don't know where to put the code the top answer is talking about nor do i know where to but the OSGI manifest.
Edit 2 : pom.xml i get when i enter eclipse-plugin by hands :
If i write eclipse-plugin by hand here is my pom.xml :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.om2m</groupId>
<artifactId>org.eclipse.om2m.sample.ipu</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
Edit 3 : I managed to remove the error by setting the main pom.xml as a parent but now when i try to build i have the following error :
[ERROR] Failed to execute goal org.eclipse.tycho:tycho-packaging-plugin:0.20.0:validate-version (default-validate-version) on project org.eclipse.om2m.sample.ipu: Unqualified OSGi version 1.0.0.qualifier must match unqualified Maven version 0.0.1-SNAPSHOT for SNAPSHOT builds ->
I've searched for the goals but I don't know where to set or edit them.
Edit 4 : Thanks to #Wim Anckaert i've dropped the .qualifier and the .snapshot from the pom.xml and the manifest and now it seems to be working !
Thanks a lot guys.
The last error seems to be a problem with the <version> of your ./pom.xml and Bundle-Version of your ./META-INF/MANIFEST.MF file. These should be equal to each other.
A part of our pom.xml:
<artifactId>be.cs.fashion.awg.core</artifactId>
<name>CERPS</name>
<version>2.1.0</version>
<packaging>eclipse-plugin</packaging>
A part of our MANIFEST.MF
Bundle-Name: CERPS
Bundle-SymbolicName: be.cs.fashion.awg.core;singleton:=true
Bundle-Version: 2.1.0
Bundle-Localization: plugin
So in your case version in pom.xml version should be "1.0.0-SNAPSHOT" or you should use Bundle-Version "0.0.1.qualifier"
We dropped the "-SNAPSHOT" and the ".qualifier" in our versions.
The value "eclipse-plugin" is not included in the combo (i.e. the drop-down listbox here), you ought to write it by hand.
Upd: Firstly you must enable tycho. To do this, add
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-maven-plugin</artifactId>
<version>0.24.0</version>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
to your pox.xml (or, preferably, to its parent).
Then, you need to know that the wizard you show on screenshot does not search for all possible values of tag, instead it adds to "Packaging" drop-down listbox most usable values and allows you to enter any value that you want.
For more details check out here

Another own Maven project as dependency - how to solve it?

I have three Java console applications - A, B and C, all are managed with Maven. Application A contains common tools classes and these tools are used by another two applications - B and C. I need to know how to solve this dependency with Maven.
I have an idea - please correct me if I am wrong, to package and install application A into local Maven repository via mvn install command and this library set as new dependency for app B and C in their pom.xml files.
Is this a good idea or is there some better way how to solve this issue?
This question seems to be related to my issue, but I'm not able to judge if is it a good solution in my situation - How do I add a project as a dependency of another project?
Yes, it's perfectly fine. This solution also scales - you may later install you artifacts to remote repositories or even Maven Central.
Some other option is to place these three projects as modules under a common parent POM with packaging set to pom. The advantage is that you would be able to install all three artifacts with a single command and i.e. update dependencies on-the-fly when using Maven Release plugin.
Yes, this seems like the right way to solve this problem. Alternatively you can deploy to a real repository. That would be even better if you want other people to build project B and C without installing A first.
I would put the code that B and C use in its own separate jar. That way B and C don't use all of project A, but just a library with the code that they need.
I would not use the advice of the linked article. It uses a system path which is not ideal because it needs an absolute path so it will only work if someone installs the projects in the same place on their file system as you.
Running mvn install will solve your problem, but then you are solving it manually. It creates many complications when your projects change. What you need is a pom.xml that makes references to your sub projects:
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>4.0.0</modelVersion>
<groupId>X</groupId>
<artifactId>X</artifactId>
<version>0.1</version>
<name>X</name>
<packaging>pom</packaging>
<modules>
<module>project_A</module>
<module>project_B</module>
<module>project_C</module>
</modules>
<build>
<defaultGoal>package</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptors>
<descriptor>src/assemble/bin.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Put this in a directory that contains those 3 directories in which each of your projects are. Then you can call mvn clean package on this directory and Maven will magically solve the problem for you, building each project in the right order and making one project available to the others if there are dependencies.
BONUS: On the example above I am also adding a reference to a Maven Assemble, which you can use to pack all your projects into a single distribution.

Maven project with JavaFX (with jar file in `lib`)

I'm setting up a maven project, that is going to use JavaFX. Since I've heard JavaFX does not come with all versions of Java, I downloaded and put the jfxrt.jar file in a lib directory in my project.
1) How do I specify that the dependency (ie., JavaFX) should not be downloaded, but which is located in lib?
2) Does this then mean the project can be built on any machine with JDK (and not necessary JDK 1.7 - update 9+) ?
2019 Update for Recent JavaFX Versions
As of Java 11, JavaFX has been decoupled from the JDK, so JavaFX libraries are no longer automatically bundled together with a JDK install (as they were for instance in the Oracle JDK 8 distribution). Instead, the JavaFX system is now designed as a set of separate libraries independent from the JDK, which can be downloaded from a repository by a tool such as Maven for use by your application.
openjfx.io have a very short tutorial on using JavaFX 11+ with Maven:
https://openjfx.io/openjfx-docs/#maven
This tutorial recommends use of the OpenJFX JavaFX Maven Plugin and provides the following sample maven pom.xml project file for a "hello, world" style application.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openjfx</groupId>
<artifactId>hellofx</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>12.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.2</version>
<configuration>
<mainClass>HelloFX</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
Note that the org.openjfx JavaFX maven plugin used for Java 11+ is different from the com.zenjava JavaFX maven plugin used for Java 8 and 9, so use the appropriate one for your Java version.
Suggested Approach
For building JavaFX apps with Maven:
Use the com.zenjava maven JavaFX plugin with Java 8 and 9 AND/OR
Use Java 8 or 9 and don't specify any kind of Maven dependency for JavaFX OR
Use the org.openjfx maven JavaFX plugin with Java 11+.
Unlike Java 7, with Java 8 it is unnecessary to set JavaFX as a maven dependency, because JavaFX is on the standard Java runtime classpath (similar to the way Swing is today).
Opinion
I think the approach in your question of placing the jfxrt.jar file in a project lib directory is flawed.
The reasons it is flawed are:
JavaFX also includes native libraries, so you would need to include them as well (in a location where jfxrt.jar would be able to find them).
A given version of JavaFX will only be certified to operate against the version of the JDK it is shipped with, so the JavaFX runtime you place in your project's lib directory may not work against a later JDK version, such as JDK 8.
Future versions of the JDK such as JDK 8 will include JavaFX on the default classpath of the JDK, so you may get conflicts with the version you place in your lib directory.
In summary, JavaFX should be treated as part of the Java runtime system, not as a project library.
JavaFX System Dependency Sample
If you must use Java 7 and you don't want to use the JavaFX maven plugin, then you can take the less recommended approach:
Reference the JavaFX library from the jdk (not your project lib directory) as a maven system dependency.
This sample is provided for Java 7 only and is not required (and will not work as is) for Java 8. Java 8, places the jfxrt.jar in ${java.home}/lib/ext/jfxrt.jar, which is on the default Java runtime classpath, making a system dependency for Java 8 irrelevant.
<dependency>
<groupId>javafx</groupId>
<artifactId>jfxrt</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<systemPath>${java.home}/lib/jfxrt.jar</systemPath>
</dependency>
If you package your application using a system dependency like this, then you need will need to write some execution instructions for your users so that they can add jfxrt.jar to the runtime classpath when running your application on Java 7. This is a very good reason not to use this approach.
If you choose to use the maven system dependency approach, you may also wish to use the maven antrun plugin to embed calls to the JavaFX ant tasks as in this sample. You may also want to use the maven enforcer plugin to ensure that your application is built against at least the minimum required version of Java containing a JavaFX version required by your application to work.

Categories