I've got some code to parse an XML file like this:
[doc := (XML.XMLParser new) parse: aFilename asURI] on: XML.SAXParseException
do: [:ex | MyCustomError raiseSignal: ex description].
I now want to handle the MyCustomError higher in the stack, by moving the XML file to a folder named 'Failed', but I get a sharing violation error because the parser has not had the opportunity to close the file.
If I alter my code like this it works, but I wonder if there is a better way:
[doc := (XML.XMLParser new) parse: aFilename asURI] on: XML.SAXParseException
do: [:ex | description := ex description].
description ifNotNil: [MyCustomError raiseSignal: description].
Code can signal an exception for errors which are resumable (non-fatal); if you trap such an error you can't be certain that the XMLParser isn't intending to keep on going. For example, code that doesn't know whether it's being called in interactive or batch mode might signal an exception for a simple informational message; the caller would know whether to handle it in an interactive way (say with a message prompt) or a batch way (writing a message to a log file).
In order for this to work the pieces of code that are communicating in this way have to know what sort of an error it is they're dealing with. (This would typically be done with a severity level, encoded either by state in the exception object or by raising a different class of exception.) If you inspect the ex object you might be able to see this information.
In any case, the evidence suggests that XMLParser is treating SAXParseException as a resumable error (otherwise, it should clean up after itself). That being so, your "fix" seems appropriate enough.
you can also run the parser on a ReadStream instead of a URL. Then you can wrap your code in an ensure block where you close the readStream.
Related
I'm trying to write a script to test all DataSources of a WebSphere Cell/Node/Cluster. While this is possible from the Admin Console a script is better for certain audiences.
So I found the following article from IBM https://www.ibm.com/support/knowledgecenter/en/SSAW57_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/txml_testconnection.html which looks promising as it describles exactly what I need.
After having a basic script like:
ds_ids = AdminConfig.list("DataSource").splitlines()
for ds_id in ds_ids:
AdminControl.testConnection(ds_id)
I experienced some undocumented behavior. Contrary to the article above the testConnection function does not always return a String, but may also throw a exception.
So I simply use a try-catch block:
try:
AdminControl.testConnection(ds_id)
except: # it actually is a com.ibm.ws.scripting.ScriptingException
exc_type, exc_value, exc_traceback = sys.exc_info()
now when I print the exc_value this is what one gets:
com.ibm.ws.scripting.ScriptingException: com.ibm.websphere.management.exception.AdminException: javax.management.MBeanException: Exception thrown in RequiredModelMBean while trying to invoke operation testConnection
Now this error message is always the same no matter what's wrong. I tested authentication errors, missing WebSphere Variables and missing driver classes.
While the Admin Console prints reasonable messages, the script keeps printing the same meaningless message.
The very weird thing is, as long as I don't catch the exception and the script just exits by error, a descriptive error message is shown.
Accessing the Java-Exceptions cause exc_value.getCause() gives None.
I've also had a look at the DataSource MBeans, but as they only exist if the servers are started, I quickly gave up on them.
I hope someone knows how to access the error messages I see when not catching the Exception.
thanks in advance
After all the research and testing AdminControl seems to be nothing more than a convinience facade to some of the commonly used MBeans.
So I tried issuing the Test Connection Service (like in the java example here https://www.ibm.com/support/knowledgecenter/en/SSEQTP_8.5.5/com.ibm.websphere.base.doc/ae/cdat_testcon.html
) directly:
ds_id = AdminConfig.list("DataSource").splitlines()[0]
# other queries may be 'process=server1' or 'process=dmgr'
ds_cfg_helpers = __wat.AdminControl.queryNames("WebSphere:process=nodeagent,type=DataSourceCfgHelper,*").splitlines()
try:
# invoke MBean method directly
warning_cnt = __wat.AdminControl.invoke(ds_cfg_helpers[0], "testConnection", ds_id)
if warning_cnt == "0":
print = "success"
else:
print "%s warning(s)" % warning_cnt
except ScriptingException as exc:
# get to the root of all evil ignoring exception wrappers
exc_cause = exc
while exc_cause.getCause():
exc_cause = exc_cause.getCause()
print exc_cause
This works the way I hoped for. The downside is that the code gets much more complicated if one needs to test DataSources that are defined on all kinds of scopes (Cell/Node/Cluster/Server/Application).
I don't need this so I left it out, but I still hope the example is useful to others too.
When exceptions occur in a UIPath project I have an email that is sent out with the exception info included. There seems to be an issue though where I can only see where the error occured by looking at the selector information such as:
Cannot find the UI element corresponding to this selector:
<html app='chrome.exe' title='Microsoft Dynamics GP' />
<webctrl aaname='Add' idx='1'
parentid='a00000000000000008549000000030009000000000001000000000000' tag='DIV' />
This info and the stack trace or any other info is not really helpful for quickly finding the source of the problem. I have looked through the UIPath documentation and forum and found only the this question, which seemed to point to using the exception.Source to show the name of the activity where the error occurred. exception.Source only returns “UiPath.Core.Activities” though instead of "Type into Copy Job# 'INPUT'" in the following example:
This obviously causes a big problem with exception handling. How can I easily return the source with each exception?
When your selector fails, you will end up with a new object of type UiPath.Core.SelectorNotFoundException. However, until the team at UiPath decides to add the Display Name into the inner exception, there is little you can do in this particular case.
Take the following example - the first line shows the Inner Exception, and the second one in red is essentially just the exception being rethrown. Note that only the latter one contains the Display Name property.
The Source itself will usually be of type UiPath.Core.Activities, but since this is just the type's name, we don't have any link to the faulting object. Here's what you can do:
Add some details to your exception. You don't want to do this for each activity, but you could have certain blocks of try-catches (example: logging into the system consists of three individual activites, and they reside in one block).
Rethrow the exception. That way the Display Name will end up in the execution log file.
Having:
Velocity template or macro
some object
How to validate the object (#if) and fail (stop further processing) in a way that is easily tracable to the place of failure (like throwing exception in Java).
I am looking for something like this:
#if ( ! $context.treasureMap.containsKey('gold'))
#fail('no golden treasure here')
#end
Background
I am writing a maven site page. The velocity context is injected by maven and contains POM information. I want to test existence of some information from effective pom. When the information is not available, I want to fail.
Requirements
fail Velocity processing > fail site generation > fail maven build.
error message should lead to the place of failure so the site should be fixed
preferably no configuration (no extensions, just constructs/tools contained in plain Velocity)
Tried
Strict Reference Mode
Unwanted configuration, do not want to fail on every occasion.
#evaluate('#end') aka syntax error
(Chose #end as most descriptive to my intent) Basically what I want. Fails the processing and maven build but the error message does not lead back to failure location:
ParseException: Encountered "#end" at line 1, column 1..
You need to make a method call which produce exception.See explanation:
The only place where one could run into trouble within Velocity is if there is a call to a method which throws an exception during runtime. For example, this VTL defines a String $foo and then attempts to call its substring() method on it would throw an IndexOutOfBoundsException:
#set ($foo = "bar")
#set ($bar = $foo.substring(0,10))
When the exception is thrown, the parser will stop processing and throw that exception up the stack tree where it can be caught in the method that caused the parser to execute. At that point, the exception can be handled gracefully.
I'm using the Slim Framework.
Most PHP errors in my application output normal PHP error messages
Example code with an error that outputs the Call Stack:
echo 'missing semicolon at eol'
Error Output:
Parse error: syntax error, unexpected T_IF, expecting ',' or ';' in /data/www/app/routes/companies_routes.php on line 737
Call Stack:
0.0002 637144 1. {main}() /data/www/html/index.php:0
But other errors ( maybe just notices ) output a limited message that doesn't have a line number, file name, or call stack. This makes debugging these errors extremely time consuming.
Code with an error that outputs a limited error message
echo $an_undefined_variable;
Limited Message
Undefined variable: an_undefined_variable
I can't figure out what's going on. I've never had this problem before. I suspect it has something to do with the way Slim handles PHP errors. I've tried wrapping these errors in Try/Catch blocks, but that doesn't solve the problem.
The problem is that Slim is handling exceptions itself ( some sort of default behavior I've yet to track down ).
I've got my code wrapped in Try/Catch blocks, so when Slim catches a PHP error, it's throwing it's own Exception that I'm then outputting in my Catch block. If I remove my Catch block, Slim them outputs it's own complete error message that contains the stack as usual.
This surely means I'm not using Slim quite right, but that's a different question.
I am reading some lines from a CSV file, converting them to business objects, aggregating these to batches and passing the resulting aggregates to a bean, which may throw an PersistenceException.
Somehow like this:
from(file:inputdir).split().tokenize("\n").bean(a).aggregate(constant(true), new AbstractListAggregationStrategy(){...}).completionSize(3).bean(b)
I have a onException(Exception.class).handled(true).to("file:failuredir").log(). If an exception occurs on bean(a), everything is handled as expected: wrong lines in inputdir/input.csv are written to failuredir/input.csv.
Now if bean(b) fails, Camel seems to fail reconstructing the original message:
message.org.apache.camel.component.file.GenericFileOperationFailedException: Cannot store file: target/failure/ID-myhostname-34516-1372093690069-0-7
Having tried various attempts to get this working, like using HawtDBAggregationRepository, toggling useOriginalMessage at onException and propagating back the exception in my AggregationStrategy, I am out of ideas.
How can I achieve the same behaviour for bean(b) which can be seen with bean(a)?
The aggregator is a stateful EIP pattern, so when it sends out a message, then its a new Exchange. So the bean(b) cannot get access to the original message that came from the file route.