I have an application that I've developed. Currently it is deployed with all its config files (including log4j.properties, as used by some external libs I use) in the same dir as my application.
So, I have a bin dir, containing my app.jar, plus a few properties files, plus a lib dir with all my external jars. The external jars are specified in a classpath specified in the app.jar's manifest file.
Now the powers that be have decreed that the new structure will be a bin dir with just the app.jar, with a lib dir at the same level (i.e. ../lib, relative to bin) for external jars and a ../etc directory for configuration files.
Easy enough, I thought -- I changed all the classpath paths from ./lib/<jarname> to ../lib/<jarname>, and added ../etc to the classpath as well.
Problem is that now any jars that use log4j don't work -- they don't see the log4j.properties file -- because, I suspect, the classpath for app.jar doesn't affect the classpath for the external jars (maybe?), and previously they were finding it simply because it was in '.'.
Any thoughts?
You can put the log4j.properties anywhere as long as it is in the classpath. so, as #skaffman suggested, put the log4j properties file in the etc directory which is already in your classpath.
An alternative to using PropertyConfigurator is to set this syetm property while running your app.
-Dlog4j.configuration=log4j.properties
So, the issue is that Log4J now doesn't find the configuration file (log4j.properties) automatically anymore?
As far as I know, Log4J by default looks in the directories that are in the classpath for the log4j.properties file. Try adding the ../etc directory in the classpath in the manifest file of your JAR.
See also Default Initialization Procedure in the Log4J Manual, it explains how Log4J looks for the configuration file and how you can change this.
log4j.properties has to be somewhere in the default package, which in your case probably means in a JAR file somewhere in the root directory of that jar file.
A better solution would be to stick it in the etc directory, and then explicitly configure log4j to use it from that location. You can do that using PropertyConfigurator - invoke that when your application starts up, by filename, URL, whatever suits you best.
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 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 want to place ABC.properties file in a directory in the classpath ahead of cmbview81.jar .
cmbview81.jar already has ABC.properties file in it. I extracted the file made some changes and made new ABC.properties file and now want to set its path ahead of cmbview81.jar file so that application will not point to the file which is in cmbview81.jar file.It should use new ABC.properties file.
I tried solutions provided here How to place a file on classpath in eclipse? but didn't work.
Put it in a separate Jar file and see to it that this Jar file is included in front of the existing Jar file in the classpath specification. The order of specification of the Jar files in the classpath is significant (it's the same idea as directly using the CLASSPATH variable).
You could also put it in your src somewhere, but just make sure then that your src folder occurs before the Jar files in the Order and Export tab of the Eclipse Java build path configuration.
I have a jar in the classpath of my server which contains the log4j.properties file on root of the jar for logging of the code. When the code in the jar runs the logging for the code is not occuring. When I analyzed the problem using java -Dlog4j.debug option I got to know that the log4j is loading the log4j.properties file of axis-ant.jar (this also is on my classpath) and using it instead of my jar's property file.
When i subsequently removed the axis-ant.jar from the classpath my jars log4j.properties file was picked immediately and logging for my code occured.
Can somebody please explain why is my log4j.properties fle not being loaded while axis-ant.jar is present?
Surprisingly the same jar with axis-ant.jar present in classpath is running with proper logging successfully in another server.. both the server have the same java 5 version installed and same version of log4j jar
You should have a look at the log4j manual. The section "Default Initialization Procedure" describes how log4j will try to find the initialization file and explains possibilities to match a special configuration (e.g. by setting the system property log4j.configuration).
If you do not want to do any special configuration you have to ensure that your configuration file will be the first one found on the classpath.
The properties file is picked up from the jar based on the order in which the jar is found in classpath by your application server. Now there is no way to conclusively tell the jar from which the properties file is to be loaded.
To get around this problem most projects include your log4j.properties file in the server classpath itself. This way this file is the first properties file to be loaded and this is the one which your logging code gets.
I'm note quite sure but it could be an order problem. Whichever log4j.properties is loaded first/last would win (I'd have to check that).
Possibly because axis-ant.jar comes before in classpath the your own jar. I assume putting your jar before in classpath then axis-ant.jar should help
I was thinking to use log4j for my standalone java project.
Is it possible to use it for java project(not a web app).
If its possible then how should I be able to initialize the properties file and where should
I put the properties file(directory structure).
Any help is appreciated.
Yes, it is possible, we do it all the time. You just need a log4j.properties file on your classpath, which in most cases means in the base directory of your jar file. If you wish to have multiple properties files with differing configurations, you can create a properties configurator in some entry point before your first logging statement.
Yes it's possible.
If you're planning to create a jar file.
Make sure that your log4j.properties is found in your classes folder in jar file.
Make sure that your log4j jar is included in your classpath.
Enjoy!
It's definitly possible to use log4j in a standalone project. Just set your classpath to include the log4j jar. As for the properties file, the apache documentation should say where to log4j looks for it (it's probably also configurable).