2017-07-18 1 views
0

Ich habe eine EJB an einer globalen Transaktion beteiligt. Es gibt einen Teil des Codes, der bei einem Fehler explizit zurückgesetzt werden soll, obwohl die gesamte Transaktion nicht fehlschlagen soll.Legit Rollback in einer verteilten Transaktion: möglich?

Als Rollback in einer CMT verboten habe ich ein BMT und versuchte, den folgenden Code:

connection.setAutoCommit(false); 
Savepoint sp= connection.setSavepoint(); 
try{ 
    //my code editing DB that could possibly fail 
}catch(SomeException ex){ 
    connection.rollback(sp); 
} 

Auf diese Weise ich meine lokale db Modifikation nur rückgängig machen, aber ich propagiere auch das nicht nach außen scheitern. Wie auch immer dieses Programm nicht mit so:

„Savepoint in einer verteilten Transaktion verboten ist“

Gibt es einen anderen Ansatz, um dieses Problem zu lösen?

Antwort

1

Der Transaktionskontext wird nicht an BTM weitergegeben. Ihre Bean wird auch nicht Teil der globalen Transaktion sein. Wenn Ihre globale Transaktion fehlschlägt, können Ihre Änderungen dennoch festgeschrieben werden.

Ich bin nicht mit Websphere-Einstellungen vertraut, aber ich würde überprüfen, ob die Verbindung. Ich erwarte, dass in die BTM injiziert wird oder übertrage ich die Verbindung irgendwie von CMT? Ich könnte versuchen, die Behälterkonfiguration zu überprüfen, wenn die Verbindung gesetzt wird, um jta/globale Transaktion zu stützen. Oder starten Sie die einige UserTransaction.begin() bevor Sie beginnen, mit der Verbindung zu arbeiten? Immer noch, wenn das funktioniert, wird Ihr Problem nicht behoben.

Die passende für Sie ist die Verwendung von geschachtelten Transaktionen, aber sie werden nicht in Java EE unterstützt. Nur, wenn WebShere einige Provider spezifische Möglichkeiten hat, sie auszuführen (ich kenne seine Fähigkeiten nicht).

Dann ist der einfachste Weg die Verwendung CMT REQUIRES_NEW, aber es hat seinen Nachteil darin, dass die db-Änderung zugesagt wird, selbst wenn die globale Transaktion zurückgesetzt wurde.

Eventuell wäre eine Änderung der Anwendungsdesing erforderlich.

2

Sie können CMT verwenden, indem Sie ein zweites EJB verwenden, das mit @TransactionAttribute(REQUIRES_NEW) annotiert ist und in dem Sie den Code eingeben, der fehlschlagen kann. Sie müssen diese EJB von der anderen EJB anrufen.

Der Container erstellt eine neue Transaktion für den Code und wird zurückgesetzt, falls er fehlschlägt.

+0

Die neue Transaktion wird auch festgeschrieben, wenn sie funktioniert. Seien Sie sich jedoch bewusst, dass die neue Transaktion unabhängig von der ersten ist, und wenn etwas dazu führt, dass die erste Transaktion rückgängig gemacht wird (aus einem anderen Grund), wird die neue Transaktion weiterhin ausgeführt. – kaczyns