Blog

Protokollierung in Websphere Application Server mit Apache commons-logging und Log4j

Sander Hautvast

Aktualisiert Oktober 23, 2025
3 Minuten

Die Protokollierung sollte einfach und übersichtlich sein. Sie sind ein wesentlicher Bestandteil der täglichen Verwaltungsarbeit und liefern wichtige Informationen für die Fehlersuche bei Produktionsstörungen. Angemessene Protokollierung spart Zeit und Geld. Wenn Sie eine Reihe von Anwendungen hosten, z.B. mehr als 10, sollten Sie die Anwendungsprotokolle voneinander und von den Plattformprotokollen und Traces trennen. Logging-Frameworks wie jdk logger und log4j, die mit dem j2ee-Container zusammenarbeiten, bieten die Möglichkeit, dies über Konfigurationsdateien zu tun. So weit, so gut.

Irgendwann (ich glaube ab 5.0) beschloss IBM, jakarta/apache commons-logging (JCL) in ihr Produkt Websphere Application Server aufzunehmen. Dabei handelt es sich um ein bekanntes Open-Source-Produkt, das eine Abstraktion bietet, unter der theoretisch jede Protokollierungsimplementierung verwendet werden kann. Die Aufnahme in WAS hat zur Folge, dass sich bei Anwendungen, die dasselbe Framework verwenden, das Protokollierungsverhalten ändern kann. Das liegt daran, dass die Protokollierungsklassen standardmäßig von einem anderen Classloader geladen werden. Dieser Classloader muss in der Lage sein, sowohl die log4j.jar als auch deren Konfigurationsdatei zu finden. Es gibt noch ein weiteres Problem: JCL muss mitgeteilt werden, dass es log4j verwenden muss. Standardmäßig wird der JDK-Logger verwendet und jede Zeile landet in SystemOut.log. Die IBM-Dokumentation dazu ist eindeutig: Legen Sie einfach eine Datei namens META-INF/services/org.apache.commons.logging.LogFactory auf dem Klassenpfad ab und schon sind Sie fertig. Der Inhalt dieser Datei stellte sich für mich als der rätselhafte Teil heraus. Ich bin fälschlicherweise davon ausgegangen, dass die Datei mit der Datei commons-logging.properties identisch sein sollte: org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactory Ich habe getan, was ich in der Dokumentation gelesen hatte, habe meine Anwendung neu bereitgestellt und alles schien in Ordnung zu sein. Bis ich den Classloading-Modus auf PARENT_FIRST änderte. Websphere-Anwendungen können diese Einstellung oder APPLICATION_FIRST haben. Im letzteren Modus werden zuerst die mit der Anwendung gebündelten jar-Dateien verwendet, bevor die Standard-Websphere-Bibliotheken geladen werden.Wenn Sie es mit einer Anwendung zu tun haben, die Sie nicht geschrieben haben und nicht ändern können (sagen wir, Sie sind der Deployer), ist PARENT_FIRST Ihr Freund im Angesicht böser Entwickler. Ich meine böse im Sinne von: j2ee.jar in die Ohrdatei aufnehmen. Das kommt vor!!! Und nicht nur diese Datei, sondern alles, was Sie heute in einem Maven-Repository finden können, das Low-Level-Funktionen enthält (wie z.B. XML-Verarbeitung oder j2ee api's ). Sie sollten nicht in der Ohrendatei sein! Wenn Sie PARENT_FIRST verwenden, werden alle korrekten Versionen der Plattformklassen vom richtigen Ort geladen. Verwenden Sie diese Option und nerven Sie dann die Entwickler. In meinem Fall war das Protokollierungsverhalten sehr uneinheitlich. Manchmal funktionierte auch APPLICATION_FIRST nicht. Und manchmal änderte ein Neustart des Servers die Protokollierung. Es war eine frustrierende Erfahrung, und in solchen Momenten ist man froh, wenn man auf die Dekompilierung von Java mit dem guten alten JAD zurückgreifen kann. Der Quelltext von org.apache.commons.LogFactory.class macht deutlich, dass die obige Konfigurationszeile falsch ist und dass Sie NIE eine Warnung erhalten, wenn Sie es nicht richtig machen. Die Klasse lädt die Datei und die komplette Zeile wird dann als Klassenname für die LogFactoryImpl interpretiert. Es handelt sich also nicht um eine Eigenschaftsdatei, und der richtige Inhalt für META-INF/services/ org.apache.commons.logging.LogFactory lautet: org.apache.commons.logging.impl.Log4jFactory Und das war's dann auch schon. Danke Apache, dass Sie die ClassNotFoundException geschluckt haben! Nach einigem Suchen bin ich auf einen weniger bekannten Teil der offiziellen SUN jarfile-Spezifikation gestoßen, der besagt, dass Service-Schnittstellen bestimmte Implementierungsklassen haben können, die in einer Datei mit dem Namen der Schnittstelle angegeben werden. Es handelt sich um eine wirklich rudimentäre IOC-Implementierung, die in den Tagen von jdk 1.3 in Mode gewesen sein muss.Ich wusste das alles wirklich nicht. Am Ende war es doch eine gute Lernerfahrung.

Verfasst von

Sander Hautvast

Contact

Let’s discuss how we can support your journey.