ClassNotFoundException 运行 jar 文件但在 Intellij 中运行良好

时间:2021-03-14 21:16:32

标签: java kotlin gradle intellij-idea jar

我在 kotlin 中使用 eclipse paho mqtt library 和 Intellij IDE 中的 Gradle 创建了一个小型 mqtt 应用程序。通过 Intellij 运行它时它运行良好,但是当我构建它并运行创建的 jar 文件时,我收到一个 NoClassDefFoundError 错误。

从我看到的其他问题来看,它看起来似乎与类路径有关,但如果这确实是问题,我不确定需要做什么,因为我使用的是 gradle 而不是库的 jar 文件.

我正在关注此tutorial

这是我的gradle文件

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.4.31'
    id 'application'
}

group = 'me.package'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
    maven {
        url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
    }
}

dependencies {
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
    testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
}

test {
    useJUnit()
}

compileKotlin {
    kotlinOptions.jvmTarget = '1.8'
}

compileTestKotlin {
    kotlinOptions.jvmTarget = '1.8'
}

application {
    mainClassName = 'com.publisher.MainKt'
}

tasks.jar {
    manifest {
        attributes 'Main-Class': 'com.publisher.MainKt'
    }
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
}

还有我的 MainKt 文件

package com.publisher

import org.eclipse.paho.client.mqttv3.*
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
import java.io.File

fun main(args: Array<String>) {
    val client = MqttClient("tcp://192.168.0.55:1883","publisher", MemoryPersistence())
    val connOpts = MqttConnectOptions()
    connOpts.isCleanSession = false
    connOpts.isAutomaticReconnect = true

    client.setCallback(object: MqttCallback {

        override fun connectionLost(cause: Throwable?) {
            println("Connection lost")
            println(cause!!.message)
        }

        override fun messageArrived(topic: String?, message: MqttMessage?) {
            println("Message Received for topic: $topic")
            println("Message: ${message!!.payload}")
        }

        override fun deliveryComplete(token: IMqttDeliveryToken?) {
            println("Message delivered")
        }

    })
    try{
        client.connect(connOpts)
        println("Connected")
        client.subscribe("config/+", 1) { topic, message ->
            println("Getting configuration for $message")
            val path = System.getProperty("user.dir")
            val file = File("$path/${message}.json")
            if(file.exists()){
                client.publish("/devices/ + $message + /config", MqttMessage(file.readBytes()))
            }
        }
    }catch (e: MqttException){
        println("Error: ${e.localizedMessage}")
        e.printStackTrace()
    }
} 

2 个答案:

答案 0 :(得分:2)

您启动应用程序的方式不包括依赖项,这意味着不包括您的 MQTT 驱动程序和 Kotlin 依赖项。

执行以下操作:

gradle distZip
# alternatively
gradle distTar

这将创建一个包含所有依赖项和启动脚本的 zip/tar 文件。使用它来启动您的应用程序。

答案 1 :(得分:0)

您可以考虑使用 Shadow 插件,因为它易于使用。您的 build.gradle 看起来像这样:

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.4.31'
    
    // Shadow plugin
    id 'com.github.johnrengelman.shadow' version '6.1.0'
    id 'java'
}

group = 'me.package'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
    maven {
        url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
    }
}

dependencies {
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
    testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
}

test {
    useJUnit()
}

compileKotlin {
    kotlinOptions.jvmTarget = '1.8'
}

compileTestKotlin {
    kotlinOptions.jvmTarget = '1.8'
}

application {
    mainClassName = 'com.publisher.MainKt'
}

tasks.jar {
    manifest {
        attributes 'Main-Class': 'com.publisher.MainKt'
    }
}

因此您的胖 JAR 是在包含所有依赖项的 /build/libs 目录中生成的。