beryx / badass-jlink-plugin

Create a custom runtime image of your modular application
https://badass-jlink-plugin.beryx.org
Apache License 2.0
385 stars 27 forks source link

Spring boot web "module not found: java.annotation" #194

Closed souhaib100 closed 3 years ago

souhaib100 commented 3 years ago

Hello, I use this example https://github.com/mockbirds/javafx-springboot-badass-jlink with gradle 7.1.1 and update the plugins in builde.gradle to the latest version and also add Spring boot web dependency:

plugins {
    id 'org.springframework.boot' version '2.5.3'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'org.openjfx.javafxplugin' version '0.0.10'
    id "org.beryx.jlink" version "2.24.1"
}

group 'de.mockbirds'
version '1.0'

sourceCompatibility = '16'
targetCompatibility = '16'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'javax.servlet:javax.servlet-api:4.0.1'
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web' /// this is what I add
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

jar {
    enabled = true
}

javafx {
    version = "16"
    modules = ['javafx.controls', 'javafx.graphics']
}

jlink {
    addExtraDependencies("javafx")
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'hellofx'

        jvmArgs = [
            '--add-reads', 'de.mockbirds.merged.module=de.mockbirds.javafx',
            '-cp', '../app/*'
        ]
    }
    mergedModule {
        additive = true
        uses 'ch.qos.logback.classic.spi.Configurator'

        excludeRequires 'com.fasterxml.jackson.module.paramnames'
        excludeProvides implementation: 'com.sun.xml.bind.v2.ContextFactory'
        excludeProvides servicePattern: 'javax.enterprise.inject.*'
        excludeProvides servicePattern: 'reactor.blockhound.integration.*'
        excludeProvides service: 'org.apache.logging.log4j.spi.Provider'
    }
    jpackage {
        imageName = 'HelloFX'
        skipInstaller = true
        installerName = 'HelloFX'
        installerType = 'pkg'
    }
    forceMerge('log4j-api')
}

application {
    mainModule.set("de.mockbirds.javafx") // name defined in module-info.java
    mainClass.set("de.mockbirds.javafx.JavaFxSpringApp")
}

When I run the application inside Idea every thing works as expected. But when I execute jpackage I had this error:

22:02:20: Executing task 'jpackage'...

> Configure project :
Project : => 'de.mockbirds.javafx' Java module

> Task :compileJava
> Task :processResources UP-TO-DATE
> Task :classes
> Task :jar
> Task :prepareMergedJarsDir

> Task :createMergedModule
Cannot derive uses clause from service loader invocation in: ch/qos/logback/classic/util/EnvUtil.loadFromServiceLoader().
Cannot derive uses clause from service loader invocation in: org/springframework/beans/factory/serviceloader/AbstractServiceLoaderBasedFactoryBean.createInstance().
error: module not found: java.annotation
1 error

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':createMergedModule'.
> Process 'command 'N:\dev\java\jdk-16.0.1/bin/javac'' finished with non-zero exit value 1

* 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 26s

> Task :createMergedModule FAILED
5 actionable tasks: 4 executed, 1 up-to-date
22:02:47: Task execution finished 'jpackage'.

The module java.annotation is located inside the the jar jakarta.annotation-api-1.3.5.jar that is needed by Spring boot web.

Is this related to that jpackage can't link the module correctly? or something ealse?

siordache commented 3 years ago

You can get rid of this error by replacing

    forceMerge('log4j-api')

with

    forceMerge('log4j-api', 'tomcat')

However, this is most likely not enough. In order to make your spring-boot-starter-web application work, you need to also apply some of the dirty tricks used by the badass-jlink-spring-petclinic.

This can get quite complicated. So, you may prefer to keep your application non-modular and use instead the badass-runtime-plugin.

souhaib100 commented 3 years ago

Thank you very much, I appreciate your help. And for your advice, to be honest this is just an example to show the error, I already have a full working application (and it's uses a lot of the dirty tricks :sunglasses:), so thanks.