Gar*_*Out 5 java log4j javafx gradle
我不知道如何添加依赖项。我的模块需要Log4j。我在模块信息中添加了要求。我还添加了gradle依赖项。我可以运行项目,但不能创建自定义运行时映像。
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.5'
}
group 'eu.sample'
version '2.0'
repositories {
mavenCentral()
}
javafx {
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
mainClassName = "$moduleName/eu.sample.app.Main"
def lin_java_home = hasProperty('org.gradle.java.home') ? getProperty('org.gradle.java.home') : System.getenv('JAVA_HOME')
def lin_fx_jmods = hasProperty('linux.fx.mods') ? getProperty('linux.fx.mods') : System.getenv('PATH_TO_FX_MODS_LIN')
def win_java_home = hasProperty('windows.java.home') ? getProperty('windows.java.home') : System.getenv('JAVA_HOME_WIN')
def win_fx_jmods = hasProperty('windows.fx.mods') ? getProperty('windows.fx.mods') : System.getenv('PATH_TO_FX_MODS_WIN')
dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.1'
}
task jlink(type: Exec) {
dependsOn 'clean'
dependsOn 'jar'
workingDir 'build'
if (lin_java_home == null) {
throw new RuntimeException("java_home is not defined.")
}
if (lin_fx_jmods == null) {
throw new RuntimeException("fx_jmods is not defined.")
}
commandLine "${lin_java_home}/bin/jlink", '--module-path', "libs${File.pathSeparatorChar}${lin_fx_jmods}",
'--add-modules', "${moduleName}", '--output', "${moduleName}", '--strip-debug',
'--compress', '2', '--no-header-files', '--no-man-pages'
}
task jlinkWin(type: Exec) {
dependsOn 'clean'
dependsOn 'jar'
workingDir 'build'
if (win_java_home == null) {
throw new RuntimeException("java_home is not defined.")
}
if (win_fx_jmods == null) {
throw new RuntimeException("fx_jmods is not defined.")
}
commandLine "${lin_java_home}/bin/jlink", '--module-path',
"${win_java_home}/jmods${File.pathSeparatorChar}libs${File.pathSeparatorChar}${win_fx_jmods}",
'--add-modules', "${moduleName}", '--output', "${moduleName}", '--strip-debug',
'--compress', '2', '--no-header-files', '--no-man-pages'
}
Run Code Online (Sandbox Code Playgroud)
当我启动任务jlink时,我得到:
错误:未找到模块org.apache.logging.log4j,应用程序必需
我在构建中检查了libs目录,但没有log4j jar。如何告诉gradle为jlink任务添加依赖项?
问题
这是您的jlink任务:
'--module-path', "libs${File.pathSeparatorChar}${fx_jmods}"
Run Code Online (Sandbox Code Playgroud)
这意味着您要添加来自以下项的依赖项:
libs:基本上是模块的jar helloFX。这是jar任务的结果,该任务仅包括项目的类和资源,但不包括其依赖项。
fx_jmods:这是JavaFX jmods的路径。
但是当您运行时,会出现以下错误:
错误:未找到模块org.apache.logging.log4j,应用程序必需
该错误意味着module-path该jlink命令的尚未完成,并且无法解析所有必需的依赖项。如上所述,我们仅包含module.jar和JavaFX(jmods)jar,而没有log4j.jar。
因此,我们需要找到一种将jar添加到模块路径的方法。
有几种可能的解决方案,可以在您的自定义映像中包含第三方依赖项。
解决方案1
We have to modify the jlink task, to include the existing dependencies in our runtime configuration.
The most immediate solution is finding where the logj4 jars are stored by gradle, in the local .gradle repository.
'--module-path', "libs${File.pathSeparatorChar}${fx_jmods}: \
/Users/<user>/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.11.1/268..a10/log4j-api-2.11.1.jar: \
/Users/<user>/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-core/2.11.1/59..e4/log4j-core-2.11.1.jar"
Run Code Online (Sandbox Code Playgroud)
While this solution works, it is not the most convenient, of course, as it depends on local paths from the user.
Solution 2
A better solution, can be done adding a task to copy the runtime dependencies, that are resolved directly by gradle, into the libs folder like:
task libs(type: Copy) {
into 'build/libs/'
from configurations.runtime
}
Run Code Online (Sandbox Code Playgroud)
and then calling this task from the jlink task:
task jlink(type: Exec) {
dependsOn 'clean'
dependsOn 'jar'
dependsOn 'libs'
...
}
Run Code Online (Sandbox Code Playgroud)
If you run ./gradlew jlink and check the libs folder you should find something like this:
build/libs/hellofx.jar
build/libs/javafx-base-11.0.1.jar
build/libs/javafx-base-11.0.1-$platform.jar
build/libs/javafx-graphics-11.0.1.jar
build/libs/javafx-graphics-11.0.1-$platform.jar
build/libs/javafx-controls-11.0.1.jar
build/libs/javafx-controls-11.0.1-$platform.jar
build/libs/javafx-fxml-11.0.1.jar
build/libs/javafx-fxml-11.0.1-$platform.jar
build/libs/log4j-api-2.11.1.jar
build/libs/log4j-core-2.11.1.jar
Run Code Online (Sandbox Code Playgroud)
where $platform is your running platform.
Notice that the libs folder now contains all the dependencies that are required for the module path, and also that the JavaFX-*-$platform jars contain the native libraries, therefore, the jmods are not needed anymore in the module-path option. This will be enough:
'--module-path', "libs"
Run Code Online (Sandbox Code Playgroud)
so your command line will be:
commandLine "${java_home}/bin/jlink", '--module-path', "libs",
'--add-modules', "${moduleName}", '--output', "${moduleName}", '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'
Run Code Online (Sandbox Code Playgroud)
You can run your jlink task now successfully.
Solution 3
As suggested by @madhead comment, you can use another plugin for the jlink task: the so called badass-jlink-plugin.
Modify your build to something like:
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.5'
id 'org.beryx.jlink' version '2.1.8'
}
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.1'
}
javafx {
modules = ['javafx.controls', 'javafx.fxml']
}
mainClassName = "${moduleName}/eu.sample.app.Main"
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'helloFX'
}
}
Run Code Online (Sandbox Code Playgroud)
Note also that the plugin has an option to create image for other platforms (see targetPlatform).
EDIT about log4j
As mentioned in the comments, the log4j dependency doesn't play well with modules yet. There is an open issue at the Apache Issue tracker:
Currently based on the given automatic modules you can't use log4j-core in a project where you like to use jlink to produce a runtime image.
I've added this to my main class:
LogManager.getLogger(MainApp.class).info("hellofx!");
Run Code Online (Sandbox Code Playgroud)
and I've added the log4j2.xml file to src/main/resources.
Running ./gradlew run, works:
> Task :run
18:24:26.362 [JavaFX Application Thread] INFO eu.sample.app.Main - hellofx!
Run Code Online (Sandbox Code Playgroud)
But, running jlink from Solution 2, creates the custom image, I can verify that the xml file is included, but when running from the image I get:
build/hellofx/bin/java -m hellofx/eu.sample.app.Main
ERROR StatusLogger Log4j2 could not find a logging implementation. \
Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
Run Code Online (Sandbox Code Playgroud)
And as mentioned, running jlink with the plugin from Solution 3 fails at the :createMergedModule task
error: package org.apache.logging.log4j.spi is not visible
provides org.apache.logging.log4j.spi.Provider with org.apache.logging.log4j.core.impl.Log4jProvider;
Run Code Online (Sandbox Code Playgroud)
[See EDIT(2), this has been fixed since version 2.1.9]
Alternative
At this point, a possible alternative could be use Slf4j instead. There is a sample listed from the plugin documentation that uses it successfully.
In summary this is required:
Gradle file:
dependencies {
compile 'org.slf4j:slf4j-api:1.8.0-beta2'
compile('ch.qos.logback:logback-classic:1.3.0-alpha4') {
exclude module: "activation"
}
}
Run Code Online (Sandbox Code Playgroud)
Module-info:
requires org.slf4j;
requires ch.qos.logback.classic;
requires java.naming;
Run Code Online (Sandbox Code Playgroud)
Main class:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(MainApp.class);
...
logger.info("hellofx!");
Run Code Online (Sandbox Code Playgroud)
logging.properties from here and logback.xml from here, with your main class.
Both running ./gradlew run or ./gradlew jlink, and build/image/bin/HelloFX work, and the message is logged to the console.
EDIT (2)
After reporting the issue to the badass-jlink-plugin's issue tracker, this was solved, and since version 2.1.19 it should work fine creating a custom image.
Since log4j is multi-release jar, there is one thing required:
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.5'
id 'org.beryx.jlink' version '2.1.9'
}
...
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'helloFX'
}
forceMerge('log4j-api') // <---- this is required for Log4j
}
Run Code Online (Sandbox Code Playgroud)
See a full working sample here.
| 归档时间: |
|
| 查看次数: |
868 次 |
| 最近记录: |