Acrobat User Community

Exception handling in Acrobat JavaScript

By Thom ParkerDecember 7, 2008

While Exception Handling sounds like a difficult topic, it is really quite simple. Exceptions are JavaScript’s way of handling most errors. They are an important feature of Core JavaScript, and a basic understanding of how exceptions work is important for effective scripting in Acrobat.

What’s an exception?

An exception is a message the JavaScript Engine passes into the script to let it know something has gone wrong. Specifically, messages from the JavaScript Engine are about something that went wrong with Acrobat JavaScript execution, such as a variable that is undefined or a bad parameter passed into a function. The process of passing the exception message into the script is called throwing an exception. Exceptions can be thrown by scripts, as well as by the JavaScript Engine, so you can make your own exception messages.

The script receives the exception message by catching it. Catching an exception is done with a special structure called a try/catch block. If a script does not contain a try/catch block, then it misses the exception message and the message is thrown up to the next script in the call stack. The call stack is a structure in the JavaScript Engine used to keep track of function calls, i.e., functions calling functions, where each function is considered as a different script. This process of throwing the exception up the call stack continues until the top level is reached. If no script has caught the exception by this point, then the exception message is displayed in the Acrobat JavaScript Console.

Checking for reported errors (exception messages) in the JavaScript Console is the simplest and most common use of exceptions in Acrobat JavaScript. Even users who have never heard of an exception can go to the Console window to look for reported errors.

Catching exceptions in code

Errors reported to the Console window are important and necessary for debugging code, but what about exceptions thrown during normal operation? There are situations where we can anticipate that a piece of code might throw an exception. In fact, sometimes we might even deliberately design code to expect and use the exception. For these situations, it’s necessary to use a try/catch block.

To try this out, we will need a piece of useful code that could reasonably throw an exception at runtime. A good example is the app.openDoc() function. Say for example we’re creating a complex form with a separate help file (think tax forms). In key areas of the form we place a Help button with a script for opening the Help file and navigating to a particular Help topic.

var myHelpDoc = app.openDoc("HelpMe.pdf");
myHelpDoc.gotoNamedDest("topic1");

However, since the Help file is separate from the form, there is no guarantee it will be available. If the help file is not there, then the app.openDoc() function will throw an exception. Try running the app.openDoc() line of code in the Console window to see what happens. The screen shot below is from Acrobat 8 Professional, version 8.12. Different versions of Acrobat may report different error messages.

Figure 1: Exception thrown in Console window.

The error message displayed in Figure 1 doesn’t match the actual problem. This is an unfortunate bug caused by changes in Acrobat’s security model. In Acrobat 7, the message correctly reports an invalid file path.

Regardless, in this case we’d like to catch the exception and give the user a helpful message. Try running the following code in the JavaScript Console. It uses a try/catch block to catch the exception thrown by the app.openDoc() code when the Help file does not exist, then displays a popup-alert box letting the user know they are missing a document.

try{
	var myHelpDoc = app.openDoc("HelpMe.pdf");
	myHelpDoc.gotoNamedDest("topic1");
}catch(e){
	app.alert("Cannot find the Help File, donĂ­t bug me again");
}

The code we want to test for an exception is contained within the curly braces in the try{} block. When a line of code throws an exception, execution stops immediately at that point and is redirected into the catch{} block. Only exceptions thrown by code within the try{} block will be caught. The try{} block must be followed immediately by a catch{} block, and the code in the catch block is only run when an exception is caught.

Notice that the catch block looks very much like a function. The parameter inside the parentheses, “e,” is the actual exception message. It is usually an Error Object containing useful information, such as the line number the error occurred on, the name of the error and descriptive text. In this code, it’s not being used because we only care that the exception happened, but this syntax must be followed exactly for the try/catch to work.

Making your own exceptions

At this point, we’ve covered all the basics on using exceptions in your code. This next bit covers throwing your own exceptions and is a little more advanced.

There are a couple situations where creating exceptions are useful; for example, if you are creating objects or functions that will be used as part of a library. In this case, you’ll want your functions to detect usage errors, such as passing in a bad parameter. These exceptions can then be used during debugging by anyone who uses your library.

Another situation is more complex. If you are writing a complex and involved set of scripts, exceptions can be used as a sophisticated error-control scheme within your program. The details of such a scheme are far beyond the scope of this article. All we’ll cover here is how to throw your own exception, and as it turns out, it’s pretty easy.

Remember that “e” parameter in the catch(e){} block. It’s the thing that’s thrown the message. Normally it’s an Error Object, but the fact is it could be anything- a string, a number, a custom object, anything. An exception is thrown with the keyword throw, so the following code throws an exception using a string as the message. Try running it from the Console window:

throw "My Exception Test"

Here are the results:

Figure 2: Custom Exception using String.

Of course, the proper way to throw an exception is with an error object. There is a generic error object in Core JavaScript and several pre-defined error objects. You can look these up in any good JavaScript Reference. One big advantage of using the pre-defined error objects is that Acrobat adds some more information to them, such as the line number and file name when one is thrown. You can find out more about this extra information in the Acrobat JavaScript Reference.

Here’s an example function that throws a TypeError:

function MyAdd(a,b) {
	if(typeof(a) != "number") throw new TypeError("Input 'a' is not a number");
	if(typeof(b) != "number") throw new TypeError("Input 'b' is not a number");
	return a + b;
}

The “MyAdd” function tests the inputs before performing the addition, then throws a TypeError exception if any inputs are not a number. Copy the function into the Console window and add the code below to try it. Change some of the parameters around to experiment with how it works.

try{
	MyAdd("Foo",10);
}catch(e){
	console.println(e.name+" on line:" +e.lineNumber+ " : " +e.message);
}

Figure 3: Using the built-in TypeError.

More information

There’s actually much more to exceptions than I’ve covered here. Find out more about exception handling, the Error Object and the code used in this article in the following references:

My favorite Core JavaScript reference is:

“The Definitive JavaScript Guide” from O’Reilly.
The official Core JavaScript web reference is here:
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference

The official Acrobat JavaScript Reference and Guide can be found on this web page:
https://www.adobe.com/devnet/acrobat.htmljavascript.html

Acrobat JavaScript tutorials and samples can be found at this WindJack Solutions’ site:
http://www.pdfscripting.com