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.
Related
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 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.
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.
I just realised that I cant use files from outside a jar archive. If thats the case then when I deploy apps that need other documents, say an xml file, do i send the xml alongside the app or there is a way out..
Thanks
I'd suggest that you simply include the required resources within the .jar file. You can have any type of files in there, including .xml-files.
Related questions:
How do I create a jar file, which includes xml and html files?
How do I read a resource file from a Java jar file?
adding non-code resources to jar file using Ant
How to bundle images in jar file
If you really prefer to load "external" files you'll have to be more clear about the problems of opening them outside of the jar file.
But this does not work if you also want to "write" to one of those files!!! If you only want to read, put everything in there. The convention is to create a package called resources in the root of you source code ("src" for example (I use Eclipse)), and just put everything in there, and then use class.getResourceAsStream(). But if you want to write to a File, for example you want persistence for User's options or other stuff, you're gonna need to write from within the .jar, to a File outside the jar, which has a lot of permission considerations and stuff, but It's possible. use System.getProperty("java.class.path"), and you can write files just next to your jar File...
I was wondering if is possible to find the content in an XML file placed in a jar thath is placed in a ear too. It would help me find the properties of java beans.
Up into the ear I can iterate through documents and see what's inside, but if it is a jar I can't iterate documents inside that.
Someone can give me some advice?
From the ear file you should be able to extract the jar file. Then you can use WinZip, 7 Zip, etc to do explore the jar file contents the GUI. Or you can run the jar tf command to extract the content of the jar file in command line. If you don't have any of these tools and using windows, then you can rename the jar file to a .zip and windows should be able to explore it (most of the cases it works).
Edits - I am not sure if you wanted to do it using Java. In that case you are looking for JarFile. I found an example of it here for exploring Jar contents programatically.
so i just tested the thing you want to do - and as long as the JAR lies in the classpath of your EAR, then you can access any file within it. basically the try to look up the file from the context-root of your application.
for example if in your JAR the file abc.xml resides under the package a.b.resources, then from say a servlet in your EAR you can access it using :
InputStream is = this.getClass().getClassLoader().getResourceAsStream("a/b/resources/abc.properties");
Yes, you can read any file that is packed into zip file. It does not matter how many nested zip file you have to open on your way. Use ZipInputStream, get needed ZipEntry, read it content. If it is still zip, open it and do it again and again until you access the required resource.