Klassenname für Logger unter Java automatisch ermitteln

Vor einiger Zeit schrieb ich einen Artikel darüber, wie der Klassenname für einen Logger ermittelt werden kann. Im Endergebnis sah die damalige Lösung, unter Nutzung der Simple Logging Facade for Java kurz SLF4J, wie folgt aus:

Logger log = LoggerFactory.getLogger(new Exception().fillInStackTrace().getStackTrace()[0].getClassName());

Damit wird der gesamte Stacktrace zusammengesammelt und entsprechend der Klassenname extrahiert. Das Problem an dieser Variante ist das der gesamte Stack dafür ausgewertet wird und für jede Nutzung eines Logs eine relativ unintuitive und lange Zeile von A nach B kopiert werden muss. Anders sieht es mit folgender Lösung aus:

package net.seeseekey.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utility class to get logger
 */
public final class Logging {

    private Logging() {
    }

    public static Logger getLogger() {

        StackWalker.StackFrame frame = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
                .walk(stream -> stream.skip(1)
                        .findFirst()
                        .orElse(null));

        if (frame == null) {
            return LoggerFactory.getLogger("Common");
        }

        return LoggerFactory.getLogger(frame.getClassName());
    }
}

Bei dieser Utility-Klasse wird der entsprechende Klassenname dynamisch über einen StackWalker ermittelt. Zurückgegeben wird hierbei der Klassenname des Aufrufers. Konnte kein Klassenname ermittelt werden, so wird stattdessen ein Logger mit dem Namen Common zurückgegeben. Damit kann der eigentliche Logger nun wie folgt angelegt werden:

Logger log = Logging.getLogger();

Der StackWalker ist ab Java 9 verfügbar und kann somit in neueren Projekten problemlos genutzt werden. Im Gegensatz zu den bisherigen Methoden Teile des Stacktrace zu erhalten, ist der StackWalker aus Performancesicht zu bevorzugen. Definiert wurde diese API in der JEP 259.

Probleme beim Deployen zu Maven Central

Im Rahmen einiger Wartungsarbeiten wollte ich eine neue Version einer Java-Bibliothek zu Maven Central deployen. Stattdessen wurde ich von der Meldung:

Execution injected-nexus-deploy of goal org.sonatype.plugins:nexus-staging-maven-plugin:1.6.7:deploy failed: An API incompatibility was encountered while executing org.sonatype.plugins:nexus-staging-maven-plugin:1.6.7:deploy: java.lang.ExceptionInInitializerError: null

überrascht. Am dahinterliegenden Problem wird bereits gearbeitet. Um das Deployment trotzdem durchführen zu können, eignet sich folgender Workaround:

export MAVEN_OPTS="--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.desktop/java.awt.font=ALL-UNNAMED"
mvn clean deploy

Anschließend wird das entsprechende Deployment durchgeführt, was je nach Auslastung einige Minuten dauern kann.

Nyan-Katze in IntelliJ IDEA

Eine Entwicklungsumgebung ist ein trister Ort. Aber manchmal hilft schon etwas Farbe, um aus einem tristen Ort etwas Schönes zu machen. So kann die IDE IntelliJ IDEA mit unterschiedlichsten Plugins erweitert und verändert werden.

Der Fortschrittsbalken in Aktion

Eines dieser Plugins ist die Nyan Progress Bar. Das Plugin ersetzt den Fortschrittsbalken durch einen Regenbogen auf dem die Nyan-Katze sich bewegt. Installiert werden kann das Plugin über den in IntelliJ IDEA integrierten Plugin-Manager. Der Quelltext des Plugins ist auf GitHub zu finden. Es ist unter der Zero-Clause BSD-Lizenz lizenziert und damit freie Software.

IntelliJ IDEA kompiliert über Maven

Normalerweise kompiliert die Java-IDE IntelliJ IDEA den Quelltext sobald, der Build-Vorgang gestartet wird. Allerdings kann es vorkommen das stattdessen jedes Mal der Kompiliervorgang über Maven angestoßen wird. Verantwortlich hierfür ist eine Einstellung der IDE.

Nachdem die Option deaktiviert wurde, kompilierte die IDE den Quellcode wieder

Zu finden ist diese Einstellung im Einstellungsdialog unter dem Punkt Build, Execution, Deployment -> Build Tools -> Maven- Runner. Dort existiert der Punkt Delegate IDE build/run actions to Maven. Wird dieser Punkt deaktiviert, ist die IDE wieder für die Kompilierung und den Build-Prozess verantwortlich.