如何在Intellij IDEA中导出runnable jar时修复java.lang.NoClassDefFoundError?

时间:2016-06-26 10:46:47

标签: java intellij-idea jar

我正在尝试从这个java库创建一个可运行的jar:

https://github.com/Jefferson-Henrique/GetOldTweets-java

创建后,jar应该能够使用命令行的输入运行。

主文件是这个Exporter类:

package me.jhenrique.main;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;

import me.jhenrique.manager.TweetManager;
import me.jhenrique.manager.TwitterCriteria;
import me.jhenrique.model.Tweet;

public class Exporter {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

    public static void main(String[] args) {
        if (args == null || args.length == 0) {
            System.err.println("You must pass some parameters. Use \"-h\" to help.");
            System.exit(0);
        } 

        if (args.length == 1 && args[0].equals("-h")) {
            System.out.println("\nTo use this jar, you can pass the folowing attributes:");
            System.out.println("   username: Username of a specific twitter account (without @)");
            System.out.println("      since: The lower bound date (yyyy-mm-aa)");
            System.out.println("      until: The upper bound date (yyyy-mm-aa)");
            System.out.println("querysearch: A query text to be matched");
            System.out.println("  maxtweets: The maximum number of tweets to retrieve");

            System.out.println("\nExamples:");
            System.out.println("# Example 1 - Get tweets by username [barackobama]");
            System.out.println("java -jar got.jar username=barackobama maxtweets=1\n");

            System.out.println("# Example 2 - Get tweets by query search [europe refugees]");
            System.out.println("java -jar got.jar querysearch=\"europe refugees\" maxtweets=1\n");

            System.out.println("# Example 3 - Get tweets by username and bound dates [barackobama, '2015-09-10', '2015-09-12']");
            System.out.println("java -jar got.jar username=barackobama since=2015-09-10 until=2015-09-12 maxtweets=1");
        } else {
            TwitterCriteria criteria = TwitterCriteria.create();

            for (String parameter : args) {
                String[] parameterSplit = parameter.split("=");

                if (parameterSplit[0].equals("username")) {
                    criteria.setUsername(parameterSplit[1]);
                } else if (parameterSplit[0].equals("since")) {
                    criteria.setSince(parameterSplit[1]);
                } else if (parameterSplit[0].equals("until")) {
                    criteria.setUntil(parameterSplit[1]);
                } else if (parameterSplit[0].equals("querysearch")) {
                    criteria.setQuerySearch(parameterSplit[1]);
                } else if (parameterSplit[0].equals("maxtweets")) {
                    criteria.setMaxTweets(Integer.valueOf(parameterSplit[1]));
                }
            }

            try {
                BufferedWriter bw = new BufferedWriter(new FileWriter("output_got.csv"));
                bw.write("username;date;retweets;favorites;text;geo;mentions;hashtags;id;permalink");
                bw.newLine();

                System.out.println("Searching... \n");
                for (Tweet t : TweetManager.getTweets(criteria)) {
                    bw.write(String.format("%s;%s;%d;%d;\"%s\";%s;%s;%s;\"%s\";%s", t.getUsername(), sdf.format(t.getDate()), t.getRetweets(), t.getFavorites(), t.getText(), t.getGeo(), t.getMentions(), t.getHashtags(), t.getId(), t.getPermalink()));
                    bw.newLine();
                }

                bw.close();

                System.out.println("Done. Output file generated \"output_got.csv\".");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

在src文件夹中还有一个TweetManager.java文件,TwitterCriteria.java文件和Tweet.java文件。 (Main.java文件只显示了如何使用代码的示例。)此外,此项目的libs文件夹中有两个jar," json-20140107.jar"和" jsoup-1.8.1.jar"。

我在java代码中做了一些小改动,我想重新创建包含此更改的got.jar文件。我正在使用Intellij IDEA。我没有任何java经验,所以这个过程到目前为止一直是猜测和检查。

问题(我认为)是当我运行我创建的jar时,jar无法找到两个libs jar" json-20140107.jar"和" jsoup-1.8.1.jar"。我从终端获得的输出是:

main_jar$ java -jar main.jar querysearch="europe refugees" maxtweets=1
Searching... 

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/client/HttpClient
    at me.jhenrique.main.Exporter.main(Exporter.java:64)
Caused by: java.lang.ClassNotFoundException: org.apache.http.client.HttpClient
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

在Intellij中制作可运行的jar时,我选择了" jar"在Artifacts选项卡中,选中" Build on make"盒子,有"出口商"作为我的主类,并确保我的类路径指向包含json和jsoup文件夹的文件夹。我还在" Dependencies"中列出了json和jsoup库。在“模块”选项卡中。 (这些都是以前与此问题相关的答案的所有建议。)

enter image description here

enter image description here

enter image description here

我已经尝试了我可以在这个主题上找到的所有其他建议,但没有任何方法可以避免此错误。我做错了什么?

编辑:已解决 - 问题是我需要使用Maven进行额外的依赖性下载我意识到问题是我有额外的依赖项(除了json和jsoup jar)需要自动下载Maven,由于我没有将项目作为Maven项目导入Intellij,因此没有发生。我一开始并不知道Maven是什么,但是当我看到我正在使用的代码中的pom.xml文件时,我看到除了json和jsoup库之外还引用了apache HttpClient库,我做了没有HttpClient库的jar。

将项目作为Maven项目导入后,会自动下载其他依赖项,并且导出的jar文件按预期工作。感谢Will提供了一个非常明确的解释,向我保证问题不在于我是如何导入我已经拥有的库的。

我在Maven和Intellij的最后一个小问题是我在这里找到的解决方案,以防其他人获得"没有主要的清单属性" Maven和Intellij的错误:Wrong Manifest.mf in IntelliJ IDEA created .jar

2 个答案:

答案 0 :(得分:0)

您应该在jar中包含依赖项,或者将jar保留在它所依赖的库中。不幸的是,我对IDEA(无)的经验太少,无法告诉你如何在jar中包含include依赖项。

答案 1 :(得分:0)

我快速创建了一个依赖于另一个Jar的Jar。

我首先使用IntelliJ

将库添加到我的项目中

IntelliJ Libraries

然后我通过转到Artifacts并选择'From modules with dependencies'来创建Jar From modules with dependencies

然后我设置了Jar的主类 Set main class for jar

我完成的jar设置看起来像这样。

completed jar setup

然后转到Build菜单并选择Build Artifacts并选择构建操作。

Build jar

你现在应该有一个罐子

completed jar

我打开jar你应该看到你的程序类文件和任何依赖项的类文件。

exploeded jar

希望有所帮助。