Maven 2 - define dependency version from transitive dependency version - java

I'll explain the question with my real situation.
I use logback 1.0.1 for logging, and it includes SLF4J 1.6.4 as a dependency. I also use the SLF4J API bridges for legacy logging API's (java.util.logging, log4j and commons-logging), which are not explicit dependencies. These must also (preferrably) be version 1.6.4.
Trying to make my pom.xml as neat and error-free as possible, I'd like to enforce that these API bridges be the same version as SLF4J. The only way I know is to manually define them as dependencies in my pom.xml using version 1.6.4. If I ever update logback and the required SLF4J version is raised, I'd need to remember to change the bridge API's to the proper version.
Can I somehow hook the legacy API's version to the version of the transitive dependency SLF4J?
Current pom.xml:
<properties>
<org.slf4j.version>1.6.4</org.slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.1</version>
<!-- requires SLF4J 1.6.4 -->
</dependency>
<!-- ... -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
<!-- here, how to bind this version value to SLF4J's version? -->
<scope>runtime</scope>
</dependency>
<!-- the other two bridge API's go here -->
</dependencies>

Not in a very beautiful way :/
There is the maven enforcer plugin: http://maven.apache.org/enforcer/enforcer-rules/
so you can ban the transitive dependencies and include the version you want: http://maven.apache.org/enforcer/enforcer-rules/bannedDependencies.html
If you use a property for the good version you dont need to mess around in the enforcer plugin version.

Dependency Convergence may help you. Thank you #wemu!
I have a same? problem.
You can clone https://gist.github.com/f35db1ac6dc8b6f45393.git
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.3</version>
<scope>runtime</scope> <!-- depends on slf4j-api:1.7.7 -->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${unified.slf4j-api.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${unified.slf4j-api.version}</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<unified.slf4j-api.version>1.7.7</unified.slf4j-api.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
At this point, things just work.
$ mvn -Dverbose=true dependency:tree verify
...
[INFO] test:enforcer-dependency-convergence-test:jar:0.1-SNAPSHOT
[INFO] +- ch.qos.logback:logback-classic:jar:1.1.3:runtime
[INFO] | +- ch.qos.logback:logback-core:jar:1.1.3:runtime
[INFO] | \- (org.slf4j:slf4j-api:jar:1.7.7:runtime - omitted for duplicate)
[INFO] +- org.slf4j:log4j-over-slf4j:jar:1.7.7:runtime
[INFO] | \- (org.slf4j:slf4j-api:jar:1.7.7:runtime - omitted for duplicate)
[INFO] \- org.slf4j:slf4j-api:jar:1.7.7:compile
[INFO]
[INFO] --- maven-enforcer-plugin:1.4.1:enforce (default) # enforcer-dependency-convergence-test ---
[INFO]
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
$
Now let's change the slf4j-api's version.
$ mvn -Dunified.slf4j-api.version=1.7.13 -Dverbose=true dependency:tree verify
...
[INFO] test:enforcer-dependency-convergence-test:jar:0.1-SNAPSHOT
[INFO] test:enforcer-dependency-convergence-test:jar:0.1-SNAPSHOT
[INFO] +- ch.qos.logback:logback-classic:jar:1.1.3:runtime
[INFO] | +- ch.qos.logback:logback-core:jar:1.1.3:runtime
[INFO] | \- (org.slf4j:slf4j-api:jar:1.7.7:runtime - omitted for conflict with 1.7.13)
[INFO] +- org.slf4j:log4j-over-slf4j:jar:1.7.13:runtime
[INFO] | \- (org.slf4j:slf4j-api:jar:1.7.13:runtime - omitted for conflict with 1.7.7)
[INFO] \- org.slf4j:slf4j-api:jar:1.7.13:compile
[INFO]
[INFO] --- maven-enforcer-plugin:1.4.1:enforce (default) # enforcer-dependency-convergence-test ---
[WARNING]
Dependency convergence error for org.slf4j:slf4j-api:1.7.7 paths to dependency are:
+-test:enforcer-dependency-convergence-test:0.1-SNAPSHOT
+-ch.qos.logback:logback-classic:1.1.3
+-org.slf4j:slf4j-api:1.7.7
and
+-test:enforcer-dependency-convergence-test:0.1-SNAPSHOT
+-org.slf4j:log4j-over-slf4j:1.7.13
+-org.slf4j:slf4j-api:1.7.13
and
+-test:enforcer-dependency-convergence-test:0.1-SNAPSHOT
+-org.slf4j:slf4j-api:1.7.13
[WARNING] Rule 0: org.apache.maven.plugins.enforcer.DependencyConvergence failed with message:
Failed while enforcing releasability the error(s) are [
Dependency convergence error for org.slf4j:slf4j-api:1.7.7 paths to dependency are:
+-test:enforcer-dependency-convergence-test:0.1-SNAPSHOT
+-ch.qos.logback:logback-classic:1.1.3
+-org.slf4j:slf4j-api:1.7.7
and
+-test:enforcer-dependency-convergence-test:0.1-SNAPSHOT
+-org.slf4j:log4j-over-slf4j:1.7.13
+-org.slf4j:slf4j-api:1.7.13
and
+-test:enforcer-dependency-convergence-test:0.1-SNAPSHOT
+-org.slf4j:slf4j-api:1.7.13
]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
...
$

Just don't directly depend on slf4j in your top level pom.

Related

stuck on javafx.graphics does not export com.sun.javafx.sg.prism to unnamed module

I've been stuck on this error now for a few days. I've googled the heck out it and tried at least a dozen different proposed solutions in various forms...
My project runs fine, UNTIL I attempt to use a specific library called MonacoFX, which, according to the GitHub page, was developed in Java 13 (I'm using Java 16.0.1 for this project). The documentation for the library is straight forward, you instantiate the library like you do with most libraries, then you simply use it. However, as soon as I attempt to instantiate it, I get this error at runtime:
Exception in thread "JavaFX Application Thread"
java.lang.IllegalAccessError: superclass access check failed:
class com.sun.javafx.sg.prism.web.NGWebView (in unnamed module #0x1937acaf)
cannot access class com.sun.javafx.sg.prism.NGGroup (in module javafx.graphics)
because module javafx.graphics does not export
com.sun.javafx.sg.prism to unnamed module #0x1937acaf
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at eu.mihosoft.monacofx#0.0.7/eu.mihosoft.monacofx.MonacoFX.<init>(MonacoFX.java:49)
at com.dustinredmond.newgistfx/com.dustinredmond.newgistfx.data.GistFile.<init>(GistFile.java:28)
at com.dustinredmond.newgistfx/com.dustinredmond.newgistfx.data.GistObject.process(GistObject.java:113)
at com.dustinredmond.newgistfx/com.dustinredmond.newgistfx.data.GistObject.<init>(GistObject.java:27)
at com.dustinredmond.newgistfx/com.dustinredmond.newgistfx.github.GitHubApi.setGitHub(GitHubApi.java:31)
at com.dustinredmond.newgistfx/com.dustinredmond.newgistfx.ui.LoginWindowController.authenticate(LoginWindowController.java:39)
at com.dustinredmond.newgistfx/com.dustinredmond.newgistfx.ui.LoginWindow.lambda$new$1(LoginWindow.java:57)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8889)
at javafx.controls/javafx.scene.control.Button.fire(Button.java:203)
at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:208)
at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3856)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1851)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2584)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:409)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:299)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:447)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:412)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:446)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
at javafx.graphics/com.sun.glass.ui.mac.MacView.notifyMouse(MacView.java:127)
It looks like the developer of the library hasn't been active on that GitHub page for quite some time now, though I did create an issue nonetheless.
I've tried the solutions where they say to use the command line argument, which mine looks like this:
--module-path /Library/Java/JavaVirtualMachines/jdk-16.0.1.jdk/Contents/Home/lib
--add-modules javafx.controls,javafx.fxml,javafx.web,javafx.graphics,javafx.media
I've tried using a separate Launcher class:
public class Launcher {
public static void main(String[] args) {
Main.main(args);
}
}
And nothing is working, the error happens at the moment I try to instantiate the library.
So I'm seeking any insight or knowledge that anyone might have on this problem ... OR ... if anyone knows of a good JavaFX library that provides language-aware code style editing, I'd be keenly interested in that.
Here is my POM file:
<?xml version="1.0" encoding="UTF-8"?>
<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>com.dustinredmond</groupId>
<artifactId>NewGistFX</artifactId>
<version>1.0-SNAPSHOT</version>
<name>NewGistFX</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>5.7.1</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>16</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>16</version>
</dependency>
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>11.1.0</version>
</dependency>
<dependency>
<groupId>net.synedra</groupId>
<artifactId>validatorfx</artifactId>
<version>0.1.13</version>
<exclusions>
<exclusion>
<groupId>org.openjfx</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.mylyn.github</groupId>
<artifactId>org.eclipse.egit.github.core</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>com.fifesoft</groupId>
<artifactId>rsyntaxtextarea</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.dustinredmond.fxtrayicon</groupId>
<artifactId>FXTrayIcon</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.kohsuke</groupId>
<artifactId>github-api</artifactId>
<version>1.133</version>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>1.5.31</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>5.5.3</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>eu.mihosoft.monacofx</groupId>
<artifactId>monacofx</artifactId>
<version>0.0.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.7</version>
<executions>
<execution>
<!-- Default configuration for running with: mvn clean javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>com.dustinredmond.newgistfx/com.dustinredmond.newgistfx.Main</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
And here is my module-info file:
module com.dustinredmond.newgistfx {
requires javafx.controls;
requires javafx.fxml;
requires org.controlsfx.controls;
requires validatorfx;
requires javafx.graphics;
requires java.prefs;
requires org.apache.commons.codec;
requires github.api;
requires org.apache.commons.io;
requires rsyntaxtextarea;
requires java.desktop;
requires FXTrayIcon;
requires org.eclipse.egit.github.core;
requires okhttp3;
requires eu.mihosoft.monacofx;
exports com.dustinredmond.newgistfx.ui;
opens com.dustinredmond.newgistfx to javafx.base;
opens com.dustinredmond.newgistfx.data to javafx.base;
}
I am grateful for any assistance that anyone can offer.
Thank you
How to debug dependencies
Include the maven dependency plugin in your project.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</build>
Run mvn dependency:tree on your project.
[INFO] --- maven-dependency-plugin:3.2.0:tree (default-cli) # NewGistFX ---
[INFO] com.dustinredmond:NewGistFX:jar:1.0-SNAPSHOT
[INFO] +- org.openjfx:javafx-controls:jar:16:compile
[INFO] | +- org.openjfx:javafx-controls:jar:win:16:compile
[INFO] | \- org.openjfx:javafx-graphics:jar:16:compile
[INFO] | \- org.openjfx:javafx-graphics:jar:win:16:compile
[INFO] +- org.openjfx:javafx-fxml:jar:16:compile
[INFO] | \- org.openjfx:javafx-fxml:jar:win:16:compile
[INFO] +- org.controlsfx:controlsfx:jar:11.1.0:compile
[INFO] +- net.synedra:validatorfx:jar:0.1.13:compile
[INFO] +- org.junit.jupiter:junit-jupiter-api:jar:5.7.1:test
[INFO] | +- org.apiguardian:apiguardian-api:jar:1.1.0:test
[INFO] | +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO] | \- org.junit.platform:junit-platform-commons:jar:1.7.1:test
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.7.1:test
[INFO] | \- org.junit.platform:junit-platform-engine:jar:1.7.1:test
[INFO] +- org.eclipse.mylyn.github:org.eclipse.egit.github.core:jar:2.1.5:compile
[INFO] | \- com.google.code.gson:gson:jar:2.2.2:compile
[INFO] +- com.fifesoft:rsyntaxtextarea:jar:3.1.3:compile
[INFO] +- junit:junit:jar:4.13.1:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- com.dustinredmond.fxtrayicon:FXTrayIcon:jar:3.1.1:compile
[INFO] +- org.kohsuke:github-api:jar:1.133:compile
[INFO] | +- org.apache.commons:commons-lang3:jar:3.9:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.12.5:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.12.5:compile
[INFO] | | \- com.fasterxml.jackson.core:jackson-core:jar:2.12.5:compile
[INFO] | \- commons-io:commons-io:jar:2.8.0:compile
[INFO] +- com.squareup.okio:okio:jar:2.10.0:compile
[INFO] | +- org.jetbrains.kotlin:kotlin-stdlib:jar:1.4.20:compile
[INFO] | | \- org.jetbrains:annotations:jar:13.0:compile
[INFO] | \- org.jetbrains.kotlin:kotlin-stdlib-common:jar:1.4.20:compile
[INFO] +- org.jetbrains.kotlin:kotlin-stdlib-jdk8:jar:1.5.31:compile
[INFO] | \- org.jetbrains.kotlin:kotlin-stdlib-jdk7:jar:1.5.31:compile
[INFO] +- com.squareup.okhttp3:okhttp:jar:4.9.2:compile
[INFO] +- org.springframework.security:spring-security-crypto:jar:5.5.3:compile
[INFO] +- commons-codec:commons-codec:jar:1.15:compile
[INFO] \- eu.mihosoft.monacofx:monacofx:jar:0.0.7:compile
[INFO] +- org.openjfx:javafx-base:jar:12.0.1:compile
[INFO] | \- org.openjfx:javafx-base:jar:win:12.0.1:compile
[INFO] +- org.openjfx:javafx-web:jar:12.0.1:runtime
[INFO] | \- org.openjfx:javafx-web:jar:win:12.0.1:runtime
[INFO] \- org.openjfx:javafx-media:jar:12.0.1:runtime
[INFO] \- org.openjfx:javafx-media:jar:win:12.0.1:runtime
Issues with your project and how to fix them
Note that your project is using javafx-controls/javafx-graphics 16 and monacofx is depending on javafx-base/javafx-web/javafx-media 12.0.1.
JavaFX does not support mixing JavaFX module versions, so it breaks.
Do not do this.
Fix the versioning in your pom.xml so that all JavaFX modules are the same version.
Also, you are defining a module-info.java file, you need to add the required dependencies to your module-info for this to work. So fix them (see my example below, note it requires javafx.web and eu.mihosoft.monacofx).
Don't do the launcher hack to create a Launcher.java file. JavaFX is not architected to run that way and it is not supported.
If you are going to run from the command line, you need to specify the module path to all of the modules you are using, not just the JDK modules. In fact you don't need the JDK modules added explicitly to the module path, they will be added automatically as they are implicitly part of the jdk image you are working with.
You are using Maven, so all of the required non-jdk dependencies to be placed on the module path are in your Maven repository, you can get them from there. If you use an IDE like Idea and have managed to get the app to run in the IDE (without using the JavaFX maven plugin to run it), then look at the command line the IDE used to run the app, specifically the module path (or -p) option, and copy everything from there and use the same thing when trying to run from the command prompt.
OR, create a proper runtime image (google it) using jlink/jdeps and perhaps jpackage, and use that to execute your app.
MonacoFX doesn't have a module-info.java file, so you won't be able to use jlink to include it until the developer creates a new package with a module-info.java file. You could file a feature request for the project for them to do that if you wish.
And maybe also another feature request for them to not require JavaFX 12 packages as dependencies
For example, in a Maven build those dependencies in the Monaco project could be marked as provided, for instance and the documentation for the Monaco project could note that in order for it work certain JavaFX modules must be on the module path.
Sample application
This is just using the sample app from MonacoFX
package com.example.monacotest;
import eu.mihosoft.monacofx.MonacoFX;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class MonacoTestApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
// create a new monaco editor node
MonacoFX monacoFX = new MonacoFX();
StackPane root = new StackPane(monacoFX);
// set initial text
monacoFX.getEditor().getDocument().setText(
"""
#include <stdio.h>
int main() {
// printf() displays the string inside quotation
printf("Hello, World!");
return 0;
}
"""
);
// use a predefined language like 'c'
monacoFX.getEditor().setCurrentLanguage("c");
monacoFX.getEditor().setCurrentTheme("vs-dark");
// the usual scene & stage setup
Scene scene = new Scene(root, 800,600);
primaryStage.setTitle("MonacoFX Demo (running on JDK " + System.getProperty("java.version") + ")");
primaryStage.setScene(scene);
primaryStage.show();
}
}
module-info.java
I only require the stuff to make Monaco work for the test. You can add the rest of the things you need into your project.
You must require javafx.web, or you will get the error shown in your question.
module com.example.monacotest {
requires javafx.web;
requires eu.mihosoft.monacofx;
exports com.example.monacotest;
}
pom.xml
We exclude the JavaFX dependencies of monacofx, and define all of the necessary dependencies for JavaFX directly in our project, with the correct versions.
<?xml version="1.0" encoding="UTF-8"?>
<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>com.example.monacotest</groupId>
<artifactId>MonacoTestApp</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<javafx.version>17.0.1</javafx.version>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>eu.mihosoft.monacofx</groupId>
<artifactId>monacofx</artifactId>
<version>0.0.7</version>
<exclusions>
<exclusion>
<groupId>org.openjfx</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Correct dependency tree:
[INFO] --- maven-dependency-plugin:3.2.0:tree (default-cli) # MonacoTestApp ---
[INFO] com.example.monacotest:MonacoTestApp:jar:1.0-SNAPSHOT
[INFO] +- org.openjfx:javafx-web:jar:17.0.1:compile
[INFO] | +- org.openjfx:javafx-web:jar:win:17.0.1:compile
[INFO] | +- org.openjfx:javafx-controls:jar:17.0.1:compile
[INFO] | | +- org.openjfx:javafx-controls:jar:win:17.0.1:compile
[INFO] | | \- org.openjfx:javafx-graphics:jar:17.0.1:compile
[INFO] | | +- org.openjfx:javafx-graphics:jar:win:17.0.1:compile
[INFO] | | \- org.openjfx:javafx-base:jar:17.0.1:compile
[INFO] | | \- org.openjfx:javafx-base:jar:win:17.0.1:compile
[INFO] | \- org.openjfx:javafx-media:jar:17.0.1:compile
[INFO] | \- org.openjfx:javafx-media:jar:win:17.0.1:compile
[INFO] \- eu.mihosoft.monacofx:monacofx:jar:0.0.7:compile

Exclude all transitive dependencies of all dependencies?

I am working on a maven project and i need to exclude all transitive dependencies. I have seen the "exclude"tag that is used inside "dependency"tag. But i have a lot of dependencies and writing this tag in every dependency is a huge task. So there is any method where i can exclude all transitive dependencies in a much easier way?
Ever since Maven 3.2.1, you can use wildcards in dependency exclusions.
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
...
</dependencies>
You will still have to insert the wildcard exclusion into every single dependency though.
Here's an example pom with a Groovy script (executed through the Groovy Maven Plugin) that excludes all transitive dependencies:
<?xml version="1.0" encoding="UTF-8"?>
<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.test</groupId>
<artifactId>non-transitive-deps</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<id>exclude-transitive-deps</id>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
def exclusion = new org.apache.maven.model.Exclusion();
exclusion.groupId='*'
exclusion.artifactId='*'
project.dependencies.each{
d -> d.addExclusion(exclusion)
}
</source>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
</dependencies>
</project>
Output for mvn dependency:tree:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # non-transitive-deps ---
[INFO] org.test:non-transitive-deps:jar:1.0-SNAPSHOT
[INFO] \- org.springframework:spring-orm:jar:4.3.7.RELEASE:compile
[INFO] +- org.springframework:spring-beans:jar:4.3.7.RELEASE:compile
[INFO] +- org.springframework:spring-core:jar:4.3.7.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.2:compile
[INFO] +- org.springframework:spring-jdbc:jar:4.3.7.RELEASE:compile
[INFO] \- org.springframework:spring-tx:jar:4.3.7.RELEASE:compile
Output for mvn validate dependency:tree:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # non-transitive-deps ---
[INFO] org.test:non-transitive-deps:jar:1.0-SNAPSHOT
[INFO] \- org.springframework:spring-orm:jar:4.3.7.RELEASE:compile
So while this groovy script solves your problem, it only does so when a Maven lifecycle phase is executed (not when you trigger a plugin goal directly). validate is the earliest stage in the lifecycle, long before dependency resolution takes place.
And no, I am not aware of any less verbose solution.

mvn dependency:build-classpath not considering includeScope parameter

mvn dependency:build-classpath -DincludeScope=test
doesn't show test jars that have been added to the pom.xml
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_${scala.binary.version}</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_${scala.binary.version}</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
However, mvn -f pom.xml dependency:tree|grep tests does show these test jars. Is this some kind of a bug in maven?
Using `mvn` from path: /usr/bin/mvn
[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) # java8-tests_2.10 ---
[INFO] org.apache.spark:java8-tests_2.10:pom:1.6.0-cdh5.11.0-SNAPSHOT
[INFO] | | +- org.apache.avro:avro-ipc:jar:tests:1.7.6-cdh5.11.0-SNAPSHOT:compile
[INFO] +- org.apache.spark:spark-core_2.10:test-jar:tests:1.6.0-cdh5.11.0-SNAPSHOT:test
[INFO] +- org.apache.spark:spark-streaming_2.10:test-jar:tests:1.6.0-cdh5.11.0-SNAPSHOT:test
I am trying the above in a more complicated project mixing scala and java code. On a simpler sample project this does work.

Maven overrides transitive dependency

Overall applicatiom I'm using Apache HttpComponents dependency:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
But also another library uses this artifact, but different version (4.3.2, not 4.5.2):
<dependency>
<groupId>com.sendgrid</groupId>
<artifactId>sendgrid-java</artifactId>
</dependency>
The problem is that API between this versions is changed and I'm getting this error:
Caused by: java.lang.ClassNotFoundException: org.apache.http.ssl.SSLContexts
How I can say to maven not to override Sendgrid's version of HttpComponents (4.3.2) with 4.5.2?
EDIT: version of httpcomponents is specified in dependencyManagement section of parent pom
Given the following parent pom.xml section:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.sendgrid</groupId>
<artifactId>sendgrid-java</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
<modules>
<module>module-a</module>
<module>module-b</module>
</modules>
Indeed in module-a the dependency tree is the following, executing:
mvn dependency:tree
We get as part of the output:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # module-a ---
[INFO] com.sample:module-a:jar:0.0.1-SNAPSHOT
[INFO] \- com.sendgrid:sendgrid-java:jar:2.0.0:compile
[INFO] +- org.json:json:jar:20140107:compile
[INFO] +- org.apache.httpcomponents:httpcore:jar:4.3.2:compile
[INFO] +- org.apache.httpcomponents:httpclient:jar:4.5.2:compile
[INFO] | +- commons-logging:commons-logging:jar:1.2:compile
[INFO] | \- commons-codec:commons-codec:jar:1.9:compile
[INFO] +- com.sendgrid:smtpapi-java:jar:1.0.0:compile
[INFO] \- org.apache.httpcomponents:httpmime:jar:4.3.4:compile
Note:
We get org.apache.httpcomponents:httpclient:jar:4.5.2:compile
We also get org.apache.httpcomponents:httpcore:jar:4.3.2:compile
A potential versons mismatch happens here between libraries of the same family
Adding then to the module-a's pom.xml the following:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.2</version>
</dependency>
</dependencies>
</dependencyManagement>
And re-running our dependency tree execution, we get as part of the output:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # module-a ---
[INFO] com.sample:module-a:jar:0.0.1-SNAPSHOT
[INFO] \- com.sendgrid:sendgrid-java:jar:2.0.0:compile
[INFO] +- org.json:json:jar:20140107:compile
[INFO] +- org.apache.httpcomponents:httpcore:jar:4.3.2:compile
[INFO] +- org.apache.httpcomponents:httpclient:jar:4.3.2:compile
[INFO] | +- commons-logging:commons-logging:jar:1.1.3:compile
[INFO] | \- commons-codec:commons-codec:jar:1.6:compile
[INFO] +- com.sendgrid:smtpapi-java:jar:1.0.0:compile
[INFO] \- org.apache.httpcomponents:httpmime:jar:4.3.4:compile
We now get httpcore and httpclient aligned, with the versions we wanted.
Also note the httpmime to version 4.3.4, it's a fix version change, but still a misalignment (should be harmless though).
In this case it seems you are adding governance at parent level in dependencyManagement (good approach), but then at the level of one of the modules you need to override it. That can happen, but better to properly comment it, for maintenance and for the future yourself looking at it in the future.
Also note: other modules in this project would not be affected by this change, that is, they will still get version 4.5.2. If the final result of the whole multimodule build is an ear or war file, for example, carefully check what you eventually get.
It is impossible in a simple maven project to have 2 different versions of the same artifact in the classpath. So you cannot have 4.3.2 and 4.5.2 versions in the classpath simultaneously.
However there are several options... You can either
use in your project the older version (4.3.*), compatible with sendgrid-java dependency (simplest way); or
update sendgrid-java dependency, if newer one is compatible with http components 4.5.* (preferred way); or
mark sendgrid-java as a 'provided' dependency, build a separate class loader in runtime and load it with correct dependencies versions (a bit tricky, but I saw this approach in a couple bank applications)

Maven transitive dependency has scope compile while when dependency has provided scope

In my project I have openejb-core dependency with scope provided. However it has transitive dependency of slf4j and its scope is compile (see screenshot). All other transitive dependencies are provided as expected.
Question: Is it bug or am I missing something?
In a sample pom I added:
<dependencies>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>4.7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Then running:
mvn dependency:tree -Dincludes=org.slf4j
The output is:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # test-junit ---
[INFO] com.sample:test-sample:jar:0.0.1-SNAPSHOT
[INFO] \- org.apache.openejb:openejb-core:jar:4.7.0:provided
[INFO] +- org.slf4j:slf4j-jdk14:jar:1.7.7:provided
[INFO] \- org.slf4j:slf4j-api:jar:1.7.7:provided
So as you can see Maven is coherent with its official documentation. The issue from your screenshot is probably on your IDE.
The table is the key point on this topic:
From it, we can see that what is transitively in scope compile or runtime goes in scope provided, what is in scope provided or test is ignored.
However, if I change my sample pom to:
<dependencies>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>4.7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
</dependencies>
And re-run the dependency tree command, the output is as following:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # test-junit ---
[INFO] com.sample:test-sample:jar:0.0.1-SNAPSHOT
[INFO] +- org.apache.openejb:openejb-core:jar:4.7.0:provided
[INFO] | \- org.slf4j:slf4j-jdk14:jar:1.7.7:provided
[INFO] \- org.slf4j:slf4j-api:jar:1.7.7:compile
Look now: it comes not as a child of the provided dependency, but at the same level.
Let's keep on.
If on my sample pom I remove the sl4f-api dependency but I add to the pom the following:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
And re-re-run the dependency tree command, I finally get the same as your screenshot:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # test-junit ---
[INFO] com.sample:test-sample:jar:0.0.1-SNAPSHOT
[INFO] \- org.apache.openejb:openejb-core:jar:4.7.0:provided
[INFO] +- org.slf4j:slf4j-jdk14:jar:1.7.7:provided
[INFO] \- org.slf4j:slf4j-api:jar:1.7.7:compile
Bingo: the dependencyManagement section is overriding the scope of the transitive dependency, affecting also the mediation on provided scope. This is not a bug, it's by design as in this section you define kind of governance concerning your dependencies. The diagram in this case is also correct and not misleading, since the dependency is only introduced by openejb-core which is then affected by the dependencyManagement decision to put sl4f-api in scope compile.

Categories