If a client loses the connection to the server, it may end up throwing
an exception with SQLState 58009, which is only supposed to be thrown
if there is a protocol error caused by a programming error. If the
connection is lost, an exception with SQLState 08006 should be thrown
instead. One way to detect this situation might be to check if the
underlying cause is a SocketException, but I haven't checked if that
would work as a general solution.
More information copied from comment posted on
I'm wondering if SQLSTATE 58009 is the correct one to use in this
situation. Class 58 is reserved for implementation-defined conditions
according to the SQL standard (ISO/IEC 9075-2:2003 - Chapter 23), so
there's no mention of what it's supposed to mean there. However,
section 8.2 of DRDA V4, vol 1 (SQLSTATE Codes Referenced by DRDA) says
this about 58009:
> Execution failed due to a distribution protocol error that caused
> deallocation of the conversation.
> This SQLSTATE reports a DRDA protocol error that causes termination
> of processing for a specific command or SQL statement. When an
> application requester returns this SQLSTATE, the application
> requester must also deallocate the conversation on which the
> application server reported the protocol error.
> Each of these errors is a programming error.
> The current connection failed because the server does not support
> the requested function. A new connection is required to allow the
> successful execution of further SQL statements.
Note that this SQLSTATE is supposed to be used only if there is a
programming error leading to protocol errors or if the server does not
support the requested function. The error in Kathey's example doesn't
match any of those error conditions.
Also, I found this comment in SQLState.java which explains the
rationale for choosing this particular SQLSTATE:
// 58009 means connection is terminated. This can be caused by any number
// of reasons, so this SQL State has a lot of instances.
// NOTE: if the disconnection is not caused by DRDA-level error, you should
// use SQL State 08006. The way I determined this is if the error occurs
// in the 'client.net' package, use 58009. If it occurs in the 'client.am'
// or any other client package, use 08006. It's really not at all clear
// from the specs when you should use one SQL state or the other, but that's
// the approach I chose (David Van Couvering).
So it seems to me we should have a more intelligent logic for choosing
when to throw 58009 and when to throw 08006. As it is now, it decides
based on which package the error was detected in. I think we need to
change this so that 58009 is thrown if the client receives invalid
data from the server, and 08006 if the connection is lost. If we
change it this way, Kathey's example will throw
SQLNonTransientConnectionException (and match SQL+DRDA).