| By Millard F. Brown | Article Rating: |
|
| November 1, 2002 12:00 AM EST | Reads: |
202 |
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.
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.
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.
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.
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.
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.
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.
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".
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.
Published November 1, 2002 Reads 202
Copyright © 2002 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
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.
- Why SOA Needs Cloud Computing - Part 1
- Cloud Expo and The End of Tech Recession
- The Transition to Cloud Computing: What Does It Mean For You?
- A Rules Engine Built in PowerBuilder
- Sybase Named “Silver Sponsor” of iPhone Developer Summit
- How PowerBuilder Got Its Groove Back
- The Cloud Has Cross-Border Ambitions
- Ulitzer Names The World's 30 Most Influential Virtualization Bloggers
- Ulitzer Named "New Media" Partner of Greatly Anticipated iStrategy Event in Berlin
- Risks and Enterprise Mobility?
- Steps for Success in Enterprise Mobility?
- Are Mobile Luddites Resisting Mobility?
- The Difference Between Web Hosting and Cloud Computing
- Sybase CTO to Speak at 4th International Cloud Computing Expo
- Why SOA Needs Cloud Computing - Part 1
- Cloud Expo and The End of Tech Recession
- The Transition to Cloud Computing: What Does It Mean For You?
- Five Reasons to Choose a Private Cloud
- Seeding The Cloud: The Future of Data Management
- The Threat Behind the Firewall
- Economy Drives Adoption of Virtual Lab Technology
- Tips for Efficient PaaS Application Design
- A Rules Engine Built in PowerBuilder
- Sybase Named “Silver Sponsor” of iPhone Developer Summit
- Where Are RIA Technologies Headed in 2008?
- PowerBuilder History - How Did It Evolve?
- The Top 250 Players in the Cloud Computing Ecosystem
- Custom Common Dialogs Using SetWindowsHookEx
- DDDW Tips and Tricks
- OLE - Extending the Capabilities of PowerBuilder
- DataWindow.NET How To: Data Entry Form
- Book Excerpt: Sybase Adaptive Server Anywhere
- Sybase ASE 12.5 Performance and Tuning
- Working with SOA & Web Services in PowerBuilder
- Office 2003 Toolbar: A New Look For Your Old PowerBuilder App
- Dynamically Creating DataWindow Objects































