I have a runnable jar file.
I have a log4j.xml file sitting in the same directory.
My classpath includes "."
env |grep CLASS
CLASSPATH=.;C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip
But when I run java -jar myrunnable.jar I get the following message.
log4j:WARN No appenders could be found for logger (org.apache.commons.configuration.PropertiesConfiguration).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Oddly enough, if I wrap that jar in a launch4j executable, it sees the log4j.xml file and uses it.
I did go to the FAQ page mentioned in the error message. It reads as follows:
This occurs when the default configuration files log4j.properties and log4j.xml can not be found and the application performs no explicit configuration. log4j uses Thread.getContextClassLoader().getResource() to locate the default configuration files and does not directly check the file system. Knowing the appropriate location to place log4j.properties or log4j.xml requires understanding the search strategy of the class loader in use.
I am at a bit of a loss in understanding what I need to do in order for my runnable jar to see the log4j.xml short of adding the -Dlog4j.configuration=file:\\\\my\crazy\long\path\to\my\eclipse\workspace\target\directory\log4j.xml to the command line which is a PITA to type out.
If I try something like java -Dlog4j.debug -Dlog4j.configuration=.\\log4j.xml -jar myrunnable.jar
log4j: Trying to find [.\\log4j.xml] using context classloader sun.misc.Launcher $AppClassLoader#265f00f9.
log4j: Trying to find [.\\log4j.xml] using sun.misc.Launcher$AppClassLoader#265f00f9 class loader.
log4j: Trying to find [.\\log4j.xml] using ClassLoader.getSystemResource().
log4j: Could not find resource: [.\\log4j.xml].
same results for different combinations log4j.xml and ./log4j.xml
If it makes a difference, this is windows 7/java 7/64 bit using log4j via the standard slf4j-log4j binding.
Additional notes:
tried java -cp . unsuccessfully
tried java -cp .\\ as well
examined jar file META-INF\MANIFEST.MF and there is no classpath entry
this particular jar was generated by maven using the maven shade plugin.
Solution (sort of)
Per Dave Newton's answer below, I changed my MANIFEST.MF file to include the following line:
Class-Path: ./
With this in place, my log4j.xml file was seen appropriately. I'm using the Maven Shade Plugin to build the jar file, so adding the Class-Path entry was a matter of configuring the ManifestResourceTransformer.
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>my.runnable.Class</mainClass>
<manifestEntries>
<Class-Path>./</Class-Path>
</manifestEntries>
</transformer>
I say "Sort of" resolved because although it does output logging information configured from my desired log4j.xml file, it means hardcoding that path into my jar and anybody using my jar has to have log4j.xml or log4j.properties in the installation directory. I wish there was a better solution that provided the standard and expected results (where the log4j.xml/log4j.properties file could be placed anywhere on your classpath), but with all the searching I've done today it does not seem to be the case.
I think I've run into yet another one of those frustrating issues where Java does not behave intuitively and anything beyond a very simple explanation of why it behaves the way it does involves reading an entire book.
When you use -jar the classpath is ignored.
You could add the config file to your manifest's Class-Path entry, but consider providing the path. It probably needs to be a file resource otherwise it'll probably try to find it on the jar's classpath value.
For Eclipse testing in Maven the easiest thing I've found to do is to put the log4j.xml in src/test/resources. It will be added to the classpath when running unit tests, etc. When we actually install our application at a customer site we place the file in /etc/... and specify it with -Dlog4j.configuration.
My best guess as to why the current directory part isn't working for you is that Eclipse is probably setting the current directory to something other than what you think it is. Try following the instructions here to print the current working directory and check it matches what you think.
UPDATE: Almost forgot. When you specify -jar the classpath options (-cp -classpath) are ignored.
-jar
Execute a program encapsulated in a JAR file. The first argument
is the name of a JAR file instead of a startup class name. In order
for this option to work, the manifest of the JAR file must contain a
line of the form Main-Class: classname. Here, classname identifies the
class having the public static void main(String[] args) method that
serves as your application's starting point. See the Jar tool
reference page and the Jar trail of the Java Tutorial for information
about working with Jar files and Jar-file manifests. When you use this
option, the JAR file is the source of all user classes, and other user
class path settings are ignored.
Related
I have built a maven Java project and deployed my JAR as an executable one on linux. I placed my log4j.xml under /src/main/resources directory during the build and hence it is now part of the final deployed JAR. I have configured log4j.xml with RollingFileAppender. So far, everything is working fine and I am able to see the logs generated.
However, wondering how to change the log level or any of the configuration within log4j.xml which is now part of the deployed JAR?
The other approaches I tried is having the log4j.xml outside in a separate directory and passed it as a configuration option to the JAR file using the below command
java -Xms512m -Xmx1024m -Dlog4j.configuration=/etc/myapp/log4j.xml -jar mylar.jar /etc/input.properties
java -Xms512m -Xmx1024m -Dlog4j.configurationFile=/etc/myapp/log4j.xml -jar mylar.jar /etc/input.properties
However, it is not working. No logs are being generated. So wondering whether I am doing this correctly or there is a better approach to implement.
from the quick look at your arguments, can you try passing the log4j path like below. (you are missing file: in the beginning of the path )
java -Dlog4j.configuration=file:/etc/cfg/log4j.properties -jar ./MyProject.jar ...
here is a similar answer present.
Currently when I execute my code I it doesn't create any log file.
the logback.xml is configured fine, however I don't see a way to configure where to find the xml file
Per the Logback manual chapter on Configuration:
Let us begin by discussing the initialization steps that logback follows to try to configure itself:
Logback tries to find a file called logback-test.xml in the classpath.
If no such file is found, logback tries to find a file called logback.groovy in the classpath.
If no such file is found, it checks for the file logback.xml in the classpath.
If no such file is found, service-provider loading facility (introduced in JDK 1.6) is used to resolve the implementation of com.qos.logback.classic.spi.Configurator interface by looking up the file META-INF\services\ch.qos.logback.classic.spi.Configurator in the class path. Its contents should specify the fully qualified class name of the desired Configurator implementation.
If none of the above succeeds, logback configures itself automatically using the BasicConfigurator which will cause logging output to be directed to the console.
The standard approach that this is trying to tell you about would be to have logback.xml be in the classpath for "normal" running, and have a logback-test.xml in the classpath to describe how you want to log when running automated tests. (For example, you may want to log to a file in your regular application, but have your automated unit tests just log to the console.) The exact process of putting a file into the classpath depends on what build system you're using. For example, with the default settings in the popular Maven build system, you would put logback.xml inside src/main/resources, and (if desired) a logback-test.xml inside src/test/resources. If you're having trouble with this step, you may want to search for or ask another question with more details about the build toolchain you're using. Also be sure to read "What is a classpath?"
Another approach, also listed in the Logback manual:
You may specify the location of the default configuration file with a system property named "logback.configurationFile". The value of this property can be a URL, a resource on the class path or a path to a file external to the application.
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
Note that the file extension must be ".xml" or ".groovy".
This wouldn't be as common, but sometimes if you need to run in a particular environment with a certain logging configuration, or run some sort of automated test directing output to a different place than your normal tests, it can come in handy to just outright configure the path like that.
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.
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.