Skip to content

Commit aa73d00

Browse files
authored
Added case for XAER_RMFAIL (#2132)
1 parent 823fb86 commit aa73d00

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package com.microsoft.sqlserver.jdbc;
77

8+
import java.net.SocketException;
89
import java.sql.CallableStatement;
910
import java.sql.ResultSet;
1011
import java.sql.SQLException;
@@ -26,6 +27,7 @@
2627

2728
import com.microsoft.sqlserver.jdbc.SQLServerError.TransientError;
2829

30+
2931
/**
3032
* Implements Transaction id used to recover transactions.
3133
*/
@@ -764,7 +766,7 @@ private XAReturnValue dtc_XA_interface(int nType, Xid xid, int xaFlags) throws X
764766
xaLogger.finer(toString() + " exception:" + ex);
765767

766768
if (ex.getMessage().equals(SQLServerException.getErrString("R_noServerResponse"))
767-
|| TransientError.isTransientError(ex.getSQLServerError())) {
769+
|| TransientError.isTransientError(ex.getSQLServerError()) || isResourceManagerFailure(ex)) {
768770
XAException e = new XAException(ex.toString());
769771
e.errorCode = XAException.XAER_RMFAIL;
770772
throw e;
@@ -943,4 +945,62 @@ private static int nextResourceID() {
943945
return baseResourceID.incrementAndGet();
944946
}
945947

948+
private enum ResourceManagerFailure {
949+
CONN_RESET("Connection reset");
950+
951+
private final String errString;
952+
953+
ResourceManagerFailure(String errString) {
954+
this.errString = errString;
955+
}
956+
957+
@Override
958+
public String toString() {
959+
return errString;
960+
}
961+
962+
static ResourceManagerFailure fromString(String errString) {
963+
for (ResourceManagerFailure resourceManagerFailure : ResourceManagerFailure.values()) {
964+
if (errString.equalsIgnoreCase(resourceManagerFailure.toString())) {
965+
return resourceManagerFailure;
966+
}
967+
}
968+
return null;
969+
}
970+
}
971+
972+
/**
973+
* Check if the root exception of the throwable should be a XAER_RMFAIL exception
974+
*
975+
* @param throwable
976+
* The exception to check if the root cause should be a XAER_RMFAIL
977+
*
978+
* @return True if XAER_RMFAIL, otherwise false
979+
*/
980+
private boolean isResourceManagerFailure(Throwable throwable) {
981+
Throwable root = Util.getRootCause(throwable);
982+
983+
if (null == root) {
984+
return false;
985+
}
986+
987+
ResourceManagerFailure err = ResourceManagerFailure.fromString(root.getMessage());
988+
989+
if (null == err) {
990+
return false;
991+
}
992+
993+
// Add as needed here for future XAER_RMFAIL exceptions
994+
if (root instanceof SocketException) {
995+
switch (err) {
996+
case CONN_RESET:
997+
return true;
998+
default:
999+
return false;
1000+
}
1001+
}
1002+
1003+
return false;
1004+
}
1005+
9461006
}

src/main/java/com/microsoft/sqlserver/jdbc/Util.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import java.net.UnknownHostException;
1414
import java.text.DecimalFormat;
1515
import java.text.MessageFormat;
16+
import java.util.List;
17+
import java.util.ArrayList;
1618
import java.util.Date;
1719
import java.util.Locale;
1820
import java.util.Properties;
@@ -1043,6 +1045,23 @@ static char[] bytesToChars(byte[] bytes) {
10431045
}
10441046
return chars;
10451047
}
1048+
1049+
/**
1050+
* @param throwable
1051+
* The exception to find root cause for.
1052+
*
1053+
* @return The root cause of the exception, otherwise null if null throwable input
1054+
*/
1055+
static Throwable getRootCause(Throwable throwable) {
1056+
final List<Throwable> list = new ArrayList<>();
1057+
1058+
while (throwable != null && !list.contains(throwable)) {
1059+
list.add(throwable);
1060+
throwable = throwable.getCause();
1061+
}
1062+
1063+
return list.isEmpty() ? null : list.get(list.size() - 1);
1064+
}
10461065
}
10471066

10481067

0 commit comments

Comments
 (0)