The line persistenceProperties.load(is);
is throwing a nullpointerexception
in the following method. How can I resolve this error?
public void setUpPersistence(){
final Properties persistenceProperties = new Properties();
InputStream is = null;
try {
is = getClass().getClassLoader().getResourceAsStream("src/test/samples/persistence.properties");
persistenceProperties.load(is);
}catch (IOException ignored) {}
finally {
if (is != null) {try {is.close();} catch (IOException ignored) {}}
}
entityManagerFactory = Persistence.createEntityManagerFactory(
"persistence.xml", persistenceProperties);
}
I have tried to experiment with this by moving the class that contains the method to various other locations within the application structure, and also by changing the line of code preceding the error in the following ways:
is = getClass().getClassLoader().getResourceAsStream("persistence.properties");
is = getClass().getClassLoader().getResourceAsStream("/persistence.properties");
is = getClass().getClassLoader().getResourceAsStream("/src/test/samples/persistence.properties");
is = getClass().getClassLoader().getResourceAsStream("other/paths/after/moving/persistence.properties");
But the error is still thrown every time the method is called.
Here is a printscreen of the directory structure of the eclipse project. The class containing the method is called TestFunctions.java
, and the location of persistence.properties
is shown:
As per feedback below, I changed the method to:
public void setUpPersistence(){
final Properties persistenceProperties = new Properties();
InputStream is = null;
try {
is = getClass().getClassLoader().getResourceAsStream("persistence.properties");
persistenceProperties.load(is);
}catch (IOException i) {i.printStackTrace();}
finally {
if (is != null) {try {is.close();} catch (IOException ignored) {}}
}
entityManagerFactory = Persistence.createEntityManagerFactory(
"persistence.xml", persistenceProperties);
}
I also moved mainTest.TestFunctions.java to src/test/java
. Together, these all cause the following new stack trace:
Exception in thread "main" java.lang.NoClassDefFoundError: maintest/TestFunctions
at maintest.Main.main(Main.java:7)
Caused by: java.lang.ClassNotFoundException: maintest.TestFunctions
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 1 more
Short answer:
Move persistence.properties
to src/main/resources
, have both Main.java
and TestFunctions.java
in src/main/java
, and use
getClass().getClassLoader().getResourceAsStream("persistence.properties");
to load the properties file.
Long answer with an explanation:
As others have hinted at - in a Maven project structure, you (typically) have two directory trees: /src/main
and /src/test
. The general intent is that any "real" code, resources, etc should go in /src/main
, and items that are test-only should go in /src/test
. When compiled and run, items in the test
tree generally have access to items in the main
tree, since they're intended to test the stuff in main; items in the main
tree, however, do not typically have access to items in the test
tree, since it's generally a bad idea to have your "production" code depending on test stuff. So, since Main.java
depends on TestFunctions.java
, and TestFunctions.java
depends on persistence.properties
, if Main is in src/main
then both TestFunctions
and persistence.properties
need to be as well.
Two things:
First, try a path of test/samples/...
or /test/samples/...
Secondly, and much more importantly, don't ever, ever, ever write this:
try {
// some stuff
} catch (IOException ignored) {}
All this says is: do some stuff, and if it goes wrong, then fail silently. That is never the right thing to do: if there's a problem, you want to know about it, rather than madly rushing on as if nothing had happened. Either do some sensible processing in your catch
block, or else don't have the try
/catch
and add a throws IOException
to your method signature so it can propagate upwards.
But at the moment, you're just sweeping things under the carpet.
ClassLoader.getResourceAsStream()
loads resources as it does for loading classes. It thus loads them from the runtime classpath. Not from the source directories in your project.
Your class Main
is in the package maintest
, and its name is thus maintest.Main
. I know that without even seeing the code because Main.java
is under a directory named maintest
, which is at directly under a source directory.
The persistence.properties file is directly under a source directory (src/test/resources
). At runtime, it's thus at the root of the classpath, in the default package. Its name is thus persistence.properties, and not src/test/samples/peristence.properties
. So the code should be
getClass().getClassLoader().getResourceAsStream("persistence.properties");
Nothing will ever be loadable from the samples directory, since thisdirectory is not under any source directory, and is thus not compiled by Eclipse, and is thus not available to the ClassLoader.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With