Giter VIP home page Giter VIP logo

badass-jlink-plugin's People

Contributors

aalmiray avatar airsquared avatar conorrr avatar dependabot[bot] avatar djviking avatar koppor avatar larsroe avatar mkroening avatar showbags avatar siordache avatar tobiasdiez avatar xp-vit avatar xzel23 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

badass-jlink-plugin's Issues

Unable to avoid circular dependency?

I'm not sure whether this is an issue with the plugin or something else, but I hope you can help me figure it out:

I'm using Spring Boot to create a JavaFX application and had to specify the mergedModule section in the gradle configuration due to a missing declaration in the autogenerated module-info (requires transitive 'org.apache.logging.log4j'). Now I can successfully jlink the image, but it doesn't run. I get this error:

java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at java.base/sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application init method
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalStateException: Cannot load configuration class: com.mycompany.my.app.Main
	at my.app.merged.module/org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(Unknown Source)
	at my.app.merged.module/org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(Unknown Source)
	at my.app.merged.module/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(Unknown Source)
	at my.app.merged.module/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(Unknown Source)
	at my.app.merged.module/org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(Unknown Source)
	at my.app.merged.module/org.springframework.context.support.AbstractApplicationContext.refresh(Unknown Source)
	at my.app.merged.module/org.springframework.boot.SpringApplication.refresh(Unknown Source)
	at my.app.merged.module/org.springframework.boot.SpringApplication.refreshContext(Unknown Source)
	at my.app.merged.module/org.springframework.boot.SpringApplication.run(Unknown Source)
	at my.app.merged.module/org.springframework.boot.SpringApplication.run(Unknown Source)
	at my.app.merged.module/org.springframework.boot.SpringApplication.run(Unknown Source)
	at my.app/com.mycompany.my.app.Main.init(Unknown Source)
	... 3 more
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.IllegalAccessException-->module my.app.merged.module does not read module my.app
	at my.app.merged.module/org.springframework.cglib.core.ReflectUtils.defineClass(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.core.AbstractClassGenerator.generate(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.proxy.Enhancer.generate(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.core.internal.LoadingCache$2.call(Unknown Source)
	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.core.internal.LoadingCache.createEntry(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.core.internal.LoadingCache.get(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.core.AbstractClassGenerator.create(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.proxy.Enhancer.createHelper(Unknown Source)
	at my.app.merged.module/org.springframework.cglib.proxy.Enhancer.createClass(Unknown Source)
	at my.app.merged.module/org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(Unknown Source)
	at my.app.merged.module/org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(Unknown Source)
	... 15 more
Caused by: java.lang.IllegalAccessException: module my.app.merged.module does not read module my.app
	at java.base/java.lang.invoke.MethodHandles.privateLookupIn(Unknown Source)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	... 30 more

I tried to fix the problem by adding a requires 'my.app' to the mergedModule section, but that created a circular dependency.

Any ideas on how to get out of this mess? Thanks!

Error when using controlsfx

Hi,

when I try to use
Implementation("org.controlsfx:controlsfx:9.0.0")

I get the following error
merged.module/module-info.java:357: error: module not found: javafx.base requires javafx.base; ^ merged.module/module-info.java:358: error: module not found: javafx.controls requires javafx.controls; ^ merged.module/module-info.java:367: error: module not found: javafx.graphics requires javafx.graphics;

I think it has to do with dependencies on javafx. ControlsFX is not modularized yet. Any ideas how to fix it? Or is this up to ControlsFX.

Add options for module and merged module archive name

With the current version of the plugin, the jars produced in the (jlinkjars directory) for the base module and the merged module and named after the module names (moduleName/merged ModuleName settings).
It would be nice to have an option similar to archiveBaseName, so that the produced files are named according to it.

jpackage seems to create it's own jlink:ed image

I have been using one JDK to run gradle (and thus to compile and link my application), and then specified the Jpackage EA JDK to the jpackage task.

I discovered that the final application then ran with the Jpackage JDK, not the one I've built and jlink:ed with.

The reason seems to be jpackage create-image apparently invokes jlink to create its own image, unless the option --runtime-image is used.

So, to actually use the image produced by the jlink task, I must specify the option --runtime-image in the imageOptionsproperty, i.e.:

jlink {
...
    jpackage {
        jpackageHome = //REPLACE WITH JPACKAGE JDK
        imageOptions     = [ '--runtime-image', "$buildDir/image"]
    }
}

I believe the jpackage task should always specify the image built by the jlink task.

If you agree, I can try to implement this and give you a PR.

createMergedModule fails with Log4j

Summary

Running jlink over a simple HelloWorld JavaFX 11 project with just a dependency on Log4j fails.

Probably, it is an issue of org.apacha.logging.Log4j itself, but maybe it is worth checking if it can be fixed somehow by modifying the tasks itself from build.gradle, or it can be bypassed.

Here is the issue in more detail: https://stackoverflow.com/questions/53762491/add-dependecies-to-runtime-image-with-gradle

As mentioned, there is already an open issue filed on Apache about Log4j and jlink command.

How to reproduce

Create a project with these files:

build.gradle

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.5'
    id 'org.beryx.jlink' version '2.1.8'
}

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.apache.logging.log4j:log4j-core:2.11.1'
}

javafx {
    modules = ['javafx.controls']
}

mainClassName = "hellofx/org.openjfx.HelloFX"

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'helloFX'
    }
}

module-info.java

module hellofx {
    requires javafx.controls;
    requires org.apache.logging.log4j;
    
    exports org.openjfx;
}

org.openjfx.HelloFX.java

public class HelloFX extends Application {

    @Override
    public void start(Stage stage) {
        StackPane pane = new StackPane(new Label("HelloFX"));
        Scene scene = new Scene(pane, 300, 200);
        stage.setScene(scene);
        stage.show();

        LogManager.getLogger().info("hellofx!");
    }

    public static void main(String[] args) {
        launch(args);
    }
}

src/main/resources/log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="org.openjfx" level="INFO"/>
        <Root level="error">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Running ./gradlew run works and prints:

> Task :run
10:33:47.782 [JavaFX Application Thread] INFO  org.openjfx.HelloFX - hellofx!

However, running ./gradlew jlink fails:

> Configure project :
Found module name 'hellofx'

> Task :createMergedModule FAILED
/.../hellofx/build/jlinkbase/tmpjars/hellofx.merged.module/module-info.java:61: 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;
                                     ^
  (package org.apache.logging.log4j.spi is declared in module org.apache.logging.log4j, but module hellofx.merged.module does not read it)
/.../hellofx/build/jlinkbase/tmpjars/hellofx.merged.module/module-info.java:62: error: package org.apache.logging.log4j.message is not visible
    provides org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory with org.apache.logging.log4j.core.message.ExtendedThreadInfoFactory;
                                     ^
  (package org.apache.logging.log4j.message is declared in module org.apache.logging.log4j, but module hellofx.merged.module does not read it)
2 errors

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':createMergedModule'.
> Process 'command '/.../jdk-11.0.1.jdk/Contents/Home/bin/javac'' finished with non-zero exit value 1

Is there anything that can be done to prevent this issue, and let the plugin finish the build?

Alternatives

A possible alternative is shown in the mentioned SO post: using the jlink command task directly (without the plugin). While this works, and the image is created (and the xml file is added to modules), the logger fails:

ERROR StatusLogger Log4j2 could not find a logging implementation. \
    Please add log4j-core to the classpath. Using SimpleLogger to log to the console...

As another alternative, using Slf4j works (based on the sample that was already linked from the documentation of the plugin).

local dependency - module not found

I do have a gradle project with a dependency on a local lib - declared in the gradle dependencies as "compile files(.....)."

Every time I get an error "Module ... not found".
If the dependency is loaded from mavenCentral ist works - if the dependency is loaded from file system it doen't work.

I tried this for demonstration purpose with apache commons lang as a dependency.
This one works:

build.gradle:

plugins {
    id 'java'
    id 'application'
    id 'org.beryx.jlink' version '2.6.6'
    id "org.javamodularity.moduleplugin" version "1.1.1"
}

group 'com.test'
version '1.0-SNAPSHOT'

sourceCompatibility = 11
mainClassName = "com.test/com.test.Start"

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1' // THIS ONE WORKS
    // compile files('commons-lang3-3.8.1.jar') // THIS ONE DO NOT WORK
}

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'jlinkTest'
    }
}

module-info.java:

module com.test {
    requires org.apache.commons.lang3;
}

com\test\Start.java:

package com.test;

import org.apache.commons.lang3.RandomStringUtils;

public class Start {

    public static void main(String[] args) {
        System.out.println(RandomStringUtils.randomAlphabetic(5));
    }
}

If i switch the dependency from "compile group" to "compile files" I can run it with gradle - but not jlink it.

Support multi-project builds

When using this plugin on an application which is depending on another subproject, $ ./gradlew clean jlink will fail, as the plugin does not find the required subproject jar.

$ ./gradlew clean jar jlink will succeed.

Having this work as expected would prevent some trouble when changing things in the dependency.

Add support for JLINK_VM_OPTIONS

The starting script contains a variable JLINK_VM_OPTIONS. I think it would be nice to have the option to add jvmArgs into the jlink {} part.

jlink image and spring boot

sorry for amatur english

when i excute jlink task for using spring-boot project
task are success but i can't run image cuz (merged.module) does not read (original.module)
==> think Spring-Boot want to read original.module not a merged. how can i change it?
so i try modify mergedModule {} but i can't solved. (maybe my skills not enough.)

errors

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::

[INFO ] LOG: Starting ClientApplication.Companion on DESKTOP-15TQOHF with PID 8240 (started by Whya5 in C:\Users\Whya5\IdeaProjects\zariel\client\build\dc-eso-client\bin)
[INFO ] LOG: No active profile set, falling back to default profiles: default
[ERROR] LOG: Application run failed
java.lang.IllegalStateException: Cannot load configuration class: org.metalscraps.eso.lang.client.ClientApplication
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.context.support.AbstractApplicationContext.refresh(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.boot.SpringApplication.refresh(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.boot.SpringApplication.refreshContext(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.boot.SpringApplication.run(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.boot.SpringApplication.run(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.boot.SpringApplication.run(Unknown Source)
		at org.metalscraps.eso.lang.client/org.metalscraps.eso.lang.client.ClientApplication$Companion.main(Unknown Source)
		at org.metalscraps.eso.lang.client/org.metalscraps.eso.lang.client.ClientApplication.main(Unknown Source)
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.IllegalAccessException-->module org.metalscraps.eso.lang.client.merged.module does not read module org.metalscraps.eso.lang.client
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.ReflectUtils.defineClass(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.AbstractClassGenerator.generate(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.proxy.Enhancer.generate(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.internal.LoadingCache$2.call(Unknown Source)
		at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.internal.LoadingCache.createEntry(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.internal.LoadingCache.get(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.core.AbstractClassGenerator.create(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.proxy.Enhancer.createHelper(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.cglib.proxy.Enhancer.createClass(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(Unknown Source)
		at org.metalscraps.eso.lang.client.merged.module/org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(Unknown Source)
		... 13 common frames omitted
Caused by: java.lang.IllegalAccessException: module org.metalscraps.eso.lang.client.merged.module does not read module org.metalscraps.eso.lang.client
		at java.base/java.lang.invoke.MethodHandles.privateLookupIn(Unknown Source)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
		at java.base/java.lang.reflect.Method.invoke(Unknown Source)
		... 28 common frames omitted

my main-module build.gradle and this sub-module build.gradle
main

allprojects {
    apply plugin: 'java'
    group group
    version '1.0'
    sourceCompatibility = 11
    targetCompatibility = 11
    compileJava.options.encoding = "utf-8"
    compileTestJava.options.encoding = "utf-8"

    repositories {
        jcenter()
        mavenCentral()
    }

}

subprojects {
    ext {
        badass = '2.6.5'
        javaModule = '1.4.1'
        jackson = "2.9.8"
        commonsio = "2.6"
        group = "org.metalscraps.eso.lang"
    }

    dependencies {
        compileOnly 'org.projectlombok:lombok:1.18.6'
        annotationProcessor 'org.projectlombok:lombok:1.18.6'
        testCompileOnly 'junit:junit:4.12'
        runtimeOnly 'ch.qos.logback:logback-classic:1.2.3'
        compileOnly 'org.slf4j:slf4j-api:1.7.25'
        implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    }
}

sub

plugins {
    id 'org.beryx.jlink' version '2.6.5'
    id "org.javamodularity.moduleplugin" version "1.4.1"
    id 'org.jetbrains.kotlin.jvm' version "1.3.21"
    id 'org.jetbrains.kotlin.plugin.spring' version '1.3.21'
    id 'org.springframework.boot' version '2.1.3.RELEASE'
}
apply plugin: 'io.spring.dependency-management'
dependencies {
    configurations.all {
        exclude group: "commons-logging", module: "commons-logging"
        exclude group: "com.google.code.findbugs", module: "jsr305"
    }

    implementation project(':library')
    implementation "com.fasterxml.jackson.core:jackson-databind:${jackson}"
    implementation "com.fasterxml.jackson.module:jackson-module-kotlin:${jackson}"
    implementation 'org.jetbrains.kotlin:kotlin-reflect'
    implementation 'org.springframework.boot:spring-boot-starter:2.1.3.RELEASE'
}

def sImageName = 'dc-eso-client'
def sModuleName = 'org.metalscraps.eso.lang.client'
def sMainClass = 'org.metalscraps.eso.lang.client.ClientApplication'
mainClassName = "${sModuleName}/${sMainClass}"
springBoot { mainClassName = sMainClass }
jar {
    manifest { attributes 'Implementation-Title': sModuleName, 'Main-Class': sMainClass }
    enabled = true
}
jlink {
    moduleName = sModuleName
    mergedModuleName = "${sModuleName}.merged.module"
    imageName = sImageName
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    imageZip = file("$buildDir/${sImageName}-${version}.zip")
    launcher {
        name = 'launch'
        jvmArgs = ['-Dlogback.configurationFile=./logback.xml',
                   "--add-opens java.base/java.lang=${sModuleName}.merged.module",
                   "--add-opens java.base/java.io=${sModuleName}.merged.module",
        ]
    }

    mergedModule {
        requires 'java.management'
        requires 'java.naming'
        requires 'java.logging'
        requires 'jdk.httpserver'
        requires 'java.scripting'
        requires 'java.sql'
        requires 'java.prefs'
        requires 'java.rmi'
        requires 'java.xml'
        requires 'java.desktop'
        requires 'java.instrument'
        requires 'jdk.unsupported'

        uses 'kotlin.reflect.jvm.internal.impl.util.ModuleVisibilityHelper'
        uses 'kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader'
        uses 'kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition'
        uses 'java.nio.file.spi.FileSystemProvider'

        provides 'com.fasterxml.jackson.core.JsonFactory' with 'com.fasterxml.jackson.core.JsonFactory'
        provides 'org.apache.commons.logging.LogFactory' with 'org.apache.commons.logging.LogFactoryService'
        provides 'kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition' with 'kotlin.reflect.jvm.internal.impl.load.java.ErasedOverridabilityCondition',
                'kotlin.reflect.jvm.internal.impl.load.java.FieldOverridabilityCondition',
                'kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition'
        provides 'kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader' with 'kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl'
        provides 'com.fasterxml.jackson.databind.Module' with 'com.fasterxml.jackson.module.kotlin.KotlinModule'
        provides 'com.fasterxml.jackson.core.ObjectCodec' with 'com.fasterxml.jackson.databind.ObjectMapper'
    }

}

tasks.jlink.doLast {
    copy {
        from('src/main/resources')
        into("$buildDir/${sImageName}/bin")
    }
}
compileKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}
compileTestKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

and my github repo
https://github.com/Whya5448/zariel/tree/KOTLIN

i'm using

gradle 5.2.1,

openjdk 11.0.2 2019-01-15 LTS
OpenJDK Runtime Environment Zulu11.29+3-CA (build 11.0.2+7-LTS)
OpenJDK 64-Bit Server VM Zulu11.29+3-CA (build 11.0.2+7-LTS, mixed mode)

thanks.

merged module and automatic module names

Let's say you have a non-modular dependency, and you have to open your module to it:

module my.module {
    requires my.dependency;

    opens my.package to my.dependency;

    exports my.package;
}

Building and running works. Even the jlink task finish successfully.

However when you run the image you get something like:

java.lang.IllegalStateException: Cannot load file my.file
        at my.module.merged.module/my.dependency.package

As we haven't opened the module to this new merged module, the error was expected: reflection doesn't work.

Two possible workarounds:

  1. Open to all
module my.module {
    requires my.dependency;

    opens my.package;

    exports my.package;
}

This obviously works, but it is not the safest use of opens.

  1. Open to the merged module:
module my.module {
    requires my.dependency;

    opens my.package to my.dependency, my.module.merged.module;

    exports my.package;
}

This produces a warning if you build the project:

warning: [module] module not found `my.module.merged.module`

But the image runs fine now.

Possible solution: I'm not sure if you can detect that the module was being opened to a non-modular jar that will go into a merged module, and then modify that entry in the module with the new name of the resulting merged module?

Runtime exception with Apache HTTP client

I've written a small JavaFX application which depends on a library that makes use of the Apache HTTP client and Jackson. It runs fine when using Gradle run but throws an exception when running on a modular runtime created with badass-jlink:

com.fasterxml.jackson.databind.ext.Java7Support <clinit>
WARNING: Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(Unknown Source)
        at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
        at javafx.base/javafx.event.Event.fireEvent(Unknown Source)
        at javafx.graphics/javafx.scene.Node.fireEvent(Unknown Source)
        at javafx.controls/javafx.scene.control.Button.fire(Unknown Source)
        at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(Unknown Source)
        at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
        at javafx.base/javafx.event.Event.fireEvent(Unknown Source)
        at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Unknown Source)
        at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1200(Unknown Source)
        at javafx.graphics/javafx.scene.Scene.processMouseEvent(Unknown Source)
        at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
        at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
        at javafx.graphics/com.sun.glass.ui.View.notifyMouse(Unknown Source)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at com.sun.javafx.reflect.Trampoline.invoke(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(Unknown Source)
        at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(Unknown Source)
        ... 48 more
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
        at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
        at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
        at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Unknown Source)
        at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source)
        at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.execchain.MainClientExec.establishRoute(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.execchain.MainClientExec.execute(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.execchain.ProtocolExec.execute(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.execchain.RetryExec.execute(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.execchain.RedirectExec.execute(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.client.InternalHttpClient.doExecute(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.client.CloseableHttpClient.execute(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.client.CloseableHttpClient.execute(Unknown Source)
        at com.fxtestapp.merged.module/org.apache.http.impl.client.CloseableHttpClient.execute(Unknown Source)
        at com.fxtestapp.merged.module/com.wavesplatform.wavesj.Node.exec(Unknown Source)
        at com.fxtestapp.merged.module/com.wavesplatform.wavesj.Node.send(Unknown Source)
        at com.fxtestapp.merged.module/com.wavesplatform.wavesj.Node.getHeight(Unknown Source)
        at com.fxtestapp/com.fxtestapp.FXMLController.handleButtonAction(Unknown Source)
        ... 58 more

here's my build.gradle

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.5'
    id 'java'
    id 'org.beryx.jlink' version '2.3.1'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 11
targetCompatibility = 11

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'com.wavesplatform', name: 'wavesj', version: '0.13.1'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.8'
}

javafx {
    modules = ['javafx.controls',
               'javafx.fxml'
    ]
}

mainClassName = "$moduleName/com.fxtestapp.MainApp"

group 'com.fxtestapp'
version '1.0-SNAPSHOT'

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher{
        name = 'MainApp'
    }
    forceMerge('wavesj')
    mergedModule {
        requires 'java.naming';
        requires 'java.logging';
        requires 'java.sql';
        requires 'java.xml';
        requires 'java.security.jgss';
        provides 'com.fasterxml.jackson.core.JsonFactory' with 'com.fasterxml.jackson.core.JsonFactory';
        provides 'com.fasterxml.jackson.core.ObjectCodec' with 'com.fasterxml.jackson.databind.ObjectMapper';
    }
}

module-info.java:

module com.fxtestapp {
    requires javafx.controls;
    requires javafx.fxml;
    requires com.fasterxml.jackson.core;
    requires wavesj;

    opens com.fxtestapp to javafx.fxml;
    exports com.fxtestapp;
}

the JavaFX application:

package com.fxtestapp;
import com.wavesplatform.wavesj.Node;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MainApp extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/Scene.fxml"));
        Scene scene = new Scene(root);
        var node = new Node();
        stage.setTitle(String.valueOf(node.getHeight()));
        stage.setScene(scene);
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

I've also tried adding Jackson and the Apache HTTP client as a dep seperately but that did not work either.

BOM support

Currently BOMs (Gradle Docs) don't seem to be supported.

I created an example repository: mwkroening/badass-jlink-bom

This commit (mkroening/badass-jlink-bom@8ad6883) breaks the prepareMergedJarsDir Task, which throws a NPE:

[mkroening@mkroening-9360 badass-jlink-bom]$ ./gradlew clean prepareMergedJarsDir --stacktrace

> Configure project :
Found module name 'io.github.mkroening.badassjlinkbom'

> Task :clean
> Task :compileJava
> Task :processResources NO-SOURCE
> Task :classes
> Task :jar
> Task :prepareMergedJarsDir FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':prepareMergedJarsDir'.
> java.lang.NullPointerException (no error message)

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':prepareMergedJarsDir'.
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$2.accept(ExecuteActionsTaskExecuter.java:121)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$2.accept(ExecuteActionsTaskExecuter.java:117)
	at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:184)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:110)
	at org.gradle.api.internal.tasks.execution.ResolveIncrementalChangesTaskExecuter.execute(ResolveIncrementalChangesTaskExecuter.java:84)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:91)
	at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionStateTaskExecuter.execute(ResolveBeforeExecutionStateTaskExecuter.java:74)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:109)
	at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionOutputsTaskExecuter.execute(ResolveBeforeExecutionOutputsTaskExecuter.java:67)
	at org.gradle.api.internal.tasks.execution.ResolveAfterPreviousExecutionStateTaskExecuter.execute(ResolveAfterPreviousExecutionStateTaskExecuter.java:46)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:93)
	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:45)
	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:94)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:63)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:49)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:46)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
	at org.gradle.execution.plan.DefaultPlanExecutor.process(DefaultPlanExecutor.java:74)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph.executeWithServices(DefaultTaskExecutionGraph.java:178)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph.execute(DefaultTaskExecutionGraph.java:154)
	at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:41)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:40)
	at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:24)
	at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:46)
	at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:49)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:40)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:33)
	at org.gradle.initialization.DefaultGradleLauncher$ExecuteTasks.run(DefaultGradleLauncher.java:383)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
	at org.gradle.initialization.DefaultGradleLauncher.runTasks(DefaultGradleLauncher.java:247)
	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:159)
	at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:134)
	at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:58)
	at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:55)
	at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:82)
	at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:75)
	at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:183)
	at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
	at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:75)
	at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:55)
	at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:31)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:58)
	at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
	at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:39)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:49)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:44)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:44)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:49)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:46)
	at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:78)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:46)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:31)
	at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:42)
	at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:28)
	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:52)
	at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:59)
	at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:36)
	at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:68)
	at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:38)
	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:37)
	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:26)
	at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
	at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:60)
	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)
	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:41)
	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:48)
	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:32)
	at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
	at org.gradle.util.Swapper.swap(Swapper.java:38)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:62)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:81)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
	at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:295)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: java.lang.NullPointerException
	at org.beryx.jlink.util.DependencyManager$_closure1.doCall(DependencyManager.groovy:52)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at com.sun.proxy.$Proxy60.test(Unknown Source)
	at org.beryx.jlink.util.DependencyManager.collectDeps(DependencyManager.groovy:85)
	at org.beryx.jlink.util.DependencyManager.<init>(DependencyManager.groovy:51)
	at org.beryx.jlink.impl.PrepareMergedJarsDirTaskImpl.execute(PrepareMergedJarsDirTaskImpl.groovy:41)
	at org.beryx.jlink.PrepareMergedJarsDirTask.createMergedModuleAction(PrepareMergedJarsDirTask.groovy:89)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:103)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:48)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:41)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:705)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:672)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$4.run(ExecuteActionsTaskExecuter.java:338)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:327)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:312)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$200(ExecuteActionsTaskExecuter.java:75)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:158)
	at org.gradle.internal.execution.impl.steps.ExecuteStep.execute(ExecuteStep.java:46)
	at org.gradle.internal.execution.impl.steps.CancelExecutionStep.execute(CancelExecutionStep.java:34)
	at org.gradle.internal.execution.impl.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:69)
	at org.gradle.internal.execution.impl.steps.TimeoutStep.execute(TimeoutStep.java:49)
	at org.gradle.internal.execution.impl.steps.CatchExceptionStep.execute(CatchExceptionStep.java:34)
	at org.gradle.internal.execution.impl.steps.CreateOutputsStep.execute(CreateOutputsStep.java:49)
	at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:42)
	at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:28)
	at org.gradle.internal.execution.impl.steps.CacheStep.executeWithoutCache(CacheStep.java:133)
	at org.gradle.internal.execution.impl.steps.CacheStep.lambda$execute$5(CacheStep.java:83)
	at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:82)
	at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:37)
	at org.gradle.internal.execution.impl.steps.PrepareCachingStep.execute(PrepareCachingStep.java:33)
	at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:38)
	at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:23)
	at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:95)
	at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:88)
	at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:52)
	at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:36)
	at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:34)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:109)
	... 128 more


* Get more help at https://help.gradle.org

BUILD FAILED in 1s
4 actionable tasks: 4 executed

Running from IDE's Gradle tasks fails

Running a Java/JavaFX 11 project from IntelliJ (2018.3) -> Tools Windows -> Gradle -> Tasks -> build -> jlink, or from NetBeans (10.0vc4) Tasks -> jlink -> jlink fails:

> Task :createMergedModule FAILED
taskData: org.beryx.jlink.data.CreateMergedModuleTaskData(forceMergedJarPrefixes:[], extraDependenciesPrefixes:[], mergedModuleName:hellofx.merged.module, mergedModuleInfo:, useJdeps:no, mergedJarsDir:/.../hellofx/build/jlinkbase/mergedjars, javaHome:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home, mergedModuleJar:/.../hellofx/build/jlinkbase/jlinkjars/hellofx.merged.module.jar, nonModularJarsDirPath:/.../hellofx/build/jlinkbase/nonmodjars, jlinkJarsDirPath:/.../hellofx/build/jlinkbase/jlinkjars, tmpMergedModuleDirPath:/.../hellofx/build/jlinkbase/tmpmerged, tmpModuleInfoDirPath:/.../hellofx/build/jlinkbase/tmpmodinfo, tmpJarsDirPath:/.../hellofx/build/jlinkbase/tmpjars)
Starting process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/jar''. Working directory: /.../hellofx Command: /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/jar --create --file /.../hellofx/build/jlinkbase/tmpmerged/hellofx.merged.module.jar --no-manifest -C /.../hellofx/build/jlinkbase/mergedjars .
Successfully started process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/jar''
Opciรณn no permitida: -
Sintaxis: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
Opciones:
    -c  crear nuevo archivo
...

(it is in Spanish, but basically Java 8 jar command doesn't understand new options)

In my case, my default Java_Home is set to 8, but the project is set to JDK11. Running any other task from the IDE like build, or run works fine (Java 11).

The jlink task somehow defaults to Java 8, instead of picking the Java version set on the project.

Of course, running from terminal ./gradlew jlink works as expected.

Allow renaming image directory and image.zip file

So far, the image dir is named image, and the produced zip is named image.zip.

While that can be changed:

jlink {
    imageDir.set(project.layout.buildDirectory.dir('myImage'))
    imageZip.set(project.layout.buildDirectory.file('myImage.zip'))
...
}

it should be more convenient using a property that could be set like:

jlink {
    imageDirName='myImage'
    imageZipName='myImage.zip'
...
}

Keywords in packages not wildcarded

Hi,
I'm getting the following error:

...merged.module/module-info.java:147: error: <identifier> expected
    exports kotlin.native.concurrent;

it seems that native is a keyword in module-info.java and has to be wildcarded. Actually I haven't yet found a way to wildcard.

Implementation not available on jlink task

Hi,
I'm using google-oauth-java-client for login purposes and everything works fine when I run the application via gradle run. However, when using jlink I get the following error:

Defaulting Uptime to NOIMPL due to (java.lang.UnsupportedOperationException) Implementation not available in this environment

It seems that some dependencies are not part of the custom runtime generated by jlink.

Any ideas?

Add proguard support?

Do you think it might be possible to add proguard into the jlink build process? I think it is always a nice addition to deployment methods.

jlinkZip task not executing

Ref: beryx/badass-runtime-plugin#3

gradle clean jlinkZip
gradle clean
gradle clean jlinkZip <-- Does not produce new zip file.

'gradle -is clean jlinkZip --info --console=plain' outputs:

Task :itemsense-v2-service:jlinkZip UP-TO-DATE
Skipping task ':itemsense-v2-service:jlinkZip' as it is up-to-date.
:itemsense-v2-service:jlinkZip (Thread[Execution worker for ':' Thread 3,5,main]) completed. Took 0.0 secs.

[Question] No .bat console

Hello,

My question is not directly related to the badass plugin, but maybe you already found some good workaround for this problem.

The windows console (when you launch the .bat) is tedious for the user in my context, and I'd like to {don't launch it | hide it | disable the quick edit mode}. I found some solutions, but nothing really clean.

Maybe you have any advice about that?

Error when a dependency has no classes in a package

Try to build a project with this dependency:

compile 'org.apache.poi:poi-ooxml:4.0.0'

Build fails with the error

Cannot derive uses clause from service loader invocation in: org/apache/commons/compress/utils/ServiceLoaderIterator.<init>().
H:\Pr\psr\build\jlinkbase\tmpjars\psr.merged.module\module-info.java:253: error: package is empty or does not exist: org.apache.poi.poifs
    exports org.apache.poi.poifs;
                          ^
1 error

My guess is that it happens because the package org.apache.poi.poifs does not have any clasess (but
org.apache.poi.poifs.crypt does). The plugin is still trying to export org.apache.poi.poifs in a generated module definition.

Assertion GDK_IS_X11_DISPLAY failed on Linux

When I try to execute the hello script from an example (like this) on Arch Linux, I get this error:

(java:4699): Gdk-CRITICAL **: 15:21:54.654: gdk_x11_display_set_window_scale: assertion 'GDK_IS_X11_DISPLAY (display)' failed 
# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# SIGSEGV (0xb) at pc=0x00007f015836642b, pid=4699, tid=4747 

See this openjfx bug report

Documentation?

Hi,
some documentation would be highly appreciated. For me the properties of the JlinkPluginExtension are not clear and the examples don't really tell either.
Thank you!
Best Burtan

Can't jlink modular FX project

Hi.
I'm trying to jlink my project with your plugin, but get some errors
Task :createMergedModule FAILED
ccm-thermometerls/build/jlinkbase/tmpjars/ru.ccm.calibration.merged.module/module-info.java:12: error: module not found: javafx.graphics requires javafx.graphics;
ccm-thermometerls/build/jlinkbase/tmpjars/ru.ccm.calibration.merged.module/module-info.java:13: error: module not found: javafx.controls requires javafx.controls;
ccm-thermometerls/build/jlinkbase/tmpjars/ru.ccm.calibration.merged.module/module-info.java:15: error: module not found: javafx.base requires javafx.base;

As I understand, when we trying to compile module-info.java, we have no javafx libs in classpath. What am I doing wrong? Can you help me? My project in attached file.
Use gradle 5.2.1
ccm-thermometerls.zip

Wrong mergedjars directory

Hi,
I've taken a look at the code and it seems that the mergedjars dir is incorrect.

mergedjars:

mergedJarsDir.set(project.layout.buildDirectory.dir(PathUtil.getMergedJarsDirPath(jlinkBasePath.get())))

delegatedModulesDir
delegatedModulesDir.set(new File(PathUtil.getDelegatedModulesDirPath(jlinkBasePath.get())))

nonModularJarsDir
nonModularJarsDir.set(new File(PathUtil.getNonModularJarsDirPath(jlinkBasePath.get())))

Compatibility Gradle 6.0

Hello,

When running a gradle build (gradle v5.x) with badass-jlink-plugin, the following warning appears:

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0. Use '--warning-mode all' to show the individual deprecation warnings.

When running with --warning-mode all, here the warning:

Configure project :org.sheepy.vsand Using method ObjectFactory.property() method to create a property of type Map has been deprecated. This will fail with an error in Gradle 6.0. Please use the ObjectFactory.mapProperty() method instead.

When I remove the jlink plugin, the warning doesn't appear anymore.

I use it in the project VSand.

prepareModulesDir task fails with "Cannot retrieve module name from module-info.java"

Hi, I am trying to build an image for my multi-module project and the prepareModulesDir task fails with the message in the issue title (after creating a 23MB merged jar).

I am afraid I cannot post the full build.gradle here since it is an internal company project, but the dependencies of the submodules are:

ui:
dependencies {
api project(':common')
api project(':env')
api project(':model')
api project(':api')
api project(':control')
implementation 'org.reactfx:reactfx:2.0-M5'
implementation 'org.kordamp.ikonli:ikonli-javafx:11.2.0'
implementation 'org.kordamp.ikonli:ikonli-fontawesome-pack:11.2.0'
implementation 'org.kordamp.ikonli:ikonli-material-pack:11.2.0'
implementation 'org.controlsfx:controlsfx:11.0.0-RC2'
implementation 'com.jfoenix:jfoenix:9.0.8'
implementation 'org.apache.commons:commons-lang3:3.8.1'
implementation 'commons-io:commons-io:2.6'
implementation 'org.apache.poi:poi:4.0.1'
implementation 'org.apache.poi:poi-ooxml:4.0.1'
implementation files('libs/scenicview.jar')
}

api:
dependencies {
api project(':model')
api project(':env')
api project(':common')
implementation 'org.reactfx:reactfx:2.0-M5'
implementation 'com.fasterxml.jackson.core:jackson-core:2.9.8'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.8'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.8'
implementation 'org.apache.httpcomponents:httpclient:4.5.7'
implementation 'org.apache.httpcomponents:httpcore:4.4.11'
implementation "org.cache2k:cache2k-api:${cache2kVersion}"
runtimeOnly "org.cache2k:cache2k-core:${cache2kVersion}"
}

control:
dependencies {
api project(':common')
api project(':env')
api project(':model')
implementation 'org.reactfx:reactfx:2.0-M5'
implementation 'org.kordamp.ikonli:ikonli-javafx:11.2.0'
implementation 'org.kordamp.ikonli:ikonli-fontawesome-pack:11.2.0'
implementation 'org.kordamp.ikonli:ikonli-material-pack:11.2.0'
implementation 'org.controlsfx:controlsfx:11.0.0-RC2'
implementation 'com.jfoenix:jfoenix:9.0.8'
implementation 'org.apache.commons:commons-collections4:4.2'
implementation 'org.apache.commons:commons-lang3:3.8.1'
}

env:
dependencies {
api project(':common')
api project(':model')
api 'net.engio:mbassador:1.3.2'
}

model:
dependencies {
implementation 'org.reactfx:reactfx:2.0-M5'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.8'
}

I don't know if you will be able to debug this, but it might be helpful to make the "Cannot retrieve module name from module-info.java" a little more verbose (eg. print out the source string it is trying to match against the patterns), so that one can have an idea of where the problem is in big projects.

JAXB incompatibility

I'm struggling to get JAXB-RI working in the jlink image.

To help troubleshooting I created a simple example project: mwkroening/badass-jlink-jaxb

Running the app directly via ./gradlew run or running the distribution built by ./gradlew assemble gives the expected output:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app>
    <greeting>Hello World.</greeting>
</app>

Running the image generated by ./gradlew jlink gives:

Exception in thread "main" javax.xml.bind.DataBindingException: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
 - with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
	at java.xml.bind/javax.xml.bind.JAXB._marshal(JAXB.java:559)
	at java.xml.bind/javax.xml.bind.JAXB.marshal(JAXB.java:417)
	at io.github.mwkroening.badassjlinkjaxb/io.github.mwkroening.badassjlinkjaxb.App.main(App.java:9)
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
 - with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
	at java.xml.bind/javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:232)
	at java.xml.bind/javax.xml.bind.ContextFinder.find(ContextFinder.java:375)
	at java.xml.bind/javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:691)
	at java.xml.bind/javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:632)
	at java.xml.bind/javax.xml.bind.JAXB$Cache.<init>(JAXB.java:97)
	at java.xml.bind/javax.xml.bind.JAXB.getContext(JAXB.java:124)
	at java.xml.bind/javax.xml.bind.JAXB._marshal(JAXB.java:548)
	... 2 more
Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at java.xml.bind/javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:92)
	at java.xml.bind/javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:125)
	at java.xml.bind/javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:230)
	... 8 more

Can this issue be fixed with the Badass JLink Plugin or is it an incompatibility of eclipse-ee4j/jaxb-api or eclipse-ee4j/jaxb-ri with jlink?

jpackage `create-image` has been renamed to `create-app-image`

When I try to run the jpackage task against the latest ea release of jpackage(Build 49) I receive the following error:

Starting process 'command '/home/user/localjava/jdk-jpackage-13//bin/jpackage''. Working directory: /home/user/company/application Command: /home/user/localjava/jdk-jpackage-13//bin/jpackage create-image --output /home/user/company/application/build/jpackage --name em --module-path /home/user/company/application/build/jlinkbase/jlinkjars --module com.company/com.company.application.Module --runtime-image /home/user/company/application/build/image
Successfully started process 'command '/home/user/localjava/jdk-jpackage-13//bin/jpackage''
Error: Invalid Option: [create-image].

It seems that create-image has been changed to create-app-image see jpackage docs

Project without dependencies with 2.1.9 fails

Running a JavaFX 11 regular project without any dependency in the dependencies block fails with version 2.1.9, but works with 2.1.8.

:createMergedModule (Thread[Daemon worker,5,main]) completed. Took 0.239 secs.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':createMergedModule'.
> Cannot invoke method getValue() on null object

The message doesn't really help to identify what is the problem.

But just adding some dependency like:

dependencies {
    compile 'org.openjfx:javafx-web:11.0.1'
}

solves the issue.

Cannot derive uses clause from service loader invocation in: .. package javax.servlet does not exist

Hi,

This is my first try to getting a custom runtime built for my JavaFX 11 / Java 11 application. It depends on LogBack-classic & slf4j for logging support. However, I'm getting the error below due to some dependency of LogBack on javax.servlet. I'm not sure how to resolve it, but perhaps it is an issue with the beryx jlink plugin, given that I've found an issue report with roughly the same error ('Cannot derive uses .. ' ) here. However, the root cause in my case seems different: package javax.servlet does not exist .

Task :createMergedModule
Cannot derive uses clause from service loader invocation in: ch/qos/logback/classic/util/EnvUtil.loadFromServiceLoader().
D:\workspaces\workspace\JFX\build\jlinkbase\tmpjars\be.kuleuven.merged.module\module-info.java:218: error: package javax.servlet does not exist
provides javax.servlet.ServletContainerInitializer with ch.qos.logback.classic.servlet.LogbackServletContainerInitializer;

Unable to create merged module, leading to failure to sign

Complete output:

josh@joshlaptop ~/ProjectSWG/devel/Holocore/holocore $ gradle jlink

> Configure project :
Found module name 'holocore'

> Configure project :pswgcommon
Found module name 'pswgcommon'

> Task :compileJava
Note: /home/josh/ProjectSWG/devel/Holocore/holocore/src/main/java/com/projectswg/holocore/resources/support/data/server_info/mongodb/users/PswgUserDatabase.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :createMergedModule
Cannot retrieve the module name of /home/josh/ProjectSWG/devel/Holocore/holocore/build/jlinkbase/tmpmerged/holocore.merged.module.jar. Using fallback value: holocore.merged.module.
java.lang.module.FindException: Unable to derive module descriptor for /home/josh/ProjectSWG/devel/Holocore/holocore/build/jlinkbase/tmpmerged/holocore.merged.module.jar
        at java.base/jdk.internal.module.ModulePath.readJar(ModulePath.java:647)
        at java.base/jdk.internal.module.ModulePath.readModule(ModulePath.java:330)
        at java.base/jdk.internal.module.ModulePath.scan(ModulePath.java:236)
        at java.base/jdk.internal.module.ModulePath.scanNextEntry(ModulePath.java:189)
        at java.base/jdk.internal.module.ModulePath.findAll(ModulePath.java:165)
        at java_lang_module_ModuleFinder$findAll.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:119)
        at org.beryx.jlink.util.Util.getModuleName(Util.groovy:80)
        at org.beryx.jlink.util.Util$getModuleName$4.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:135)
        at org.beryx.jlink.impl.CreateMergedModuleTaskImpl.genModuleInfoBadass(CreateMergedModuleTaskImpl.groovy:81)
        at org.beryx.jlink.impl.CreateMergedModuleTaskImpl$genModuleInfoBadass$1.callCurrent(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:156)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:176)
        at org.beryx.jlink.impl.CreateMergedModuleTaskImpl.genModuleInfo(CreateMergedModuleTaskImpl.groovy:54)
        at org.beryx.jlink.impl.CreateMergedModuleTaskImpl$genModuleInfo.callCurrent(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:156)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:176)
        at org.beryx.jlink.impl.CreateMergedModuleTaskImpl.execute(CreateMergedModuleTaskImpl.groovy:37)
        at org.beryx.jlink.CreateMergedModuleTask.createMergedModuleAction(CreateMergedModuleTask.groovy:100)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:48)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:41)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:704)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:671)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:117)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:106)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:85)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:65)
        at org.gradle.api.internal.tasks.execution.ActionEventFiringTaskExecuter.execute(ActionEventFiringTaskExecuter.java:44)
        at org.gradle.api.internal.tasks.execution.TimeoutTaskExecuter.execute(TimeoutTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.SnapshotAfterExecutionTaskExecuter.execute(SnapshotAfterExecutionTaskExecuter.java:38)
        at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:49)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:61)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:44)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:49)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:44)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:337)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:325)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:318)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:304)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.NullPointerException
        at java.base/sun.security.util.SignatureFileVerifier.verifyManifestMainAttrs(SignatureFileVerifier.java:542)
        at java.base/sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:335)
        at java.base/sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:269)
        at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:316)
        at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:230)
        at java.base/java.util.jar.JarFile.initializeVerifier(JarFile.java:757)
        at java.base/java.util.jar.JarFile.getInputStream(JarFile.java:838)
        at java.base/jdk.internal.module.ModulePath.deriveModuleDescriptor(ModulePath.java:545)
        at java.base/jdk.internal.module.ModulePath.readJar(ModulePath.java:643)
        ... 81 more

> Task :jlink FAILED
Error: null
java.lang.NullPointerException
        at java.base/sun.security.util.SignatureFileVerifier.verifyManifestMainAttrs(SignatureFileVerifier.java:542)
        at java.base/sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:335)
        at java.base/sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:269)
        at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:316)
        at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:230)
        at java.base/java.util.jar.JarFile.initializeVerifier(JarFile.java:757)
        at java.base/java.util.jar.JarFile.getInputStream(JarFile.java:838)
        at java.base/jdk.internal.module.ModulePath.readJar(ModulePath.java:651)
        at java.base/jdk.internal.module.ModulePath.readModule(ModulePath.java:330)
        at java.base/jdk.internal.module.ModulePath.scanDirectory(ModulePath.java:283)
        at java.base/jdk.internal.module.ModulePath.scan(ModulePath.java:231)
        at java.base/jdk.internal.module.ModulePath.scanNextEntry(ModulePath.java:189)
        at java.base/jdk.internal.module.ModulePath.find(ModulePath.java:153)
        at java.base/java.lang.module.Resolver.findWithBeforeFinder(Resolver.java:825)
        at java.base/java.lang.module.Resolver.resolve(Resolver.java:118)
        at java.base/java.lang.module.Configuration.resolve(Configuration.java:411)
        at java.base/java.lang.module.Configuration.resolve(Configuration.java:245)
        at jdk.jlink/jdk.tools.jlink.internal.Jlink$JlinkConfiguration.resolve(Jlink.java:220)
        at jdk.jlink/jdk.tools.jlink.internal.JlinkTask.createImageProvider(JlinkTask.java:486)
        at jdk.jlink/jdk.tools.jlink.internal.JlinkTask.createImage(JlinkTask.java:396)
        at jdk.jlink/jdk.tools.jlink.internal.JlinkTask.run(JlinkTask.java:272)
        at jdk.jlink/jdk.tools.jlink.internal.Main.run(Main.java:54)
        at jdk.jlink/jdk.tools.jlink.internal.Main.main(Main.java:33)


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':jlink'.
> Process 'command '/home/josh/Java/latest_jdk/bin/jlink'' finished with non-zero exit value 4

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 17s
11 actionable tasks: 8 executed, 3 up-to-date

module-info.java

open module holocore {
	requires java.sql;
	requires java.management;
	requires jdk.management;
	
	requires org.jetbrains.annotations;
	requires org.mongodb.driver.sync.client;
	requires org.mongodb.bson;
	requires me.joshlarson.jlcommon;
	
	requires pswgcommon;
}

build.gradle

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
	id 'application'
	id 'java'
	id 'idea'
	id "com.github.johnrengelman.shadow" version "4.0.3"
	id "org.javamodularity.moduleplugin" version "1.2.1"
	id "org.beryx.jlink" version "2.1.6"
}

mainClassName = 'com.projectswg.holocore.ProjectSWG'
sourceCompatibility = 11
targetCompatibility = 11

sourceSets {
	display { }
	utility { }
	integration { }
}

test {
	afterSuite { TestDescriptor td, TestResult tr ->
		if (td.parent == null) {
			println 'Tests run: (' + tr.getTestCount() + '), Failures: (' + tr.getFailedTestCount() + ')' // IMPORTANT - this is required for Lightspeed
		}
	}
}

shadowJar {
	baseName = "Holocore"
	classifier = null
	version = null
}

repositories {
	jcenter()
}

dependencies {
	compile project(':pswgcommon')
	
	compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.23.1'
	compile group: 'org.mongodb', name: 'mongodb-driver-sync', version: '3.9.1'
	compile group: 'me.joshlarson', name: "fast-json", version: '3.0.0'
	
	testCompile 'junit:junit:4.12'
	
	displayCompile project(':pswgcommon')
	displayCompile sourceSets.main.output
	
	utilityCompile project(':pswgcommon')
	utilityCompile sourceSets.main.output
	utilityCompile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.23.1'
	utilityCompile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.6.3'
	utilityCompile group: 'me.joshlarson', name: "fast-json", version: '3.0.0'
	
	integrationCompile project(':pswgcommon')
	integrationCompile project(':client-holocore')
	integrationCompile sourceSets.main.output
	integrationCompile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.23.1'
	integrationCompile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.6.3'
	integrationCompile 'junit:junit:4.12'
}

task CreateConvertLoginJar(type: ShadowJar) {
	archiveName = 'ConvertLogin.jar'
	manifest.attributes 'Main-Class': 'com.projectswg.utility.ConvertLogin'
	from sourceSets.utility.output
	configurations = [project.configurations.utilityRuntime]
	exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA')
}

task CreatePacketCaptureProcessor(type: ShadowJar) {
	archiveName = 'PacketCaptureProcessor.jar'
	manifest.attributes 'Main-Class': 'com.projectswg.utility.packets.ProcessPacketCapture'
	from sourceSets.utility.output
	configurations = [project.configurations.utilityRuntime]
	exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA')
}

Warning when module names end with a digit.

I have dependencies on, among others, org.apache.commons:commons-math3:3.6.1.

When this is merged and compiled I get the following warning:

> Task :Base:createDelegatingModules
/Users/lennartb/RaT/git/BMF/Base/build/jlinkbase/tmpjars/commons.math3/module-info.java:2: warning: [module] module name component math3 should avoid terminal digits
open module commons.math3 {
                   ^
1 warning

I guess a fix could be done in Util.getModuleName(File f), but since this method mostly relies on ModuleFinderto infer the module name, I don't know if it's a good idea to mess with the name? I should perhaps just keep calm and ignore the warning.

exclude awt, swing, ...

I'm trying this plugin, and I really like it a lot... I seem to have a problem with the generated image though: it generates a 'modules' library, but that one seems to contain a lot of java modules which are absolutely not necessary by the application. I'm embedding vert.x, which is a server side library, and the modules include libraries like swing and awt (amongst others I don't really want)

Why would that be? Thx.

Allow more module paths

I am currently trying to add the javafx jmods (linux and mac) to the module path. The problem is that it seems to be overwritten. I'm guessing that is caused by this code in JlinkTaskImpl.

commandLine = ["$td.javaHome/bin/jlink",
                           '-v',
                           *options,
                           '--module-path',
                           "$jdkHome/jmods/$SEP${project.files(td.jlinkJarsDir).asPath}",
                           '--add-modules', td.moduleName,
                           '--output', imageDir]

It might be a good idea to allow the user to pass in a list of paths that can then be appended to --module-path
Current fix is just to put all the necessary jmods in in $jdkHome/jmods

Merged module created is not found on createDelegatingModules

I do not really why this is happening, but the plugin cannot find the merged module it created when dealing with the createDelegatingModules task.

I do not know if this is important, but this is failing on a dependency that is another project in the multi-project structure I am using in Gradle (compile project(':bst-java'))

I am using Windows 10 with the latest Gradle, Java 10 and badass-jlink-plugin versions available.

Here is the jlink configuration from my build.gradle :

jlink {
    launcherName = 'openbst'
    moduleName = 'zrrk.bst.openbst'
    mergedModuleName = 'zrrk.bst.dependencies.module'
    mergedModule {
        requires 'java.desktop'
        requires 'javafx.web'
		    requires 'javafx.media'
		    requires 'javafx.swing'
    }
    forceMerge 'log4j'
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
}

Here is the relevant logging information from the plugin's tasks :

> Task :openbst:prepareMergedJarsDir
Task ':openbst:prepareMergedJarsDir' is not up-to-date because:
  Value of input property 'forceMergedJarPrefixes' has changed for task ':openbst:prepareMergedJarsDir'
taskData: org.beryx.jlink.data.PrepareMergedJarsDirTaskData(forceMergedJarPrefixes:[log4j], mergedJarsDir:C:\ws\BST\openbst\build\jlinkbase\mergedjars, jlinkJarsDirPath:C:\ws\BST\openbst\build/jlinkbase/jlinkjars, nonModularJarsDirPath:C:\ws\BST\openbst\build/jlinkbase/nonmodjars)
modularJars: []
nonModularJars: [findbugs-annotations-3.0.1.jar, log4j-api-2.11.1.jar, log4j-core-2.11.1.jar, miglayout-swing-5.2.jar, miglayout-core-5.2.jar, bst-java-2.0-SNAPSHOT.jar, classindex-3.4.jar, txtmark-0.13.jar, gson-2.8.5.jar, commons-io-2.6.jar, commons-compress-1.18.jar, xz-1.8.jar]
modularJarsRequiredByNonModularJars: []
Copying modular jars required by non-modular jars to C:\ws\BST\openbst\build/jlinkbase/jlinkjars...
Copying mon-modular jars to C:\ws\BST\openbst\build/jlinkbase/nonmodjars...
Merging content into C:\ws\BST\openbst\build\jlinkbase\mergedjars...
:openbst:prepareMergedJarsDir (Thread[Task worker for ':' Thread 2,5,main]) completed. Took 28.771 secs.
:openbst:createMergedModule (Thread[Task worker for ':' Thread 2,5,main]) started.

> Task :openbst:createMergedModule
Task ':openbst:createMergedModule' is not up-to-date because:
  Output property 'mergedModuleJar' file C:\ws\BST\openbst\build\jlinkbase\jlinkjars\zrrk.bst.dependencies.module.jar has been removed.
taskData: org.beryx.jlink.data.CreateMergedModuleTaskData(mergedModuleName:zrrk.bst.dependencies.module, javaHome:C:\Program Files\Java\jdk-10.0.2, mergedModuleInfo:requires java.desktop;
requires javafx.web;
requires javafx.media;
requires javafx.swing;, jdepsEnabled:false, mergedJarsDir:C:\ws\BST\openbst\build\jlinkbase\mergedjars, mergedModuleJar:C:\ws\BST\openbst\build\jlinkbase\jlinkjars\zrrk.bst.dependencies.module.jar, nonModularJarsDirPath:C:\ws\BST\openbst\build/jlinkbase/nonmodjars, jlinkJarsDirPath:C:\ws\BST\openbst\build/jlinkbase/jlinkjars, tmpMergedModuleDirPath:C:\ws\BST\openbst\build/jlinkbase/tmpmerged, tmpModuleInfoDirPath:C:\ws\BST\openbst\build/jlinkbase/tmpmodinfo, tmpJarsDirPath:C:\ws\BST\openbst\build/jlinkbase/tmpjars)
Starting process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/jar''. Working directory: C:\ws\BST\openbst Command: C:\Program Files\Java\jdk-10.0.2/bin/jar --create --file C:\ws\BST\openbst\build/jlinkbase/tmpmerged/zrrk.bst.dependencies.module.jar --no-manifest -C C:\ws\BST\openbst\build\jlinkbase\mergedjars .
Successfully started process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/jar''
Generating module-info in C:\ws\BST\openbst\build\jlinkbase\tmpjars...
Compiling module-info from C:\ws\BST\openbst\build\jlinkbase\tmpjars\org.apache.logging.log4j...
Starting process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/javac''. Working directory: C:\ws\BST\openbst Command: C:\Program Files\Java\jdk-10.0.2/bin/javac -p C:\ws\BST\openbst\build\jlinkbase\tmpmerged;C:\ws\BST\openbst\build/jlinkbase/jlinkjars -d C:\ws\BST\openbst\build\jlinkbase\tmpmodinfo C:\ws\BST\openbst\build\jlinkbase\tmpjars\org.apache.logging.log4j/module-info.java
Successfully started process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/javac''
Copy from C:\ws\BST\openbst\build/jlinkbase/tmpmerged/zrrk.bst.dependencies.module.jar into C:\ws\BST\openbst\build\jlinkbase\jlinkjars\zrrk.bst.dependencies.module.jar...
Insert module-info from C:\ws\BST\openbst\build/jlinkbase/tmpmodinfo into C:\ws\BST\openbst\build\jlinkbase\jlinkjars\zrrk.bst.dependencies.module.jar...
Inserting module-info into C:\ws\BST\openbst\build\jlinkbase\jlinkjars\zrrk.bst.dependencies.module.jar...
Starting process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/jar''. Working directory: C:\ws\BST\openbst Command: C:\Program Files\Java\jdk-10.0.2/bin/jar --update --file C:\ws\BST\openbst\build\jlinkbase\jlinkjars\zrrk.bst.dependencies.module.jar -C C:\ws\BST\openbst\build\jlinkbase\tmpmodinfo module-info.class
Successfully started process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/jar''
:openbst:createMergedModule (Thread[Task worker for ':' Thread 2,5,main]) completed. Took 23.939 secs.
:openbst:createDelegatingModules (Thread[Task worker for ':' Thread 2,5,main]) started.

> Task :openbst:createDelegatingModules
Task ':openbst:createDelegatingModules' is not up-to-date because:
  Task has failed previously.
taskData: org.beryx.jlink.data.CreateDelegatingModulesTaskData(mergedModuleName:zrrk.bst.dependencies.module, javaHome:C:\Program Files\Java\jdk-10.0.2, nonModularJarsDir:C:\ws\BST\openbst\build\jlinkbase\nonmodjars, delegatingModulesDir:C:\ws\BST\openbst\build\jlinkbase\delegating, jlinkJarsDirPath:C:\ws\BST\openbst\build/jlinkbase/jlinkjars, tmpModuleInfoDirPath:C:\ws\BST\openbst\build/jlinkbase/tmpmodinfo, tmpJarsDirPath:C:\ws\BST\openbst\build/jlinkbase/tmpjars)
Creating delegating modules...
Compiling delegate module zrrk.bst.bstjava ...
Starting process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/javac''. Working directory: C:\ws\BST\openbst Command: C:\Program Files\Java\jdk-10.0.2/bin/javac -p C:\ws\BST\openbst\build/jlinkbase/jlinkjars -d C:\ws\BST\openbst\build/jlinkbase/tmpmodinfo C:\ws\BST\openbst\build\jlinkbase\tmpjars\zrrk.bst.bstjava/module-info.java
Successfully started process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/javac''
C:\ws\BST\openbst\build\jlinkbase\tmpjars\zrrk.bst.bstjava\module-info.java:3: error: module not found: zrrk.bst.dependencies.module
    requires transitive zrrk.bst.dependencies.module;
                                             ^
1 error


> Task :openbst:createDelegatingModules FAILED
:openbst:createDelegatingModules (Thread[Task worker for ':' Thread 2,5,main]) completed. Took 6.118 secs.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':openbst:createDelegatingModules'.
> Process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/javac'' finished with non-zero exit value 1

* Try:
Run with --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':openbst:createDelegatingModules'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:110)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
        at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:51)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
        at org.gradle.execution.taskgraph.LocalTaskInfoExecutor.execute(LocalTaskInfoExecutor.java:42)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:277)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:262)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:135)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:130)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.execute(DefaultTaskPlanExecutor.java:200)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.executeWithWork(DefaultTaskPlanExecutor.java:191)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.run(DefaultTaskPlanExecutor.java:130)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files\Java\jdk-10.0.2/bin/javac'' finished with non-zero exit value 1
        at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:395)
        at org.gradle.process.ExecResult$assertNormalExitValue.call(Unknown Source)
        at org.beryx.jlink.impl.CreateDelegatingModulesTaskImpl.createDelegatingModule(CreateDelegatingModulesTaskImpl.groovy:60)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.beryx.jlink.impl.CreateDelegatingModulesTaskImpl$_execute_closure1.doCall(CreateDelegatingModulesTaskImpl.groovy:33)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.beryx.jlink.impl.CreateDelegatingModulesTaskImpl.execute(CreateDelegatingModulesTaskImpl.groovy:32)
        at org.beryx.jlink.impl.CreateDelegatingModulesTaskImpl$execute.call(Unknown Source)
        at org.beryx.jlink.CreateDelegatingModulesTask.createDelegatingModulesAction(CreateDelegatingModulesTask.groovy:74)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:46)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:801)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:768)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:131)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:120)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:99)
        ... 31 more

Can't use variables to specify the targetPlatform jdkHome

In essence, this doesn't work:

def javaHomeLinux = '/home/josh/Java/jdk-11.0.1'
def javaHomeMac = '/home/josh/Java/mac/jdk-11.0.1'
def javaHomeWindows = '/home/josh/Java/windows/jdk-11.0.1'

jlink {
	addOptions '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'
	targetPlatform('linux', javaHomeLinux)
	targetPlatform('mac', javaHomeMac)
	targetPlatform('windows', javaHomeWindows)
}

but this does:

jlink {
	addOptions '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'
	targetPlatform('linux', '/home/josh/Java/jdk-11.0.1')
	targetPlatform('mac', '/home/josh/Java/mac/jdk-11.0.1')
	targetPlatform('windows', '/home/josh/Java/windows/jdk-11.0.1')
}

Some output that I think will be useful:
Using variables: (can see the quotes around '/home/josh/Java/windows/jdk-11.0.1')

$ gradle clean jlink
Starting process 'command '/home/josh/Java/jdk-11.0.1/bin/jlink''. Working directory: /home/josh/ProjectSWG/devel/Launcher/launcher Command: /home/josh/Java/jdk-11.0.1/bin/jlink -v --module-path '/home/josh/Java/windows/jdk-11.0.1'/jmods/:/home/josh/ProjectSWG/devel/Launcher/launcher/build/jlinkbase/jlinkjars:/home/josh/ProjectSWG/devel/Launcher/launcher/build/libs/launcher-1.1.13.jar --add-modules com.projectswg.launcher --output /home/josh/ProjectSWG/devel/Launcher/launcher/build/image/launcher-windows

Using strings:

$ gradle clean jlink
Starting process 'command '/home/josh/Java/jdk-11.0.1/bin/jlink''. Working directory: /home/josh/ProjectSWG/devel/Launcher/launcher Command: /home/josh/Java/jdk-11.0.1/bin/jlink -v --module-path /home/josh/Java/windows/jdk-11.0.1/jmods/:/home/josh/ProjectSWG/devel/Launcher/launcher/build/jlinkbase/jlinkjars:/home/josh/ProjectSWG/devel/Launcher/launcher/build/libs/launcher-1.1.13.jar --add-modules com.projectswg.launcher --output /home/josh/ProjectSWG/devel/Launcher/launcher/build/image/launcher-windows

jlink build error with dependency apache-poi

Issuing ./gradlew jlink with the apache-poi dependency:
compile ('org.apache.poi:poi:4.0.1')

I get this error:
Cannot derive uses clause from service loader invocation in: org/apache/commons/compress/utils/ServiceLoaderIterator.<init>(). /home/user/workspace/TestGluonApplication/build/jlinkbase/tmpjars/TestGluonApplication.merged.module/module-info.java:191: error: package is empty or does not exist: org.apache.poi.poifs exports org.apache.poi.poifs;

This issue is the same as the closed issue: Error when a dependency has no classes in a package #7


My environment:
host Ubuntu 18.04.1
gradle 5.0
openjdk 11.0.1
Javafx 11.0.1


here's my build.gradle:
plugins {
id 'org.openjfx.javafxplugin' version '0.0.5'
id 'org.beryx.jlink' version '2.1.9'
}

repositories {
jcenter()
mavenCentral()
}

mainClassName = 'testgluonapplication/com.gluonapplication.GluonApplication'

dependencies {
compile ('org.apache.poi:poi:4.0.1')
compile ('org.apache.poi:poi-ooxml:4.0.1')
}

javafx {
version = "11.0.1"
modules = [ 'javafx.controls',
'javafx.fxml',
'javafx.web'
]
}

compileJava {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls',
'--add-modules', 'javafx.fxml',
'--add-modules', 'javafx.web'
]
}
}

jlink {
javaHome = '/usr/lib/jvm/jdk-11.0.1+13'
options = ['--strip-debug', '--compress', '2',
'--no-header-files', '--no-man-pages'
]
addExtraDependencies("javafx")
launcher {
name = 'testgluonapplication'
}
}


Here's my module-info.java:
module testgluonapplication {

requires javafx.controls;
requires javafx.fxml;
requires javafx.web;

requires poi;
requires poi.ooxml;

exports com.gluonapplication;
}


Here's my javafx code:
package com.gluonapplication;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class GluonApplication extends Application {

HSSFWorkbook workbookH = null;
XSSFWorkbook workbookX = null;

@Override
public void start(Stage stage) {		
	StackPane root = new StackPane(
			new Label("Hello JavaFX World! <<<<<<<<<<<<<<"));			
	stage.setScene(new Scene(root));
	stage.show();
   } 

}

The classes and folders for org.apache.poi.poifs are copied OK in my build/jlinkbase folders and so the poifs package is not empty and does exist, contrary to the error message. Tried forceMerge 'poi' but this didn't help. Any thoughts what to try?

Uninformative error message when jpackage command not found

No informative error message is displayed when jpackageHome is incorrectly configured or the jpackage tool is not available. It is necessary to use the Gradle --info option to get to figure out what caused the error.

Example output without --info:

[178]$ gradle bitcoinj-wallettemplate:jpackage
Including wallettemplate because Gradle 5.3 and Java 12

> Configure project :bitcoinj-wallettemplate
Found module name 'wallettemplate'

> Task :bitcoinj-wallettemplate:jpackage FAILED
The jpackage task is experimental. Use it at your own risk.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':bitcoinj-wallettemplate:jpackage'.
> A problem occurred starting process 'command '/Users/sean/.sdkman/candidates/java/12.0.0-open/bin/jpackage''

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.3/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 0s
20 actionable tasks: 1 executed, 19 up-to-date

`UnsupportedCharsetException: Cp65001` on Windows

I'm trying to link my project using jlink on Windows, but get this charset exception. I tried changing the terminal to UTF-8 by chcp 65001 which did not resolve the issue. Also passing
-Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 in gradle.properties did not resolve the issue.

I am running Windows 10 with OpenJDK 12. The jlink task works fine both on Linux and macOS.
The issue is also present in the badass-jlink-example-log4j2-javafx example project.

Steps to reproduce:

  • Fresh installation of Windows 10
  • Install OpenJDK 12
  • Install git
  • Clone example repo
  • run .\gradlew jlink
> Task :prepareModulesDir FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':prepareModulesDir'.
> Cp65001

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':prepareModulesDir'.
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:63)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:49)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:46)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: java.nio.charset.UnsupportedCharsetException: Cp65001
        at org.beryx.jlink.util.Util.getDefaultModuleName(Util.groovy:77)
        at org.beryx.jlink.data.JlinkPluginExtension$_closure2.doCall(JlinkPluginExtension.groovy:66)
        at org.beryx.jlink.data.JlinkPluginExtension$_closure2.call(JlinkPluginExtension.groovy)
        at org.gradle.api.internal.provider.DefaultProvider.getOrNull(DefaultProvider.java:41)
        at org.gradle.api.internal.provider.AbstractMappingProvider.getOrNull(AbstractMappingProvider.java:54)
        at org.gradle.api.internal.provider.AbstractMinimalProvider.withFinalValue(AbstractMinimalProvider.java:75)
        at org.gradle.api.internal.provider.DefaultPropertyState.makeFinal(DefaultPropertyState.java:123)
        at org.gradle.api.internal.provider.AbstractProperty.beforeRead(AbstractProperty.java:74)
        at org.gradle.api.internal.provider.DefaultPropertyState.isPresent(DefaultPropertyState.java:154)
        at org.gradle.api.internal.tasks.properties.bean.AbstractNestedRuntimeBeanNode$DefaultPropertyValue.getValue(AbstractNestedRuntimeBeanNode.java:151)
        at org.gradle.api.internal.tasks.properties.bean.AbstractNestedRuntimeBeanNode$DefaultPropertyValue.validate(AbstractNestedRuntimeBeanNode.java:165)
        at org.gradle.api.internal.tasks.DefaultTaskInputPropertySpec.validate(DefaultTaskInputPropertySpec.java:68)
        at org.gradle.api.internal.tasks.execution.DefaultTaskProperties.validate(DefaultTaskProperties.java:197)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:50)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:109)
        at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionOutputsTaskExecuter.execute(ResolveBeforeExecutionOutputsTaskExecuter.java:67)
        at org.gradle.api.internal.tasks.execution.ResolveAfterPreviousExecutionStateTaskExecuter.execute(ResolveAfterPreviousExecutionStateTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:93)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:45)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:94)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        ... 24 more


* Get more help at https://help.gradle.org

BUILD FAILED in 10s
8 actionable tasks: 6 executed, 2 up-to-date

Module java.xml.bind not found although dependency is available

Hi,
I am trying to use this plugin for our project but it seems that the dependencies to jersey-server and jakarta.xml.bind-api break the "createMergedModule" task.

> Task :test:createMergedModule FAILED
<path>/test/build/jlinkbase/tmpjars/test.merged.module/module-info.java:72: error: module not found: java.xml.bind
    requires java.xml.bind;

I was able to reproduce this with the below build.gradle.

plugins {
    id 'java-library-distribution'
    id 'org.beryx.jlink' version '2.10.3'
}

ext.moduleName = 'test'
mainClassName = 'test.Test'

dependencies {
    implementation "org.glassfish.jersey.core:jersey-server:2.28"
    implementation "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2"
}

jar {
    inputs.property('mainClassName', mainClassName)
    doLast {
        exec {
            executable = 'jar'
            args = [
                '--update', '--file', "$archiveFile.orNull",
                '--main-class', "$mainClassName"
            ]
        }
    }

    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
}

It seems to me, that "prepareMergedJarsDir" never copied "jakarta.xml.bind-api" to "jlinkjars" even though it is a full fledged module. Nor was the content extracted to "mergedJars".

Am I missing some plugin configuration, or did I encounter a bug?

Kind regards.

Duplicate data in packages produced by jpackage

I tried making a macOs .app using the jpackage functionality for the first time and, although all went well and the app works as expected, the total size of the app directory is 1.5x the size it should be (the jlink task produces a total size of ~100MB in my case, whereas the .app is ~150MB).
After checking the contents of the .app I noticed something weird:
apart from the Plugins/Java.runtime directory (which seems to include all of the jlink task results), there is a Java/mods directory, which includes separate jar files + the merged module file. If I understand correctly, all these jars are already merged inside the "modules" file residing in the libs directory (Plugins/Java.runtime/contents/home/lib) of the runtime image produced by jlink.
Although I prefer to have separate jars than the huge uber-merged modules file produced by jlink (this is another discussion, I would love to have some more info on this and whether it is optional), there seems to be some kind of duplication here.
Any thoughts would be appreciated.

EDIT: I just deleted the Java/mods directory from the produced .app and the app still launches and works fine. This verifies that the directory is unneeded and I am wondering why it is being produced. I suspect it is a jpackage thing and the badass plugin has nothing to do with it.

Task jlink FAILED. Error: Module XXX not found

Hello,

I finally managed to make my project fully compatible with java 9 (all projects and dependencies are modules). Gradle run works from scratch. I'm able to manually make a jlink build of my project (using the jars built by gradle). Now I try to use the badass-jlink-plugin, but something goes wrong when I type "gradle jlink" :
Task jlink FAILED. Error: Module XXX not found

The module XXX (org.lwjgl.stb btw, but the name is probably irrelevant here) is one external dependency of my project, but it's still a true module (contains a module-info.java and so on). Here the stacktrace.

I'm not sure where is the problem, since my project should already be fully compliant with java 9 (I already made a functional jlink build).

If you want to have a look on the repo, here a command to clone everything (submodules could be a bit tricky otherwise):
git clone --single-branch -b testJLink --recursive [email protected]:Ealrann/VSand.git

The project defining the application (and the jlink) is org.sheepy.vulkan.sand.

Linux permissions are wrong

Hey,
just a small bug. When building on linux the script files don't have the execution flag set.

-rwxr-xr-x 1 frederik frederik 24584 Nov 22 22:46 java
-rwxr-xr-x 1 frederik frederik 24672 Nov 22 22:46 jrunscript
-rwxr-xr-x 1 frederik frederik 24640 Nov 22 22:46 keytool
-rw-r--r-- 1 frederik frederik   185 Nov 22 22:46 livesets-manager-app
-rw-r--r-- 1 frederik frederik   203 Nov 22 22:46 livesets-manager-app.bat

createMergedModule gives 'duplicate module on application module path'

The error output looks like this:

Task ':airgapfx-wallet:createMergedModule' is not up-to-date because:
  Task has failed previously.
taskData: org.beryx.jlink.data.CreateMergedModuleTaskData(forceMergedJarPrefixes:[], extraDependenciesPrefixes:[javafx], mergedModuleName:org.consensusj.supernautfx.merged.module, mergedModuleInfo:requires java.logging;
requires java.desktop;, useJdeps:no, mergedJarsDir:/Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/mergedjars, javaHome:/Users/sean/.sdkman/candidates/java/12.0.1-open, mergedModuleJar:/Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/jlinkjars/org.consensusj.supernautfx.merged.module.jar, nonModularJarsDirPath:/Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/nonmodjars, jlinkJarsDirPath:/Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/jlinkjars, tmpMergedModuleDirPath:/Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpmerged, tmpModuleInfoDirPath:/Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpmodinfo, tmpJarsDirPath:/Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpjars)
Starting process 'command '/Users/sean/.sdkman/candidates/java/12.0.1-open/bin/jar''. Working directory: /Users/sean/git/wallet-framework/airgapfx-wallet Command: /Users/sean/.sdkman/candidates/java/12.0.1-open/bin/jar --create --file /Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpmerged/org.consensusj.supernautfx.merged.module.jar --no-manifest -C /Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/mergedjars .
Successfully started process 'command '/Users/sean/.sdkman/candidates/java/12.0.1-open/bin/jar''
Generating module-info in /Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpjars...
Compiling module-info from /Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpjars/org.consensusj.supernautfx.merged.module...
Starting process 'command '/Users/sean/.sdkman/candidates/java/12.0.1-open/bin/javac''. Working directory: /Users/sean/git/wallet-framework/airgapfx-wallet Command: /Users/sean/.sdkman/candidates/java/12.0.1-open/bin/javac -p /Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpmerged:/Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/jlinkjars -d /Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpmodinfo /Users/sean/git/wallet-framework/airgapfx-wallet/build/jlinkbase/tmpjars/org.consensusj.supernautfx.merged.module/module-info.java
Successfully started process 'command '/Users/sean/.sdkman/candidates/java/12.0.1-open/bin/javac''
error: duplicate module on application module path
  module in javafx.fxml
error: duplicate module on application module path
  module in javafx.graphics
error: duplicate module on application module path
  module in javafx.controls
error: duplicate module on application module path
  module in javafx.base
4 errors

> Task :airgapfx-wallet:createMergedModule FAILED

I'm building on a Mac and somehow I ended up with *-linux.jar jars in /jlinkbase/jlinkjars/

If I manually remove them with:

rm build/jlinkbase/jlinkjars/*-linux.jar

Then jpackage gets a lot further.

Jackson2 createMergedModule cannot derive uses clause

I have problem with adding Jackson2 Databind dependency to my custom runtime image. Project compile successful but application get exception while running. To reproduce problem I cloned example openjfx with log4j added new dependency to build.gradle:
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'
added require to module-info:
requires com.fasterxml.jackson.databind;
to start() added few lines with mapper:

ObjectMapper mapper = new ObjectMapper();
        String jsonInString = "{\"name\":\"user1\",\"age\":20}";
        try {
            User user = mapper.readValue(jsonInString, User.class); //User is simple POJO
        } catch (IOException e) {
            LogManager.getLogger().log(Level.ERROR, e);
        }

And when I run task jlink with gradle5 I get:

Executing task 'jlink'...

Configure project :
Found module name 'hellofx'

Task :compileJava
Task :processResources
Task :classes
Task :jar
Task :prepareMergedJarsDir

Task :createMergedModule
Cannot derive uses clause from service loader invocation in: com/fasterxml/jackson/databind/ObjectMapper$2.run().
Cannot derive uses clause from service loader invocation in: com/fasterxml/jackson/databind/ObjectMapper.secureGetServiceLoader().

Task :createDelegatingModules
Task :prepareModulesDir
Task :jlink

BUILD SUCCESSFUL in 36s
8 actionable tasks: 8 executed

But when I run app I get:

Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make org.openjfx.User() accessible: module hellofx does not "opens org.openjfx" to module hellofx.merged.module
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.Constructor.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.Constructor.setAccessible(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.util.ClassUtil.checkAndFixAccess(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.impl.CreatorCollector._fixAccess(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.impl.CreatorCollector.setDefaultCreator(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addDeserializerConstructors(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(Unknown Source)
at hellofx.merged.module/com.fasterxml.jackson.databind.ObjectMapper.readValue(Unknown Source)
at hellofx/org.openjfx.HelloFX.start(Unknown Source)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(Unknown Source)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(Unknown Source)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(Unknown Source)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(Unknown Source)
... 1 more

Besides. I discovered that adding non modular dependencies to modular project is very painful. Is there a repository or list of popular dependencies/libraries which can be easily added to modular project?

merged module and jpackage

When you have non-modular dependencies and you use automatic module to include then in your module descriptor, that works fine for running your app or even using the jlink plugin to create a custom image.

However it doesn't work for the jpackage (ea) tool, as it fails saying that jlink (the built in tool) doesn't work with automatic modules.

I've done a quick test, where I replaced the module and the non-modular dependencies with the merged module resulting from the jlink plugin. I could successfully build the installer in this way. However when running the resulting app, it failed because it couldn't find the main class in this merged module.

So I was wondering if we could split the merged module in two modules: the app module without the non-modular dependencies, and the merged module with all those non-modular dependencies.

That would be useful as we could have, as a result of the jlink task, a folder with all the modules, and still set the module argument of jpackage to the app module (and not to the merged module).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.