Hauptklasse konnte nicht gefunden oder geladen werden

8u3631984

Bekanntes Mitglied
Hallo zusammenn ich baue gerade ein Spring Boot Project mit Kotlin als DSL.

Hier meine Main Class :

Die Klasse befindet sich im Package :
package de.cms.media;

Java:
@SpringBootApplication
public class MediaApp implements WebMvcConfigurer {

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

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/v1/**").allowedOrigins("http://localhost:8081");
  }
}

Hier ein Auszug aus meiner build.gradle.kts
Java:
plugins {
    java
    jacoco  
    id("com.palantir.docker") version "0.34.0" apply true
}

tasks.withType<Jar> {
    manifest {
        attributes["Main-Class"] = "de.cms.media.MediaApp"
    }
}

java.sourceCompatibility = JavaVersion.VERSION_17
java.targetCompatibility = JavaVersion.VERSION_17
...


Wenn ich nun die JAR DAtei starte :
Bash:
[sebastian@laptop-sebastian java-media-cms]$ java -jar build/libs/java-media-cms.jar
Fehler: Hauptklasse de.cms.media.MediaApp konnte nicht gefunden oder geladen werden
Ursache: java.lang.NoClassDefFoundError: org/springframework/web/servlet/config/annotation/WebMvcConfigurer

Hat jemand eine Idee was ich machen kann ?
 
Ich hab keine Ahnung von Gradle - aber in Maven benutzt spring ein eigenes Plugin um ein entsprechendes Jar mit allen Abhängigkeiten zu bauen. Weil mit dem Standard-Build kommt natürlich nur ein Jar mit deinen eigenen Klassen raus, den rest müsste man mit -cp zu allen Libs angeben.

Ich hab keine Ahnung wie das in Gradle aussieht - aber ist das entsprechend analog da eingebunden? Das kann man da nicht sehen, bzw. wenn ich die plugins section interpretiere würde ich eher sagen nein.
 
Ja, das ist da ebenso aufgebaut.

Gradle hat da die Ziele "bootRun" zum starten und "bootJar" um das jar file zu bauen.

Wobei auch beim normalen buld das auch mit gebaut wird.

Daher wäre die Frage, wie das Projekt und das jar File überhaupt gebaut wurden. Ist es evtl. kein per Spring Initializr gebautes Projekt? Oder wurde da irgendwie ohne gradle das jar File gebaut?
 
Ja, das ist da ebenso aufgebaut.

Gradle hat da die Ziele "bootRun" zum starten und "bootJar" um das jar file zu bauen.

Wobei auch beim normalen buld das auch mit gebaut wird.

Daher wäre die Frage, wie das Projekt und das jar File überhaupt gebaut wurden. Ist es evtl. kein per Spring Initializr gebautes Projekt? Oder wurde da irgendwie ohne gradle das jar File gebaut?
Ich baue das Project per
Bash:
gradle clean build docker
 
Das ist auch ein Projekt, welches per Spring Initializr erstellt wurde?

Also einfaches Beispiel:
  • start.spring.io und einfaches demo Projekt mit MVC Abhängigkeit
  • gradle clean build und ich erhalte in build/libs demo-0.0.1-SNAPSHOT.jar und demo-0.0.1-SNAPSHOT-plain.jar

Das erste enthält im jar auch alle Abhängigkeiten und ist dementsprechend groß.

Das docker Ziel habe ich jetzt bei mir nicht mit ausgeführt, da ich diesbezüglich auf diesem Rechner bisher kein Setup für habe. Aber ich würde da eigentlich nicht erwarten, dass dies an den Ergebnissen aus dem build Lauf etwas ändern würde.
 
Ich habe das Project per gradle init erzeugt.
Wie sieht bei dir die build.gradle Datei aus ?
Also konkret welche Plugins sind da enthalten ?

Ist das Plugin org.springframework.boot notwendig ?
 
Der normale Weg bei Spring Boot ist die Erstellung der Projekte über den Spring Initializer. Dann hast Du das Spring Plugin und eine Basis Konfiguration über ein Parent Projekt (bei Maven - ob das bei Gradle prinzipiell ähnlich ist, weiss ich nicht. Ich nutze eigentlich sonst immer Maven).

Das ist der einfache, schnelle Einstieg in Java der gerade am Anfang wichtig ist.

Prinzipiell notwendig ist das nicht. Du kannst - so du weisst, was Du machst - auch alles selbst machen. Da ich die Abhängigkeiten gerne selbst verwalten und prüfen will und nicht durch ein Parent Projekt - welches nicht unter meiner Kontrolle ist - alles vorgegeben bekommen möchte - löse ich das meist auch immer auf. Dann habe ich die notwendigen Elemente aus den parent Projekten direkt bei mir in meinem Maven Projekt.
==> Das setzt aber voraus, dass Du weisst, was Du machst.

Du kannst Dein Gradle Projekt nutzen. Nur eben musst du dann dafür sorgen, dass Du auch die Abhängigkeiten hast. Bei dem Spring Initializr Projekt wird in der jar Datei in BOOT-INF/lib eine Kopie der Abhängigkeiten abgelegt:
Code:
   creating: BOOT-INF/lib/
 extracting: BOOT-INF/lib/spring-webmvc-6.0.4.jar 
 extracting: BOOT-INF/lib/spring-web-6.0.4.jar 
 extracting: BOOT-INF/lib/spring-boot-autoconfigure-3.0.2.jar 
 extracting: BOOT-INF/lib/spring-boot-3.0.2.jar 
 extracting: BOOT-INF/lib/jakarta.annotation-api-2.1.1.jar 
 extracting: BOOT-INF/lib/spring-context-6.0.4.jar 
 extracting: BOOT-INF/lib/spring-aop-6.0.4.jar 
 extracting: BOOT-INF/lib/spring-beans-6.0.4.jar 
 extracting: BOOT-INF/lib/spring-expression-6.0.4.jar 
 extracting: BOOT-INF/lib/spring-core-6.0.4.jar 
 extracting: BOOT-INF/lib/snakeyaml-1.33.jar 
 extracting: BOOT-INF/lib/jackson-datatype-jsr310-2.14.1.jar 
 extracting: BOOT-INF/lib/jackson-module-parameter-names-2.14.1.jar 
 extracting: BOOT-INF/lib/jackson-annotations-2.14.1.jar 
 extracting: BOOT-INF/lib/jackson-core-2.14.1.jar 
 extracting: BOOT-INF/lib/jackson-datatype-jdk8-2.14.1.jar 
 extracting: BOOT-INF/lib/jackson-databind-2.14.1.jar 
 extracting: BOOT-INF/lib/tomcat-embed-websocket-10.1.5.jar 
 extracting: BOOT-INF/lib/tomcat-embed-core-10.1.5.jar 
 extracting: BOOT-INF/lib/tomcat-embed-el-10.1.5.jar 
 extracting: BOOT-INF/lib/micrometer-observation-1.10.3.jar 
 extracting: BOOT-INF/lib/logback-classic-1.4.5.jar 
 extracting: BOOT-INF/lib/log4j-to-slf4j-2.19.0.jar 
 extracting: BOOT-INF/lib/jul-to-slf4j-2.0.6.jar 
 extracting: BOOT-INF/lib/spring-jcl-6.0.4.jar 
 extracting: BOOT-INF/lib/micrometer-commons-1.10.3.jar 
 extracting: BOOT-INF/lib/logback-core-1.4.5.jar 
 extracting: BOOT-INF/lib/slf4j-api-2.0.6.jar 
 extracting: BOOT-INF/lib/log4j-api-2.19.0.jar

Und wenn man sich die MANIFEST.MF anschaut, dann wird deutlich, dass Spring da deutlich mehr macht:
Code:
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.demo.DemoApplication
Spring-Boot-Version: 3.0.2
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
Build-Jdk-Spec: 17

Aber das wird nicht so zwingend gebraucht. Ich habe in der Vergangenheit Spring Boot in eine normale App eingebaut, da ich die Dependency Injection von Spring haben wollte. Es geht sehr viel! Nur man muss dann über viele Stolpersteine drüber.

Und bei Dir scheitert es gerade schon an den Abhängigkeiten, die Du nicht mit bereit stellst.
 
Und schau Dir start.spring.io an - selbst wenn Du da nicht die Projekte verwenden willst: Du kannst Dir ansehen, was da an Projekt aufgebaut wird. Das ist auf jeden Fall immer eine gute Unterstützung um dann zu schauen, was denn die Spring Entwickler vorgesehen haben um dann die notwendigen Dinge auch bei sich zu machen.

Aber wie @LimDul gesagt hat: Es ist sehr zu empfehlen wirklch damit zu arbeiten. Das ist der einfachste und beste Weg. Wenn dann etwas nicht geht, dann findest Du leichter Hilfe, denn das ist der Weg, den eigentlich alle kennen. Selbst wer das aus irgend welchen Gründen nicht nutzen will, der kennt es.
 
Ja vielen lieben Dank habe das nun per springboot.io noch mal gebaut und meine build.gradle angepasst.
Das Problem war das fehlende Plugin.

Nun sieht es so aus und klappt auch :

Bash:
plugins {
    java
    jacoco
    id("org.springframework.boot") version "2.7.8" apply true
    id("com.palantir.docker") version "0.34.0" apply true
}

springBoot{
    mainClass.set("de.cms.media.MediaApp")
}
 

Neue Themen


Zurück
Oben