relative path doesn't work when executing jar - java

i am developping an application where i have to specify the path of a file called dao.properties it works just fine but when i execute the jar using the cmd : java -jar StockManagement.jar i get the error that the file is not found (it works fine in netbeans)
the class and the file are in the same folder.
i've tried a lot of relative paths and nothing works so this is my last hope
here is the code and the hierarchy:
thank y in advance

If your file is in your code base you should use the classLoader to load it.

If I'm not mistaken, the way you're using ClassLoader is it looking for a file path relative to where it is being called.
From the picture, it seems that you're using ClassLoader from the DAOFactory class, is that right? You're declaring the path to your file to be
stock/DAO/dao.properties
If you're calling it from DAOFactory, Java looks for the file in
<where DAOFactory is>/stock/DAO/dao.properties
If DAOFactory and dao.properties reside in the same file I think your file path should just be
dao.properties
So it looks in the same folder that DAOFactory is in.
EDIT: Use DAOFactory class to read in properties file.
Using something like the following code snippet, call this function from the DAOFactory class using just the main method to try to see if you can read the properties file without anything else. Change any classes or names you need to to work on your local machine.
public static String getProperty(String property) {
String value = "";
try (InputStream is = DAOFactory.class.getResourceAsStream("dao.properties")) {
Properties prop = new Properties();
prop.load(is);
value = prop.getProperty(property);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}

Related

How to specify the path for getResourceAsStream() method in java

I know this question has been asked several times but I still can't get it work by those solutions.
I have a maven project. And one Config.java file located in consumer/src/main/java. Here's the content:
import java.util.Properties;
public class Config {
Properties configFile;
public Config() {
configFile = new Properties();
try {
configFile.load(this.getClass().getClassLoader().
getResourceAsStream("property_table.config.txt"));
} catch(Exception e) {
e.printStackTrace();
}
}
public String getProperty(String key) {
String value = this.configFile.getProperty(key);
return value;
}
public static void main(String[] args) {
Config config = new Config();
System.out.println("URL: " + config.getProperty("URL"));
System.out.println("PASSWORD: " + config.getProperty("PASSWORD"));
}
}
I kept getting nullpointer exception. I know that's because it can't find the file property_table.config.txt.
At first I put the property_table_config.txt file in the same folder(consumer/src/main/java/) as Config.java file. And tried use /property_table_config.txt and 'property_table_config.txt`. Neither of them work.
And then I tried using absolute path, not working. And tried using /main/java/property_table_config, not working either.
Then I saw this solution: https://stackoverflow.com/a/2103625/8159477.
So I make a directory called resources and put it under main folder (i.e. the path of the folder is consumer/src/main/resources, and create a sub-folder config under resources. After putting the property_table_config.txt file there, I changed the code into this:
configFile.load(this.getClass().getClassLoader().getResourceAsStream("/config/property_table.config.txt"));
But this still didn't work. Can anyone give some hint on this? Any suggestions will be appreciated!!
According to Class.getResourceAsStream:
This method delegates to this object's class loader. If this object was loaded by the bootstrap class loader, the method delegates to ClassLoader.getSystemResourceAsStream.
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
This is how I understand the comments:
If you use ClassLoader.getResourceAsStream, send the absolute path from package root, but omitting the first /.
If you use Class.getResourceAsStream, send either a path relative the the current Class object (and the method will take the package into account), or send the absolute path from package root, starting with a /.
But in addition to this, you need to be cognizant of your build system. With maven, resource files are stored under src/main/resources.
So, in your case, I believe making the following changes should resolve the issue:
Put the file in src/main/resources.
Change the code to
this.getClass()
.getResourceAsStream("/property_table.config.txt")
//or `Config.class.getResource...
Alternatively, use
this.getClass().getClassLoader()
.getResourceAsStream("property_table.config.txt")`
I've tried this with a similar setup, and it works as expected.
ClassLoader().getResourceAsStream() is looking files only in classpath.
What you need is to have your config file in directory which is in classpath.
So, you have options:
when you run your java application from command line you can set path to directory in -cp parameter or CLASSPATH system variable. point there is: directory from where you need to get config file must be in class path - not a file. (e.g. if file location is c:\my_projects\test-project\config\my_config.properties and c:\my_projects\test-project\ is in classpath then getResourceAsStream call will be ClassLoader().getResourceAsStream("config/my_config.properties")
you can package your file into jar file and root of jar file is starting point for getResourceAsStream("config/my_config.properties")
If your Maven project is a jar project you need to use Maven resource plugin to put additional resource(s) into jar.
BTW: Maven does not put anything into jar file from src/main/java/ directory (if you do not explicitly specify it for resource plugin)
If you use IDE like Eclipse with your Maven project src/main/resources is a part of build classpath. Double check is it there and if it is not - do "Update Maven Project" or add it manually.
Still ClassLoader will see your properties file from src/main/resources folder only when you run project in IDE not from standalone Jar file - if you did not package your file or provide location in classpath.
hi can you try this one
String dirBase = new ClassPathResource("property_table.config.txt").getURI().getPath().replace("property_table.config.txt", "");
Can you try following code.
Config.class.getResourceAsStream("property_table.config.txt")
Update:
This is the code I tried.
package test;
import java.util.Properties;
public class Config
{
Properties configFile;
public Config()
{
configFile = new Properties();
try
{
configFile.load(Config.class.getResourceAsStream("property_table.config.txt"));
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String getProperty(String key)
{
String value = this.configFile.getProperty(key);
return value;
}
public static void main(String[] args)
{
Config config = new Config();
System.out.println("URL: " + config.getProperty("URL"));
System.out.println("PASSWORD: " + config.getProperty("PASSWORD"));
}
}
And I placed property_table.config.txt file withn test package and it worked.

NPE When Getting File. Works on IDE Run but Not Jar Launch [duplicate]

I have a simple java application that loads a properties file from the current package.
this.getClass().getResourceAsStream("props.properties");
This works fine when the property file I want is in the current package. However, I want to package this application as a JAR and define and override with a new properties file where I use it. Is there a way to load the first resource named "props.properties" that is on the classpath?
I want it to be as easy to override the properties file via command line:
java.exe -classpath props.properties;myJar.jar com.test.MyApp
I don't want to have to unpack the JAR and modify the properties file to change something. I feel like I'm missing something obvious...
The javadoc for Class.getResourceAsStream() documents the lookup logic:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
So in other words, the resource name passed to the method should look like /com/package/p2/props.properties if the props.properties is stored in the com.package.p2 package instead of the current class's.
I'm sure it's too late for the answer but it could be interesting for googlers
this small code snippet helpers to load a properties file from any where in the Classpath.
ClassLoader cl = ClassLoader.getSystemClassLoader();
if (cl != null) {
URL url = cl.getResource(CONF_PROPERTIES);
if (url == null) {
url = cl.getResource("/" + CONF_PROPERTIES);
}
if (url != null) {
try {
InputStream in = url.openStream();
props = new Properties();
props.load(in);
} catch (IOException e) {
// Log the exception
} finally {
// close opened resources
}
}
}
If all else fails you could use two different file names, say props-default.properties inside myJar.jar and props.properties to override on the command-line. In your code, you'd try loading the props.properties file first and fallback to props-default.properties if it wasn't found.
I'm not sure, but maybe: ClassLoader.getResourceAsStream()
EDIT:
I don't think this is significantly different to this.getClass().getResourceAsStream() from the question, since as mentioned you still have to get the ClassLoader you want to use to load the resource.
Since you provide the resource in the -classpath in your example, it should be available from the same class loader as your "main" class (in the SUN JVM, that's sun.misc.Launcher$AppClassLoader, not sure if this can/does vary for other JVM implementations).

Am I accessing these resource files in java incorrectly?

I have two classes. One is intended to be a common library and another a client that consumes from the library.
The library is structured as below:
public class Library
{
public Library()
{
String pathToResourceA="src/main/resources/A.xls";// A.xls is present within resources
String key="apples";
Resource res= loadResourceBasedOnDoc(pathToResource,key);
...//process resource
}
}
It's corresponding test class
public class LibraryTest
{
#Test
public void testLibrary()
{
new Library();// works as expected- the test passes and the resource is loaded.//ie. A.xls is found in the right place
}
}
However, when I try to access the library from my client in the following manner
import packagename.Library
public class Client{
Library lib;
public Client()
{
lib= new Library();// throws a FileNotFoundException!
}
}
I get a FileNotFoundException. I'm guessing this is something to do with defining the right value to pathToResourceA in class A but cant figure out what it is. Any thoughts would be appreciated. Thanks!
Code for loadResourcesBasedonDoc
protected Resource loadResourceBasedOnDoc(String filename,String password)
{
InputStream in = null;
try {
in = new FileInputStream(filename);
//further in is processed...
The problem is that you are using relative file paths:
String pathToResourceA="src/main/resources/A.xls";// A.xls is present within resources
This is then processed in the loadResourceBasedOnDoc method as follows:
in = new FileInputStream(filename);
This call looks for the file (src/main/resources/A.xls) on the file system. Because the path is relative, it looks for the file in a directory that is relative to the current working directory. In your unit test, the current working directory is probably the directory from which the test is launched. Assuming that is the root of your project, the test likely finds A.xls on the file system within your project.
To solve this, I recommend using full pathnames in the loadResourceBasedOnDoc as follows:
String programLaunchDir = System.getProperty("user.dir")
in = new FileInputStream(programLaunchDir + File.separator + filename);
The user.dir system property should be the current working directory. So if you can enforce that the program is launched from that dir, you are all set. Otherwise, you might want to wrap you program in a batch file or shell script that passes the directory to the program.

Get "null" when I'm using getResourceAsStream to read properties file in Android Studio

I recently just start to using Android Studio for my programming study.
I've faced a problem today which is keep getting "null" when I using getResourceAsStream to read a properties file from JUNIT TEST.
I used to locate the .properties file under "src" directory when I was using Eclipse. But in Android Studio, it won't work.
Here is the code that part of a class called BeanFactory,:
private static Properties properties;
static {
properties = new Properties();
InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
properties.load(is);
}catch (IOException e) {
e.printStackTrace();
}
}
In Eclipse, I located the the prop file under src, and it works just fine.
But in Android Studio, I've tried put the "bean.properties" file in several different directory. Such as /src, or/src/main/java, nothing worked out.
Where should I put the prop file? Is there any configurations that I should do for this?
Placing resources into assets is not acceptable in some cases. I solved this problem by packing required resourses into special jar file and placing this jar into libs directory.Thus you still can access them via standard Java technique.
There are two issues. In general resources are stored in a jar, with the compiled .class files.
getResource and getResourceAsStream are methods of a class. The resource is searched in the jar of this class (in general). So with inheritance getClass().getResource("...") might be dangerous.
The second, more grave pitfall is, that the path is relative to the package (directory) of the class, unless you use "/...".
Another way is to use ResourceBundle instead of Properties. ResourceBundle has a PropertiesResourceBundle for *.properties.
ResourceBundle properties = ResourceBundle.getBundle("bean");
try this:
1.put your own bean.properties file in app/src/main/assets
2.change you code to:
private static Properties prop;
static {
prop = new Properties();
try {
InputStream is = IWorkApplication.getInstance().getResources().getAssets().open("bean.properties", Context.MODE_PRIVATE);
prop.load(is);
} catch (IOException e) {
e.printStackTrace();
}
PS.IWorkApplication.getInstance() is define in my own application class.
Hope to be useful

Create File object of file from parent directory in java

I have this issue of accessing a file in one of the parent directories.
To explain, consider the following dir structure:-
C:/Workspace/Appl/src/org/abc/bm/TestFile.xml
C:/Workspace/Appl/src/org/abc/bm/tests/CheckTest.java
In the CheckTest.java I want to create a File instance for the TestFile.xml
public class Check {
public void checkMethod() {
File f = new File({filePath value I want to determine}, "TestFile.xml");
}
}
I tried a few things with getAbsolutePath() and the getParent() etc but was getting a bit complicated and frankly I think I messed it up.
The reason I don't want to use "C:/Workspace/Appl/src/org/abc/bm" while creating the File instance is because the C:/Workspace/Appl is not fixed and in all circumstances will be different at runtime and basically I don't want to hard-code.
What could be the easiest and cleaner way to achieve this ?
Thank you.
You should load it from Classpath in this case.
In your CheckTest.java, try
FileInputStream fileIs = new FileInputStream(CheckTest.class.getClassLoader().getResourceAsStream("org/abc/bm/TestFile.xml");
Use System.getProperty to get the base dir or you set the base.dir during application launch
java -Dbase.dir=c:\User\pkg
System.getProperty("base.dir");
and use
System.getProperty("file.separator");
What could be the easiest and cleaner way to achieve this ?
For accessing static resources use:
URL urlToResource = this.getClasS().getResource("path/to/the.resource");
If the resource is expected to change, write it to a sub-directory of user.home, where it is easy to locate later.
First of all, you can't get a reference to the source file path on runtime.
But, you can access the resrources included at your classpath (where you complied .class files will be).
Normally, your compiler will copy the xml file included at your srouce directory into the build directory, so at last, you could end up having something like this:
C:/Workspace/Appl/classes/org/abc/bm/TestFile.xml
C:/Workspace/Appl/classes/org/abc/bm/tests/CheckTest.class
Then, with your classpath pointing to the compiled classes root dir, you get the resources from this directory, using the ClassLoader.getResource method (or the equivalent Class.getResource() method).
public class Check {
public void checkMethod() {
java.net.URL fileURL=this.getClass().getResource("/org/abc/bm/tests/TestFile.xml");
File f=new File( fileURL.toURI());
}
}
One could do this:
String pathOfTheCurrentClass = this.getClass().getResource(".").getPath();
File file = new File(pathOfTheCurrentClass + "/..", "Testfile.xml");
or
String pathOfTheCurrentClass = this.getClass().getResource(".").getPath();
File filePath = new File(pathOfTheCurrentClass);
File file = new File(filePath.getParent(), "Testfile.xml");
But as Tomas Naros points out this gives you the file located in the build path.
Did you try
URL some=Test.class.getClass().getClassLoader().getResource("org/abc/bm/TestFile.xml");
File file = new File(some.getFile());

Categories