Не запускается JAR содержащий проект Spring Boot (Gradle компиляция) Не найден главный класс

Рейтинг: 1Ответов: 1Опубликовано: 28.07.2023

Абсолютно все вопросы об этой проблеме задавались ещё в 2018-2021 годах в то время как на момент создания этого вопроса идёт лето 2023 года, соответственно за это время уже вышло много новых версий spring от 2-ой до 3-ей, а значит изменений тоже произошло не мало. Почему я про это говорю? Потому что я пересмотрел все возможные вопросы (включая этот и этот) и ни один из них мне не помог.

Из IDEA проект нормально работает, а из скомпилированного jar - плохо. Теперь я знаю, что через IDEA jar нормально не создаётся, по этому я его собирал с помощью gradle build (который в себя включает инструкции jar (без зависимостей) и bootJar (с зависимостями)).

Казалось бы все должно быть хорошо, т. к. сам jar архив построен правильно:

 - META-INF
   - MANIFEST.MF
 - BOOT-INF
   - classpath.idx
   - layers.idx
   - classes
     - application.properties
     - com -> классы проекта
     - static -> статика
     - templates -> шаблоны
     - META-INF -> манифест
   - lib -> зависимости

layers.idx:

- "dependencies":
  - "BOOT-INF/lib/"
- "spring-boot-loader":
- "snapshot-dependencies":
- "application":
  - "BOOT-INF/classes/"
  - "BOOT-INF/classpath.idx"
  - "BOOT-INF/layers.idx"
- "META-INF/"

MANIFEST.MF:

Manifest-Version: 1.0
Main-Class: com.vladceresna.netufos.NetufosApplication
Start-Class: com.vladceresna.netufos.NetufosApplication
Spring-Boot-Version: 3.1.0
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
Implementation-Title: netufos
Implementation-Version: 0.1

build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:3.0.1")
    }
}
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.0'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.vladceresna'
version = '0.1'
sourceCompatibility = '17'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

jar {
    manifest {
        attributes 'Main-Class': 'com.vladceresna.netufos.NetufosApplication'
    }
    from{
        configurations.runtimeClasspath.collect {it.isDirectory() ? it : zipTree(it)}
    }
}
repositories {
    mavenCentral()
}
dependencies {
    implementation 'redis.clients:jedis:4.0.0'

    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:3.1.1.RELEASE'

    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.projectlombok:lombok'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
}
tasks.withType(Jar) {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE

    manifest {
        attributes["Main-Class"] = "com.vladceresna.netufos.NetufosApplication"
    }
}

tasks.named('test') {
    useJUnitPlatform()
}

Если понадобится ещё какой-то код, то я его предоставлю.

Итак, проект работает из IDE, но не работает из jar собранного с помощью gradle build. Такой jar просто не запускается из-за ошибки

Error: Could not find or load main class com.vladceresna.netufos.NetufosApplication
Caused by: java.lang.ClassNotFoundException: com.vladceresna.netufos.NetufosApplication

Хотя на самом деле класс существует!

То что я ищу - это актуальное решение этой проблемы, так как все вопросы, как мне кажется, устаревшие.

Ответы

▲ 1

Итак, после 3 дней поиска решения проблемы она всё таки решилась!

Всем кто столкнётся с такой проблемой рекомендую прочитать вот это "постоянно обновляющееся", а значит современное руководство по spring-gradle-plugin, который отвечает за gradle сборку именно проектов spring boot. Обычная сборка через Build Artefact не подойдёт! Читая приведённую статью я выбирал из неё как по мне нужный код и вставлял в свой build.gradle - именно он отвечает за всю сборку, и от него зависит какой она будет. Я не знаю какие именно изменения повлияли на правильность создания JAR, но точно знаю, что все они не лишние. Теперь мой build.gradle выглядит так:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:3.0.1")
    }
}
plugins {
    id 'application'
    id 'java'
    id 'org.springframework.boot' version '3.1.0'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.vladceresna'
version = '0.1'
sourceCompatibility = '17'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}
application{
    mainClass = 'com.vladceresna.netufos.NetufosApplication'
}
springBoot{
    mainClass = 'com.vladceresna.netufos.NetufosApplication'
    mainClassName = "com.vladceresna.netufos.NetufosApplication"
}

jar {
    manifest {
        attributes 'Main-Class': 'com.vladceresna.netufos.NetufosApplication'
    }
    from{
        configurations.runtimeClasspath.collect {it.isDirectory() ? it : zipTree(it)}
    }
}
repositories {
    mavenCentral()
}
dependencies {
    implementation 'redis.clients:jedis:4.0.0'

    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:3.1.1.RELEASE'

    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.projectlombok:lombok'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    implementation 'org.springframework.boot:spring-boot-starter-tomcat'
}
tasks.withType(Jar) {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
tasks.named('bootJar') {
    mainClass = 'com.vladceresna.netufos.NetufosApplication'
    launchScript()
}
tasks.named('test') {
    useJUnitPlatform()
}

Единственное что сделано не так как в статье, это реализация зависимости tomcat, так как providedRuntime() не существует(выдаёт ошибку), то я использовал просто implementation