I have a fairly simple Spring Boot app. One yaml file with spring gateway configurations, and then one file with the main Application class and the main function.
I build the jar file as follows:
./gradlew clean bootJar -x test
It gets built without problems.
The build.gradle.kts file looks like this:
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")
}
However, when I run this
java -jar build/libs/ReverseProxy-0.0.1-SNAPSHOT.jar
I keep getting:
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: {}
I’m not really sure where I am going wrong?
Can someone help?
UPDATE
The below did not help. Any ideas?
// 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("**/*.*"))
}
UPDATE 2
If I comment this out from the gradle file,
implementation("org.springframework.cloud:spring-cloud-starter-gateway")
It works. Only problem is that since this is a reverse proxy, its a dependency I very much need.
2
Answers
You are not including resources in the jar.
Only including main source set –
Refer this
Add files to Gradle sourceSets in Kotlin DSL
The "No qualifying bean of type ‘org.springframework.boot.autoconfigure.web.ServerProperties’ available" message is indicating that the
ServerProperties
@ConfigurationProperties
bean has not been created. For reactive applications, it is usually created byReactiveWebServerFactoryAutoConfiguration
.It’s not easy to tell why that auto-configuration hasn’t been applied. I would start by running with
-Ddebug
and checking the auto-configuration report to see ifReactiveWebServerFactoryAutoConfiguration
was actually applied.If that doesn’t help, I would suggest creating a minimal reproducible example so that folks can help you.