I tried for first time create Spring Boot app with Kotlin,Gradle and run it on heroku.
Project created in IntelliK Idea 2022.1 (Ultimate Edition) with Spring Initializr
When app is runned by ide on localhost everything is working fine, but when I try to run app from jar file there are non stop some problems.
First problem:
no main manifest attribute, in build/libs/app-0.0.1-plain.jar
So I added to build.gradle.kts
tasks.jar {
manifest {
attributes["Main-Class"] = "com.example.package.ApplicationKt"
}
}
Second problem:
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
To resolve that one I added to tasks.jar
from(sourceSets.main.get().output)
dependsOn(configurations.runtimeClasspath)
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
})
Next one:
Entry META-INF/LICENSE.txt is a duplicate but no duplicate handling strategy has been set
My solution:
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
And finally the boss:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instanti
ation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is java.lang.
IllegalStateException: No ServletContext set
I don't know how to resolve that one, I tried to replace
implementation("org.springframework.boot:spring-boot-starter-web")
to
implementation("org.springframework.boot:spring-boot-starter-webflux")
But it didn't work. In console I see that there is a lot of negative matches, one of them:
@ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)
Also I have tried to run it on java 11 but with same result. Have someone idea what I should do?
To run app I used:
java -jar build/libs/app-0.0.1-plain.jar --server.port=8080
My final build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.6.7"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.6.21"
kotlin("plugin.spring") version "1.6.21"
}
group = "com.example"
version = "0.0.1"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
tasks.jar {
manifest {
attributes["Main-Class"] = "com.example.package.ApplicationKt"
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
// To add all of the dependencies
from(sourceSets.main.get().output)
dependsOn(configurations.runtimeClasspath)
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
})
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
runtimeOnly("org.postgresql:postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
CodePudding user response:
You are using the wrong JAR for deployment to Heroku. There are (2) JARs that are created when the Spring Boot Gradle plugin is applied.
- A plain JAR which created by the Java plugin and the
plain
classifier configured by the Spring Boot Gradle plugin - A uber JAR or "fat" JAR created by the Spring Boot Gradle plugin
The uber JAR is an executable JAR and is what you should deploy to Heroku.
See the documentation for more details: https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#packaging-executable