简体   繁体   English

Gradle构建的JAR找不到Gson

[英]JAR built by Gradle can't find Gson

The problem is solved, read the last section. 问题已解决,请阅读最后一节。

The "background" 的背景”


I'm making a ToDoApp just for a side project, as an excuse to learn Gradle. 我正在为一个副项目制作ToDoApp ,以此作为学习Gradle的借口。 The initial build worked fine and the JAR worked as expected. 最初的版本运行良好,而JAR则按预期运行。 [a] . [a] But that version had no external dependencies; 但是该版本没有外部依赖性。 it was self-contained. 它是独立的。

I was encouraged to add persistence to the project and I decided to use the GSON library (version 2.6.2) to work with JSON. 我被鼓励在项目中添加持久性,因此决定使用GSON库(版本2.6.2)来处理JSON。 I use IntelliJ IDEA (2016.1.2) to write code. 我使用IntelliJ IDEA(2016.1.2)编写代码。

Now, I added the gson-2.6.2 artifact via the Maven Repository option in IntelliJ (in Project Structure ). 现在,我通过IntelliJ中的Maven Repository选项(在Project Structure中 )添加了gson-2.6.2工件。 While writing the code, I added the library to the classpath of the project when prompted by IntelliJ. 在编写代码时,当IntelliJ提示时,我将库添加到了项目的类路径中。 The code compiles and works fine when I run it in my IDE. 当我在IDE中运行代码时,代码可以编译并正常运行。 Here's a sample run: 这是一个示例运行:

========ToDo App========


The following commands are recognised:
 ► help
    Display this help message.
 ► add <name>
    Add a new Todo task with the given name and also displays its corresponding ID.
 ► get <id>
    Displays the task with the given id.
 ► mark <id>
    Toggles the given task as completed or incomplete.
 ► print
    Displays all tasks in order of their creation.
 ► update <id> <new text>
    Updates the item with the given id to store the new text.
 ► del <id>
    Deletes the task with the given id.
 ► exit
    Exit the program.


The tasks are :
>> add Get the Gradle build to work. 
New item added with id = 1
>> add Push the stable system to GitHub and wait for Travis to give the green signal.
New item added with id = 2
>> add Proceed
New item added with id = 3
>> print
The tasks are :
•  Get the Gradle build to work.  [ID: 1 Completed: false]
•  Push the stable system to GitHub and wait for Travis to give the green signal. [ID: 2 Completed: false]
•  Proceed [ID: 3 Completed: false]
>> exit

It works fine. 工作正常。 The JSON data gets saved as I expect: JSON数据已按预期保存:

{"currentId":3,"toDos":{"1":{"id":1,"name":" Get the Gradle build to work. ","completed":false},"2":{"id":2,"name":" Push the stable system to GitHub and wait for Travis to give the green signal.","completed":false},"3":{"id":3,"name":" Proceed","completed":false}}}

When I rerun the code, the data is read back properly. 当我重新运行代码时,将正确读取数据。 I'm very happy with my code. 我对自己的代码感到非常满意。

The "situation" “情况”


Here's my build.gradle : 这是我的build.gradle

group 'ml.cristatus'
version = '0.2'

apply plugin: 'java'

sourceCompatibility = 1.7

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.google.code.gson:gson:2.6.2'
}

jar {
    manifest {
        attributes 'Main-Class': 'ml.cristatus.todo.ToDoApp'
    }
}

When I run gradle build on my Ubuntu 16.04 terminal, the JAR file is built with the following output: 当我在Ubuntu 16.04终端上运行gradle build时,将使用以下输出构建JAR文件:

:compileJava
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 7.036 secs

This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.13/userguide/gradle_daemon.html

So I somehow managed to make the thing compile. 因此,我设法将其编译。 But when I try to run it, using java -jar build/libs/ToDoApp-0.2.jar , the code doesn't work: 但是,当我尝试使用java -jar build/libs/ToDoApp-0.2.jar运行它时,代码不起作用:

========ToDo App========


Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gson/Gson
    at ml.cristatus.todo.repository.ToDoRepositoryWithJSON.<init>(ToDoRepositoryWithJSON.java:25)
    at ml.cristatus.todo.ToDoApp.REPL(ToDoApp.java:38)
    at ml.cristatus.todo.ToDoApp.main(ToDoApp.java:17)
Caused by: java.lang.ClassNotFoundException: com.google.gson.Gson
    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)
    ... 3 more

I'm probably making some newbie mistake, but I can't seem to be able to put my finger on it. 我可能会犯一些新手错误,但似乎无法对此付诸行动。 What am I doing wrong? 我究竟做错了什么? It is also interesting to note that the code compiles yet it can't find the gson artifact. 有趣的是,代码可以编译,但找不到gson工件。 I'm guessing it has something to do with the classpath? 我猜它与类路径有关? I don't know. 我不知道。 I'm not sure. 我不确定。

Please help me in this regard. 请在这方面帮助我。

Solution

I just added this line to the jar {} block: 我刚刚将此行添加到jar {}块中:

from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }

Courtesy of this tutorial . 本教程的礼貌。


[a] Here's the version 0.1 binary. [a]这是0.1版本的二进制文件。

You have to add jar file with gson jar to classpath. 您必须将带有gson jar的jar文件添加到classpath。 When you are starting application ( "java -jar build/libs/ToDoApp-0.2.jar" ). 启动应用程序时( “ java -jar build / libs / ToDoApp-0.2.jar” )。 There is multiple ways it can be achiveved. 有多种方法可以实现它。

One possible way is: 一种可能的方法是:

Add task into your gradle, which copy dependencies (gson.jar in your case) into "lib" directory. 将任务添加到gradle中,这会将依赖项(在您的情况下为gson.jar)复制到“ lib”目录中。 And when you are starting your application, add it to classpath. 并且在启动应用程序时,将其添加到classpath中。 For example in this way "java -cp build/lib/gson.jar -jar build/libs/ToDoApp-0.2.jar" 例如,以这种方式“ java -cp build / lib / gson.jar -jar build / libs / ToDoApp-0.2.jar”

Maybe better for you will be: 也许对您更好:

Add dependencies into your manifest. 将依赖项添加到清单中。 It is discussed in this answer how to copy the dependencies libraries JARs in gradle It should work for you. 在此答案中讨论了如何在gradle中复制依赖库JAR。它应该对您有用

Next Option is: 下一个选项是:

Create an "uberjar" it means add all dependencies into one big jar file. 创建一个“ uberjar”意味着将所有依赖项添加到一个大的jar文件中。 Personally I don't like it. 我个人不喜欢它。 But it will work in your case. 但这将适合您的情况。 How to create uberjar in gradle is here discussed here: Building a uberjar with Gradle 这里讨论了如何在gradle中创建uberjar: 使用Gradle构建uberjar

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM