Bei der Verwendung einer ausführbaren JAR-Datei ist es schwierig, den Speicherort der Log4j2-Konfigurationsdatei anzugeben. Es funktioniert gut, wenn ich alle JARs trenne, aber wenn ich versuche, sie in einer ausführbaren JAR-Datei zu kombinieren, wird die log4j2.xml
-Datei aus irgendeinem Grund nicht von der Befehlszeile abgerufen.
Ich habe die folgenden zwei Methoden zum Festlegen des Speicherorts ausprobiert:
Java -Djava.libary.path=..\bin -cp ..\config -jar MyApplication.jar
Java -Djava.libary.path=..\bin -Dlog4j.configurationFile=..\config\log4j2.xml -jar MyApplication.jar
Keiner von denen arbeitet. Ich habe auch versucht, das Verzeichnis mit der Konfigurationsdatei zum Klassenpfad in der JAR-Manifestdatei hinzuzufügen:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.2
Created-By: 1.7.0_21-b11 (Oracle Corporation)
Main-Class: com.abc.MyApplication
Class-Path: ../config/
Ich hatte mit dieser Methode auch keinen Erfolg. Irgendwelche Ideen, was ich falsch machen könnte?
Vielen Dank im Voraus für jede Hilfe!
BEARBEITEN
Ah, ich glaube, ich habe das Problem falsch verstanden. Ursprünglich war dies der Fehler, den ich in der Befehlszeilenausgabe sah:
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
Aber irgendwann, während ich Dinge änderte, änderte sich die Fehlermeldung, ohne dass ich es bemerkte:
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
Ich fand heraus, dass, obwohl die ausführbare JAR, die ich baute, die JARs log4j-core-2.1.jar
und log4j-api-2.1.jar
darin und in den Klassenpfad der MANIFEST
-Datei enthielt, ein Problem auftrat. Die Art und Weise, wie ich meine Ant-Datei geschrieben habe, um die Bibliotheken in einem einzelnen JAR zu kombinieren, kopierte die Verzeichnisse und Klassendateien erfolgreich, kopierte jedoch nicht die anderen Typen, die offensichtlich auch notwendig sind (z. B. Log4j-config) .xsd, Log4j-events.dtd usw.).
Um dies zu beheben, änderte ich die Art, wie ich die JARs in meiner Ant-Build-Datei zusammenführte, folgendermaßen:
<jar destfile="${dist}/${jarName}" basedir="${classes}"
excludes=".svn">
<!-- Merge this JAR with all the JARs in the lib directory, so that
we are only creating one distribution JAR that includes all the
libraries that you need. -->
<fileset dir="${classes}" includes="**/*.class" />
<zipgroupfileset dir="${lib}" includes="**/*.jar" />
<!-- Specify the manifest file of the JAR -->
<manifest>
<attribute name="Main-Class" value="com.abc.MyApplication"/>
<attribute name="Class-Path" value=". ${manifest.classpath}"/>
</manifest>
</jar>
Und das Problem wurde behoben und alle Dateien aus den JARs wurden in mein neu erstelltes JAR kopiert.
Nachdem das Problem behoben wurde, funktionierte der zweite der oben genannten Befehle, um den Speicherort der Konfigurationsdatei anzugeben. (Wie unten in @rewolf
angegeben, funktioniert der erste Befehl nicht, da der in MANIFEST
der JAR angegebene Klassenpfad jeden in der Befehlszeile angegebenen Klassenpfad überschreibt.
Vielen Dank für Ihre Antworten, sie haben mir definitiv geholfen, den richtigen Weg zu finden, um meine Fehler herauszufinden.
Was in der Java-Dokumentation nicht sehr gut erklärt wird, ist, dass Sie bei Verwendung einer ausführbaren Jar nur den Klassenpfad verwenden, wie er in der Manifest-Datei angegeben ist. Die Argumente -cp
oder --classpath
werden nicht abgehört.
-Dlog4j.configurationFile=directory/file.xml
sollte auf jeden Fall funktionieren. Ich gehe davon aus, dass Sie unter Windows laufen, wenn Sie die Richtung des Schrägstrichs angeben. Sind Sie sicher, dass Sie es aus dem richtigen relativen Verzeichnis ausführen?
Update
Ich habe es gerade in Windows ohne Probleme ausprobiert. Ich habe das folgende Manifest verwendet:
Manifest-Version: 1.0
Built-By: andrew.flower
Build-Jdk: 1.7.0_67
Class-Path: lib/log4j-api-2.1.jar lib/log4j-core-2.1.jar
Created-By: Apache Maven 3.2.3
Main-Class: com.andrew_flower.test.Log4jTest
Archiver-Version: Plexus Archiver
Die Log4j2-Dosen befinden sich in einem lib/
-Verzeichnis, und log4j2.xml
befindet sich im conf/
-Verzeichnis. Ich habe den folgenden Befehl ausgeführt und die Konfiguration erfolgreich gefunden.
Java -Dlog4j.configurationFile=conf\log4j2.xml -jar log4j2test1-1.0-SNAPSHOT.jar
Ich habe das Problem gelöst, den Speicherort der log4j2-Konfiguration in einer ausführbaren Jar anzugeben, die ich aus Eclipse erstellt habe, indem ich dies in meinen Java-Code einfügte:
System.setProperty("log4j.configurationFile", "resources/log4j2.xml");
Ich habe ein Paket und daher musste ich den Pfad zu meinem "resources" -Ordner angeben (in meinem "src" -Ordner in Eclipse):
System.setProperty("log4j.configurationFile", "com/company/app/resources/log4j2.xml");
Beachten Sie, dass ich "src" nicht in meinen Pfad aufgenommen habe. Ich denke, es ist der Pfad im Ordner "bin", der erforderlich ist: in meinem Fall "de/company/app/resources/log4j2.xml".
Meine Konfigurationsdatei sieht so aus:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level - %msg%n"/>
</Console>
<RollingFile
name="RollingFile"
fileName="${sys:logFilename}"
filePattern="${sys:logFilename}-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="1 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</appenders>
<loggers>
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</root>
</loggers>
Beachten Sie auch, dass ich den Pfad der laufenden Protokolldatei + den Namen "$ {sys: logFilename}" dynamisch zuweise, indem Sie Folgendes in meinen Java-Code einfügen:
System.setProperty("logFilename", "logs/myApp.log");
Damit diese beiden dynamischen System.setProperty-Zuweisungen funktionieren, müssen sie vor der "getLogger" -Anweisung ausgeführt werden, sodass mein Java-Code folgendermaßen aussieht:
import org.Apache.logging.log4j.LogManager;
import org.Apache.logging.log4j.Logger;
public class MyTestLoggingClass {
public static Logger logger = null;
...................
setUpLogging();
...............
public static void setUpLogging() {
System.setProperty("log4j.configurationFile", "com/company/app/resources/log4j2.xml");
System.setProperty("logFilename", "logs/myApp.log");
logger = LogManager.getLogger(Logger.class.getName());
}
}
Wenn "logger" zu Beginn meiner Klasse deklariert ist (aber ohne "getLogger" vor meinen 2 System.setProperty-Anweisungen aufzurufen), kann ich in anderen Methoden auf "logger" verweisen. Ich bin jedoch verpflichtet, es zu initialisieren, und so habe ich "null" gewählt, aber später mit der "getLogger" -Anweisung aktualisiert - da ich es nicht "final" machen kann (kann es nur einmal zuweisen), kann es statisch gemacht werden. eine konstante Klassenvariable.
die 2 log4j2-Gläser, die ich im Build-Pfad enthalten habe, sind:
log4j-api-2.6.2.jar
log4j-core-2.6.2.jar
Für andere, die dieses Problem haben könnten ...
Wenn Sie also eine log4j2.xml in Ihrem Programmordner für Ihre exampleApp in C:\Program Files\ExampleApp
haben, dann ...
Java.exe -Dlog4j.configurationFile=file://c:/program%20files/exampleapp/log4j2.xml -jar exampleApp.jar ...
...sollte arbeiten
Ich hatte dieses Problem mit Version 2.8 von Log4j2. Dies war nicht mehr der Fall, als die entsprechenden Log4j2-Gläser durch Version 2.6 von Log4j2 ersetzt wurden.