I am facing a ClassNotFoundException when I try to run my docker image - I just don't understand why this is happening.
When running with docker run --rm -i spring-boot-config-demo:dev this results into
Exception in thread "main" java.lang.ClassNotFoundException: com.example.DemoApplication
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:46)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
However I am able to run it with gradlew.bat bootRun and even with java -jar .\build\libs\app.jar without any issues.
Even when I unzip the jar and have a look at at MANIFEST.MF it seems right. Any idea???
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.DemoApplication
Spring-Boot-Version: 2.4.4
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
This is what my settings.gradle looks like
// Required so that gradle knows where to pull plugins from
pluginManagement {
repositories {
maven {
url 'https://artifact.foobar.com/internal'
}
}
}
rootProject.name = 'demo'
And my build.gradle file
plugins {
// https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/
id 'org.springframework.boot' version '2.4.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE
id 'java'
}
springBoot {
// https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#packaging-executable-configuring-main-class
mainClassName = 'com.example.DemoApplication'
}
bootJar {
archiveFileName = 'app.jar'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
maven {
url 'https://artifact.foobar.com/internal'
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.azure:azure-data-appconfiguration:1.1.11'
implementation 'com.microsoft.azure:spring-cloud-azure-appconfiguration-config-web:1.3.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
test {
useJUnitPlatform()
}
And here is my Dockerfile
# Stage 1 - Build the application
FROM docker.artifact.foobar.com/gradle:7.0.0-jdk11 as build
# Change working directory
WORKDIR /app
# Copy files to gradle image
COPY ./src .
COPY ./build.gradle .
COPY ./settings.gradle .
# Build
RUN gradle bootJar -x test --no-watch-fs
# Stage 2 - Run the application
FROM gcr.io/distroless/java:11 as run
WORKDIR /app
COPY --from=build /app/build/libs/app.jar /app/app.jar
CMD ["app.jar"]
And folder structure, where DemoApplication.java contains my public static void main(String[])
│ .gitignore
│ build.gradle
│ Dockerfile
│ gradlew
│ gradlew.bat
│ README.md
│ settings.gradle
├───.gradle
│ [...]
├───build
│ [...]
├───gradle
│ └───wrapper
│ gradle-wrapper.jar
│ gradle-wrapper.properties
└───src
├───main
│ ├───java
│ │ └───com
│ │ └───example
│ │ DemoApplication.java
│ │ HelloController.java
│ │ MessageProperties.java
│ │
│ └───resources
│ application.yml
│ bootstrap.properties
│
└───test
└───java
└───com
└───example
DemoApplicationTests.java
Content of DemoApplication.java
package com.example;
// ...
@SpringBootApplication
@EnableConfigurationProperties(MessageProperties.class)
public class DemoApplication {
// ...
public static void main(String[] args) {
// ...
}
}