[an error occurred while processing this directive]
> developer > web app development
Handling Errors and Exceptions in XML-based Components
by Gus Kaechelin, Principle Applicaton Engineer, Novell
Date Created: 2000-11-29 11:26:00.000
  Introduction
introduction
When writing SilverStream ePortal components that generate output as HTML, it is relatively easy to handle errors or exceptions that crop up during processing. However, when generating component output as a string of XML, or more efficiently as an XML DOM object, error handling is a bit more tricky. This article details a useful approach for handling errors that may occur while processing XML-based components.

Let's assume a component uses a simple loop to create a list of documents and related descriptions. The component first checks to see if a version of its resulting XML is cached in the user's context and if so, uses it. The getComponentData method for SilverStream's ePortal component is as follows:



Notice that the code first checks for a cached version of the XML. If one does not exist, the component retrieves the XML document using the createXMLDocument method. The component then caches the returned XML document in the user's context for future reference. This technique reduces the processing requirements for data that remains static throughout a given user session.

The createXMLDocument method, for example, is simple and uses a loop to create and populate an in-memory XML DOM object. The code for this method is as follows:



When this component is installed and executed within the ePortal framework, it produces the following XML document with a content type of MIME_TYPE_XMLDOM.



And that's your component. Now, let's also assume that the following XSL document exists to style the XML generated by the above component.



With the XML-producing component and the above XSL stylesheet, the essential pieces are in place to produce the desired user output for the component. Once the generated XML document is styled by the above XSL document, the component output appears as follows:



At this point everything should be working fine. But, what if something goes terribly wrong during the runtime execution of the component? How will the error be presented to the user? With luck, a stack trace will appear on the console, but a stack trace won't be very useful to the end user. And even if it was, chances are the end user wouldn't see the console. So generally, the user is left with component output that looks like this:



It is bad form to let the user see an exception, even if it has been properly caught and re-thrown. To cure this problem, you need a simple, yet meaningful way to get exception or application error messages to the client. You can do this by adding a small amount of code to the component itself and a utility template to the XSL stylesheet.

First, make the necessary changes to the component. Start by modifying the existing catch clause of the createXMLDocument method. You no longer want to null out the XML document. Instead, you want to catch the exception, strip off its description from the class name, and add the exception string to the user's context. The resulting code for the catch is as follows:



Note that the error text is added to the user's context using a key, which is made up of a constant that represents the component's class name and the static string _ERROR. This allows many components to add error messages to the same user context without creating confusion. If the error string was simply added using the _ERROR key, another component containing the same error processing code might incorrectly process the error as its own.

The code will now handle all exceptions that might be thrown by the createXMLDocument method. The error message, however, is still the same error message that was included in the exception. This message may not be the most user-friendly, and for that reason, you may want to add an additional catch for specific exceptions. Suppose there is the potential for the createXMLDocument method to throw a security exception. You can add the following catch to handle the security exception, and instead of putting a generic error message into the user's context, use a specific, user-friendly message.



The new createXMLDocument method looks like this:



Now that the createXMLDocument method knows how to handle errors properly, you need to tell the getComponentData method how to process the errors. To do this, you'll need to make changes in getComponentData to modify the XML document that was returned from either the cache or the createXMLDocument method. You'll also need to add an error attribute to the root element of the XML document. First, check for an error in the user's context. If an error exists set its text. If there is no error, set the error text to an identifier that can be searched later by the XSL stylesheet. In this case the text will be "none".



Once the error text has been set, add it as an attribute to the root node of your XML document. First, get the root element of your XML DOM as a NodeList. Do this by using the getElementsByTagName method and pass "document_list" as the tag name of your root element. Once a node list is returned, get the first node in the list as a Node object (this is element zero of the NodeList array), and then cast it to an Element. You'll then have the root element of your XML DOM object, on which you can call the setAttribute method.



Now the component is complete. When the component executes without errors, the generated XML looks like this:



Note that the only difference between this XML document and the original is the error attribute, which is now associated with the main "document_list" node. It's this attribute that you will need to code for in your XSL stylesheet.

At this point, you'll need to make some design decisions regarding how you want your components to act when errors are encountered. For our example here, let's display the error message to the user via a JavaScript alert box on the client.

To do this, first edit the XSL stylesheet to add the following template:



This template says: If there is an error attribute on the root node and it is not equal to the value "none", add a <script> block to the generated HTML that contains an alert box. The alert box text is then set to be the text passed in the error attribute. Once this is complete, the only coding that remains is to explicitly call the handle_error template at the beginning of the XSL. Calling the handle_error template first allows the alert box to display, and then allows the styled output to display after the alert has been dismissed. This tactic is helpful when an exception or error condition is encountered after some results have already been retrieved. The updated XSL stylesheet now looks like this:



The example code is now complete. All that remains is to test it and see what the output looks like. For testing purposes, let's throw a security exception after the first iteration of the loop that builds the document nodes (in the createXMLDocuments method). This is most like a real-life scenario and provides a good test case. Now when the component executes, the following XML is generated:



When this XML is styled, the XSL stylesheet immediately calls the handle_error template, which sees that the error attribute on the root node is not equal to "none". The XSL then generates the following HTML for the component:



When this HTML is rendered in the browser, the user is first presented with this dialog box:



Once the user dismisses this dialog, the remainder of the page is rendered and looks like this:



There you have it-a simple, flexible and reusable technique to present exception and error information to the user when using XML-based components. Of course this is not the only way to handle errors and exceptions in XML-based components, but hopefully it will spur your imagination to create even more useful techniques. If you'd like the source code that was used to create this example, the component java class (ErrorHandlingExample.java) and the XSL stylesheet (ErrorHandlingExample.xsl) are included in the ErrorHandlingExample.jar file, which can be downloaded here.