Skip to content

Commit cad7a73

Browse files
authored
Exceptions improvements (#1275)
* Updated TransactionRollbackException Javadoc The previous message may have been inadvertently copied from another class. Also, make this extend exception instead of a generic throwable (recoverable). Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Report new ClosedChannelException when connectivity is lost Closes #1269 Of course we can't do much for Oracle Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Base DatabaseException class Closes #1274 Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Make MySQLBatchException a VertxException And do not capture the (unnecessary) stacktrace. Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Deprecate PgException getCode in favor of sqlState Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Fix DB2ErrorMessageTest testConnectInvalidDatabase Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Removed redundant method from PgException Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Deprecate MSSQLException number in favor of errorCode Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Better error message format DB2Exception and MySQLException Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Fixed DB2PreparedQueryTestBase testPrepareError Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Fixed DB2PreparedQueryCachedTest testPrepareError Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Renamed ClosedChannelException to ClosedConnectionException Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Simplified doc about DatabaseException Signed-off-by: Thomas Segismont <tsegismont@gmail.com> --------- Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
1 parent 4583b09 commit cad7a73

File tree

27 files changed

+275
-231
lines changed

27 files changed

+275
-231
lines changed

vertx-db2-client/src/main/java/io/vertx/db2client/DB2Exception.java

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,52 +15,23 @@
1515
*/
1616
package io.vertx.db2client;
1717

18+
import io.vertx.sqlclient.DatabaseException;
19+
1820
/**
19-
* A {@link RuntimeException} signals that an error occurred.
21+
* The {@link DatabaseException} for DB2.
2022
*/
21-
public class DB2Exception extends RuntimeException {
22-
private static final long serialVersionUID = 4249056398546361175L;
23+
public class DB2Exception extends DatabaseException {
24+
private static final long serialVersionUID = -1793293963771077543L;
2325

24-
private final int errorCode;
25-
private final String sqlState;
26-
2726
public DB2Exception(int errorCode, String sqlState) {
28-
super("An error occurred with a DB2 operation. SQLCODE=" + errorCode + " SQLSTATE=" + sqlState);
29-
this.errorCode = errorCode;
30-
this.sqlState = sqlState;
27+
super(formatMessage(null, errorCode, sqlState), errorCode, sqlState);
3128
}
3229

3330
public DB2Exception(String message, int errorCode, String sqlState) {
34-
super(message);
35-
this.errorCode = errorCode;
36-
this.sqlState = sqlState;
37-
}
38-
39-
/**
40-
* Get the error code in the error message sent from DB2 server.
41-
*
42-
* @return the error code
43-
*/
44-
public int getErrorCode() {
45-
return errorCode;
46-
}
47-
48-
/**
49-
* Get the SQL state in the error message sent from DB2 server.
50-
*
51-
* @return the SQL state
52-
*/
53-
public String getSqlState() {
54-
return sqlState;
31+
super(formatMessage(message, errorCode, sqlState), errorCode, sqlState);
5532
}
5633

57-
/**
58-
* Get the error message in the error message sent from DB2 server.
59-
*
60-
* @return the error message
61-
*/
62-
@Override
63-
public String getMessage() {
64-
return super.getMessage();
34+
private static String formatMessage(String message, int errorCode, String sqlState) {
35+
return (message != null ? message : "An error occurred with a DB2 operation") + ", SQLCODE=" + errorCode + " SQLSTATE=" + sqlState;
6536
}
6637
}

vertx-db2-client/src/main/java/io/vertx/db2client/impl/codec/DB2Codec.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
*/
1616
package io.vertx.db2client.impl.codec;
1717

18-
import java.util.ArrayDeque;
19-
2018
import io.netty.channel.ChannelHandlerContext;
2119
import io.netty.channel.CombinedChannelDuplexHandler;
2220
import io.vertx.db2client.impl.DB2SocketConnection;
21+
import io.vertx.sqlclient.ClosedConnectionException;
22+
23+
import java.util.ArrayDeque;
2324

2425
public class DB2Codec extends CombinedChannelDuplexHandler<DB2Decoder, DB2Encoder> {
2526

@@ -33,18 +34,16 @@ public DB2Codec(DB2SocketConnection db2SocketConnection) {
3334
DB2Decoder decoder = new DB2Decoder(inflight);
3435
init(decoder, encoder);
3536
}
36-
3737

3838
@Override
3939
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
40-
clearInflightCommands("Failed to read any response from the server, the underlying connection may have been lost unexpectedly.");
40+
clearInflightCommands(ClosedConnectionException.INSTANCE);
4141
super.channelInactive(ctx);
4242
}
4343

44-
private void clearInflightCommands(String failureMsg) {
44+
private void clearInflightCommands(Throwable failure) {
4545
for (CommandCodec<?, ?> commandCodec : inflight) {
46-
commandCodec.cmd.fail(failureMsg);
46+
commandCodec.cmd.fail(failure);
4747
}
4848
}
49-
5049
}

vertx-db2-client/src/test/java/io/vertx/db2client/DB2ErrorMessageTest.java

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,15 @@
1515
*/
1616
package io.vertx.db2client;
1717

18-
import static io.vertx.db2client.junit.TestUtil.assertContains;
19-
20-
import org.junit.Test;
21-
import org.junit.runner.RunWith;
22-
23-
import io.vertx.core.impl.NoStackTraceThrowable;
2418
import io.vertx.db2client.impl.drda.SQLState;
2519
import io.vertx.db2client.impl.drda.SqlCode;
2620
import io.vertx.ext.unit.TestContext;
2721
import io.vertx.ext.unit.junit.VertxUnitRunner;
22+
import io.vertx.sqlclient.ClosedConnectionException;
23+
import org.junit.Test;
24+
import org.junit.runner.RunWith;
25+
26+
import static io.vertx.db2client.junit.TestUtil.*;
2827

2928
@RunWith(VertxUnitRunner.class)
3029
public class DB2ErrorMessageTest extends DB2TestBase {
@@ -33,18 +32,15 @@ public class DB2ErrorMessageTest extends DB2TestBase {
3332
public void testConnectInvalidDatabase(TestContext ctx) {
3433
options.setDatabase("DB_DOES_NOT_EXIST");
3534
DB2Connection.connect(vertx, options, ctx.asyncAssertFailure(err -> {
36-
ctx.assertTrue(err instanceof DB2Exception || err instanceof NoStackTraceThrowable, "The error message returned is of the wrong type. It should be a DB2Exception, but it was of type " + err.getClass().getSimpleName());
37-
if (err instanceof DB2Exception) {
35+
if (err instanceof DB2Exception) {
3836
DB2Exception ex = (DB2Exception) err;
3937
assertContains(ctx, ex.getMessage(), "provided was not found", "The connection was closed by the database server");
4038
ctx.assertTrue(ex.getErrorCode() == SqlCode.DATABASE_NOT_FOUND ||
4139
ex.getErrorCode() == SqlCode.CONNECTION_REFUSED,
42-
"Wrong SQL code received. Expecting " + SqlCode.DATABASE_NOT_FOUND + " or " + SqlCode.CONNECTION_REFUSED + ", but received " + ex.getErrorCode());
40+
"Wrong SQL code received. Expecting " + SqlCode.DATABASE_NOT_FOUND + " or " + SqlCode.CONNECTION_REFUSED + ", but received " + ex.getErrorCode());
4341
assertContains(ctx, ex.getSqlState(), "2E000", SQLState.AUTH_DATABASE_CONNECTION_REFUSED);
44-
} else {
45-
//TODO remove this if the GHAction build stops failing
46-
//GitHub actions build is losing the connection to the DB in this test for some reason
47-
assertContains(ctx, err.getMessage(), "Failed to read any response from the server, the underlying connection may have been lost unexpectedly.");
42+
} else if (!(err instanceof ClosedConnectionException)) {//GitHub actions build is sometimes losing the connection to the DB in this test for some reason
43+
ctx.fail("The error message returned is of the wrong type. It should be a DB2Exception, but it was of type " + err.getClass().getName());
4844
}
4945
}));
5046
}
@@ -228,7 +224,7 @@ public void testDuplicateKeys(TestContext ctx) {
228224
conn.query("INSERT INTO immutable (id, message) VALUES (1, 'a duplicate key')").execute(ctx.asyncAssertFailure(err -> {
229225
ctx.assertTrue(err instanceof DB2Exception, "The error message returned is of the wrong type. It should be a DB2Exception, but it was of type " + err.getClass().getSimpleName());
230226
DB2Exception ex = (DB2Exception) err;
231-
227+
232228
assertContains(ctx, ex.getMessage(), "Duplicate keys were detected on table ");//Db2/z doesn't send back table name + options.getUser().toUpperCase() + ".IMMUTABLE");
233229
ctx.assertEquals(SqlCode.DUPLICATE_KEYS_DETECTED, ex.getErrorCode());
234230
}));
@@ -285,11 +281,11 @@ public void testDuplicateObject(TestContext ctx) {
285281
}));
286282
}));
287283
}
288-
289-
//This test has to be run manually, I haven't found a good way to automate stopping a DB2 connection that doesn't end gracefully
290-
//To run this, uncomment @Test and use mvn test -Dtest=DB2ErrorMessageTest#testInflightCommandsFailWhenConnectionClosed
291-
//During the 60 second wait call 'docker kill <container_id>', docker stop will end gracefully, so it has to be docker kill.
292-
//@Test
284+
285+
//This test has to be run manually, I haven't found a good way to automate stopping a DB2 connection that doesn't end gracefully
286+
//To run this, uncomment @Test and use mvn test -Dtest=DB2ErrorMessageTest#testInflightCommandsFailWhenConnectionClosed
287+
//During the 60 second wait call 'docker kill <container_id>', docker stop will end gracefully, so it has to be docker kill.
288+
//@Test
293289
public void testInflightCommandsFailWhenConnectionClosed(TestContext ctx) {
294290
DB2Connection.connect(vertx, options, ctx.asyncAssertSuccess(conn1 -> {
295291
conn1.query("CALL dbms_alert.sleep(60)").execute(ctx.asyncAssertFailure(t -> {

vertx-db2-client/src/test/java/io/vertx/db2client/tck/DB2PreparedQueryCachedTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ protected void cleanTestTable(TestContext ctx) {
5555
@Override
5656
public void testPrepareError(TestContext ctx) {
5757
msgVerifier = (err) -> {
58-
ctx.assertEquals("The object '" + rule.options().getUser().toUpperCase() + ".DOES_NOT_EXIST' provided is not defined", err.getMessage());
58+
ctx.assertTrue(err.getMessage().startsWith("The object '" + rule.options().getUser().toUpperCase() + ".DOES_NOT_EXIST' provided is not defined"));
5959
};
6060
super.testPrepareError(ctx);
6161
}

vertx-db2-client/src/test/java/io/vertx/db2client/tck/DB2PreparedQueryTestBase.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
package io.vertx.db2client.tck;
22

3+
import io.vertx.db2client.junit.DB2Resource;
4+
import io.vertx.ext.unit.TestContext;
5+
import io.vertx.sqlclient.tck.PreparedQueryTestBase;
36
import org.junit.Before;
47
import org.junit.ClassRule;
5-
import org.junit.Ignore;
68
import org.junit.Rule;
79
import org.junit.Test;
810
import org.junit.rules.TestName;
911

10-
import io.vertx.db2client.junit.DB2Resource;
11-
import io.vertx.ext.unit.TestContext;
12-
import io.vertx.sqlclient.tck.PreparedQueryTestBase;
13-
1412
public abstract class DB2PreparedQueryTestBase extends PreparedQueryTestBase {
1513

1614
@ClassRule
@@ -48,7 +46,7 @@ protected boolean cursorRequiresTx() {
4846
@Override
4947
public void testPrepareError(TestContext ctx) {
5048
msgVerifier = (err) -> {
51-
ctx.assertEquals("The object '" + rule.options().getUser().toUpperCase() +".DOES_NOT_EXIST' provided is not defined", err.getMessage());
49+
ctx.assertTrue(err.getMessage().startsWith("The object '" + rule.options().getUser().toUpperCase() + ".DOES_NOT_EXIST' provided is not defined"));
5250
};
5351
super.testPrepareError(ctx);
5452
}

vertx-mssql-client/src/main/java/io/vertx/mssqlclient/MSSQLException.java

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,29 @@
1111

1212
package io.vertx.mssqlclient;
1313

14+
import io.vertx.sqlclient.DatabaseException;
15+
1416
import java.util.ArrayList;
1517
import java.util.List;
1618

1719
/**
18-
* A {@link RuntimeException} signals that an error occurred.
20+
* The {@link DatabaseException} for MS SQL Server.
1921
*/
20-
public class MSSQLException extends RuntimeException {
22+
public class MSSQLException extends DatabaseException {
2123

22-
private final int number;
2324
private final byte state;
2425
private final byte severity;
25-
private final String message;
26+
private final String errorMessage;
2627
private final String serverName;
2728
private final String procedureName;
2829
private final int lineNumber;
2930
private List<MSSQLException> additional;
3031

31-
public MSSQLException(int number, byte state, byte severity, String message, String serverName, String procedureName, int lineNumber) {
32-
super(null, null, false, false);
33-
this.number = number;
32+
public MSSQLException(int number, byte state, byte severity, String errorMessage, String serverName, String procedureName, int lineNumber) {
33+
super(formatMessage(number, state, severity, errorMessage, serverName, procedureName, lineNumber), number, null);
3434
this.state = state;
3535
this.severity = severity;
36-
this.message = message;
36+
this.errorMessage = errorMessage;
3737
this.serverName = serverName;
3838
this.procedureName = procedureName;
3939
this.lineNumber = lineNumber;
@@ -46,8 +46,12 @@ public void add(MSSQLException e) {
4646
additional.add(e);
4747
}
4848

49+
/**
50+
* @deprecated use {@link #getErrorCode()} instead
51+
*/
52+
@Deprecated
4953
public int number() {
50-
return number;
54+
return getErrorCode();
5155
}
5256

5357
public byte state() {
@@ -59,7 +63,7 @@ public byte severity() {
5963
}
6064

6165
public String errorMessage() {
62-
return message;
66+
return errorMessage;
6367
}
6468

6569
public String serverName() {
@@ -74,14 +78,20 @@ public int lineNumber() {
7478
return lineNumber;
7579
}
7680

77-
@Override
78-
public String getMessage() {
81+
/**
82+
* @return additional errors reported by the client, or {@code null}
83+
*/
84+
public List<MSSQLException> additional() {
85+
return additional;
86+
}
87+
88+
private static String formatMessage(int number, byte state, byte severity, String errorMessage, String serverName, String procedureName, int lineNumber) {
7989
StringBuilder sb = new StringBuilder("{")
8090
.append("number=").append(number)
8191
.append(", state=").append(state)
8292
.append(", severity=").append(severity);
83-
if (message != null && !message.isEmpty()) {
84-
sb.append(", message='").append(message).append('\'');
93+
if (errorMessage != null && !errorMessage.isEmpty()) {
94+
sb.append(", message='").append(errorMessage).append('\'');
8595
}
8696
if (serverName != null && !serverName.isEmpty()) {
8797
sb.append(", serverName='").append(serverName).append('\'');
@@ -90,9 +100,6 @@ public String getMessage() {
90100
sb.append(", procedureName='").append(procedureName).append('\'');
91101
}
92102
sb.append(", lineNumber=").append(lineNumber);
93-
if (additional != null) {
94-
sb.append(", additional=").append(additional);
95-
}
96103
return sb.append('}').toString();
97104
}
98105
}

vertx-mssql-client/src/main/java/io/vertx/mssqlclient/impl/codec/TdsMessageCodec.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import io.netty.buffer.ByteBufAllocator;
1515
import io.netty.channel.ChannelHandlerContext;
1616
import io.netty.channel.CombinedChannelDuplexHandler;
17-
import io.vertx.core.impl.NoStackTraceThrowable;
17+
import io.vertx.sqlclient.ClosedConnectionException;
1818
import io.vertx.sqlclient.impl.command.CommandBase;
1919
import io.vertx.sqlclient.impl.command.CommandResponse;
2020

@@ -64,7 +64,7 @@ private void fail(ChannelHandlerContext ctx, Throwable cause) {
6464

6565
@Override
6666
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
67-
fail(ctx, new NoStackTraceThrowable("Fail to read any response from the server, the underlying connection might get lost unexpectedly."));
67+
fail(ctx, ClosedConnectionException.INSTANCE);
6868
super.channelInactive(ctx);
6969
}
7070

vertx-mysql-client/src/main/java/io/vertx/mysqlclient/MySQLBatchException.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
package io.vertx.mysqlclient;
1313

14+
import io.vertx.core.VertxException;
15+
1416
import java.util.HashMap;
1517
import java.util.List;
1618
import java.util.Map;
@@ -19,14 +21,14 @@
1921
* {@code MySQLBatchException} is thrown if an error occurs during executions when using {@link io.vertx.sqlclient.PreparedQuery#executeBatch(List)}.
2022
* The client will try to execute with all the params no matter if one iteration of the executions fails, the iteration count is counted from zero.
2123
*/
22-
public class MySQLBatchException extends RuntimeException {
24+
public class MySQLBatchException extends VertxException {
2325
/**
2426
* A mapping between the iteration count and errors, the key is consistent with the batching param list index.
2527
*/
2628
private final Map<Integer, Throwable> iterationError = new HashMap<>();
2729

2830
public MySQLBatchException() {
29-
super("Error occurs during batch execution");
31+
super("Error occurs during batch execution", true);
3032
}
3133

3234
/**

0 commit comments

Comments
 (0)