Bug #1587
closedHow can I handle errors of the type 'xml input file does not exist?
100%
Description
I downloaded Saxon-CE version 1.0 and after getting some code to work, I have attempted to implement one of the solutions for passing parameters from the URL to the HTML file to the XSLT transform object. That seems to work but the Javascript API method for handling errors does not handle the error that happens when the processor executes the asynchronous GET for the xml input file, upon with the transformation takes place.
Below are the scripts that make up the bulk of the booting in the HTML file. As you can see from the code, I'm expecting Saxon.requestXML(xmlfile) to return null if the file does not exist. But it apparently always returns some object. Likewise, I'm expecting proc.updateHTMLDocument(xml) to raise an exception but it doesn't either. I believe that the GET on the xml file being done asynchronously is the cause of the problem with the error not being raised. So, how can such an exception be trapped? How many other exceptions might not be catchable?
@<script type="text/javascript" language="javascript" src="../SaxonceDebug/Saxonce.nocache.js"></script>
<script type="text/javascript" language="javascript"> var errors = new Array(); function errorHandler(saxonError) { errors.push(saxonError.message + " " + saxonError.level + " " + saxonError.time); } function getURLParams() { var params = {}; var hrefstr = window.location.href; hrefstr.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { params[key] = value; }); return params; } function onSaxonLoad() { var params = getURLParams(); var xmlfile = params['xmlfile']; if (xmlfile == null) { document.getElementById('status').innerHTML = "The 'xmlfile' parameter is not present in the URL.
"; return; } Saxon.setErrorHandler(errorHandler); Saxon.setLogLevel("FINE"); var xml = Saxon.requestXML(xmlfile); try { xml = Saxon.requestXML(xmlfile); if (xml == null) { document.getElementById('status').innerHTML = "The 'xmlfile' parameter specifies a filename, '" + $xmlfile + "', that cannot be read."; return; } } catch(e) { window.alert('requestXML: ' + e.message); } var xsl = Saxon.requestXML('prof.xsl'); var proc = Saxon.newXSLT20Processor(xsl); proc.setParameter(null, 'xmlfile', xmlfile); document.getElementById('status').innerHTML = "
Page loading...
"; try { proc.updateHTMLDocument(xml); } catch(e) { window.alert(e.message); } if (errors.length > 0) { window.alert(errors.toString()); } } </script>@Updated by Philip Fearon over 12 years ago
When using setErrorHandler, exceptions are intentionally blocked by Saxon-CE (though there may potentially be some unhandled exceptions). Instead it is left for the developer to provide a method to keep track of exceptions through the errorHandler callback function - possibly by keeping a count of the number of error messages or by throwing your own exception.
In light of this, it will probably keeps things simpler not to use setErrorHandler. This errorHandler feature was really provided to allow third-party tools to replace or enhance the functionality of the developer console logging - hence the need to prevent exceptions so they wouldn't interfere with logging.
With no errorHandler callback set, exceptions for asynchronous operations should be thrown in the same way as for synchronous operations. All exceptions should therefore be catchable.
Updated by Jeff Holt over 12 years ago
Hi, Philip. I've been waiting to see if an update shows up from your email server as a result of my replying to an email I received on your response. It doesn't look like it will, so I'll duplicate it here.
If I understand you correctly, then simply removing the call to setErrorHandler() should allow me to catch all errors from the method that throws an exception, which I presume to be updateHTMLDocument.
I tried that and it doesn't work. The console says an exception is thrown but it isn't being caught by the code shown in the original post.
SaxonCE.XSLT20Processor 20:54:53.635
SEVERE: Exception java.lang.RuntimeException in onResponseReceived: HTTP Error 404 Not Found for URI http://localhost/...
I can clearly see from the FINEST logging that the GET that results in a 404 is being submitted asynchronously. As an aside, I fail to see why it's necessary to do that operation asynchronously, not do I see why I am not allowed to configure it to GET synchronously.
As I said earlier, it seems pretty obvious that the asynchronous GET is the reason why updateHTMLDocument is not throwing an exception. I strongly believe that some thread is running out of band and is writing an error to the log but is not causing the caller to throw an exception.
Updated by Philip Fearon over 12 years ago
- Tracker changed from Support to Bug
- Status changed from New to In Progress
- Assignee set to Philip Fearon
Updated by Philip Fearon over 12 years ago
Apologies for the delayed response on this one.
~~It is clearly a bug when the exception is not thrown in an asynchronous get operation and no errorHandler function has been assigned ~~ I'm looking into this and will report back when I know more.-
I've had a complete rethink on this issue. wrapping a try/catch around a function call that operates asynchronously is clearly not going to be effective here, so using your own errorHandler (registered by calling @setErrorHandler@) is actually the best (and only) option. I will run some code to ensure that this can be done effectively
Regarding the necessity of an asynchronous operation: The XSLT compile operation for long XSLT files may take some time to complete, it therefore helps to improve responsiveness if the source XML is requested asynchronously before the compile is initiated, the file can then be retrieved during the compile - it will therefore hopefully be ready as soon as compilation is complete.
The callback from the XMLHTTPRequest is involved here, and this is responsible for calling to the log handler if an exception occurs - so something is probably going awry here, which is what I think you're suggesting.
With regard to providing an option to force a synchronous operation we'll look into this but I hesitate slightly on this because whilst it simplifies error handling it does have a performance penalty. In the mean time, when you have an operation that needs to wait for a transform to complete, you can provide a callback function before intitiating the transform by calling the setSuccess(fn) function of XSLT20Processor object. (this was intended for other transform functions that return a result - so this use case hasn't been tested, but it should work equally well with updateHTMLDocument()
)
Updated by Philip Fearon over 12 years ago
To test the callback worked for asynchronously operations, I ran the following code where the file tryx.xml does not exist:
<script type="text/javascript" language="javascript">
onComplete = function() {
window.alert("complete");
}
var onError = function(saxonError) {
window.alert(saxonError.message);
}
onSaxonLoad = function() {
Saxon.setErrorHandler(onError);
Saxon.run( {
stylesheet: 'try.xsl',
source: 'tryx.xml',
logLevel: 'SEVERE',
success: onComplete
} );
}
</script>
As expected, the onError
callback was initiated and, in this case, the window.alert() showed the HTTP 404 error message. Running the test again, but with the 'tryx.xml' file existing, a callback to onComplete
was made and this time the window.alert() showed 'complete' - again as expected. This shows that these two callbacks can be used with the updateHTMLDocument function so that a status message can be updated to reflect the success or failure of a transform.
However, when using the above code in the XMLQuire-WE XSLT editor (extended for Saxon-CE), there was an issue: The onError
callback was never made - even though XMLQuire's own 'Saxon-CE' console showed the 404 error. What's actually happening here is that Saxon-CE has logic that assumes that the errorHandler callback can be overriden if an external system such as XMLQuire registers to handle errors through the external system interface. This logic is at fault and is therefore a bug which has been fixed for the next maintenance of Saxon-CE - I'm not sure if this affects you as this only affects Saxon-CE when the browser in use is actually hosted by XMLQuire (no other editors yet use the external system interface that causes this issue).
Updated by Jeff Holt over 12 years ago
Thanks, Philip, for your very prompt attention. What I'm working on is in the very early stages and so I would say that if the next release comes within, say, 6 months, then I would be quite satisfied.
When I early suggested that I needed control over the synchronous nature of the code that performs the GET, I was not thinking clearly. I somehow got it into my mind that the reading of the XML file was performed upon the filesystem. It's embarrassing that I could see evidence of an HTTP GET but still think the XML file was being read from the filesystem.
Therefore, I retract my request for control over the synchronous nature of the code that performs the GET.
Updated by Philip Fearon over 12 years ago
- Status changed from In Progress to Resolved
Ok Jeff, thanks for getting back to us - while we don't give timelines, its ressonably safe to say the next maintenance release for Saxon-CE will be well within your time-frame.
For info: it is possible (though not recommended for most circumstances because browsers need additional privileges) to use Saxon-CE with the file system if you're using URIs starting with file://
In this case, we do actually switch to synchronous requests to avoid issues with error handling.
Please let us know if you have any other issues or questions.
Updated by O'Neil Delpratt almost 12 years ago
- Status changed from Resolved to Closed
- Sprint/Milestone set to Release 1.1
- % Done changed from 0 to 100
- Found in version set to 1.0
- Fixed in version set to 1.1
Bug fixed for Saxon-CE version 1.1 release
Please register to edit this issue