How to configure 'mainClassName' for Spring Boot Application in a Kotlin Gradle multi-module project? - spring-boot

I have a Gradle multi-module project in Kotlin using Spring Boot in some of the modules.
I use the 'org.springframework.boot' and 'io.spring.dependency-management' plugin in the project's root build.gradle which besides other things provide the bootRun task.
AFAIK I need to configure the mainClassName (or entry point) like this:
springBoot {
mainClassName = 'de.shinythings.hexagon.HexagonApplicationKt'
}
While this works in the subproject that contains the actual Spring Boot application it does not work in the root project.
I want to be able to configure it in the root project because I want to be able to run my project with ./gradlew bootRun instead of ./gradlew configuration:bootRun.
Other tasks like ./gradlew build or ./gradlew test work fine.
Here is the root project's build.gradle (link):
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.10'
id 'org.springframework.boot' version '2.3.4.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
implementation project(':configuration')
}
springBoot {
mainClassName = 'de.shinythings.hexagon.HexagonApplicationKt'
}
subprojects {
group = 'de.shinythings.hexagon'
version = '0.0.1-SNAPSHOT'
repositories {
mavenCentral()
}
ext {
mockKVersion = '1.10.2'
}
apply plugin: 'org.jetbrains.kotlin.jvm'
apply plugin: 'io.spring.dependency-management'
dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}
dependencyManagement {
imports {
mavenBom('org.springframework.boot:spring-boot-dependencies:2.3.4.RELEASE')
}
}
compileKotlin {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
freeCompilerArgs = ["-Xjsr305=strict"]
allWarningsAsErrors = true
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
freeCompilerArgs = ["-Xjsr305=strict"]
allWarningsAsErrors = true
}
}
}
In the subproject/module this setting works (link) :
plugins {
id 'org.springframework.boot'
id 'org.jetbrains.kotlin.plugin.spring' version '1.4.10'
}
dependencies {
implementation project(':common')
implementation project(':application')
implementation project(':adapters:persistence')
implementation project(':adapters:web')
implementation 'org.springframework.boot:spring-boot-starter'
implementation('com.h2database:h2')
}
springBoot {
mainClassName = 'de.shinythings.hexagon.HexagonApplicationKt'
}
What do I have to do to configure the mainClassName is the root's project build.gradle?

Related

Gradle, Kotlin, Multi Module Project: Getting build errors while compiling this project

I am getting the following error on running gradle build command on root folder.
E:\Code\mdh>gradle build
> Task :multidemo:compileKotlin FAILED
e: E:\Code\mdh\multidemo\src\main\kotlin\com\simbalarry\multidemo\SampleController.kt: (3, 23): Unresolved reference: somelib
e: E:\Code\mdh\multidemo\src\main\kotlin\com\simbalarry\multidemo\SampleController.kt: (18, 12): Unresolved reference: Tester
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':multidemo:compileKotlin'.
> Compilation error. See log for more details
* 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 5s
4 actionable tasks: 1 executed, 3 up-to-date
Below is my project structure and multidemo project is using some functionalities of somelib. Also, I have deliberetly kept somelib as spring boot project as I will be adding more spring boot related functionalities later.
Root Project
|
|---settings.gradle
|---somelib
| |
| |---build.gradle
| |---settings.gradle
| |---src/main/kotlin/somepackage/Tester.kt
| |---src/main/kotlin/somepackage/SomeLibApplication.kt
|
|---multidemo
| |---build.gradle
| |---settings.gradle
| |---src/main/kotlin/somepackage/SampleController.kt
| |---src/main/kotlin/somepackage/MultidemoApplication.kt
Below are the contents of every file
Root/settings.gradle
include ':somelib', ':multidemo'
somelib/build.gradle
plugins {
id 'org.springframework.boot' version '2.1.3.RELEASE'
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
id 'org.jetbrains.kotlin.plugin.spring' version '1.3.21'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.simbalarry'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
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'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
somelib/settings.gradle
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'somelib'
somelib/src/main/kotlin/somepackage/Tester.kt
package com.simbalarry.somelib
/*
* Created on : 17-03-2019
* Author : Nayan Kurude
*/
object Tester {
fun getOutputText(): String {
return "Sample Text"
}
}
somelib/src/main/kotlin/somepackage/SomelibApplication.kt
package com.simbalarry.somelib
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
#SpringBootApplication
class SomelibApplication
fun main(args: Array<String>) {
runApplication<SomelibApplication>(*args)
}
multidemo/build.gradle
plugins {
id 'org.springframework.boot' version '2.1.3.RELEASE'
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
id 'org.jetbrains.kotlin.plugin.spring' version '1.3.21'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.simbalarry'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
mavenLocal()
}
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'
compile project(':somelib')
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
multidemo/settings.gradle
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'multidemo'
multidemo/src/main/kotlin/somepackage/MultiDemoApplication.kt
package com.simbalarry.multidemo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
#SpringBootApplication
class MultidemoApplication
fun main(args: Array<String>) {
runApplication<MultidemoApplication>(*args)
}
multidemo/src/main/kotlin/somepackage/SampleController.kt
package com.simbalarry.multidemo
import com.simbalarry.somelib.Tester
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
/*
* Created on : 17-03-2019
* Author : Nayan Kurude
*/
#RestController
class SampleController {
#RequestMapping("/hello")
fun hello(): String {
return Tester.getOutputText()
}
}
Could anyone please tell me where am i doing something wrong.
As I said in comments: somelib is supposed to be a library. So it shouldn't apply the spring boot plugin, whose role is to create a Spring Boot application.
Your build.gradle file for somelib should look like this:
plugins {
id 'java-library' // 1
id 'org.springframework.boot' version '2.1.3.RELEASE' apply false // 2
id 'io.spring.dependency-management' version '1.0.6.RELEASE' //3
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
id 'org.jetbrains.kotlin.plugin.spring' version '1.3.21'
}
group = 'com.simbalarry'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencyManagement { // 4
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}
ext['kotlin.version'] = '1.3.21' // 5
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'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
Some explanations (see the comments in the code):
Applies the java library gradle plugin, since that's what you want to create: a library that can be used in the other project
Adds the Spring Boot plugin to the classpath of the build without applying it, in order to be able to use its BOM later. See https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/gradle-plugin/reference/html/#managing-dependencies-using-in-isolation
Applies the spring dependency management plugin to be able to specify dependencies without version, by using the version numbers specified in the spring boot BOM
Configure the dependency management plugin to use the spring boot BOM
Override the kotlin version used in the BOM (1.2.71) by the one you want to use. See https://docs.spring.io/dependency-management-plugin/docs/current-SNAPSHOT/reference/html/#dependency-management-configuration-bom-import-override-property

Gradle not creating a Tomcat deployable war

I'm running into an issue with building a war with Gradle 4.8.1. Here is the build.gradle:
buildscript {
ext {
springBootVersion = '2.0.3.RELEASE'
}
repositories {
jcenter()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
}
}
apply plugin: 'idea'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'
archivesBaseName = 'sample'
//war {
// archiveName = 'sample.war'
// group = 'my.group'
// version = '2.0.0-SNAPSHOT'
//}
sourceCompatibility = 1.8
repositories {
jcenter()
maven { url "${nexusUrl}/content/groups/public" }
}
dependencies {
// Spring
compile 'org.springframework.boot:spring-boot-starter-actuator'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile 'org.springframework.boot:spring-boot-starter-log4j2'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
compile 'org.springframework.boot:spring-boot-starter-web'
testCompile 'org.springframework.boot:spring-boot-starter-test'
// Lombok
compile "org.projectlombok:lombok:1.18.0"
// Data
compile ('org.postgresql:postgresql') {
exclude module: 'slf4j-simple'
}
// Http
compile "org.apache.httpcomponents:httpclient:4.5.5"
}
configurations {
all*.exclude module: 'spring-boot-starter-logging'
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: "${nexusUrl}/content/groups/public/") {
authentication(userName: nexusUsername, password: nexusPassword)
}
snapshotRepository(url: "${nexusUrl}/content/repositories/snapshots") {
authentication(userName: nexusUsername, password: nexusPassword)
}
pom.version = '2.0.0-SNAPSHOT'
pom.artifactId = 'sample'
pom.groupId = 'my.group'
}
}
}
I also tried removing the 'maven' plugin, archivesBaseName, and the uploadArchive task while uncommenting the war task and I get the same result. When using uploadArchive the war deploys to the nexus server fine and I get no errors. When deploying the war to tomcat (in both instances) tomcat 7 and 8 throw no errors and I receive no logs from either catalina or the project, although archiveName inside the war task does not properly rename the war. I have tried this on two other machines/tomcat instances with the same result. When building this as a fat jar, or running this in IntelliJ, everything works as expected (including the logging).
Any help or direction would be greatly appreciated.
It sounds like it is not initializing the servlet at all. Make sure to extend the SpringBootServletInitializer for WAR deployment.
Spring Boot Docs - Traditional Deployment
I was also facing the same issue. The issue is Spring application doesnt get initialized when the war is deployed on tomcat.
After a lot of struggle, I figured out that I needed to extend SpringBootServletInitializer in my application. So my effective code looks like
public class SyncApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SyncApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SyncApplication.class, args);
}
}
Looks like this SpringBootServletInitializer directs war plugins generate bootstrapping code while building the war, and thus spring context is initialized while deploying the app.

Spring boot gradle kotlin build

I am trying to create JAVA springboot project with gradle build.I wanted to try out new kotlin support for springboot. Wondering how i can add bootrun task inside build.gradle.kts file.
plugins {
}
val coreServiceVersion = "3.0.0"
dependencies {
}
That's the over all structure of build.gradle.kts
You can use the following configuration:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
val kotlinVersion = "1.2.41"
id("org.springframework.boot") version "2.0.2.RELEASE"
id("org.jetbrains.kotlin.jvm") version kotlinVersion
id("org.jetbrains.kotlin.plugin.spring") version kotlinVersion
id("io.spring.dependency-management") version "1.0.4.RELEASE"
}
val coreServiceVersion = "3.0.0"
version = "1.0.0-SNAPSHOT"
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = listOf("-Xjsr305=strict")
}
}
repositories {
mavenCentral()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
compile("org.jetbrains.kotlin:kotlin-reflect")
compile("com.fasterxml.jackson.module:jackson-module-kotlin")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
See https://github.com/sdeleuze/spring-boot-kotlin-demo/ for a complete project.

Ktor startup example errors

I'm very new to Kotlin and Ktor and Gradle, wanted to try Ktor, so gone through the steps explained here, and ended up with this code, and structure shown in the screenshot:
As seen there are lots of error, how to fix them?
package blog
import org.jetbrains.ktor.netty.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.host.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.response.*
fun main(args: Array<String>) {
embeddedServer(Netty, 8080) {
routing {
get("/") {
call.respondText("My Example Blog", ContentType.Text.Html)
}
}
}.start(wait = true)
}
The build.gradle file is auto generated as:
group 'Example'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.1.4-3'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'java'
apply plugin: 'kotlin'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
testCompile group: 'junit', name: 'junit', version: '4.12'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
You have incomplete build.gradle script (missing dependencies) - see here for details. Here's the good one:
group 'Example'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.1.4-3'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'java'
apply plugin: 'kotlin'
sourceCompatibility = 1.8
ext.ktor_version = '0.4.0'
repositories {
mavenCentral()
maven { url "http://dl.bintray.com/kotlin/ktor" }
maven { url "https://dl.bintray.com/kotlin/kotlinx" }
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
compile "org.jetbrains.ktor:ktor-core:$ktor_version"
compile "org.jetbrains.ktor:ktor-netty:$ktor_version"
compile "ch.qos.logback:logback-classic:1.2.1"
testCompile group: 'junit', name: 'junit', version: '4.12'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
kotlin {
experimental {
coroutines "enable"
}
}
I would recommend using the IntelliJ Ktor plugin to bootstrap your app. The ./gradlew run script runs right out of the box with this configuration without you needing to fiddle with the Gradle configuration. It's the easiest way to get started.
Here is an example Ktor app that uses the configuration: https://gitlab.com/tinacious/ktor-example
If you'd like to run your application from IntelliJ, check out this answer for the run configuration I use: https://stackoverflow.com/a/65350680/1870884

Gradle Unable to retrieve local repository

I have the following setup in my build.gradle file
repositories {
mavenCentral()
mavenLocal()
maven {
url '/Users/me/.m2/repository'
}
A library under the directory doesn't get imported into my project. I create another project with Maven and the library is imported. What is missing in the gradle setup?
Here is the file:
buildscript {
ext {
springBootVersion = '1.3.5.RELEASE'
}
repositories {
mavenCentral()
mavenLocal()
maven {
url '/Users/vewu/.m2/repository'
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
jar {
baseName = 'sample'
version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
mavenLocal() // <-- I need to add this one
}
dependencies {
compile('org.springframework.cloud:spring-cloud-starter-stream-kafka')
compile('org.springframework.boot:spring-boot-starter-integration')
compile 'mylibrary:mypackage:1.3.18'
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.RELEASE"
}
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
}
}
I just recognize that I need to add mavenLocal() on the repository block outside of the buildscript as well.

Resources