0

I'm encountering an issue while implementing a Spring multi-module project and need some help. The goal is to structure the modules using Spring and build each module into a container using Docker.

First, the file structure is as follows:

root-project/
├── module-adjust/
│   ├── Dockerfile
│   ├── build.gradle
│   └── src/
├── module-common/
│   ├── Dockerfile
│   ├── build.gradle
│   └── src/
├── module-user/
│   ├── Dockerfile
│   ├── build.gradle
│   └── src/
├── module-video/
│   ├── Dockerfile
│   ├── build.gradle
│   └── src/
├── build.gradle
└── settings.gradle

I've confirmed that the application code with the main method in each module runs correctly and processes requests when executed directly.

root-project/
├── module-adjust/
│   ├── Dockerfile
│   ├── build.gradle
│   └── src/
├── module-common/
│   ├── Dockerfile
│   ├── build.gradle
│   └── src/
├── module-user/
│   ├── Dockerfile
│   ├── build.gradle
│   └── src/main/java/com/sparta/
│                       └── **UserApplication.java**
│                       └── controller/
│                           └── **UserController.java**
├── module-video/
│   ├── Dockerfile
│   ├── build.gradle
│   └── src/
├── build.gradle
└── settings.gradle

UserApplication.java

package com.sparta;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

UserController.java

package com.sparta.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("")
class UserController {
    @GetMapping("/test")
    public String hello() {
        return "Hello, this is Adjustment Controller";
    }
}

The issue arises when trying to build this project using Docker.

error at git actions when build docker

And this is long long error log

#45 35.64 * Exception is:
#45 35.64 org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':module-adjust:bootJar'.
#45 35.64   at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38)
#45 35.64   at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
#45 35.64   at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
#45 35.64   at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
#45 35.64   at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
#45 35.64   at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
#45 35.64   at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
#45 35.64   at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
#45 35.64   at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
#45 35.64   at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
#45 35.64   at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
#45 35.65   at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
#45 35.65   at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
#45 35.65   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331)
#45 35.65   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318)
#45 35.65   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314)
#45 35.65   at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
#45 35.65   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314)
#45 35.65   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
#45 35.65   at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
#45 35.65   at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
#45 35.66   at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
#45 35.66   at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
#45 35.66 Caused by: org.gradle.api.internal.tasks.properties.PropertyEvaluationException: Error while evaluating property 'mainClass' of task ':module-adjust:bootJar'.
#45 35.66   at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:32)
#45 35.66   at org.gradle.api.internal.tasks.execution.TaskExecution.lambda$visitRegularInputs$1(TaskExecution.java:317)
#45 35.66   at org.gradle.internal.execution.impl.DefaultInputFingerprinter$InputCollectingVisitor.visitInputProperty(DefaultInputFingerprinter.java:103)
#45 35.66   at org.gradle.api.internal.tasks.execution.TaskExecution.visitRegularInputs(TaskExecution.java:315)
#45 35.66   at org.gradle.internal.execution.impl.DefaultInputFingerprinter.fingerprintInputProperties(DefaultInputFingerprinter.java:63)
#45 35.66   at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.captureExecutionStateWithOutputs(AbstractCaptureStateBeforeExecutionStep.java:109)
#45 35.66   at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.lambda$captureExecutionState$0(AbstractCaptureStateBeforeExecutionStep.java:74)
#45 35.66   at org.gradle.internal.execution.steps.BuildOperationStep$1.call(BuildOperationStep.java:37)
#45 35.66   at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
#45 35.67   at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
#45 35.67   at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
#45 35.67   at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
#45 35.67   at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
#45 35.67   at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
#45 35.67   at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
#45 35.67   at org.gradle.internal.execution.steps.BuildOperationStep.operation(BuildOperationStep.java:34)
#45 35.68   at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.captureExecutionState(AbstractCaptureStateBeforeExecutionStep.java:69)
#45 35.68   at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:62)
#45 35.68   at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:43)
#45 35.68   at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.executeWithNonEmptySources(AbstractSkipEmptyWorkStep.java:125)
#45 35.68   at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:61)
#45 35.68   at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:36)
#45 35.68   at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
#45 35.68   at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36)
#45 35.68   at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23)
#45 35.68   at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:75)
#45 35.68   at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:41)
#45 35.68   at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.lambda$execute$0(AssignMutableWorkspaceStep.java:35)
#45 35.68   at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:289)
#45 35.68   at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:31)
#45 35.68   at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:22)
#45 35.69   at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:40)
#45 35.69   at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:23)
#45 35.69   at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.lambda$execute$2(ExecuteWorkBuildOperationFiringStep.java:67)
#45 35.69   at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:67)
#45 35.69   at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:39)
#45 35.69   at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:46)
#45 35.69   at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:34)
#45 35.69   at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:48)
#45 35.69   at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:35)
#45 35.69   at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:61)
#45 35.69   at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:127)
#45 35.69   at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:116)
#45 35.69   at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
#45 35.69   at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
#45 35.69   at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
#45 35.69   at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
#45 35.69   at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
#45 35.69   at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
#45 35.69   at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
#45 35.69   at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
#45 35.69   at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
#45 35.69   at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
#45 35.69   at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
#45 35.69   at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
#45 35.69   at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
#45 35.69   at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
#45 35.69   at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
#45 35.69   at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
#45 35.69   at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
#45 35.69   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331)
#45 35.69   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318)
#45 35.70   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314)
#45 35.70   at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
#45 35.70   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314)
#45 35.70   at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
#45 35.70   at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
#45 35.70   at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
#45 35.70   at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
#45 35.70   at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
#45 35.70 Caused by: org.gradle.api.internal.provider.AbstractProperty$PropertyQueryException: Failed to calculate the value of task ':module-adjust:bootJar' property 'mainClass'.
#45 35.70   at org.gradle.api.internal.provider.AbstractProperty.finalizeNow(AbstractProperty.java:284)
#45 35.70   at org.gradle.api.internal.provider.AbstractProperty.lambda$beforeRead$0(AbstractProperty.java:276)
#45 35.70   at org.gradle.api.internal.provider.ValueState.finalizeOnReadIfNeeded(ValueState.java:137)
#45 35.70   at org.gradle.api.internal.provider.AbstractProperty.beforeRead(AbstractProperty.java:276)
#45 35.70   at org.gradle.api.internal.provider.AbstractProperty.beforeRead(AbstractProperty.java:268)
#45 35.70   at org.gradle.api.internal.provider.AbstractProperty.calculateOwnValue(AbstractProperty.java:162)
#45 35.70   at org.gradle.api.internal.provider.AbstractMinimalProvider.getOrNull(AbstractMinimalProvider.java:105)
#45 35.70   at org.gradle.api.internal.provider.ProviderResolutionStrategy$1.resolve(ProviderResolutionStrategy.java:27)
#45 35.70   at org.gradle.util.internal.DeferredUtil.unpack(DeferredUtil.java:59)
#45 35.70   at org.gradle.util.internal.DeferredUtil.unpackOrNull(DeferredUtil.java:49)
#45 35.70   at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:38)
#45 35.70   at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:30)
#45 35.70   ... 69 more
#45 35.70 Caused by: org.gradle.api.InvalidUserDataException: Main class name has not been configured and it could not be resolved from classpath 
#45 35.70   at org.springframework.boot.gradle.plugin.ResolveMainClassName$ClassNameReader.transform(ResolveMainClassName.java:173)
#45 35.70   at org.springframework.boot.gradle.plugin.ResolveMainClassName$ClassNameReader.transform(ResolveMainClassName.java:162)
#45 35.70   at org.gradle.api.internal.provider.ValueSupplier$Present.transform(ValueSupplier.java:511)
#45 35.70   at org.gradle.api.internal.provider.TransformBackedProvider.mapValue(TransformBackedProvider.java:91)
#45 35.70   at org.gradle.api.internal.provider.TransformBackedProvider.calculateOwnValue(TransformBackedProvider.java:82)
#45 35.70   at org.gradle.api.internal.provider.AbstractMinimalProvider.calculateValue(AbstractMinimalProvider.java:115)
#45 35.70   at org.gradle.api.internal.provider.FlatMapProvider.calculateOwnValue(FlatMapProvider.java:53)
#45 35.70   at org.gradle.api.internal.provider.AbstractMinimalProvider.calculateValue(AbstractMinimalProvider.java:115)
#45 35.70   at org.gradle.api.internal.provider.TransformBackedProvider.calculateOwnValue(TransformBackedProvider.java:81)
#45 35.70   at org.gradle.api.internal.provider.AbstractMinimalProvider.calculateValue(AbstractMinimalProvider.java:115)
#45 35.70   at org.gradle.api.internal.provider.AbstractMinimalProvider.withFinalValue(AbstractMinimalProvider.java:168)
#45 35.70   at org.gradle.api.internal.provider.DefaultProperty.finalValue(DefaultProperty.java:157)
#45 35.70   at org.gradle.api.internal.provider.DefaultProperty.finalValue(DefaultProperty.java:33)
#45 35.70   at org.gradle.api.internal.provider.AbstractProperty.finalizeNow(AbstractProperty.java:281)

This is Dockerfile running build at module directory

# Base image
FROM openjdk:17-jdk-slim

# Set working directory
WORKDIR /app

# Copy Gradle files from the root context to the service context

COPY gradlew /app/
COPY gradle /app/gradle/
COPY settings.gradle /app/
COPY build.gradle /app/
COPY module-common/build.gradle /app/module-common/
COPY module-adjust/build.gradle /app/module-adjust/
COPY module-common/src /app/module-common/src
COPY module-adjust/src /app/module-adjust/src

# Ensure gradlew is executable
RUN chmod +x gradlew

# Build the application
RUN ./gradlew build -x test --stacktrace

# Copy the built JAR file
COPY build/libs/adjustment-*.jar app.jar

# Expose port
EXPOSE 8080

# Run the application
CMD ["java", "-jar", "app.jar"]

And this is build.gradle code of module

dependencies {
    implementation project(':module-common')
}

springBoot{
    mainClass.set('com.sparta.AdjustApplication') // main class location
}

this is build.gradle code of root

plugins {
    id 'application'
    id 'java'
    id 'org.springframework.boot' version '3.1.5'
    id 'io.spring.dependency-management' version '1.1.3'
}

bootJar {
    enabled = false
}
jar {
    enabled = true
}
repositories {
    mavenCentral()
}

subprojects { // 모든 하위 모듈들에 이 설정을 적용합니다.
    group 'com.example'
    version '0.0.1-SNAPSHOT'

    sourceCompatibility = '17'

    apply plugin: 'java'
    apply plugin: 'java-library'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
        implementation 'org.springframework.boot:spring-boot-starter-web'
    }
    test {
        useJUnitPlatform()
    }
}
  1. The error code indicates that the issue is with finding the main class. So, I first checked whether the main class is incorrectly specified.

  2. I tested whether other errors occur when excluding bootJar, and it didn’t change anything. I tried:

tasks.named('bootJar') {
    enabled = false
}

And

bootJar {
    enabled = false
}
jar {
    enabled = true
}
  1. I also tried to specify the main class for bootRun:
bootRun {
    mainClass = 'com.sparta.AdjustApplication' // Please enter the actual path of the main class here
}

Despite numerous attempts, I haven’t found a solution. If anyone has had similar experiences and found a resolution, please let me know! Thanks!

1 Answer 1

0

Fortunately, I found the answer myself. The issue was with settings.gradle. Looking at the code again, settings.gradle contained information for all modules along with the root. The problem was that I copied this as-is for the build.

settings.gradle

rootProject.name = 'adjustment'
include 'module-user'
include 'module-video'
include 'module-common'
include 'module-adjust'

During the build process, the issue occurred because the module was building while referencing other modules. Therefore, I corrected this by adding only the necessary content to settings.gradle.

module-user/settings.gradle

rootProject.name = 'adjustment'
include 'module-user'
include 'module-common'

In addition, I updated the code as follows for the final Docker build.

# Base image
FROM openjdk:17-jdk-slim

# Set working directory
WORKDIR /app

# Copy Gradle files from the root context to the service context
COPY gradlew /app/
COPY gradle /app/gradle/
COPY build.gradle /app/

COPY module-common/build.gradle /app/module-common/
COPY module-common/src /app/module-common/src

COPY module-user/build.gradle /app/module-user/
COPY module-user/src /app/module-user/src

#Copy settings.gradle for module
COPY module-user/settings.gradle /app/ 

# Ensure gradlew is executable
RUN chmod +x gradlew

# Build the application
RUN ./gradlew build -x test --stacktrace

# Check the build output directory
RUN ls -l module-user/build/libs/

# Copy the built JAR file to /app.jar
RUN cp module-user/build/libs/module-user-0.0.1-SNAPSHOT.jar /app.jar

# Expose port
EXPOSE 8080

# Run the application
CMD ["java", "-jar", "/app.jar"]

Let me know if you have any better solutions.Thank you.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.