Welcome!

PowerBuilder Authors: Dan Joe Barry, Carmen Gonzalez, Ian Thain, Yakov Werde, Paul Slater

Related Topics: PowerBuilder

PowerBuilder: Article

Exception Handling Using PowerBuilder, EAServer, and JavaServer Pages

Exception Handling Using PowerBuilder, EAServer, and JavaServer Pages

Exception Handling Using PowerBuilder, EAServer, and JavaServer Pages Basic Techniques and Pitfalls

PowerBuilder's Try-Catch-Finally exception handling mechanism brings a great deal of power and versatility to application and component development. It's important to be able to manage and handle exceptions thrown by service components, particularly when you are deploying to a Web environment. When you develop with PowerBuilder 9's JSP targets, you need to know how to throw exceptions from PowerBuilder components and how to catch and handle the exceptions within your JSP target. This article examines the techniques you can use and the challenges you will face in adding robust exception handling to your JSP Web application.

Try-Catch-Finally in PowerBuilder
WHY WE USE TRY-CATCH-FINALLY

The Try-Catch-Finally method of exception handling was introduced in PowerBuilder 8. This is the same model used in Java, and is a very useful construct for reusable, object-oriented development. Why? The primary contribution that this construct makes to development is that it promotes encapsulation of exception handling. In other words, the object that creates and throws the exception can manage the exception handling mechanism within that object. Messages and error information can also be formatted and passed up the call stack easily and without the calling object needing to be aware of nested exceptions or internal handling mechanisms.

THE THROWABLE OBJECT
Try-Catch-Finally exception handling in PowerBuilder is based on the Throwable object. In addition to the properties, events, and functions inherited from PowerObject, the Throwable object declares one instance variable, called Text, and two methods. The methods are SetMessage and GetMessage. Together, these methods allow you to store, pass, and retrieve error information up the call stack by throwing an exception from the object where the exception occurred to a higher-level object that handles the exception. PowerBuilder also supplies other exception objects, all of them descended from Throwable. Figure 1 shows the PowerBuilder 9 Object Browser displaying the hierarchy of exception objects.

Fig 1

Note that there are several descendants of RuntimeError. Each one of these descendants is used to signal a particular type of runtime exception. An interesting and useful feature of the RuntimeError exception and its descendants is that these objects will automatically populate instance variables for the object, routine, and script line when one of these exceptions is thrown. This can be used to pass a wealth of information about the context where the exception occurred.

USING SETMESSAGE AND GETMESSAGE
Listing 1 shows the use of SetMessage and GetMessage within a Try-Catch-Finally block. This script is the implementation of a window function of_exception(integer ai_exCode). Depending on what is passed to the function, a different error message will be generated. The CATCH block can handle the error (displaying its error message) without regard to where in the TRY block the exception occurred. Execution will always continue with the FINALLY block, whether or not an exception is thrown.

Note: A complete application showcasing the techniques in this article may be downloaded from www.power3.com (click on "Downloads") as well as from Sybase's CodeXchange site, http://codexchange.Sybase.com.

You have seen how to use and handle exceptions within a script. However, one of the most important uses of exceptions is to pass error information out of a called method where it can be handled (caught) by a higher-level script.

Throwing Exceptions from a PowerBuilder Function
PowerBuilder allows you to throw an exception from within a function. This exception can then be caught and handled by a script further up the call stack. To do this, simply create an exception and throw it:

// function of_exception()
exception ex
ex = create exception
ex.setMessage(as_msg)
Throw(ex)
RETURN 1

The only problem is that the script shown above won't compile or save. Instead, you'll get an error message:

Error C0203: Exception type 'exception' must either be caught in this method, or declared in the throws clause of this method prototype.

What does this mean? Look at the function prototype area at the top of the script painter. You'll see that there is a place, just below the arguments, where you can fill in information about which exceptions the function throws. Just enter the type of the exception thrown by the function in the edit box next to "Throws". Now your script will compile.

Note: It's not necessary (nor will it compile) to include RuntimeError in the "Throws" declaration. PowerBuilder automatically declares this for you.

Creating an EAServer Component That Throws an Exception
At this point it would seem simple to create a PowerBuilder component that throws an exception and deploy the component to EAServer. Start by creating an EAServer component and add the of_exception method (see the previous code example). Don't forget - you'll need to add "exception" to the throws clause of the function signature before the component will compile or save.

Next, you'll need to deploy the component. If you haven't already done so, create a project to deploy the component as a standard component. When you try to deploy, you'll get an error message (see Listing 2).

What happened? The answer is that PowerBuilder components deployed to EAServer need to throw a "user exception." The user exception must be inherited (as a standard user object) from one of the PowerBuilder exception types. Create a standard class user object inherited from exception and save it as "userexception." Now you can modify your function's code:

userexception ue
ue = CREATE userexception
ue.SetMessage("This is a test exception!!")
Throw ue
RETURN 1

Once you've made the changes to your component, deploy it again. It should deploy without generating any error message.

Exception Handling in JSPs
Now you have a PowerBuilder component that will throw an exception. You'll need to catch that exception and take appropriate action. In this case, the client for the component will be a JavaServer Page (JSP.) At this point, you should create a JSP Web target and a new 4GL JSP page. You'll be adding code to the JSP to call the of_exception function on your component and to handle the thrown exception.

USING TRY-CATCH-FINALLY WITHIN A JSP
After you've created the JSP, add the component by dragging it from the system tree onto the JSP in the JSP painter. Add an expression server script (using the <%=..%> tag) and write one line of code to invoke the of_exception function on your component. Assuming you instantiated the component on your JSP with the name exception_ test, the code will look like this:

exception_test.of_exception()

When you run the JSP, you should get an error similar to that shown in Figure 2.

Fig 2

You see the text of your error message, assigned using the SetMessage() method. However, that's about the only good thing about this result. Your user has ended up on the wrong page, and isn't getting much in the way of useful information. The next step is to add code to catch the exception in the body of the JSP. Delete the expression script element and add a new server script (using <%?%>):

short thing;
try
{
thing = exception_test.of_exception();
out.print(thing);
}
catch (p3_test.userexception ue)
{
out.println("<BR>An exception
occurred<BR>");
out.println("<BR>");
}

Now, when you run the JSP, you'll see the page shown in Figure 3.

Fig 3

Not bad. This code is executing on the same page, and you have control over what the user sees. But you need access to the message you've set within the exception. If you attempt to use getMessage() to access the message text, you'll get an error message because methods are not available as part of the IDL that's generated for exceptions. Perhaps the Text instance variable of the exception can be used to retrieve the message. If you change the JSP script to include a reference to the Text instance variable, as shown in the following code, you'll get an error when you deploy the Web application.

short thing;
try
{
thing = exception_test.of_exception();
out.print(thing);
}
catch (p3_test.userexception ue)
{
out.println("<BR>An exception occurred<BR>");
out.println(ue.Text);
out.println("<BR>");
}

This is because the instance variables of the userexception have not been exposed. Change the deployment properties of the PowerBuilder component to "Expose public instance variables" as shown in Figure 4, then redeploy the component.

Fig 4

After you've redeployed the component, the Web application should deploy without error. But when you run the JSP, you'll see another error, as shown in Figure 5.

Fig 5

Even though the deployment error is gone, the Text variable is still not available to your JSP. The solution to this is to create your own instance variable on the userexception and override the SetMessage function to save your message into that variable. The following code overrides SetMessage.

super::setMessage(newmessage)

messageText = newmessage

At this point change the JSP to access ue.messagetext, and when you redeploy the Web application and call the JSP, you'll see the display shown in Figure 6. The script used to produce this page is shown in Listing 3. This is a simplistic example, since the exception can be enclosed in an expression script element (<%=?%>) to see the message content. However, you can extend this technique to include more information in additional instance variables.

Fig 6

Remember that you will need to pass all of your exception information via instance variables. Even if you define custom methods, they won't be included in the exception's IDL, and therefore won't be available. But you can send a wealth of information this way. For instance, consider wrapping your exception information in XML. Then you can use XSL to format and display the information in an orderly, meaningful format.

USING A JSP ERROR PAGE
JSP Web applications also offer another exception handling facility, the Error Page. This allows you to define a single page to handle one or more exception types. A JSP Error Page is little more than an ordinary JSP. What makes it exceptional (pun intended) is that when you define a page as an Error Page, you gain access to the implicit exception object. How do you define a page as an Error Page? Simply include the page directive "isErrorPage" as shown in Figure 7.

Fig 7

To cause unhandled exceptions to be caught by the Error Page, you need to add the page to the Error Mapping property of the Web application's deployment descriptor. Figure 8 shows the Error Mapping dialog. There are a few important points to note about the settings you make in this dialog. First, be sure to precede the URL for the Error Page with a slash ("/"). You'll also need to set the value in the "Error" column to "N". If you are handling an HTTP error (such as 404-page not found), the Error column should be set to "Y".

Fig 8

Once you have created error mappings and deployed the Web application, uncaught exceptions and errors will transfer control to the Error Page, where the contents of the exception object can be manipulated and displayed.

Conclusion
When you are creating Web applications based on PowerBuilder components, it's important to be able to gracefully and meaningfully handle errors and exceptions that occur within your components. PowerBuilder JSP Web Targets can be configured to catch exceptions thrown by your components at a page level using the Try-Catch-Finally construct. You can also handle exceptions and HTTP errors at an application-wide level using Error Pages defined in the Web application's deployment descriptor.

More Stories By Millard F. Brown

Millard F. Brown is vice president of Power3, LLC, a company providing consulting and training services for the enterprise. He has beend developing PowerBuilder applications since PowerBuilder 2 and is the co-author of two new PowerBuilder 9 books: PowerBuilder 9: Advanced Client/Server Development and PowerBuilder 9: Internet and Distributed Application Development.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.