I developed and tested my program on Eclipse Indigo. No problem finding the properties file when run.
I created a runnable jar using Eclipse export.
The program cannot find the properties file when the program is run from the jar.
The properties file is not in the jar, it is in a subdirectory of the directory where the jar is deployed.
As noted above, this directory is on the classpath in the Eclipse run configuration.
C:/myApp/myApp.jar C:/myApp/properties/myApp.properties
props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("myApp.properties"));
Do I just need to edit the Jar manifest to put the config directory on the classpath?
properties.load(this.getClass().getResourceAsStream(configFileSrc));
This should work.
In my case, configFileSrc = "/apiconfig/appconfig.properties"
I had to add staticresources dir in the build path.
Thanks
Yes. Make sure you specify the path of the config directory relative to the directory where the jar is located. Since you said above that the config directory is a sub directory of the jar location, this will probably just be
<configDir>
where <configDir> is your configuration directory name.
You will also need to use an absolute resource name for the lookup, by adding a slash to the properties file name:
props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("/myApp.properties"));
This is because the relative name your specify will have the package path of the class appended to it, which you don't want.
Is there any specific reason you need to use the contextClassLoader? A simpler invocation would be to use the classLoader of the class containing the lookup. And, since the class can delegate to it's classLoader, you can simply say:
props.load(getClass().getResourceAsStream("/myApp.properties"));
Finally - have you considered putting the properties file in the jar itself? If it's not going to change at all, this would be a better option. You wouldn't need to specify the classPath in that case. Note that if you want, you could put it in a sub-directory in the jar , but you would have to change the resource path you looked for, and again use an absolute resource name
Here is some info on absolute and relative resource names:
http://docs.oracle.com/javase/1.5.0/docs/guide/lang/resources.html
Hope this helps!
The real problem here is that you need to make up your mind where your application is going to load the properties from when the application is deployed.
(How it works in Eclipse is kind of irrelevant ... unless you expect your users to install Eclipse to run your app!)
If you want it to load the properties from the JAR file, they need to be in the JAR file.
If you want it to load the properties from the file system, they need to be in the file system. That means you have two subsidiary issues:
Where in the file system will your application look? Bear in mind that this has to work for all of the OS platforms you support, and that different OSes have different conventions for where "configuration settings* should be stored.
Is there a default version of the properties file, and how will you install it?
If you want to load it from the CLASSPATH and not the JAR file, that means you cannot make your application an executable JAR. (Running as java -jar ... will ignore all attempts to set an external classpath.)
If you opt for a non-executable JAR file AND loading the properties from the classpath, you have more problems:
How do you set the classpath?
How do you install the properties file "alongside" the JAR file?
Are there security concerns with a (potentially) user writable directory on the application's classpath?
This is probably the worst option.
Once you have decided how (from where) your application needs to load its properties when deployed, the code for implementing your scheme is relatively straightforward. (Modulo the problems mentioned above.)
You could even combine a couple of options; e.g. look for the properties file in the file system and then fall back to a "default" properties file in the JAR file. Or you could make the file system location of the properties file a command line option or supply it via an environment variable or via -D and the system properties.
Related
Need help in understanding about classpath and file path. We have a third party jar where they need to refer commons-logging property file . The have specified in below way to refer it.
String fileLocation="commons-logging.properties";
If i place the file inside jar it works fine, which is not permitted. IS there any way to make the jar refer the file outside the jar. I cant make any code change. I tried to search for solution, but couldnt get what i want.
Everything depend on how this jar trying to read this file. If it tries to open it as a resource, via ClassLoader, then it should be inside your jar, but if like a external file, then no problem to put it outside and use absolute path into that file.
So just check this functionality and if you need to use file from outside - you have to change it and open this file via Path or File classes.
You need to put the properties file on the classpath of your Java application. You already did this by adding it to the root of the jar file.
One possibility is to add a specific folder, e.g. config, to your classpath. The properties file should then be placed in that folder.
Another option is to put the properties file into its own jar file and add this to your applications classpath.
But in the end I prefer the first option to add the file in a folder which is available in the classpath.
i hv created the .jar file by building my project in netbeans.
The .jar file exist in "dist/myproject.jar". But when i move it to
any other system will it find the paths specified for images etc in
project?
As i am giving the paths like
(C:/Users/Lucky/Documents/NetBeansProjects/CoverageAnalyzer/src/coverageanalyzer/icons/icon.png).
OR When i write path just to approach root directory as
(icons/icon.png), so then also?
Summary: What is the actual way that i can write/copy my .jar file to
any other system without spoiling the paths and program run correctly
on any other system. Thanks in advance.help will be appriciated
You can use one of the following approaches:
Use relative paths (relative to the executable file location) instead of absolute paths.
Use paths under a known absolute path (an installation folder, path from environment variable / configuration file / registry key, the user's directory (user.home) etc.)
Use resources embeded into your jar. See Class.getResource() and Class.getResourceAsStream()
Note that you should consider cross-platform (Windows/Linux/Mac) and resource hiding issues when selecting a suitable approach.
The solution is to put the auxiliary files as resources into to jar. The program must then load them from the class path instead of the file system.
Have a look at Class.getResourceAsStream.
We have a jar which needs to read a properties file. The properties file needs to edited without rebuilding the application, therefore it is excluded from the build.
In order for the application to see the properties file, it is placed it a folder which is on the java classpath. The format of the Windows command line used to run the application is as follows:
java -cp application.jar;.\lib_folder\*; com.company.Start
Java correctly picks up all the jar files in the lib_folder. The properties file is placed in the same folder, but the application cannot see it and is throwing a FileNotFoundException. Are we doing anything obviously wrong?
Thanks very much
The class resolution happens starting from the path given in cp. If you provide .\lib_folder in the classpath without the star, and the properties file is inside this folder, then it will be picked up. Currently the properties file itself is in the classpath.
it is placed it a folder which is on the java classpath
Your class path only contains JARs, the notation .\lib_folder\* means every jar from a folder, but not the folder itself.
The properties file is placed in the same folder, but the application cannot see it
The folder itself need to be added, however I suspect you shouldn't be adding files to the "lib" directory and you should be using a different directory like "config"
and is throwing a FileNotFoundException.
When you try to obtain a Resource you get null not this exception. Try the following
InputStream is = getClass().getClassLoader().getResourceAsStream("resource.properties");
This returns null if the file is not found.
Are we doing anything obviously wrong?
FileInputStream looks for a direct file, it doesn't use the classpath.
If you're using ResourceBundle to read the property files, then just add the top level project containing the .properties files to the classpath.
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.
I have a maven project with typical project structure. At the base of the project, I have a directory names res that has some resources (> 500 MB).
I am trying to use
this.class().getClassLoader().getResourceAsStream("res/xxx")
this code fragment to read from that folder, but it returns a null resource stream.
I have a few workarounds below, but none of these are acceptable due to reasons explained below.
I can move the folder to {base}/target/classes, and it will be read, but it will also get cleaned when I do a mvn clean. Hence, this approach doesn't work. For some reason, specifying the path as ../../res/xxx also doesn't work.
I can move the folder to {base}/src/resources, but then it will get copied to target/classes and the jar. Hence this is also not acceptable.
Though I am open to trying some other java APIs, I may have to use the class loader mechanism only as there is some external library component that is also trying to access the res folder using the similar approach.
Is there some way I can read the res folder from projects base directory? Is there some setting in pom.xml file that can help me with that?
Use this.class().getClassLoader().getResourceAsStream("/res/xxx") and then you will be reading from the root of the classpath irrespective of the actual file/folder location in windows or Linux. This is actually one of the safest ways to read files especially when you do not know how your application will eventually be deployed.
It means though that your classpath must include the parent of res and that res/ must be copied over when you deploy your app
Otherwise, if you want to use relative paths, try this snippet (taken from this SO answer):
String filePath = new File("").getAbsolutePath();
filePath.concat("path to the property file");
If you use this.class().getClassLoader().getResourceAsStream("/res/xxx"), it is going to try to load resources from the classpath. If that's not want you want to do, you're going to need to specify an absolute path.
Resource on Classpath
If you don't want the resource built into your JAR, I'd suggest having a different maven project with the file in it, under the src/main/resources directory. This will create a jar file with the file in it, which will be ~500MB.
After this, you can include a dependency on this project in your project containing your application code. This will then be able to reference it from the jar file using getResourceAsStream(...).
If you don't want this large jar file to ship with your application, make sure you mark the dependency with <scope>provided</scope>.
File from Absolute Path
You will need to take the file location as a parameter in your main method, and then use new File("C:\\path\\to\\your\\file.txt") and then use a FileReader to read it in.