Is it just me, or is all exceptions from system.db.runXXXXX
methods raised as java.lang.Exception
? Would be really nice to be able to catch e.g. exceptions like constraint violation exceptions without catching SQL errors.
When running queries from the query browser they are raised properly, just seems like in scripts they are all the same.
If you follow the chain of âcaused byâ youâll get to the underlying SQL Exception. See .getCause().
Thank you, tried that. However, this boils down to a com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException
which I can not compare to, as trying to import this in my script gives me the error
import error, no module named 'mysql'.
I know there must be something I can do to be able to import this, just can't keep thinking that's a lot of work done trying to catch a simple error?
You canât import these. Even in the gateway, theyâre in isolated classloaders. Fortunately, JDBC requires all driver exceptions to extend SQLException, which you can catch or find in the cause hierarchy, and then examine the exceptionâs reason and simple classname for further decisions.
Must be tired, canât seem to figure this out 
Would really appreciate if you would make an example catching e.g. the constraint violation exception.
Tried catching the SQLException, this is just ignored and catching the java.lang.Exception just boils down to the MySQLIntegrityConstraintViolationException when looking at the causes.
Writing some SQL deleting from a table which can be referenced from a lot of other tables and really donât want to write a query that checks these constraints when I know I can just catch an exception.
Something like this:
import java.lang.Exception
from java.sql import SQLException
try:
# whatever
pass
except java.lang.Exception, e:
# Find SQL cause
sqle = e
while sqle:
if SQLException.isInstance(sqle):
break
sqle = sqle.cause
if sqle:
# Look closer at the SQL Exception
print sqle.reason, sqle.getClass().simpleName
else:
# rethrow non-sql exceptions
raise e
EDIT:
Fixed .isinstance()
=> .isInstance()
. Java method for [class objects](file:///usr/share/doc/java-sdk-docs-1.8/html/api/java/lang/Class.html), fwiw.
2 Likes
My code
try:
system.db.runPrepUpdate("DELETE FROM test WHERE id = ?", [tid])
except (java.lang.Exception), e:
sqle = e
while sqle:
if isinstance(sqle, SQLException):
break
sqle = sqle.cause
if sqle:
print "THE REASON:", sqle.reason, "THE CLASS:", sqle.getClass().simplename
else:
raise e
This reraises the exception at raise e
. Seems like SQLException isnât found.
In your example you used SQLException.isinstance(sqle)
, this gives SQLException doesnât have attribute âisinstanceâ error.
EDIT: Fixed copye paste indent errors
Seems like even though looping the causes of the raised java.lang.Exception ends with the MySQLIntegrityConstraintViolationException, which, according to docs, should be a subclass of SQLException, any comparison I can think of (isinstance(e, SQLException), issublcass(e.getClass(), SQLException)) results in False result.
Only thing that seems to work is
if "MySQLIntegrityConstraintViolationException" in str(sqle):
EDIT: Below seems to solve my problem until I figure out the right way to catch that error (probably never unless someone provide a solution
)
try:
system.db.runPrepUpdate("DELETE FROM test WHERE id = ?", [tid])
except (java.lang.Exception), e:
while e:
if "MySQLIntegrityConstraintViolationException" in str(e):
break
e = e.getCause()
else:
raise
Whoops. Typo. Should be SQLException.isInstance(sqle)
. Sorry.
Also returns False when comparing to the MysqlâŚvery.long.exception.nameâŚViolationException
In my test I am using MS SQL Server, and although com.microsoft.sqlserver.jdbc.SQLServerException
extends java.sql.SQLException
, the exception in Ignition is never an instance of SQLException
.
Sample code:
from java.lang import Exception as JException
try:
# Something to try.
except JException, e:
sqle = e
while sqle:
print 'Class: %s. Cause: %s' % (sqle.__class__.__name__, sqle.cause)
sqle = sqle.cause
The output:
Class: Exception. Cause: com.inductiveautomation.ignition.client.gateway_interface.GatewayException: Parameter x was not defined for stored procedure y.
Class: GatewayException. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: Parameter x was not defined for stored procedure y.
Class: GatewayResponse$GatewayThrowable. Cause: None
In my case, the inner most exception is never an instance of SQLException
but an instance of the inner class GatewayThrowable
. Not sure if this is by design or if this is unintended behavior.
It would be nice, though, to be able to retrieve the actual instance of the exception.
3 Likes
That's interesting. The true cause exception probably can't be deserialized outside the gateway since the JDBC driver classes aren't loaded elsewhere.
Only solution I found that is able to catch the exception is (using MySQL off course)
while e:
if "MySQLIntegrityConstraintViolationException" in str(e):
break
e = e.getCause()
else:
raise
Also, the only way I found to get the actual exception type is using str(e) which will resolve into, in my case, the MySQL exception, just printing/checking against the class name never shows any of the causes as a MySQL exception, just gateway exceptions.
Thanks @cesrom this worked for me.