Resource path change during jar execution - java

I'm trying to read a json file in a Resources directory and I use the following:
jsonObject = this.readJson(this.getClass().getClassLoader().getResource("jsonFileName").getPath());
In the IDE it runs correctly but when I build thw jar and try to run it by java -jar jarName I get a "File not found" Error and when I checked the path, it looks like this:
...projectName/target/projectName-1.0-SNAPSHOT.jar!/kb/is/identity.json
When running on the IDE the paths looks like this:
...projectName/target/classes/kb/is/identity.json

It's important to use getResourceAsStream, not getResource.
Have a look at How getClassLoader().getResourceAsStream() works in java

getResource("jsonFileName") - in this case root directory is project name using it under Idea, but when you run it under jar - I think that root path is User Home.
If I remember correctly, you can fix it with using / in resource path.
E.g. when using Maven, you have a resource directory. You have identity.json in the resource root. Using getClass().getResourceAsStream("/identity.json") receive this file (in Idea and in jar), because when you build a jar, all resources are copied to the root of the jar file.

Related

Get project directory from java classes

I have a problem with System.getProperty("user.dir") giving different directory when run by IDE and when I manually compile & run it in cmd. My thing is this, I have project structure like this:
project
- exports
- src
- main
- java
- Main
- file1
- file2
One of the args in main method is the name of one of those 2 files, that I then access.
When I configure my run in IDE it works like a charm - the directory I get is C:\Users\**\**\**\project and it is able to read and write to the file.
But when I compile it in cmd javac Main.java and then run it, I get C:\Users\**\**\**\project\src\main\java and because of that, I am unable to access the file without having to modify the path.
My question is, is there like a golden way, that would work for both these cases, without me having to alter the returned path?
EDIT:
For clear understanding, I know what System.getProperty("user.dir") returns, but my question was, if it is possible to get the same result somehow with using Path or if I have to get the path and edit it, so that it will end in project directory?
in IDE I get: C:\Users\petri\Desktop\CZM\bicycle-statistics
in cmd: C:\Users\petri\Desktop\CZM\bicycle-statistics\src\main\java
I want to get the same path in cmd, that I got in IDE.
I tried using Paths.get("").toAbsolutePath(), but it is the same thing.
So, what I did is this:
Path path = Paths.get("").toAbsolutePath();
while (!path.endsWith("project")) {
path = path.getParent();
}
And it works, but I am trying to ask, if there is some more elegant way, because I will have to defend my solution in front of my supervisor.
Normally your IDE will build source files in src/main/java and write the class files out to some other directory, like target/classes.
If your IDE built the project that way, then you can run it from the command line by switching to your project directory (cd C:\Users\**\**\**\project using your example) and then running:
java -classpath target/classes Main
assuming that target/classes is where your IDE put the files. If you really do have the class files in the source directory, then use -classpath src/main/java.
If you always run the program from the project directory, then you can assume within the program that the current directory is the project directory. You don't even have to use user.dir then, just use relative path names for everything, e.g., path/to/whatever.dat will automatically resolve to C:\Users\**\**\**\project\path\to\whatever.dat.
One of the args in main method is the name of one of those 2 files
Then make sure you enter the name correctly.
E.g. if the current working directory is the project folder, then name file1 will refer to the file1 file. If the current working directory is the java folder, then the argument to the program needs to be ..\..\..\file1.
That is because you give relative file names, which means they are relative to the current working directory.
Alternatively, give a fully qualified name, then the argument will be the same, regardless of what the current working directory is:
C:\Users\**\**\**\project\file1

Java find the relative path of the configuration file in the war file

I am trying to access the config.properties file which was previously placed in the config folder. after some research, I moved it to the WEB-INF folder. but even after I moved it, it still return java.lang.NullPointerException whenenver I run my my program. code used to store some password information as below:
ClassLoader resource = ConnectionManager.class.getClass().getClassLoader();
URL path = ConnectionManager.class.getClass().getResource("/WEB-INF/config.properties");
props.load(new FileInputStream(path.getFile()));
String passwordds = props.getProperty("datasource.password");
these are the codes that I found and I try to use it but still I got the null exception.
I cannot use absolute path due to this project will be deploy to production server as in .war file. please advise what is the best way as I am still beginner.
You should check the war your build tool generated, and find where your config file really are.
For maven project, the default resource dir is /src/main/resources/
So /src/main/resources/config.properties will be put at /WEB-INF/classes/config.properties in a war.
You can use getClass().getResourceStream("/config.properties") (getResource sometimes not work will in j2ee environment) to get it.

Using relative path in a maven project

I have a maven project with these standard directory structures:
src/main/java
src/main/java/pdf/Pdf.java
src/test/resources
src/test/resources/files/x.pdf
In my Pdf.java,
File file = new File("../../../test/resources/files/x.pdf");
Why does it report "No such file or dirctory"? The relative path should work. Right?
Relative paths work relative to the current working directory. Maven does not set it, so it is inherited from whatever value it had in the Java process your code is executing in.
The only reliable way is to figure it out in your own code. Depending on how you do things, there are several ways to do so. See How to get the real path of Java application at runtime? for suggestions. You are most likely looking at this.getClass().getProtectionDomain().getCodeSource().getLocation() and then you know where the class file is and can navigate relative to that.
Why does it report "No such file or dirctory"? The relative path should work. Right?
wrong.
Your classes are compiled to $PROJECT_ROOT/target/classes
and your resources are copied to the same folder keeping their relative paths below src/main/resources.
The file will be located relative to the classpath of which the root is $PROJECT_ROOT/target/classes. Therefore you have to write in your Pdf.java:
File file = new File("/files/x.pdf");
Your relative path will be evaluated from the projects current working directory which is $PROJECT_ROOT (AFAIR).
But it does not matter because you want that to work in your final application and not only in your build environment. Therefore you should access the file with getClass().getResource("/path/to/file/within/classpath") which searches the file in the class path of which the root is $PROJECT_ROOT/target/classes.
No the way you are referencing the files is according to your file system. Java knows about the classpath not the file system if you want to reference something like that you have to use the fully qualified name of the file.
Also I do not know if File constructor works with the classpath since it's an abstraction to manage the file system it will depend where the application is run from. Say it is run from the target directory at the same level as source in that case you have to go one directory up and then on src then test the resources the files and finally in x.pdf.
Since you are using a resources folder I think you want the file to be on the classpath and then you can load a resource with:
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("<path in classpath>");
Then you can create a FileInputStream or something to wrap around the file. Otherwise use the fully qualiefied name and put it somewere like /home/{user}/files/x.pdf.

How to get the absolute path of the executed jar?

How do I get the location of the executed jar? I found a lot of solutions but none of them work for me. When I run them in my IDE everything is fine. As soon as I build a jar file and run it with java -jar myapp.jar the output is like /.../myapp.jar!/foo/bar
I will run the code in myapp.jar - not in any library.
Location of jar: /home/me/dev/myapp/myapp.jar
Expected output: /home/me/dev/myapp/
I don't want the working directory as I would get with System.getProperty("user.dir");
Why I want to do this:
I want to store and load a file beside the actual jar. Like
/home/me/bin/myapp/myapp.jar
/home/me/bin/myapp/license.key
I want to avoid storing the file into some generic folder like System.getProperty("user.home");. And I don't want to store the file within the jar file.
java.nio.file.Paths.get(".").toAbsolutePath() will return absolute path to current directory.
I use something along these lines:
[YourClass].class.getProtectionDomain().getCodeSource().getLocation().getPath()
Regards

geting error in specifying class path when running program from cmd

I am trying to run program from command prompt
Here is my director structure
In the classes directory i have this structure
In the email folder i have two properties file general-mail-settings.properties and customer-mail-settings.properties
Now when i run the command
D:\vintnes\lasses>java -cp ".;..\dependency-jars\*" com/softech/ls360/integration/BatchImport vintners
Then i get the error that
java.lang.Exception: Email Properties File not found: src\main\resources\email\general-mail-settings.properties (The system cannot find the path specified)
at
...
I tried this to specify path
java -cp ".;..\dependency-jars\*;.\email\*.*" com/softech/ls360/integration/BatchImport customer
But still i am getting the error. I tried ;email\* and \email\*, but still i am getting the error. How can i specify path so program get run?
Thanks
You put a path to src/main/resources in your code somewhere. This is a directory used by Maven builds to hold "resource" files (files that aren't code but that should be copied into the finished artifact, like configuration files or media). The contents of src/main/resources are copied directly into the root of the artifact as-is, so in this case, the email directory is copied straight into your classes directory. Remove the src/main/resources part of the path from your properties lookup.

Categories

Resources