I am completely new to programming and I am now doing a project that I need to read a specific XML file in java. My code is using the absolute path of the file I need but I have to distribute the project to somewhere. That required XML file will not be in the project folder but in another folder which I will distribute with the JAR file of the project. Is it possible for it to get that path if I don't know where the user will put my program and the folder containing the XML file?
The program is supposed to run on Windows.
You have different possible solutions:
pass the file location as parameter to the main method (if you have a main method)
set an system property with the location of the file (you can do that with the -D option on the java command, with the syntax -Dproperty=value)
set an environment variable (with export command in linux)
put the file in the classpath and retrieve it with getResourceAsStream
access the file from an external server exposing it via HTTP
Related
I’m working on a background Spring service that runs from the command line using a nohup command.
I’m hitting the following error:
java.io.FileNotFoundException: class path resource [templates/] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/Users/gestes/Documents/workspace/bge/bge-proj/myProcess/target/myProcess-0.2.2.jar!/templates/
The jar file is being created and does exist at:
/Users/gestes/Documents/workspace/bge/bge-proj/myProcess/target/myProcess-0.2.2.jar
When I extract the jar file contents, there is a /templates/ directory.
Looking at the exception, there is an “ ! “ after the jar file name, and I thought that tells what it can’t find, but clearly, it is there.
What am I missing?
If in your code you are trying to access the folder using a java File, you cannot do that. You need to use an inputStream
This is because things inside a Jar are not actually files on the disk. They are compiled inside of a jar. Yes it may be there when you extract the jar, but it's not actually a normal disk file when the jar is bundled
I am developing a program that uses a sqlite file as a database. When I compile and test my program I haven't any problem:
Conection c = DriverManager.getConnection(
"jdbc:sqlite:/home/mehdi/my_database.sqite");
as you can see in above, the code shows a direct path that set to database file (this path is only in my system).
So it works fine, but my problem starts when I create an executable jar file of my program, if I create executable jar file and share it with other users, when they run the executable jar it doesn't work.
My first question: how do I set my database path for an executable jar file in my code?
My second question: is it possible for the database to be along side the executable jar? (and i can move my executable jar file with its database)
some_path/my_program_file.jar
some_path/my_database.sqite
The best option is externalizing the database path instead of hardcoding it, and letting the user choose where to put the actual sqlite file.
You could put the sqlite file in the same directory as the program archive, but please note that this does not really help in locating the file from your code, because relative paths are definitely resolved against the JVM (process) working directory, not the location of the JAR:
new File(".").getAbsolutePath()
There are ways to get the location of the JAR:
getClass().getProtectionDomain().getCodeSource().getLocation()
but they are deploy-dependent, so it's not a very robust strategy to rely on.
Most Java program are configured with external files put in well-known locations (like the current JVM directory or a .myapp/conf.properties in the user home), and individual properties can be overridden in the starting command line, as either system properties -Dkey=value or program arguments (there's a library to simplify this)
Java uses relative paths when you do not specify the absolute path. I'm not sure if it works for the DriverManager though. What this means is that if you call jdbc:sqlite:my_database.sqite it should look for my_database.sqite in the folder the jar is executed from. So if the user calls java -jar my_program_file.jar from the folder where the database is it will work. If the user calls the jar from another location it won't. To fix that, you have to grab the path where the jar is located, like so:
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
This was showcased in another SO post.
I have written a java program which different classes where during the process it generates lots of files (say txt files) and then reads the files and operates on them. I have made the project as a JAR file where I can run it from command with no problem as JAR is in the same directory.
However, I want to run this JAR file on a remote server where the PATHs are not the same, so then it generates error, because in my project for instance it should read a file from /Programs/Folder/here whereas in the server this cannot happen as there is no /Programs/Folder... directory. Do I have to change all the paths in my program according to the new location I wanna put my jar or there is another way around it?
I would appreciate your help.
Best wishes
I would think the best way is to pass the directory name where the files in as an argumrnt to the java command line.
Read it from the parameter args in main
This simplest and best solution is to change all of your paths in files inside of your project to be relative paths. You can also simply pass the directory you would like the files stored in to String args[] as parameters
what i prefer is i use relative path and then read relative path using classloader.try it.
At the moment, in my java program, I am accessing a file that is in the project folder. When I'm loading the file its path is "./src/package/package/file.txt". When I build the program into an executable it dosen't work.
I would prefer the files to be outside of the .jar, but in the same folder, how would I got about this?
Samishal
You can use a relative path if they are in the same folder, such as ./file.txt. That should carry over even with a compiled JAR.
Otherwise, if you're going to be using the same machine and are confident of the placement of the files, you could use an absolute path, however I don't recommend it.
You can use Class.getResourceAsStream to get the InputStream. It works for jar package too. It is not possible to access the file in jar file using File API directly.
InputStream ins = Class.getResourceAsStream("/gigadot/exp/resource.properties");
More details at http://blog.gigadot.net/2010/10/loading-classpath-resources.html
Because the relative path is relative to where your command prompt is when you execute the program, not from where the program lives.
You somehow need to tell the program where to find resources. Most people use a .sh/.bat script to figure out where the script itself lives, and either pass -D flags or set the classpath based on that location.
as a note, I $0 gives you the script as it was run on the command line in linux (it could be relative or absolute), and you can use dirname from there to find it's directory, and alter the java command line.
in windows %~dp0 gives you the directory of the batch script which was run, and you can use that to form your java command line.
I found a way to set the classpath for the resource file. I am using a batch file to run my JAR. I have set the path like this
echo off
cd..
set BASEDIR=E:\SampleSourceCode
java -Dfile.encoding=UTF-8 -cp %BASEDIR%\lib\*;%BASEDIR%\data\;%BASEDIR%\resources\ com.example.main.Main
But now when I do any changes to the contents of the resource folder (properties file), the GUI does not recognize the database from the data folder. How do I proceed?
I think you're asking:
Q: If I change the contents of an external properties file, will a running Java process automatically update the property files originally read from the file?
A: No, it won't.
The general solution is:
Modify the property in your program
Have your program re-write the external properties file
the best way to set a library to execute a .jar file that requires outside resources, is simple use the following batch file:
javaw -Djava.library.path=<path to library> -jar <name>.jar
in this way, anything that you change will still be accepted as long as it occurs in your path to library.(or in the jar itself.)