How to get a resource that is in the same class package that will use it?

Asked

Viewed 343 times

5

I created a Java project with the following structure:

src
 |-br.foo.settings
 |     |- settings.json
 |     |- Settings.java
 |   
 |- ... outros pacotes ...

As I am used to the JSON file format, I thought of creating one to define the main settings of the application (as you can see, it is in the package br.foo.settings).

To illustrate, there is some information about repositories, dependencies, directories where I should save application data, etc. An example of structure:

{
    locais: [
        {"padrao":"stackoverflow"},
        {"usuario":"2"},
        ...
    ],
    ...
}

The class Settings is responsible for obtaining a configuration value based on key. For example, suppose I want the value of key "standard" (in "sites") I would call a method that returns the "stackoverflow".

The problem...

All of this works normally when I run tests and run the project in the IDE, but when I do build and try to run the . created jar is launched an exception of NullPointerException for not finding the file settings.json.

Here’s my first question:

This file is not packaged along with the . jar?


Well, continuing, as the file is in the same class package Settings, I am using the following code to get the file:

// Settings.java 
File arquivoDeConfiguracao = FileUtils.toFile(getClass().getResource("settings.json"));

The use of "getClass().getResource(...)" it’s always worked for me, but in this case it’s frustrating me!

Is there any way to package this . json file along with . jar? I’m pretty sure the problem is this, because the method I’m using to get the file is picking up a null object, but the funny thing is that when I run by the IDE it works OK.

My second question is:

I am using Maven and noticed that it has a directory called "Resources". If I move this JSON file there, it will be packaged along with . jar?

I accept alternative suggestions, for now I am considering this to read the JSON file the best. For example, some other way to write a file with data that should be used by the application that is not creating enum?

  • 1

    To answer your first question you can open the .jar with some application that opens zip files and see if the file is inside. If it is inside, probably the problem is in the parameter of getResource() which would have to be the file path based on the root of the jar.

  • @Gabrieloshiro I’ll check, I hadn’t thought about it.

  • Your second question is easier, "Yes!". If you are using Maven it is always advisable to use their directory structure, since Maven was developed under the concept "Convention on configuration". The directory res will bundled next to the jar unless you specify that you do not want to pack them.

  • @Gabrieloshiro I extracted the files from the . jar and the JSON file is there, following the same structure as in the question. I don’t know what the problem is, I’m almost starting the project from scratch because I haven’t been able to solve it for weeks.

  • 1

    Which way do you pass to getResource()? Try to pass the path of your jar by swapping the points of the Packages for bars src/br/foo/settings/settings.json

  • Thanks for the tips @Gabrieloshiro, I managed to solve! : D

Show 1 more comment

1 answer

3


I managed to solve the problems, but I made some changes in the structure of the project.

src
 |- java
 |    |
 |    |- br.foo.settings
 |           |- Settings.java
 |- resources
       |- settings.json

I’m getting the file through InputStream as follows:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream inputstr = classLoader.getResourceAsStream("settings.json"); // YEAAH!
inputstr.close();

In case the above way doesn’t work, some Google searches led me to that library that makes a more accurate search for the file.

To convert this stream for a String, I followed that answer (sensational) no Stackoverflow making use of an object Scanner.

import java.io.InputStream;
import java.util.Scanner;

public class Foo {
    public static void main(String... args) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream inputstr = classLoader.getResourceAsStream("settings.json");

        String json = new Scanner(inputstr, "UTF8").useDelimiter("\\A").next();
        System.out.println(json); // YEAHH :D
        inputstr.close();
    }
}
  • You can mark your own answer as accepted so that it is stated in the statistics that the problem has been solved (important for the Beta phase of Sopt) ;-)

  • 1

    @Gabrieloshiro The system imposes that you can only accept your own answer at least 2 days after the question has been posted.

  • @Victorstafusa I’m on, bro ;)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.