system.db.runUpdateQuery Exception Handling

Running system.db.runUpdateQuery inside try/except clause, if the code is failed by sql (e.g. wrong data format, duplicate name, etc.), try/except fails to handle the SQL thrown exceptions, is this as expected?

2 Likes

Normal jython try: -- except: won't trap java exceptions. You often need two except: clauses, the first being except java.lang.Throwable, t: or similar.

Some related discussions.

Note that when catching such exceptions in Vision Client scope or Designer scope, the real SQL exception is not available--it won't serialize and the JDBC classes don't exist in those scopes anyways.

2 Likes

Thank you for the prompt help,

@CTavakoli how did you solve it? can you share your python code?

Cheers, Alex

@Alex_SHARIKOV below is a sample code:

@CTavakoli,

Please remove the screenshot. Put your pasted text of your code back in place. Highlight it all. Then click the "Preformatted Text" button in the comment editor. That will make a nicely formatted code block with all the nice features.

I think it would be cleaner like this

from java.lang import Throwable
results = {"success": None, "error": None}
try:
	results["success"] = something_to_try()
except Exception, e:
	results["error"] = e
except Throwable, t:
	results["error"] = t

return results

If you're catching Throwable and doing the same thing, there's no reason to catch Exception first; Exception is a subclass of Throwable.

No, Exception in this usage is jython's Exception. Sneaky. I like it. (This is what I do, too.)

3 Likes

Thanks @dkhayes117 and @CTavakoli

Sorry for long replay :slight_smile:

I had different requirements for my error handling mechanism. The requirements:

  1. It should look clean in the View component:
    a. only one except clause so it’s easily repeated in other components (less code duplication)
    b. the error handling happens in the standalone script
  2. Error handling raise depends on the location of the error occurred:
    a. If an error occurred during development in Designer it needs to show the Native Error Window.
    b. If an error occurred during usage by an Operator it needs to display the error on the screen, so the Operator can copy/screenshot it and send it to the developers.

I posted my solution in another thread, and also see below with some comments. Your requirements must be different, so it's just for information only:

Perspective View Component script:

def runAction(self, event):
	try:
		# some nested script with an error when calling system.db.runUpdateQuery(query)
		db_helper.call_update_db_with_error()
	except:
		# this will catch all type of exceptions and pass it to the .error() function
		utils.error(self)

Custom script module in Scripting:

def error(_self):
	# this provides the information on type and stack trace of the exception
	ex_type, ex, stacktrace = sys.exc_info()
	
	# check if exception raised by Java Throwable
	is_java_ex = type(ex_type) == type(java.lang.Exception)
	cause = str(ex.getCause()) + ' ***** ' if is_java_ex else ''
	
	# check if it was cased during the development so send back to the Designer with the cause
	if _self.session.props.device.type == 'designer':
		raise Exception, (cause, ex), stacktrace

	# else: show it on the operator screen for sending it to the developers
	trigger = ' ***** by ' + _self.name + ' from ' + _self.page.props.path
	
	message = cause + traceback.format_exc() + trigger
	params = {'message': message}
	log(message, 'error')
	system.perspective.openPopup(
		'random_id',
		'Popup/ErrorMessage',
		params=params,
		title='EXECUTION ERROR: Contact developers',
		modal=True
	)

You could get really fancy, and add a decorator implementation, so that you can do something like:

@handle_errors
db_helper.call_update_db_with_error

Probably overkill, though.

I like this idea and I don't think it is an overkill if it helps my productivity:

it's just I have a basic knowledge of decorator s so It looks like I have to decorate the most of my db_helper functions. That might create a problem of throwing an error too early when I have a nested execution of the functions in the db_helper or other script modules and I'll lose the stack trace.

But, not too sure, haven't tried it yet.