Try-Catch FAQ. Version 2015.1 11 February 2015. InterSystems Corporation 1 Memorial Drive Cambridge MA 02142 www.intersystems.com



Similar documents
Using the Caché SQL Gateway

Using the Studio Source Control Hooks

Caché License Management

Using Encrypted File Systems with Caché 5.0

Caché Integration with a Network Appliance Filer

Identifying Memory Fragmentation within the Microsoft IIS Environment

Creating SOAP and REST Services and Web Clients with Ensemble

Ensemble X12 Development Guide

The first time through running an Ad Hoc query or Stored Procedure, SQL Server will go through each of the following steps.

Developing Ensemble Productions

Using the Caché Objective-C Binding

Caché Data Integrity Guide

Caché Data Integrity Guide

Symantec Enterprise Vault

Oracle Insurance Policy Administration. Version

Software Hosting and End-User License Subscription Agreement

Enterprise Reporter Report Library

Caché High Availability Guide

CS 111 Classes I 1. Software Organization View to this point:

Symantec Enterprise Vault

Symantec Enterprise Vault

Monitoring Ensemble. Version March InterSystems Corporation 1 Memorial Drive Cambridge MA

Programming and Software Development (PSD)

CACHÉ: FLEXIBLE, HIGH-PERFORMANCE PERSISTENCE FOR JAVA APPLICATIONS

RedBlack CyBake Online Customer Service Desk

Adeptia Suite LDAP Integration Guide

StarterPak: HubSpot and Dynamics CRM Lead and Contact Synchronization

Start Oracle Insurance Policy Administration. Activity Processing. Version

FlexTrac Client Support & Software Maintenance Policies

Help for ADP s Mobile App

How To Use Deepsee

ABAP SQL Monitor Implementation Guide and Best Practices

Microsoft Dynamics GP. Payroll Connect

Chapter 1 Fundamentals of Java Programming

SOFTWARE AS A SERVICE AGREEMENT

CA Clarity Project & Portfolio Manager

FAQ: How to create Effective Messages

ACOT WEBSITE PRIVACY POLICY

Human Resources 9.1 Basic Navigation Guide

ADDENDUM ThomasNet Mirrored Site Program

Revised 10/13 SUBSCRIBER AGREEMENT. Introduction

Transactionality and Fault Handling in WebSphere Process Server Web Service Invocations. version Feb 2011

ALM Works End-User License Agreement for Structure Plugin

We suggest you retain a copy of these End User Terms of Use for your records.

Using Workflow with Ensemble

Symantec Enterprise Vault

Product Overview and Examples

March Oracle Business Intelligence Discoverer Statement of Direction

Canon USA, Inc. WEBVIEW LIVESCOPE SOFTWARE DEVELOPMENT KIT DEVELOPER LICENSE AGREEMENT

Read This Internet Service Agreement Carefully Before Using Our Internet Services.

AXIS12 DRUPAL IN A BOX ON THE CLOUD

Service Description: Cisco Prime Home Hosted Services. This document describes the Cisco Prime Home Hosted Services.

MCC TERMS AND CONITIONS

HSS Specific Terms HSS SOFTWARE LICENSE AGREEMENT

Kofax Export Connector for Microsoft SharePoint

EView/400i Management Pack for Systems Center Operations Manager (SCOM)

New Features in Primavera Contract Management 14.1

Installation Guide Supplement

Image Control. Administrator Guide

TECHNOLOGY Computer Programming II Grade: 9-12 Standard 2: Technology and Society Interaction

Defining Workflows. Version November InterSystems Corporation 1 Memorial Drive Cambridge MA

Oracle Retail MICROS Stores2 Functional Document Tax Free - Manual Receipt Number Assignment Release September 2015

Open Source Used In Cisco D9865 Satellite Receiver Software Version 2.20

WhatsUpGold. v14.2. Getting Started with WhatsUp Gold MSP Edition

Provider secure web portal & Member Care Information portal Registration Form

Quest ChangeAuditor 5.1 FOR ACTIVE DIRECTORY. User Guide

WE RECOMMEND THAT YOU PRINT OUT AND KEEP A COPY OF THIS AGREEMENT FOR YOUR FUTURE REFERENCE.

Siebel Application Deployment Manager Guide. Siebel Innovation Pack 2013 Version 8.1/8.2 September 2013

fåíéêåéí=péêîéê=^çãáåáëíê~íçêûë=dìáçé

Introduction to PL/SQL Programming

Oracle Cloud. Creating a Business Intelligence Cloud Extract E

Designing with Exceptions. CSE219, Computer Science III Stony Brook University

New Features Guide. Adaptive Server Enterprise 15.7 SP50

Java Application Developer Certificate Program Competencies

SPYDERS END USER LICENSE AGREEMENT TERMS AND CONDITIONS

FOR WINDOWS FILE SERVERS

TERMS & CONDITIONS: LIMITED LICENSE:

ORACLE HYPERION DATA RELATIONSHIP MANAGEMENT

LANDesk Management Suite 8.7 Extended Device Discovery

ICE for Eclipse. Release 9.0.1

Fundamentals of Java Programming

Review Employee Leave Balances

Temperature & Humidity SMS Alert Controller

Caché High Availability Guide

AcroTime Workforce Management Time & Labor Human Resources Payroll Service Terms and Conditions

Installation and Configuration Guide

Computing Concepts with Java Essentials

Enhanced Diagnostics Improve Performance, Configurability, and Usability

mguard Device Manager Release Notes Version 1.6.1

MDM Zinc 3.0 End User License Agreement (EULA)

SOCIETY OF ECONOMIC GEOLOGISTS, INC.

Commission % is always based on the full amount of the NGR level reached.

Approve or Reject Purchase Requistions, Contracts, and Purchase Orders

Oracle Retail MICROS Stores2 Functional Document Sales - Reasons Release September 2015

Business Partner Program

Handling Exceptions. Copyright 2006, Oracle. All rights reserved. Oracle Database 10g: PL/SQL Fundamentals 8-1

Schema Classes. Polyhedra Ltd

Dell InTrust Preparing for Auditing Microsoft SQL Server

THOMSON REUTERS (TAX & ACCOUNTING) INC. FOREIGN NATIONAL INFORMATION SYSTEM TERMS OF USE

Software Usage Agreement for Beckhoff Software Products

Transcription:

Try-Catch FAQ Version 2015.1 11 February 2015 InterSystems Corporation 1 Memorial Drive Cambridge MA 02142 www.intersystems.com

Try-Catch FAQ Caché Version 2015.1 11 February 2015 Copyright 2015 InterSystems Corporation All rights reserved.,,,, Caché WEBLINK, and Distributed Cache Protocol are registered trademarks of InterSystems Corporation.,, InterSystems Jalapeño Technology, Enterprise Cache Protocol, ECP, and InterSystems Zen are trademarks of InterSystems Corporation. All other brand or product names used herein are trademarks or registered trademarks of their respective companies or organizations. This document contains trade secret and confidential information which is the property of InterSystems Corporation, One Memorial Drive, Cambridge, MA 02142, or its affiliates, and is furnished for the sole purpose of the operation and maintenance of the products of InterSystems Corporation. No part of this publication is to be used for any other purpose, and this publication is not to be reproduced, copied, disclosed, transmitted, stored in a retrieval system or translated into any human or computer language, in any form, by any means, in whole or in part, without the express prior written consent of InterSystems Corporation. The copying, use and disposition of this document and the software programs described herein is prohibited except to the limited extent set forth in the standard software license agreement(s) of InterSystems Corporation covering such programs and related documentation. InterSystems Corporation makes no representations and warranties concerning such software programs other than those set forth in such standard software license agreement(s). In addition, the liability of InterSystems Corporation for any losses or damages relating to or arising out of the use of such software programs is limited in the manner set forth in such standard software license agreement(s). THE FOREGOING IS A GENERAL SUMMARY OF THE RESTRICTIONS AND LIMITATIONS IMPOSED BY INTERSYSTEMS CORPORATION ON THE USE OF, AND LIABILITY ARISING FROM, ITS COMPUTER SOFTWARE. FOR COMPLETE INFORMATION REFERENCE SHOULD BE MADE TO THE STANDARD SOFTWARE LICENSE AGREEMENT(S) OF INTERSYSTEMS CORPORATION, COPIES OF WHICH WILL BE MADE AVAILABLE UPON REQUEST. InterSystems Corporation disclaims responsibility for errors which may appear in this document, and it reserves the right, in its sole discretion and without notice, to make substitutions and modifications in the products and practices described in this document. For Support questions about any InterSystems products, contact: InterSystems Worldwide Customer Support Tel: +1 617 621-0700 Fax: +1 617 374-9391 Email: support@intersystems.com

Table of Contents Try-Catch FAQ... 1 General Questions... 1 Try-Catch and Older Error-Handling Mechanisms... 5 Try-Catch FAQ iii

Try-Catch FAQ General Questions What is Try-Catch? Try-Catch is a language construct in Caché ObjectScript that allows applications to handle exceptional conditions, called exceptions. Try defines a block of code for which exceptions are handled by a paired Catch block. Exceptions include all Caché ObjectScript system errors such as <DIVIDE> and <UNDEFINED>, which are thrown implicitly when the language encounters an error; they also encapsulate other types of exceptional conditions, which can be thrown explicitly by the application with the Throw command. If an exception is thrown in the Try block, control is transferred to the Catch block, and execution resumes there. Exceptions can be thrown from code that is not in a defined Try block. When that happens, the next exception handler on the stack catches the exception, unwinding the stack as necessary. The exception handler that catches the exception may be a Catch, but it may alternatively be a $ZTRAP or $ETRAP handler (more on this below). An exception, when thrown, causes the application to deviate from the normal flow of control and resume execution at the first available exception handler on the stack (the deepest stack level), unwinding the stack if necessary until one is found. When using Try-Catch, typically the first available exception handler would be a Catch block. The exception object is available to the Catch block, and can be inspected to recover information about the exception. What is the difference between an exception and an error? The term error can have multiple meanings, so this article avoids using it as a technical term. An exception is an object that is a subclass of the %Exception.AbstractException class. Several types of exceptions are modeled as subclasses of %Exception.AbstractException. Caché ObjectScript system errors, such as <DIVIDE> and <UNDEFINED> are exceptions of the class %Exception.SystemException. Exceptions of this form are automatically instantiated and thrown by the system when such errors occur. There are other classes of exceptions that can be instantiated by the application and thrown using the Throw command. %Exception.StatusException is an exception class to model %Status errors, and %Exception.SQL models SQLCODE errors. You can also create your own exception class by extending these exception classes. Is there support for Finally blocks? No, but it s easy to get that functionality. You put the code that you always want to have executed after the Catch: Try { Catch { // Finally-like code here, since code paths goes here, // unless an exception is thrown in the Catch. I called a method that returned an error %Status value. How do I throw it as an exception? %Exception.StatusException has a method, CreateFromStatus, to create an exception object that can then be thrown with the Throw command. For example, if the variable sc contains a %Status value, the following code will throw it as an exception: Try-Catch FAQ 1

General Questions if $$$ISERR(sc) { throw ##class(%exception.statusexception).createfromstatus(sc) Note: This functionality is also accessible from the macros $$$ThrowStatus and $$$THROWONERROR. How do I throw an exception from an error SQLCODE? The %Exception.SQL class has a method, CreateFromSQLCODE, to create an exception object that can then be thrown with the Throw command. For example, if the variable SQLCODE contains an SQLCODE value and %msg its message, the following code throws it as an exception: if SQLCODE<0 { throw ##class(%exception.sql).createfromsqlcode(sqlcode,%msg) What happens if an exception occurs inside my Catch block? Exceptions that are thrown inside a Catch block are just like exceptions that occur anywhere else outside of the Try block the next available exception handler on the stack handles them. You can nest another Try-Catch within the Catch block itself in order to catch additional exceptions within your exception handling code. Can I convert from an exception to a %Status or SQLCODE Yes, exception objects have methods AsStatus and AsSQLCODE that do just that. What can I do with an exception when I catch it? The Catch block is a fully functioning Caché ObjectScript environment and you can use any commands you need. There are some things that you may typically want to do in order to process the exception, which are described here. These actions need not be entirely contained within the Catch block; they can be done in code following the Catch block if desired. First, because Catch handles multiple kinds of exceptions, your application may want to distinguish among different exceptions in order to determine what to do. You can use the $classname function or the %IsA method (inherited from the Caché %Library.Base class) to determine the class or superclass of the exception object. You can inspect the Name and Code properties of the exception object to determine the type of error. You often want to undo work that has been done prior to the exception, release a lock or other resource, and/or roll back a transaction. You may want to log it to the standard application error log by calling LOG^%ETN. If the exception is not a %Exception.SystemException, set $ZERROR to a meaningful value prior to calling LOG^%ETN; this value will be used as the Error Message field in the log entry. (The application error log is visible in the Management Portal s Application Error Log page.) Additionally, you can get a summary of the exception to display to the user using the DisplayString method of the exception object. Upon completion of all the above you would typically do one of several things: Continue processing or return from the current procedure Re-throw the exception to the next exception handler on the stack Throw a new exception Halt the process Here s an example that illustrates some of these concepts: 2 Try-Catch FAQ

General Questions func(id) public { Try { ; Flag indicates if we locked the global Set locked=0 ; If we cannot get the lock, throw a user-created ; exception with the information we need Lock +^mygbl(id):0 If '$test { Throw ##class(exception.myexception).%new("unable to lock",$name(^mygbl(id))) Set locked=1 Set sc=$system.obj.compile("myclass") If $$$ISERR(sc) { Throw ##class(%exception.statusexception).createfromstatus(sc) ; Some further processing which may throw exceptions ;... If locked { Lock -^mygbl(id) Catch exception { ; Release the lock resource before doing anything else If locked { Lock -^mygbl(id) ; First determine what sort of exception this is If exception.%isa("%exception.systemexception") { ; Log error in Cache error log Do BACK^%ETN ; Throw my exception class rather than the system exception Throw ##class(exception.myexception).createfromsystemexception(exception) ElseIf $classname(exception)="exception.myexception" { ; Ignore this sort of exception and just return to code ; after the catch block Else { ; We will just throw these to outer error handler Throw exception I use Try-Catch in an outer-level procedure that will call other procedures, which in turn call other procedures. At some deep stack level, an exception occurs that gets caught in my outer-level Catch. How do I recover the call stack where the exception occurred? For exceptions of the class %Exception.SystemException (such as the <UNDEFINED> Caché ObjectScript system error), you can use the $stack function to inspect the error stack. For other exception classes, the code that throws the exception needs to be modified to allow the exception handler to recover the stack. The following example shows how to use the $stack function for system exceptions and one way to capture the stack for other classes of exception. It comes in two parts: a custom exception class to extend %Exception.StatusException with stack information, and an example routine that both logs and displays the captured information, for both system exceptions and other types of exceptions. The exception class: Class MyException.Status Extends %Exception.StatusException { Property Stack [ MultiDimensional ]; /// Convert a %Status into an exception ClassMethod CreateFromStatus(pSC As %Status) As %Exception.AbstractException { // You could choose to override %OnNew and put this code that // captures the stack there instead of here in CreateFromStatus. // We put it here because we only need to capture the stack in // the outer exception, and it is more simply insulated from // future changes in the superclasses. // First, call CreateFromStatus in the superclass to instantiate // the object and fill in the standard exception information. set exc=##super(psc) // Clear $ecode so that $stack() refers to the current stack, // not the error stack. Try-Catch FAQ 3

General Questions set $ecode="" // Subtract one level because we don't need // to see this method itself in the stack. set exc.stack=$stack-1 for i=1:1:exc.stack { set exc.stack(i)=$stack(i)_ " "_$stack(i,"place")_" "_$stack(i,"mcode") quit exc The example routine that both logs and displays the exception information: #include %occinclude testexc(throwsystemexception) { try { do sub1($g(throwsystemexception)) catch exc { if exc.%isa("%exception.systemexception") { set stack=$stack(-1) // For System Exceptions, get the stack from the // built-in error stack using $stack(). for i=1:1:stack { set stack(i)=$stack(i)_ " "_$stack(i,"place")_" "_$stack(i,"mcode") else { if $extract($classname(exc),1,12)="myexception." { // Exceptions from package MyException will carry the // stack of the exception in the multidimensional // Stack property. merge stack=exc.stack // Set $ze explicitly because it's needed by BACK^%ETN // and only SystemExceptions set it implicitly. set $ze=exc.displaystring() do BACK^%ETN write!,"exception occurred: ",exc.displaystring() write!," class: ",$classname(exc) write!," name: ",exc.name write!," code: ",exc.code if $data(stack) { write!," stack:" for i=1:1:stack { write!," ",stack(i) write! sub1(throwsystemexception) { if throwsystemexception { do systemexception else { do myexception myexception() PUBLIC { set sc=$$$error($$$generalerror,"this is my status code") throw ##class(myexception.status).createfromstatus(sc) systemexception() PUBLIC { // get a <DIVIDE> error set x=1\0 The output from the test routine: USER>do ^testexc(1) Exception occurred: <DIVIDE> 18 systemexception+2^testexc class: %Exception.SystemException name: <DIVIDE> code: 18 stack: DO +3^testexc +1 do sub1($g(throwsystemexception)) DO +40^testexc +1 do systemexception DO systemexception+2^testexc +1 set x=1\0 4 Try-Catch FAQ

Try-Catch and Older Error-Handling Mechanisms USER>do ^testexc(0) Exception occurred: ERROR #5001: this is my status code class: MyException.Status name: 5001 code: 5001 stack: DO +3^testexc +1 do sub1($g(throwsystemexception)) DO +42^testexc +1 do myexception DO myexception+2^testexc +1 throw ##class(myexception.status).createfromstatus(sc) USER>do ^%ER For Date: T 16 Feb 2012 2 Errors Error:?L 1. <DIVIDE>systemexception+2^testexc at 1:25 pm. $I=/dev/ttys001 ($X=0 $Y=299) $J=8225 $ZA=0 $ZB=$c(13) $ZS=16384 ($S=16504448) set x=1\0 2. ERROR #5001: this is my status code at 1:25 pm. $I=/dev/ttys001 ($X=0 $Y=310) $J=8225 $ZA=0 $ZB=$c(13) $ZS=16384 ($S=16504336) Try-Catch and Older Error-Handling Mechanisms Caché supports other mechanisms for handling exceptions, such as $ZTRAP. Which should I use? Use Try-Catch. It s the recommended exception handling mechanism in Caché for several reasons: 1. In most cases, Try-Catch allows you to create more readable and elegant code, which makes it easier to maintain your application. 2. It has no runtime performance cost for activities that succeed (that is, where there is no exception). This generally leads to a performance benefit. 3. Because it s easier to use, Try-Catch code is less prone to error. (For example, it helps avoid the construction with $ZTRAP that can create an infinite loop.) 4. For existing applications, it can provide a path to a consistent exception handling interface by encapsulating code with other InterSystems mechanisms to handle exceptions. 5. Try-Catch gives you access to the exception object and therefore allows you to recover all information about the exception that was thrown, regardless of what type of exception occurs. How do Try-Catch and exceptions interact with the older ObjectScript error handlers? If an exception is thrown, and an older error handler, $ZTRAP or $ETRAP, is the first available exception handler on the stack, control is passed to that error handler in the normal way. The exception object, however, will not be available. If the exception thrown was a system exception (%Exception.SystemException), the $ZERROR value will be set as expected; for other exception classes caught by a $ZTRAP or $ETRAP, the $ZERROR value will be set to <NOCATCH>. In either case, the flow of control is the same. If code in a Try block calls a procedure, method, or subroutine that sets $ZTRAP and then an exception occurs inside that procedure, the $ZTRAP catches the exception because it s at a deeper stack level. If code is using $ZTRAP and calls a procedure, method, or subroutine that uses Try-Catch and an exception occurs within the Try, then the Catch catches it (again, because it s at the deeper stack level). In short, exception handling uses whatever is at the deepest stack level. Try-Catch FAQ 5