Java get path of executing jar without .jar file - java

I am trying to export my app into jar using intelij Idea artifacts. I export everything except for resources (14,5GB is in my opinion too much for .jar file) so I have put /res folder inside same folder as jar.
Right now my structure looks like this:
/SAR.jar
/res/colors/
/res/icons/
/res/map/
However I cant access this resources. I am using the following code to get path:
dir = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath() + "/res/icons/");
It works when running from IDE and it prints correct location. But when I build an artifact and run it through cmd I get the null pointer and it prints this path: D:/JavaProject/SAR/out/artifacts/SAR_jar/SAR.jar/res/icons. But my resources are not inside jar file they are only in same directory.
Any ideas? I have done only android projects in path and I simply cant get this resources system with jars to work.
Thanks in forward

You are trying to access the ressources with a path dependent of your source code location, which is obviously not the case since you separated the code (or bytecode in the case of the jar) and the ressources. You must access them with a path relative to the jar or an absolute path.
I think you just need the following path (if the jar was ran from the directory containing the jar) :
new File("res/icons/icon.png")

Related

Getting the location of a folder next to my .jar file

In a program I am making, I need to access images in a folder placed alongside it. The program works fine when I run it with Eclipse, but when I export it to a .jar file, it does not get the location of the folder properly.
File roomF = new File("Assets/Rooms/1/0.png");
In the IDE, roomF refers to the correct location:
C:\Users\[Username]\Desktop\Eclipse Java\[Project name]\Assets\Rooms\1\0.png
However, in the .jar file, it refers to this:
C:\Users\[Username]\Assets\Rooms\1\0.png.
How can I fix this?
You should not have resources outside of your JAR or dependencies that need a local path in order to work. Create a resource folder in your project and load the file from there.
There are two solutions to this:
Place your JAR at:
'C:\Users[Username]\Desktop\Eclipse Java'
This way, when you are accessing Assets/Rooms/1/0.png, it points to the correct location.
Make a folder where you will place your JAR everytime. Create the path 'Assets/Rooms/1' in the folder and place your file 0.png there, hence you wouldn't be needing to place your JAR each time you make a new one as said in step 1.

How to give relative path in a executable jar?

I have a Spring app that I am deploying as a .jar.
The app has to write to a folder located in /src (precisely /src/main/resources/patches). I have this path directly in the code.
In application.properties: PATCH_DIR = src/main/resources/patches
The app has to also read a json file from src/main/resources/myJson.json, the path also being directly written in the code.
Prior to deploying, while running from the IDE everything goes well, the app sees the file and the folder and reads and writes correctly.
After building the .jar the paths change, the file is located in myJar.jar/BOOT-if/classes/myJson.json and the folder is respectively in myJar.jar/BOOT-if/classes/patches.
How can I specify these paths in the code in a way that even after building the jar they stay relevant to my application?
Edit: I can specify the path of the file as: PatchApplication.class.getClassLoader().getResource("myJson.json").getPath();
This should solve the problem, as the path is relative to the class and not to the root of the project, but it does not improve anything.
You should specify a path in your file system,instead of the path inside a .jar.When you run your app ,it would access the given path.
generally all the classes goes to classes folder in jar.
all the classes ending after src/main/java goes to /classes/ folder
and similarly all the resources file
Eg. your source folder have src/main/java/com/mypack/ABC.java than you will find this in jar as /classes/com/mypack/ABC.class .
Try using /classes/patches and /classes/myJson.json.
This should work

Launch .jar with config outside of jar, but be able to do it from ANY current directory

I've been wrestling with a particular problem. I have a Java program in a .jar file, and I have a lib directory and a config directory outside of the .jar, but in the same directory as the jar itself exists in.
I am trying to reference config/foo.config from within the code. Referencing it as a relative file works if I'm in the same directory as the jar. I've also tried using getResourceAsStream and making sure config is in the classpath.
So far, so good, but I also have to be able to launch the .jar from any directory.
So, if my structure is like so:
/prog/util/myprog/myprog.jar
/prog/util/myprog/config
/prog/util/myprog/config/foo.config
/prog/util/myprog/lib
(and a whole bunch of 3rd party jars within lib)
How do I correctly set up the classpath in my Manifest file so that config can be referenced?
The classpath in my manifest looks like so:
Class-Path: config/ lib/jar1.jar lib/jar2.jar (etc)
I am currently using getResourceAsStream("/foo.config").
This all works if I am in the /prog/util/myprog directory and run:
java -jar myproj.jar
However, I cannot, say, be in /prog and run:
java -jar util/myprog/myprog.jar
When I do this, the config file cannot be found.
How do I solve this issue?
EDIT: Some additional notes based on comments/suggestions, though I'm not sure this is feasible:
1) We can't use an absolute path for the file system, we don't know where the program will be stored, just that the config directory will be in the same directory as the jar.
2) I would like to be able to have something that works both when the code is jar'd, but also would work not-jar'd such as when I'm running in debug mode in Eclipse. At that point, the config directory is a sibling of the src, bin, and lib directories.
EDIT Part 2: Ok, between a colleague and myself, we came up with the following:
String configDirectory = new File(QueueMonitor.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent() + "/config";
When we are in Eclipse and running in debug mode, the File object points to the bin directory, so getting the parent then appending "/config" works for our needs during development/testing.
Likewise, from a .jar file, the File object points to the jar itself, so getting the parent and appending "/config" gives us what we need as well.
I'm a little hesitant, though. I'm wondering if there's some potential problem or unintended consequence that I am not seeing in this solution. Any thoughts on that?
You should be able to use the Finding the path to a jar from a Class inside it? technique to find the location of your jar. From there it's just a matter of climbing in/out of folders.

How to export a a jar file correctly?

I mean I tried to export my java game like this : EXPORT>Jar File but if I do this it doesn't start.
And if I export to executable jar file it doesn't export my resources into the jar file.
I mean if I play the game in eclipse the sound works. But if I export to executable jar file it doesn't work. I guess it is not exporting the sound too.
This is the code I tried to use to launch the jar file :
java jar -cvfe ProjectZero.jar Main.Launcher Main.Launcher.class
Here are two solutions for solving this problem, hope this is clear enough:
Solution #1 - You want your resources outside of the JAR file
Just copy/paste the folder containing your resources in the same folder containing the JAR file. (Make sure the directory matches pathes mentioned in the application.)
Solution #2 - You want your resources inside the JAR file
If you want the resources to be directly included in the JAR file, you could use the function getResource() to get the images/sounds. Then make sure that resources are visible in both: "/src" and "/bin" folders.
For example, if you have the following application code:
ImageIcon myIcon = new ImageIcon(this.getClass().getResource("/resources/icon.gif"));
your file should be visible in:
/myApp/src/resources/icon.gif
/myApp/bin/resources/icon.gif
Then you can export your application as a JAR file, it will contain the resources.

Access .properties file at same level as working directory

I am working on a Java project that I want to deliver to my client as a .jar file. However, I want to allow the client to be able to change the parameters of the program without having to recompile or recreate the .jar. Basically, I want to be able to load .properties files from classes inside the .jar but locate those .properties files outside of the .jar and even outside the working directory.
I have been testing my attempts inside Eclipse, which might be causing some of the problem but I don't see how at the moment. My setup is a follows. I have one project that contains a few classes that I build a .jar file from. I have a .properties file that is used to create a ResourceBundle whenever a class for the .jar is created. I specify that an additional directory, "conf/", be included in the .jar classpath within the .jar manifest.
Once the .jar file is built, it is copied to the lib/ directory of another project which I am using for testing. This test project includes the .jar file as a library ("Add External Jars..") in the Java Build Path. The .properties file is located the conf/ directory which is at the same level as lib/, src/, and bin/ but I am unable to accces it there. The only way I have been able to get it to work is to locate conf/ under src/ (and bin/) but I would like to be able to use it up one level. Is this possible?
Here's the entry in the .jar manifest file...
Class-Path: ../conf/
Here's the ResourceBundle call that I tried (didn't work)...
rb = ResourceBundle.getBundle("..conf.BaseProject");
Here's the directory structure that works now (names have been changed to protect the innocent)...
/Project
/Project/bin
/Project/bin/conf
/Project/bin/conf/BaseProject.properties
/Project/bin/TestClass.class
/Project/lib
/Project/lib/BaseProject.jar
Here's the directory layout I want (again, file names not important)...
/Project
/Project/bin
/Project/bin/TestClass.class
/Project/conf
/Project/conf/BaseProject.properties
/Project/lib
/Project/lib/BaseProject.jar
You can get it using the Classloader.
I like Spring's ClassPathResource

Categories

Resources