I have built a java application and I've been using slf4j/log4j for logging. I would now like to provide the user with the possibility of changing logging levels without needing to re build the .jar file.
I've read around that to do this your properties file needs to be inside of the classpath of the application. I've tried using the Class-Path header in the MANIFEST.MF file to achieve this, however it is not working.
These are the two examples I've tried.
Class-Path:./config/
Class-Path:C:/users/user/directory/tools/config/
However none of these seem to be added to the classpath as I've tried printing its contents once the application starts running.
As suggested by this question, I ended up adding a parameter to the java execution command. Bear in mind that if you execute through bash commands, as I do, you need to add the full path to the directory.
java -Dlog4j.configuration=file:/path/to/log4j.properties -jar myApp.jar
I don't like this since it makes it extremely dependent on path configuration but it will suffice.
Please find below a list of possible solutions.
1) java -jar myApp.jar will search for the log4j.properties in following order
root of myApp.jar
the directories specified in the header Class-Path: of the myApp.jar
2) java -Dlog4j.configuration=file://path/to/file//log4j.properties -jar myApp.jar will use the properties file specified by -Dlog4j.configuration=...
3) java -Xbootclasspath/a:../config -jar myApp.jar will search for the log4j.properties in following order
directory ../config/
root of myApp.jar
the directories specified in the manifest header Class-Path: of the myApp.jar
I believe solution 1) should solve your problem like following
make sure there is no log4j.configuration in the root of myApp.jar
the manifest header contina for example Class-Path: config/
and the directory structure of your installation is
./myApp.jar
./config/
edit A possibe solution to avoid the hardcoded path, but use a defined location for the log4j.properties file could be as below.
assume following structure of your application
c:\somewhere\myApp.jar
c:\somewhere\config\log4j.properties
c:\somewhere\run_myapp.cmd
run_myapp.cmd
#echo off
... do your necessary preparation here
java -Dlog4j.configuration=file:%~dp0log4j_2.properties -jar myApp.jar
This will use always the config\log4j.properties relative to your myApp.jar.
%~pd - expands to drive letter and path of run_myapp.cmd
With this solution your users need to store the properties file at the given place but don't need to change the run_myapp.cmd script.
Related
I have trained a model using maltparser version 1.8.1, and I can parse text just fine, but I tried to do it from a non-local directory,
java -Xmx6G -jar /Users/me/maltparser-1.8.1/maltparser-1.8.1.jar -c /Users/me/maltparser-1.8.1/configFile -m parse
and I get the following error:
Couldn't find the MaltParser configuration file: /Users/me/maltparser-1.8.1/configFile.mco
However, the file definitely exists. I copied the text from the error:
$ ls /Users/me/maltparser-1.8.1/configFile.mco
/Users/me/maltparser-1.8.1/configFile.mco
The only way that I can get it to work is if I run java in the directory where the configuration file is. Is there something special that I have to do to use a full path for the configuration file?
It would be possible, I suppose, to cd in a shell script to make this work, but I still want to understand why doing it this way doesn't work.
I was facing the same problem, but then I looked into the source code and found out that you need to provide the relative path of the configuration file from the place you are executing the java command. This is because the path where you have executed the program is prepended to the path of the config file you provide as argument, unless you have mentioned the working directory as argument(in this case put the config in the working directory).
I have a Java application which I'm executing on Linux direct from an executable jar file
java -cp .:./lib -Duser.timezone=GMT -Dlog4j.debug -jar programName.jar
The program uses a number of other jar files which are all in one directory and 4 properties files all of which are in another directory (the current directory). Both directories are included in the CLASSPATH.
Simple enough right.
It would be, except that Log4j fails to find log4j.properties. The only way I have managed to make it find log4j.properties is to include it in programName.jar
This is not what I want, I want to have it using log4j.properties residing in the same directory as all the other properties files, they are in the CLASSPATH and are found as you would expect.
The other jar files being used are:
jdom-2.0.5.jar
log4j-1.2.17.jar
ojdbc7.jar
quartz-2.2.1.jar
slf4j-api-1.7.7.jar
slf4j-log4j12-1.7.7.jar
I'm wondering if slf4j-log4j12-1.7.7.jar does some configuration which prevents log4j from scanning the CLASSPATH when looking for the properties file. My code does not include any instructions which aim to specify the location of the properties file.
I've not yet tried executing the program without the -jar option, I will try that next.
Does this ring any bells so far ?
Add an argument to jvm (log4j.configuration). e.g.:
java -cp .:./lib -Dlog4j.configuration=file:log4j.properties -Duser.timezone=GMT ...
You may want to see this answer for more options.
I want to change levels of logging as part of a configuration file . Well I can place logging configuration as part of src/main/resources but that defeats the purpose as jar has to be exploded for that.
What I want to do is put a configuration file as part of vertx deployment.
I tried passing a -cp logging.properties but that didn't work.
Any suggestions?
So in case of vertx you can pass arguments for you class path.
Basically if you need to pass logging configuration, you can do -cp /path/to/logging/properties
Found this after going through a lot of documentation.
Surely will help someone
the file is searched for in the root of the classpath, but this means that you have to pass the directory your logging.properties is in, not the file itself, e.g. in your case
java -cp . -jar xxx.jar
if the file is in the current directory.
not quite sure which path is put in front, maybe you have to remove the logging.properties file from your jar in this case.
I have read the answer about executable jars and adding the current path to the classpath here.
I added the plugins to pom.xml, I checked and this line is in fact added to MANIFEST.MF:
Class-Path: .
Now according to log4j2 documentation, it will look in the current classpath for a log4j2.xml file.
My understanding is, that if I place log4j2.xml in the same directory as the jar, and execute the jar while I am in that directory, then it will find the log4j2.xml.
However, it only finds it when I add a
-Dlog4j.configurationFile=/path/to/file
to the java command.
What am I missing?
Frankly, it just seems easier to forget about the classpath stuff and just add a bunch of -D terms to the java command line.
I think the . is evaluated as current directory relative to the java process current working directory (when processes are started by the OS, they are given a working directory). You can see the working directory of the JVM that runs your program by examinating the system property user.dir from withing your program.
# current directory is /home/rick
$pwd
/home/rick
# the code archive is not in the current wd
$ls /home/rick/myapps
app.jar
# the conf file is
$ls .
log4j2.xml
# This will work as expected
$java -jar /home/rick/myapps/app.jar
Strictly speaking, the JAR doesn't even need to be on your filesystem: for example, it could be downloaded from the network and extracted in memory.
I want to add the classpath through a command line call. The call looks like this:
java -cp ..\conf -jar ..\lib\switcher.jar
In the conf directory is an XML file that defines the application context and the log4j.properties file. But when I run this command, Java obviously can't find those two files, although I've added them to the class path.
I also tried specifying the absolute path of the conf directory, but it didn't work either.
Any hints?
If you use the -jar option, java.exe ignores the classpath. It will only look in that jar.
Try using the manifest Class-Path instead to get Java to look in auxiliary jars.
I guess your XML file may contain the used ClassPath ...
Unfortunatly, the java command doesn't understand any subtle way to express your class path. You HAVE to give it a list of directories/jar/zip. Any other way of setting the classpath will result in no action.