7

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:


**EDIT: **

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  
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
CodeMed
  • 9,527
  • 70
  • 212
  • 364
  • 2
    `is` must be null if it's causing the exception. Have you used the debugger to figure out why? – AdamMc331 Oct 13 '14 at 19:28
  • Do you have explicit no argument constructor for class `Properties`? If so, please post it. – PM 77-1 Oct 13 '14 at 19:31
  • Could you try to clean and rebuild your project? When you moved TestFunctions to src/test/java but keep referencing it from src/main/java then the project shouldn't even be compilable... – Puce Oct 14 '14 at 00:09
  • unrelated note: consider to use try-with-resources to close your streams. – Puce Oct 14 '14 at 00:09
  • @Puce This question is now resolved. thank you for your insights. I am still trying to get hbm2ddl to create the tables in the MySQL database. create-drop is not doing the job. Do you work with hbm2ddl? here is the link: http://stackoverflow.com/questions/26348480/persisting-hyperjaxb-generated-entities-to-mysql-from-eclipse/26349641?noredirect=1#comment41383819_26349641 – CodeMed Oct 14 '14 at 16:57

7 Answers7

7

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.

logi-kal
  • 7,107
  • 6
  • 31
  • 43
Sbodd
  • 11,279
  • 6
  • 41
  • 42
5

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.

chiastic-security
  • 20,430
  • 4
  • 39
  • 67
  • @CodeMed This now looks like it's correctly reading in the persistence file, but that your persistence file is specifying a class that doesn't exist. – chiastic-security Oct 13 '14 at 19:54
  • 1
    @CodeMed Sounds like the problem you reported is now fixed! Debugging the rest of it sounds like a new question, with rather different tags etc. – chiastic-security Oct 13 '14 at 20:07
  • @CodeMed Well, it rather depends on exactly what the problem is! But sounds like `persistence` and `hibernate` and `java` would be a good start. – chiastic-security Oct 13 '14 at 20:10
  • @CodeMed No, they're not the same problem. The null pointer exception came from not finding the properties file, and that's now fixed. The class not found exception can't be generated by any of the code you've posted, except for the bit where the properties file gets parsed and analysed. The problem is in there somewhere, and it's a different issue (one that you didn't hit till now because of the null pointer exception). – chiastic-security Oct 14 '14 at 15:11
2

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.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Do you see in my original posting above that `is = getClass().getClassLoader().getResourceAsStream("persistence.properties");` also throws the same error? – CodeMed Oct 13 '14 at 19:40
2

I will try to make it more Simple for this Question!

Here your main class is in src/main/java as you mentioned, so you should create another source for storing your properties file saying src/main/resources which you had already done and just store your properties file in this source, so in Run time it will directly refer this path and access the file,

You can add this piece of code as well to access the properties file

is = ClassLoader.getSystemResourceAsStream("your_properties_file");

and you can use load(is) accordingly.

To Conclude

If your main class is in src/main/java then you should keep your properties file in src/main/resources and use the respective snippet to load this.

OR

If your main class is in src/test/java then you should keep your properties file in src/test/resources and use the respective snippet to load this.

1

Your IDE works with two different scopes:

  • production scope: src/main/java + src/main/resources folders and
  • test scope: src/test/java + src/test/resources

Seems you are trying to execute you program from production scope, while persistence.properties file is placed into test scope.

How to fix:

  • Place your test into src/test/java or
  • Move persistence.properties into src/main/resources
ursa
  • 4,404
  • 1
  • 24
  • 38
0

InputStream is = this.getClass().getResourceAsStream("/package_name/property file name")

PropertyFileOject.load(is)

In my case error was due to maven was not treating my config folder inside src/main/java as source folder.

Recreated config package in src/main/java ..Copied files to it and re-compiled using maven. Files were there in target directory and hence in war. Error resolved.

0

I recently had the same problem and came upon the solution that I had to put my resources in a path the same way organized as where was getClass().getResourceAsStream(name) situated. And I still had a problem after doing that. Later on, I discovered that creating a package org.smth.smth only had created a folder named like that "org.smth.smth" and not a folder org with a folder smth and a folder inside smth... So creating the same path structure solved my problem. Hope this explanation is understandable enough.