Log4J (v2) nachträglich in allen Klassen hinzufügen

Marantis

Mitglied
Hallo zusammen,

wir haben folgende Aufgabenstellung: Log4J nachträglich in allen Java-Klassen hinzufügen

Einmalig zu erledigen, manuell bpsw. per Textersetzungen durch Eclipse oder Netbeans, allerdings in mehr als 1000 Klassen. Daher einzeln von Hand in allen Klassen zu aufwendig.

Wir sind dankbar für reale und aufgabenbezogene Tips und Hilfen



Letztendlich teilt sich das Problem in 3 bzw. 5 Bereiche auf: (in allen Klassen aka *.java Dateien)

1. "imports" hinzufügen

[CODE lang="java" title="Log4J imports"]
package my.example;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
[/CODE]


2. den Logger innerhalb der Klasse als Konstante definieren

[CODE lang="java" title="Log4J Konstante"]
public final class MyClass {

private static final Logger LOG = LogManager.getLogger(MyClass.class);
[/CODE]


3. Die "catch" Anweisungen korrigieren

[CODE lang="java" title="Log4J catch"]
} catch (ExceptionA a) {
LOG.error(a.getLocalizedMessage(), a);
} catch (ExceptionB b) {
LOG.error(b.getLocalizedMessage(), b);
} catch (ExceptionC c) {
LOG.error(c.getLocalizedMessage(), c);
}
[/CODE]

Speziell zu beachten sind die 2 folgenden Punkte

A) Bei der Logger Konstante ist die korrekte Klasse (MyClass) zu definieren (klassen-abhängig)
B) Bei der catch Anweisung ist der korrekte Name der Variable (abc) zu übernehmen (variablen-abhängig)

Da bis dato überhaupt kein Logger eingesetzt wurde, können wir hier auch nicht einfach pauschal bestehende Text ersetzen. Der Logger muss somit komplett "neu" zu allen Klassen hinzugefügt werden.

Aufgaben bzw. Problematik:
  • Definition der korrekten RegEx Anweisungen, um diese in der IDE (Eclipse oder Netbeans) als Suchen/Ersetzen Pattern projektübergreifend verwenden zu können.
  • Problematik hier: Insbesonders die letzten beiden Punkte (A und B) lassen vermuten, dass das mit RegEx allein nicht zu lösen ist.



Wie würdet ihr das Problem lösen?

Vielen Dank für eure Hilfe.
 
Zuletzt bearbeitet:
Beim catch hilft wahrscheinlich dateiübergreifendes Suchen und Ersetzen eines Editors.
Ich bin mir aber unsicher, ob das auch mehrzeilig und bei unterschieldichen Einrückungen klappt.

Ansonsten schreib Dir einfach ein Tool, in Java ist alles notwendige drin.
 
Also eine Idee, die mir in den Sinn kommt: AOP (Aspect oriented programming). Dann könntest Du das, was Du da brauchst, evtl. schon komplett erledigen. (Das Hinzufügen macht ja erst einmal nichts. Alles was Du machen willst, ist ja ein Logging im catch so ich Dich richtig verstanden habe.

Das ginge also etwas in diese Richtung:

Dort wird aber nichts mit dem catch gemacht - wie das aussehen könnte, sieht man z.B. hier:

Also der Hintergrund ist, dass das, was Du da an Funktionalität beschrieben hast, erst einmal sehr gut durch ein Aspect abgebildet werden könnte. Und statt das an vielen Stellen immer wieder zu bauen (doppelter Code) ist hier die Idee halt, das an nur einer Stelle zu implementieren und dann zu "verknüpfen".


Wenn dann das Logging mehr benutzt werden soll (Macht ja Sinn, das dann generell zu verwenden), dann bekommen die Klassen alle nach und nach die entsprechenden Anpassungen. Diese kann man ggf. auch verkürzen z.B. mittels Lombok - dann hast Du erst einmal nur eine @Log4j2 Annotation auf der Klasse.
Aber diese Anpassungen kommen nicht als ein großer Block sondern werden nach und nach erfolgen - halt immer, wenn eine Klasse angepackt wird.

Wenn das so aber keine Alternative ist, dann müsste man sich zur Not etwas bauen. Das kann zur Not ein einfacher Text-Editor sein:
- Import am Anfang einfügen
- Alle class xyz .... { finden ... nach dem { kommt dann die Klassenvariable.
- alle catch (Exception xyz) { finden um da dann das LOG dazu zu schreiben.

So Ihr klare Coding Standards habt, sollte man da einiges automatisch abhandeln können.
 
Import am Anfang einfügen
Eclipse hat eine Möglichkeit organize imports für ganze Dateibäume.

Deshalb würde ich das Einfügen des Import als nicht so wichtig ansehen.

Ausgenommen ist, dass man organize imports eventuell nicht bennutzen will, weil es gegen die Projektrichtlinien verstösst oder einem die Versions-Historie verschmutzt.

Wenn man eine Automatik nutzt, kann man eventuell auch die Klassen-Identifier vollqualifiziert in den Code Einfügen.
 
Eclipse hat eine Möglichkeit organize imports für ganze Dateibäume.
Fügt das auch fehlende Imports hinzu? Das halte ich für schwierig, da dies ja auch nicht immer eindeutig ist.

Ich kenne das organize imports nur als neu Strukturierung der Imports und dem Löschen nicht benötigter imports.
 
Also scheint da Eclipse tatsächlich für mehrere Dateien sowas zu machen (so es eindeutig ist). Das ist interessant.

Bei Logger kann es da zu Problemen kommen, denn im Modul java.logging ist java.util.logging.Logger.
(Umkehrschluss: Ab Java 9 mit modul-info.java müsste es eindeutig sein, so java.logging nicht eingebunden wurde.)
 
Dumme Frage am Rande, aber: ihr habt in 1000 Klassen einfach "leere" Catch-Blöcke, in denen jetzt überall stumpf geloggt werden soll?
 
Es gibt keine dummen Fragen ^^

Die Antwort lautet (wir, sprich unser Kunde, der gerade seinen steinalten Code optimiert) hat zwar try..catch aber bisher ohne jegliches Logging.

Daher können wir auch nicht "bestehenden" Code (scheibchenweise) durch die notwendigen oben beschriebenen Code-Fragmente ersetzen.

Zusätzlich danke an die versch. Ideen und Tips:

Zu den einzelnen Antworten

dateiübergreifendes Suchen und Ersetzen eines Editors.

nein, das funktioniert leider nicht, da bspw. der Klassenname dadurch nicht kontextsensitiv ermittelt und hinzugefügt wird, bspw. in der Anweisung:

[CODE lang="java" title="Name der Klasse"]private static final Logger LOG = LogManager.getLogger(==> MyClass <== .class);[/CODE]

Das gleiche Problem existiert in der Ermittlung und Übernahme der Variablennamen in den einzelnen Catch-Anweisungen.

organize imports für ganze Dateibäume

Das funktioniert allerings erst NACHDEM der Logger in den Klassen definiert wurde und diesen kann man eben nicht einfach pauschal in allen Klassen hinzufügen, da der Name der Klasse dynamisch ermittelt und eingetragen werden muss.

AOP (Aspect oriented programming)

Hatten wir auch schon im Blick. Nur ist die Einarbeitung und Verwendung für einen eigentlich ziemlich primitiven Einzelfall wie mit Kanonen auf Spatzen schießen.


Ansonsten schreib Dir einfach ein Tool, in Java ist alles notwendige drin.

Genau das machen wir gerade!

Es wäre aber schön gewesen, wenn wir uns das hätten sparen können oder zumindest erleichtern, denn Log4J ist jetzt nicht gerade eine unbekannte LIB und das generelle AUTOMATISIERTE Erweitern von Klassen, um zusätzliche Implementierungen (bspw. um einen Logger) ist jetzt eigentlich auch nicht gerade neu oder unüblich.

Wir hatten gehofft, uns mit ein paar Tips und Tricks, die Coding-Arbeit (zumindest in Teilen) sparen zu können.

Wenn wir fertig sind, werden wir den Code veröfffentlichen.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben