getClass().getResource 上的 NullPointerException 不适用于 Apache Spark
NullPointerException on getClass().getResource not working for Apache Spark
我有一个maven项目,我正在使用一些写在文件中的资源。为了将它们添加到类路径中,在POM文件中我定义如下:
<build>
<!-- custom resource folders -->
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
</build>
我使用的资源文件夹是:
src/main/resources/A-resources
src/main/resources/B-resources
因此,在 A-resources
和 B-resources
这两个文件夹中,我都有一些文件,我想从中读取内容。我有以下代码用于从这些文件中读取一些选项:
try {
// Error appears on the next line ("InputStream in = ... ")
InputStream in = getClass().getResource("/A-resources/some_file.conf").openStream();
setOptions(in); // -> some function for reading options from files
in.close();
} catch (IOException e) {
// should not happen
throw new RuntimeException(e);
}
在本地,这工作正常。但是,当我为 运行 群集上 Spark 上的整个代码构建一个 fat jar 时,它会抛出 NullPointerException。
我怀疑,虽然它们是在类路径中构建的,但资源可能没有在 fat jar 中导出。我该如何解决这个问题?也许在 POM 文件中有一些额外的选项?
编辑:
当我检查 fat jar 时,我可以看到文件在那里:
...
714 Wed Jun 07 11:14:58 CEST 2017 resources/A-resources/some_file.conf
...
如果我改变:
InputStream in = getClass().getResource("/A-resources/some_file.conf").openStream();
至
InputStream in = getClass().getResource("/resources/A-resources/some_file.conf").openStream();
它将在 Spark 上运行(因此,通过更改代码中的所有内容以添加此 /resources
作为前缀)。然而,有了这个改变——本地部分就不起作用了。我如何使它对两者都起作用,也就是说,而不是在胖罐子里放这个:
resources/A-resources/some_file.conf
直接拥有:
A-resources/some_file.conf
我评论了:
The most likely explanation is that the resource path is incorrect. Check the JAR file to see what has been included in it, and what the actual path is.
旁白:运行 jar -tvf
将为您提供 JAR 文件中所有资源的列表。
事实证明,是问题的根源。 (有时有根据的猜测结果是正确的......)
您回复了:
Thanks, this almost solved the problem (see edit). Although it works for spark, now the local part is broken. Any idea how to make it work for both?
看看您的发现,以及您所说的和您所做的,我认为您解决问题的方法是错误的。在我看来,您最初在代码中使用的路径是正确的:它有意义,并且在本地情况下有效。
我的诊断是您构建 JAR 文件的方式存在问题。看一下 POM 文件。
根据我在 "Specifying Resource Directories" 中阅读的内容,我认为您的 POM 文件应该有一个单独的 <resource>dir</resource>
用于每个资源目录。
如果这没有帮助,请查看与构建 JAR 文件的 Maven 相关的任何 POM 配置。
我有一个maven项目,我正在使用一些写在文件中的资源。为了将它们添加到类路径中,在POM文件中我定义如下:
<build>
<!-- custom resource folders -->
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
</build>
我使用的资源文件夹是:
src/main/resources/A-resources
src/main/resources/B-resources
因此,在 A-resources
和 B-resources
这两个文件夹中,我都有一些文件,我想从中读取内容。我有以下代码用于从这些文件中读取一些选项:
try {
// Error appears on the next line ("InputStream in = ... ")
InputStream in = getClass().getResource("/A-resources/some_file.conf").openStream();
setOptions(in); // -> some function for reading options from files
in.close();
} catch (IOException e) {
// should not happen
throw new RuntimeException(e);
}
在本地,这工作正常。但是,当我为 运行 群集上 Spark 上的整个代码构建一个 fat jar 时,它会抛出 NullPointerException。
我怀疑,虽然它们是在类路径中构建的,但资源可能没有在 fat jar 中导出。我该如何解决这个问题?也许在 POM 文件中有一些额外的选项?
编辑:
当我检查 fat jar 时,我可以看到文件在那里:
...
714 Wed Jun 07 11:14:58 CEST 2017 resources/A-resources/some_file.conf
...
如果我改变:
InputStream in = getClass().getResource("/A-resources/some_file.conf").openStream();
至
InputStream in = getClass().getResource("/resources/A-resources/some_file.conf").openStream();
它将在 Spark 上运行(因此,通过更改代码中的所有内容以添加此 /resources
作为前缀)。然而,有了这个改变——本地部分就不起作用了。我如何使它对两者都起作用,也就是说,而不是在胖罐子里放这个:
resources/A-resources/some_file.conf
直接拥有:
A-resources/some_file.conf
我评论了:
The most likely explanation is that the resource path is incorrect. Check the JAR file to see what has been included in it, and what the actual path is.
旁白:运行 jar -tvf
将为您提供 JAR 文件中所有资源的列表。
事实证明,是问题的根源。 (有时有根据的猜测结果是正确的......)
您回复了:
Thanks, this almost solved the problem (see edit). Although it works for spark, now the local part is broken. Any idea how to make it work for both?
看看您的发现,以及您所说的和您所做的,我认为您解决问题的方法是错误的。在我看来,您最初在代码中使用的路径是正确的:它有意义,并且在本地情况下有效。
我的诊断是您构建 JAR 文件的方式存在问题。看一下 POM 文件。
根据我在 "Specifying Resource Directories" 中阅读的内容,我认为您的 POM 文件应该有一个单独的 <resource>dir</resource>
用于每个资源目录。
如果这没有帮助,请查看与构建 JAR 文件的 Maven 相关的任何 POM 配置。