Spring Boot Jar не может найти файлы автоматической конфигурации

У меня довольно простое приложение Spring Boot. Один файл yaml с конфигурациями шлюза Spring, а затем один файл с основным классом приложения и основной функцией.

Я создаю файл jar следующим образом:

./gradlew clean bootJar -x test

Строится без проблем.

Файл build.gradle.kts выглядит следующим образом:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.3.2"
    id("io.spring.dependency-management") version "1.1.6"
    kotlin("jvm") version "1.9.24"
    kotlin("plugin.spring") version "1.9.24"
    application
}

application {
    mainClass.set("com.example.reverseproxy.ReverseProxyApplicationKt")
}

group = "com.example"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

repositories {
    mavenCentral()
}

extra["springCloudVersion"] = "2023.0.3"

dependencies {
    /* kotlin co-routines */
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")

    /* kotlin reflection */
    implementation("org.jetbrains.kotlin:kotlin-reflect")

    /* spring web */
//    implementation("org.springframework.boot:spring-boot-starter-webflux")

    /* spring cloud gateway */
    implementation("org.springframework.cloud:spring-cloud-starter-gateway")
    implementation("org.springframework.boot:spring-boot-starter-actuator")

    /* test - dependencies */
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")

//    testImplementation("io.projectreactor:reactor-test")
//    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
//    implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
    implementation(kotlin("stdlib-jdk8"))

}

dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
    }
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs += "-Xjsr305=strict"
        jvmTarget = "17"
    }
}


tasks.withType<Test> {
    enabled = false
    useJUnitPlatform()
}

tasks.withType<Jar> {

    duplicatesStrategy = DuplicatesStrategy.EXCLUDE

    manifest {
        attributes["Main-Class"] = "com.example.reverseproxy.ReverseProxyApplicationKt"
    }

    archiveBaseName.set("ReverseProxy")
    archiveVersion.set("0.0.1-SNAPSHOT")

    from(sourceSets.main.get().output)

    // Include dependencies in the JAR file
    dependsOn(configurations.runtimeClasspath)
    from({
        configurations.runtimeClasspath.get()
            .filter { it.name.endsWith("jar") }
            .map { zipTree(it) }
    })

    // exclude specific signed files from being included in the final JAR
    exclude("META-INF/*.SF")
    exclude("META-INF/*.DSA")
    exclude("META-INF/*.RSA")
}

tasks.named("bootJar") {
    dependsOn("jar")
}
tasks.named("bootJar") {
    mustRunAfter("jar")
}
tasks.named("bootDistZip") {
    dependsOn("jar")
}
tasks.named("bootDistZip") {
    mustRunAfter("jar")
}
tasks.named("bootDistTar") {
    dependsOn("jar")
}
tasks.named("bootDistTar") {
    mustRunAfter("jar")
}
tasks.named("startScripts") {
    dependsOn("bootJar")
}
tasks.named("startScripts") {
    mustRunAfter("bootJar")
}

Однако, когда я запускаю это

java -jar build/libs/ReverseProxy-0.0.1-SNAPSHOT.jar

Я продолжаю получать:

19:35:51.003 [main] WARN org.springframework.context.annotation.AnnotationConfigApplicationContext -- Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'httpClientSslConfigurer' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration$NettyConfiguration.class]: Unsatisfied dependency expressed through method 'httpClientSslConfigurer' parameter 0: No qualifying bean of type 'org.springframework.boot.autoconfigure.web.ServerProperties' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
19:35:51.006 [main] ERROR org.springframework.boot.SpringApplication -- Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'httpClientSslConfigurer' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration$NettyConfiguration.class]: Unsatisfied dependency expressed through method 'httpClientSslConfigurer' parameter 0: No qualifying bean of type 'org.springframework.boot.autoconfigure.web.ServerProperties' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

Я не совсем уверен, где я ошибаюсь?

Может ли кто-нибудь помочь?

Репо (минимально воспроизводимый пример):

https://github.com/dreamstar-enterprises/docs/tree/master/Spring%20BFF/ReverseProxy

ОБНОВЛЯТЬ

Ниже не помогло. Есть идеи?

// ensure that both compiled classes and resources are included in the JAR file
from(sourceSets.main.get().output)
sourceSets.main.configure {
    resources.srcDirs("src/main").includes.addAll(arrayOf("**/*.*"))
}

ОБНОВЛЕНИЕ 2

Если я закомментирую это из файла Gradle,

implementation("org.springframework.cloud:spring-cloud-starter-gateway")

Оно работает. Единственная проблема в том, что, поскольку это обратный прокси-сервер, мне очень нужна его зависимость.


50
2

Ответы:

Вы не включаете ресурсы в банку. Включая только основной исходный набор -

from(sourceSets.main.get().output)

Обратитесь к этому Добавьте файлы в исходные наборы Gradle в Kotlin DSL


Решено

Сообщение «Нет подходящего bean-компонента типа org.springframework.boot.autoconfigure.web.ServerProperties» указывает на то, что bean-компонент ServerProperties@ConfigurationProperties не был создан. Для реактивных приложений его обычно создает ReactiveWebServerFactoryAutoConfiguration.

Судя по предоставленному вами образцу, проблема, похоже, вызвана вашим необычным build.gradle.kts файлом.

Обычно для проверки того, почему не была применена автоконфигурация. Я бы использовал -Ddebug, однако ваша банка неправильно упакована, поэтому это не работает.

Если вы запустите unzip -l build/libs/ReverseProxy-0.0.1-SNAPSHOT.jar с вашим текущим приложением, вы увидите, что оно содержит как файлы .class, так и .jar из Spring. Это основная причина вашей проблемы.

Чтобы это исправить, вы можете удалить src/main/resources/META-INF/MANIFEST.MF и упростить build.gradle.kts файл до следующего:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.3.2"
    id("io.spring.dependency-management") version "1.1.6"
    kotlin("jvm") version "1.9.24"
    kotlin("plugin.spring") version "1.9.24"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

repositories {
    mavenCentral()
}

extra["springCloudVersion"] = "2023.0.3"

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.springframework.boot:spring-boot-autoconfigure")
    implementation("org.springframework.cloud:spring-cloud-starter-gateway")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation(kotlin("stdlib-jdk8"))
}

dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
    }
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs += "-Xjsr305=strict"
        jvmTarget = "17"
    }
}

С этими изменениями банка выглядит нормально и будет работать.


Интересные вопросы для изучения