Set a Path for database file in java - java

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.

Related

Will my executable jar include files I added in the file structure?

I'm trying to comprehend how creating executable jars and file paths work, so please bear with me.
I have a small program, which is supposed to upload some Firmware to Servers. These Firmwares have a combined size of about 650MB. All in all, the Project Folder takes up about 2.2GB of space.
In the program itself, I have some Strings that refer to the name of the folder that contains the firmware.
"src\\com\\java\\myProgram\\data\\bios_fw\\"+biosFWPath+"\\"+biosFW
When testing in the IDE, this works without problem.
So here's my question(s): Will this still work if I build the program as executable jar? I have already noticed that the jar I created holds only about 450MB. Does it even contain the firmware then? And if it does, will the program be able to find the path specified?
Furthermore, what would be the proper way of "installing" these folders together with the jar on a Users PC?
Thanks!
As a .jar file is a java archive file, you can open it and look yourself as we don't know how you build your .jar.
But considering the future, I would remove the absolute path and use a relative path to a directory where you can insert the firmware in case the fw got updated, so you don't have to build your program each time.
The proper way, when you want to keep the FW in your project is using ClassLoader.

Problems about distribution of java project

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

How to get location of runnable .jar File when run from GNOME

I am developing a small Java application using Swing, that is supposed to run on Windows/Linux and MacOS.
Eventually it will ship as a runnable jar with some config files in the same folder. To load them I need the path to the folder the jar is stored in within the program.
There are already a couple of threads like this one or this one.
My problem is, that all the solutions discussed there work fine, when I run the program from within eclipse or call the runnable jar from a terminal like so:
java -jar /path/to/jar/jarfile.jar
However when I click on the jar file in Cinnamon or Gnome (which is what most of the users will know to do), I do not get the correct paths. (MacOS users report the same issue)
Here is what I've tried so far and what the output is when run via double click (all those display the desired path when run from eclipse or a terminal):
ClassLoader.getSystemClassLoader().getResource(".").getPath()
Output: file:/usr/lib/jvm/java-6-openjdk-common/jre/lib/ext/pulse-java.jar!/
SomeClass.class.getProtectionDomain().getCodeSource().getLocation().getPath();
Output: ./
System.getProperty("user.dir");
Output: /home/myusername
Is there any other way to do it or am I doing something wrong when exporting the jar? Any help would be appreciated!
Cheers
Nick
Make it simple, and use a startup script (.bat/.sh file) to run your application. This startup script will get the path of its own location in the filesystem, and pass it as an argument or system property to the Java application. This has the additional advantage of being able to pass other arguments, like the size of the heap, etc.
On windows, %~dp0 is the path of the directory containing the executed bat file. On Unix, you can use $(dirname $0).
You could store all config files as resources in a jar, and copy them to files in home.dir + ".AppName/".
Painful as it is, the Preferences API, Preferences.systemNodeForPackage, seems the wisest alternative, if there is little structured config data. There is an inputStream method for import; your initial config template could be a resource in the jar.
Just get the class path using System.getProperty("java.class.path") and scan it for your ".jar" name. Note that path separators are OS dependent (File.pathSeparator)

Java file access

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.

Create folder in jar file dir

Im looking for a solution to create a new folder in the folder, where the .jar file is located.
So if i have a test.jer file in C:\test\temp I would like to be able to create a new folder (newFolder) : C:\test\temp\newFolder.
Anyone know how to do this.
I have tried to use
System.getProperty("user.dir").
But this only gives me the correct, if i double click the jar file.
I need it to be run from a scheduler and then the location is changed.
In general you cannot easily figure out where your JAR file is at runtime. The execution environment of your VM can tell you the user directory (as you said), but that is the directory from which the VM was started. So if you double click your JAR, that's actually the directory where the JAR is. But if you call java on the commandline, for example
c:\some\directory> java -cp c:\temp\test.jar main.Class
then "user.dir" will contain "c:\some\directory".
This lack of information is intentional, because it allows the VM to transparently load classes from different locations.
Your best choice to do what you want would be to pass the directory of choice as a commandline argument. And in the worst case, you could use "user.dir" as default. But what the best solution really is depends on why you want to place the directory where the JAR is.

Categories