Wie löst man die Transaktionsprotokollierung in Java?

8

Ich möchte Folgendes erreichen:

Innerhalb einer Transaktion möchte ich mehrere Protokollnachrichten generieren. Diese Protokollmeldungen sollten nur geschrieben werden, wenn die Transaktion erfolgreich übergeben wurde. Wenn die Transaktion zurückgesetzt wird, dürfen die Protokollnachrichten nicht protokolliert werden.

Ich konnte nichts finden, um dies zu erreichen (mit Frühling, Winterschlaf, Atomikos), also schrieb ich diesen kleinen Wrapper (ich habe ein paar Convenience-Methoden weggelassen):

%Vor%

Was halten Sie von diesem Ansatz? Gibt es größere oder kleinere Fehler oder Probleme damit? Oder noch besser, gibt es dafür fertige Lösungen?

UPDATE:

Da ich auch JTA verwende, habe ich eine neue Idee. Würde die Implementierung des TransactionLoggers als Empfänger einer transaktionsbewussten Nachrichtenwarteschlange das Zeitproblem lösen oder würde es die Dinge nur noch komplexer machen?

UPDATE:

Ich denke, dass die Protokollierung in einer Datenbank und das periodische Schreiben von Protokolleinträgen aus dieser Datenbank in eine periodische Aufgabe, wie in den Kommentaren vorgeschlagen, eine sehr gute Lösung für dieses Problem ist:

PROs:

  • Normale Implementierung leisten
  • integriert sich in TransactionManager
  • Protokolleinträge in den Protokolldateien können nach Zeitstempel
  • sortiert werden

CONs:

  • Log-Dateien sind nicht auf dem neuesten Stand (abhängig vom Periodic-Task-Intervall)
  • datenbankstrukturabhängig
  • Die Protokollierung einfacher nicht transaktionaler Ereignisse wird dbconnection-abhängig
  • wahrscheinlich ein größerer Overhead für die Gesamtprotokollierung

Hier sind die Vor- und Nachteile, die ich mit dem Wrapper sehe, den ich gepostet habe:

PROs:

  • Datenbank- und Framework-unabhängig
  • einfache Implementierung
  • Protokolldateien sind immer auf dem neuesten Stand

CONs:

  • Protokolleinträge in den Protokolldateien sind nicht nach Ereigniszeitstempel, sondern nach "transaction-completition" -Zeitstempel geordnet (lange Transaktionen führen zu sehr gemischten Protokolldateien.
  • rollback() und commit() müssen "manuell" aufgerufen werden, was zu Programmierfehlern führen kann (und möglichem OutOfMemoryError, wenn das Aufrufen dieser Methoden vergessen wird)

Ich denke, eine Kombination dieser beiden, wie das Protokollieren von Protokollsätzen im "Wrapper" -Ansatz, ist wegen der möglichen inkonsistenten Protokolldateien (vergessene Protokolleinträge aufgrund eines Anwendungsabsturzes) schlechter als die Verwendung eines der beiden erwähnten Ansätze. .

Meine Entscheidung ist jetzt, meinen "Wrapper" zu behalten. Die folgenden Gründe sind für diese Entscheidung entscheidend (in der Reihenfolge ihrer Wichtigkeit):

  1. Ich bevorzuge Protokolldateien, die über perfekt geordnete Protokolleinträge immer auf dem neuesten Stand sind
  2. Lange Transaktionen sind in meinem Fall sehr selten
  3. Ich kann die Verwendung von rollback() und commit() auf nur wenige Methoden reduzieren.
  4. Diese Lösung existiert bereits jetzt.

Übrigens: Ich möchte mein Englisch verbessern. Also, wenn Sie irgendwelche Fehler in meinem Artikel bemerken, werde ich mich freuen, wenn Sie sie aufzeigen.

UPDATE:

Einfach ausgedrückt benutze ich es so:

%Vor%

Das ist immer noch nicht perfekt, aber im Moment scheint es mir eine "gute Lösung" zu sein. Der nächste Schritt wird Aspekte verwenden, um meine Transaktions-Methoden zu dekorieren.

UPDATE:

Ich füge das in meine Frage ein, weil ich mich schlecht fühlte, meine eigene Antwort zu akzeptieren, obwohl jemand anderes mich auf den Weg gebracht hat.

Ich verwende jetzt einen AOP-Ansatz im Wesentlichen mit dem folgenden Logger. (In meiner realen Anwendung habe ich mehr als einen Logger und alle diese Logger werden von einem benutzerdefinierten Singleton-Manager verwaltet.):

%Vor%

und dieser Aspekt: ​​

%Vor%

In meiner applicationContext.xml habe ich die folgenden Zeilen:

%Vor%

Das funktioniert bis jetzt gut.

PROs:

  • Datenbank- und Framework-unabhängig
  • einfache Implementierung
  • Protokolldateien sind immer auf dem neuesten Stand
  • rollback() und commit() werden automatisch nach jeder Transaktion
  • aufgerufen

CONs:

  • (Log-Einträge in den Log-Dateien sind nicht nach Event-Timestamp sortiert, sondern nach "transaction-completition" -Zeitstempel. Ich denke, das ist kein großer Nachteil, da die DB-Aktionen wirklich stattfinden, wenn die Transaktion ausgeführt wird und die LogRecords einer Transaktion werden immer noch korrekt sortiert.)
AlexS 16.03.2012, 08:44
quelle

5 Antworten

1

Warum erstellen Sie nicht einen Aspekt und implementieren einen Rat, vor allem einen Nach der Rückmeldung, überprüfen Sie die Dokumentation des Frühlings, die seit 2.0 verfügbar ist:

%Vor%

Wenn Sie nur anmelden müssen, wenn alles in Ordnung ist, erstellen Sie den Hinweis und lassen Sie Ihren Code sauber:

%Vor%     
Defrag 20.05.2012, 06:45
quelle
3

Wenn Sie möchten, dass ein Logger seine Log-Nachrichten nur dann "festschreibt", wenn die Transaktion festgeschrieben ist, dann wäre Ihre beste Lösung, wenn Ihr Logger ein XAResource wäre und XA-Transaktionen verwendet. Das bedeutet, dass Ihr XALogger vom Transaktionsmanager eine Prepare / Commit-Benachrichtigung erhält. Auf diese Weise wird Ihre XAResource zu einem "Resource Manager", der an einer XA-Transaktion teilnimmt. Ihr XALogger muss genau wie JMS- und JDBC-Ressourcen beim Transaktionsmanager registriert sein. Sie können entweder eine JCA-Implementierung schreiben oder (einfacher) Ihren XALogger mit dem aktuellen java.transaction.Transaction

registrieren

transaction.enlistResource(myXALogger)

und implementieren Sie XAResource (JavaDoc)

    
raphaëλ 23.05.2012 07:00
quelle
0

Es ist nicht klar, was du mit der rec.setMillis(System.currentTimeMillis()); erreichen willst. Das protokollierte Ereignis trat zum Zeitpunkt der Datensatzerstellung und nicht zum Zeitpunkt der Festschreibung auf. Es wird nur bis zur Commit-Zeit im RAM gepuffert. Indem Sie es auf diese Weise überschreiben, protokollieren Sie die Commit-Zeit und nicht die Ereignisauftrittszeit. Beim Lesen des Protokolls müssen Sie einen Hinweis auf die tatsächliche Reihenfolge haben, oder Sie werden nicht in der Lage sein, kausale Beziehungen zu interpretieren.

Ihre Lösung leidet auch unter Problemen bei der Wiederherstellung nach einem Absturz. Der Transaktionsmanager verarbeitet das Commit für Transaktionsressourcen, die volatilen Protokollnachrichten gehen jedoch verloren. Das kann oder kann nicht tolerierbar sein, abhängig von Ihren Anforderungen.

    
Uncredited 16.03.2012 11:12
quelle
0

Also, ich möchte abholen, wo die Kommentare Sie verlassen haben :) @MichaelBorgwardt schlägt vor, zu einer Datenbank zu loggen und @cherouvim fügte hinzu, dass Sie die Protokolleinträge regelmäßig aus der Datenbank in die Datei schreiben sollten.

Es ist auch möglich, die Umwandlung der Protokolleinträge in die Datei direkt nach dem Festschreiben der Transaktion durch einen bestimmten Thread zu starten (auf diese Weise wird die Lücke zwischen dem Commit und dem Haben in der Datei vermieden).

Eine andere Möglichkeit wäre, eine Protokolldatei für jede Transaktion zu schreiben. Beim 'Rollback' löschen Sie es. Bei 'commit' hängen Sie es an Ihre bereits existierende Logdatei an (oder Sie entscheiden sich sowieso, keine Logdatei zu haben, sondern ein logdir und bei 'commit' verschieben Sie die einzelne Logdatei).

    
Angelo Fuchs 03.04.2012 20:53
quelle
-2

Es gibt einen Abschnitt zum Thema Protokollierung in der Frühlingsreferenz.

Es zeigt, wie man verschiedene Logging-Frameworks konfiguriert, darunter log4j

In Ihrem Fall wäre die letzte Zeile der Konfiguration:

%Vor%     
Anil Kumar C 08.05.2012 11:12
quelle

Tags und Links