简体   繁体   English

运行生成的 jar 文件时,如何使 Apache Derby 数据库正常工作?

[英]How can I make my Apache Derby database work when I run my generated jar file?

I have created a JavaFX application and have a generated Jar file (generated with Gradle) that will launch.我创建了一个 JavaFX 应用程序,并生成了一个将启动的 Jar 文件(使用 Gradle 生成)。

When the application does launch, it doesn't connect to the embedded database though.当应用程序启动时,它不会连接到嵌入式数据库。 I feel as though I am missing something very simple but after a lot of research, I haven't been able to figure it out.我觉得好像我错过了一些非常简单的东西,但经过大量研究,我一直无法弄清楚。 When running the jar file from the command prompt, I get the following error: java.lang.ClassNotFoundException: org.apache.derby.jdbc.EmbeddedDriver从命令提示符运行 jar 文件时,出现以下错误:java.lang.ClassNotFoundException: org.apache.derby.jdbc.EmbeddedDriver

From the reading I have done, I understand I may be able to add this to my classpath but I have not been successful with this after multiple attempts and I have made this application to be run on another computer.从我所做的阅读中,我知道我可以将它添加到我的类路径中,但是在多次尝试后我没有成功,我已经让这个应用程序在另一台计算机上运行。 This is possible, right?可能的,对吧?

If possilbe, I would love to change something in my build.gradle file or surround the .jar in a folder or something like that that would make this simple for the person running the program.如果可能的话,我很想更改我的 build.gradle 文件中的某些内容,或者将 .jar 包含在一个文件夹中或类似的东西中,这将使运行程序的人变得简单。 Program size is not a concern short of multiple gigabytes.程序大小不是几个千兆字节的问题。

You've got two problems你有两个问题

  • The driver class is not in your app jar驱动程序类不在您的应用程序 jar 中
  • If you embed that db into the app jar, you're not going to be able to write to it如果您将该数据库嵌入到应用程序 jar 中,您将无法写入它

You can make a 'fat jar' but the isn't going to solved the second problem.你可以做一个“胖罐子”,但这不会解决第二个问题。 You really need to make an installer to do this, in order to leave the db in the file system, so it can be written to.您确实需要制作一个安装程序来执行此操作,以便将 db 保留在文件系统中,以便可以将其写入。

Problem问题

Part of what Gradle does is dependency management . Gradle 所做的部分工作是依赖管理 That means it knows what dependencies you need and how to find them (based on configurations in the build script).这意味着它知道您需要哪些依赖项以及如何找到它们(基于构建脚本中的配置)。 When you execute/build your application via Gradle the tool will automatically search repositories, download+cache dependencies, and place those dependencies on the class-path/module-path.当您通过 Gradle 执行/构建应用程序时,该工具将自动搜索存储库、下载+缓存依赖项,并将这些依赖项放在类路径/模块路径上。 Once you deploy your JAR file Gradle is no longer involved, so your deployment is responsible for including the needed dependencies.一旦您部署了 JAR 文件,Gradle 就不再涉及,因此您的部署负责包括所需的依赖项。

In other words, you need to ship your application's dependencies with your application JAR file.换句话说,您需要将应用程序的依赖项与应用程序 JAR 文件一起发送。


Solutions解决方案

You basically just need to make sure you include your application's dependencies with your application.您基本上只需要确保将应用程序的依赖项包含在您的应用程序中。 Here are at least three ways to do that.这里至少有三种方法可以做到这一点。

Copy Dependencies复制依赖

Copy the dependencies into a build folder as part of the build process.作为构建过程的一部分,将依赖项复制到构建文件夹中。 Here's an example of such a task, using the Kotlin DSL :这是使用Kotlin DSL执行此类任务的示例:

tasks {
    val jar by existing(Jar::class)

    val copyDependencies by registering(Copy::class) {
        from(configurations.runtimeClasspath)
        into(jar.get().destinationDirectory)
    }

    jar.configure {
        finalizedBy(copyDependencies)
    }
}

Now if you execute ./gradlew jar Gradle will create the JAR file and then copy the dependencies into the same directory as the JAR file.现在,如果您执行./gradlew jar Gradle 将创建 JAR 文件,然后将依赖项复制到与 JAR 文件相同的目录中。 Then you just need to make sure all the JAR files are deployed together.然后您只需要确保所有 JAR 文件都部署在一起。

If I remember correctly, the default class-path is the working directory.如果我没记错的话,默认的类路径是工作目录。 But to specify the class-path you would use -cp , -classpath , or --class-path when executing your application.但是要指定类路径,您将在执行应用程序时使用-cp-classpath--class-path The module-path, if needed, is set with -p or --module-path .如果需要,可以使用-p--module-path设置模块--module-path

Fat JAR脂肪罐

Create a so-called "fat" or "uber" JAR file.创建所谓的“fat”或“uber”JAR 文件。 That's a JAR file that includes not just your own application code but all your application's dependencies as well.这是一个 JAR 文件,不仅包含您自己的应用程序代码,还包含您应用程序的所有依赖项。 You could configure the jar task for this, but it would probably be easier for you to simply apply the Gradle Shadow Plugin .您可以为此配置jar任务,但简单地应用Gradle Shadow Plugin可能会更容易。

// Kotlin DSL
plugins {
    id("com.github.johnrengelman.shadow") version "<version>"
    // other plugins...
}

And then you'd create the fat JAR with ./gradlew shadowJar .然后您将使用./gradlew shadowJar创建胖 JAR。 See the user guide for more information.有关更多信息,请参阅用户指南。

Self-Contained Application自包含应用程序

Create a self-contained executable using a tool like jpackage .使用jpackage类的工具创建一个独立的可执行文件。 This tool gives you an application that has all its code and the JRE embedded, and then gives you an installer or native executable (eg exe on Windows).该工具为您提供一个应用程序,其中包含所有代码嵌入的 JRE ,然后为您提供安装程序或本机可执行文件(例如 Windows 上的exe )。 Here's the user guide for jpackage .这是jpackage用户指南 There are Gradle plugins to make using jpackage from Gradle easier, such as The Badass JLink Plugin .有一些 Gradle 插件可以让使用来自 Gradle 的jpackage变得更容易,比如The Badass JLink Plugin

Note jpackage was added in Java 14 and was incubating until Java 16. Also note that jpackage can't "cross-package".注意jpackage是在 Java 14 中添加的,并且一直在孵化到 Java 16。还要注意jpackage不能“跨包”。 That is to say, if you build your application on Windows then you can only create installers/executables for Windows;也就是说,如果您在 Windows 上构建应用程序,那么您只能为 Windows 创建安装程序/可执行文件; same for MacOS and Linux. MacOS 和 Linux 也一样。 If you need to package for multiple platforms then you'll need access to each platform.如果您需要为多个平台打包,那么您需要访问每个平台。


JavaFX JavaFX

Since you've tagged this question with JavaFX I want to give a note of caution.由于您已使用 JavaFX 标记了此问题,因此我想提醒您注意。 Though if you're not using JavaFX 9+ then this is not relevant to you.但是,如果您不使用 JavaFX 9+,那么这与您无关。

Technically JavaFX only supports being loaded as named modules.从技术上讲,JavaFX 仅支持作为命名模块加载。 That means it needs to be placed on the module-path, either via --module-path or by including it in the custom-runtime image built by jlink / jpackage .这意味着它需要通过--module-path或通过将其包含在由jlink / jpackage构建的自定义运行时映像中来放置在模块路径上。 As of JavaFX 16 a warning is now emitted if JavaFX is loaded from unnamed modules (ie the class-path).从 JavaFX 16 开始,如果从未命名的模块(即类路径)加载 JavaFX,则会发出警告。

Executable JAR files are placed on the class-path.可执行 JAR 文件放置在类路径中。 That includes fat JARs.这包括胖 JAR。 And if you are not using a JDK that includes JavaFX—meaning you have Gradle pull in the JavaFX dependencies—then JavaFX will be included in your fat JAR and be placed on the class-path.如果您没有使用包含 JavaFX 的 JDK——这意味着您在 JavaFX 依赖项中有 Gradle 拉取——那么 JavaFX 将包含在您的胖 JAR 中并放置在类路径中。 Now, despite not being supported and now emitting a warning, nothing seems to currently break if JavaFX is on the class-path.现在,尽管不受支持并且现在发出警告,但如果 JavaFX 在类路径上,目前似乎没有任何问题。 Except for one caveat: Your main class must not be a subclass of javafx.application.Application .除了一个警告:您的主类不能是javafx.application.Application的子类。 You'd have to create a separate main class that simply launches JavaFX.您必须创建一个单独的主类来简单地启动 JavaFX。

Because of all this, I would highly recommend using jpackage to deploy JavaFX applications.因此,我强烈建议使用jpackage来部署 JavaFX 应用程序。 You may want to read this Q&A as well.您可能还想阅读此问答

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

相关问题 如何以编程方式启动Apache derby jar文件? - How can I start apache derby programmatically jar file? 如何将derby数据库与build .jar文件一起使用? - how can i use derby database with the build .jar file? 如何使我的可执行JAR不需要JDK运行 - How can I make my executable JAR not need JDK to run 如何在可执行文件 jar 中运行 lombok 功能? - How can I run lombok features in my executable jar file? 在我的数据库 Java Derby 中插入新数据时生成的 ID 错误 - Error with the ID generated when i insert new data in my database Java Derby 当我在html代码中运行jar文件时,由于RuntimeException而无法正常工作 - When i run my jar-file in my html-code it won't work because of a RuntimeException 如果Derby仅是客户端/服务器,如何将数据库文件保存在特定的文件夹中? - How can I have my database files in my specific folder and if Derby is only client/server? 当我从jar运行我的应用程序时,为什么新的File(path)不起作用? - Why does new File(path) doesn't work when I run my application from jar? 如何将数据库文件保存在JAR中? - How do I keep my database file inside my JAR? 为何运行该文件时,除非我在Jar所在的文件夹中,否则为什么我无法访问其文件? - Why can't I access a file within my jar unless I'm in the folder with the Jar when I run it?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM