Jib Main class error with spring boot multi module (gradle) - spring-boot

root-projec
ㄴ sub1-project
build.gradle
ㄴ sub2-project
build.gradle
build.gradle
I'm trying to build all subprojects as jibs in the root project.
The following script is the build.gradle file of the root and sub modules.
...
jib {
from {
image = "eclipse-temurin:17"
}
to {
image = "abc/${project.name}:${project.version}"
tags = ["latest"]
}
}
cd root-project
./gradlew jib
Execution failed for task ':jib'.
> com.google.cloud.tools.jib.plugins.common.MainClassInferenceException: Main class was not found, perhaps you should add a `mainClass` configuration to jib
Of course there are no classes in the root project. Why do you want to include the main class in the root project when building the jib? I'd like to find a way to exclude this.
Additionally, is there any way to build with jib when building with a specific profile as follows?
There is a way to write a script in maven, but gradle has grammatical difficulties.
./gradlew clean build -P build-docker-image

Related

Gradle project dependency problems

I have a multi-project Gradle build that is configured as this:
keycloak
|-- keycloak-spi-1
|-- keycloak-spi-2
|-- keycloak-theme
the subprojects build jars that i want to include inside docker that is build in the parent with Jib but, an error message appears:
Obtaining project build output files failed
Gradle is version 7.4.1
Thanks
After some investigation, Jib use the output of jar task during the image build and, in this case, jar task must not compile sources but copy the shadowJars from all the subprojects. I take this approach but not work:
task jar(type: Jar, overwrite: true) {
subprojects {
from(tasks.shadowJar)
}
into "${buildDir}/libs"
doLast {
delete jar.archiveFile
}
}

Can I call the Gradle properties task on all projects at once in a multi-project build?

I would like to view the properties of a Gradle project, to manually ensure the values look right.
When I call the properties task from the root of a multi-project build, it lists the properties of the root project:
$ gradle -q properties
------------------------------------------------------------
Root project
------------------------------------------------------------
allprojects: [root project 'myapp', project ':api', project ':model', project ':ui']
ant: org.gradle.api.internal.project.DefaultAntBuilder#12345
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory#12345
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated#12345
asDynamicObject: DynamicObject for root project 'myapp'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope#12345
[...]
I can also request the properties for each individual subproject:
$ gradle -q :api:properties
------------------------------------------------------------
Project :api - The shared API for the application
------------------------------------------------------------
allprojects: [project ':api']
ant: org.gradle.api.internal.project.DefaultAntBuilder#12345
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory#12345
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated#12345
asDynamicObject: DynamicObject for project ':api'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope#12345
[...]
However, what I really want to do is list the properties for a given project and all its subprojects at once.
I'm a bit surprised that calling the task at the root level only gives the root level properties. This seems to contradict the Gradle documentation about executing tasks by name in a multi-project build:
The command gradle test will execute the test task in any subprojects, relative to the current working directory, that have that task. If you run the command from the root project directory, you’ll run test in api, shared, services:shared and services:webservice. If you run the command from the services project directory, you’ll only execute the task in services:shared and services:webservice.
The basic rule behind Gradle’s behavior is: execute all tasks down the hierarchy which have this name. Only complain if there is no such task found in any of the subprojects traversed.
How do I list all properties for a project and its subprojects at once? And as a bonus, why isn't the properties task run at the root level also running for the sub-projects? I am using the currently latest version of Gradle (6.7.1).
Per this Gradle Forum response, the properties task is not running for subprojects since the impliesSubProjects property of the properties task is true in the property implementation:
The task is configured to ignore subproject tasks by the HelpTasksPlugin using an internal API
[…]
Then TaskNameResolver does not look at subprojects for the task if impliesSubProjects is true.
Experimentation shows that the impliesSubProjects property can be configured in the build file, allowing the task to be run for the parent project and all its children:
properties {
impliesSubProjects = false
}
Output
$ gradle -q properties
------------------------------------------------------------
Root project
------------------------------------------------------------
allprojects: [root project 'myapp', project ':api', project ':model', project ':ui']
ant: org.gradle.api.internal.project.DefaultAntBuilder#12345
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory#12345
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated#12345
asDynamicObject: DynamicObject for root project 'myapp'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope#12345
[...]
------------------------------------------------------------
Project :api - The shared API for the application
------------------------------------------------------------
allprojects: [project ':api']
ant: org.gradle.api.internal.project.DefaultAntBuilder#12345
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory#12345
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated#12345
asDynamicObject: DynamicObject for project ':api'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope#12345
[...]
------------------------------------------------------------
Project :model - Shared object model
------------------------------------------------------------
[...]
Note, however, that the impliesSubProjects property is defined in the internal API (org.gradle.api.internal.AbstractTask and is not part of the public Task API (see Avoid using internal Gradle APIs for more details on internal APIs). Therefore, as mentioned in the linked forum response, this is not intended to be used in builds:
keep in mind that it’s an internal implementation detail not intended to be used by builds and there are no guarantees it will keep working in future Gradle releases.
However, in the case of a one-off property comparison that's not a persistent part of the build, this sort of unintended usage is likely acceptable.
May be I understood your question incorrectly. If you want to list all properties including all subproject along with the root project, then you can create a build file as follows:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
allprojects {
repositories {
mavenCentral()
}
group = "com.nononsensecode"
version = "0.0.1"
}
plugins {
kotlin("jvm") version "1.4.20" apply false
base
}
configure(subprojects) {
apply {
plugin("org.jetbrains.kotlin.jvm")
}
configure<JavaPluginExtension> {
sourceCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
targetCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
}
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = listOf("-Xjsr305=strict")
}
}
dependencies {
val implementation by configurations
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))
}
task("listAllProperties") {
val subProjectPropertiesMap = mutableMapOf<String, Map.Entry<String, Any?>>()
subprojects.forEach { subProject ->
subProject.properties.forEach { property ->
subProjectPropertiesMap[subProject.name] = property
}
}
val allProperties = AllProperties(properties, subProjectPropertiesMap)
println(allProperties)
}
}
data class AllProperties(
val properties: Map<String, Any?>,
val subProjectProperties: MutableMap<String, Map.Entry<String, Any?>>
)
Then run the task gradlew listAllProperties. If you want, you can create a toString method to print all properties in a beautiful way.

Gradle tasks shown in intellij but can not be run

I have a multi module project with the following structure:
root_project
module1
module2
module3
I try to apply the java plug-in to all projects using the following code:
allprojects {
apply plugin: 'java'
group = 'com.mysoftware'
sourceCompatibility = 1.8
version = '1.3'
repositories {
mavenCentral()
}
}
Additionally I add the javafx plugin to module3. The java and javafx tasks are now shown in the intellij gradle view, but when trying to execute them, I get this error:
Task 'jfxJar' not found in root project 'module3'.
Furthermore, running the tasks task show me that neither the java tasks nor the javafx tasks are available, despite being shown in the gradle view in intellij.
I tried rebuilding and refreshing the whole project without success. I use the Use default gradle wrapper configuration.
The error message you got Task 'jfxJar' not found in root project 'module3' indicates that Gradle considers the subproject module3 as a Root project: this can happen if you created a settings.gradle file in the sub-project directory, which is not a valid setup (only one settings.gradle file can exist in a multiproject build, located in the root directory)

IntelliJ gradle integration issue with independent gradle subprojects

I have two independent gradle projects that I also want to build from one main gradle project:
main-project
build.gradle
settings.gradle
--subproject-one
build.gradle
settings.gradle
--module-a
build.gradle
--subproject-two
build.gradle
settings.gradle
--module-b
build.gradle
My top settings.gradle includes all modules from the sub projects:
file('subproject-one').eachDir { dir ->
if(dir.list().contains("build.gradle")) {
include dir.name
project(":${dir.name}").projectDir = dir
}
}
file('subproject-two').eachDir { dir ->
if(dir.list().contains("build.gradle")) {
include dir.name
project(":${dir.name}").projectDir = dir
}
}
Now i have a dependency from module-b in subproject-two to module-a in subproject-one. I use a compile switch (useProjectDependencies) to include them as project dependencies when I build from the main project and as normal dependencies when i build from the subprojects:
if(useProjectDependencies){
compile project(':module-b')
} else {
//Client dependencies
compile "my.group.id:module-b
}
Via gradle I'm now able to build the main-project including the subproject and also each subproject on it's own.
When I open the main-project now via IntelliJ I see all the modules are recognized correctly and also the cross references to classes between the modules work correctly (refactoring interface between to components are working great).
When I now try to use the gradle integration from Intellij and click on assemble for the module-b then it incorrectly uses the build.gradle form and settings.gradle from subproject-two and doesn't use the project dependencies. It looks like IntelliJ or the gradle daemon searches for the first settings.gradle in a bottom up way from the module-b instead of using the one in the main-project.
When I build via terminal from the main-project folder all works correctly:
gradlew :module-b:assemble //correct *settings.gradle* and *build.gradle* is used
When I delete the settings.gradle and build.gradle from subproject-two then the build.gradle from the main-project is correctly used.
Is there a way to specify the settings.gradle and build.gradle that is used as part of the IntelliJ gradle integration?

Gradle multi-project build

I have the following project structure:
my-project
+my-project-data
+my-project-service
+my-project-example
Where each of these my-project-data, my-project-service, my-project-examples are defined as sub project to my-project in settings.gradle file. Of course, my-project-services has a dependency to my-project-data. And my-project-examples has a dependencies to my-project-data and my-project service.
In the project my-project-examples I want to have some class with main method and make some queries to DB (Assume that main class is in package com.project.main). Moreover I want to execute this in command line:
java -jar my-project.jar
But to do this I have to set Main-Class attribute. Where do I have to do this in root project build.gradle or somewhere else and what have to be the value of attribute?
You can use the application plug-in which provides exactly what you need.
Add the following to your example's project build.gradle:
apply plugin: 'application'
mainClassName = "com.company.package.YourClassWithMain"
Then, simply run the sample by executing 'gradle run' (or using gradle wrapper) under the example project directory.

Resources