In this article, exceptions are covered.
Working with Exceptions
Instead of returning a %Status response, you can raise and throw an Exception. You are then responsible for catching the exception and validating it. IRIS provides five main classes to handle exceptions effectively. Additionally, you can create custom exception class definition based on your needs.
These exceptions are different from %Status, so you can't directly/efficiently use the exception object with $SYSTEM.OBJ.DisplayError() or $SYSTEM.Status.DisplayError(). Instead, use the DisplayString() method to display the exception message Alternatively, you can convert the exception to %Status using the AsStatus() method and use the display methods mentioned above.
All exceptions inherit from %Exception.AbstractException. When you instantiate the object, use the %OnNew() callback method to set values since the formal parameters are common.
Set exception = ##Class(%Exception.General).%New(pName, pCode, pLocation, pData, pInnerException)
Where:
- pName - is the Name is the name of the error(error message).
- pCode - is the error code (like $$$GeneralError, $$$NamespaceDoesNotExist, or custom numbers when using a general exception).
- pLocation - is the location where the error occurred.
- pData - Data is extra information supplied for certain errors.
- pInnerException - is an optional inner exception.
Let's continue with the 5 major exceptions
%Exception.SystemException
This exception is raised when a system process terminates with an error. IRIS raises this system error by default. Additionally, $ZERROR and $ECODE are defined when this exception is raised.
ClassMethod SystemException()
{
Set $ECODE=""
Set $ZREFERENCE=""
Set $ZERROR=""
Try {
Write ^(1)
}
catch ex {
Write $ECODE,!
Write $ZERROR,!
Write ex.DisplayString()
}
}
Result
,M1,
<NAKED>SystemException+5^Learning.myexcept.1
<NAKED> 30 SystemException+5^Learning.myexcept.1
LEARNING>
%Exception.StatusException
This Exception behaves similarly to the %Status type exception. You can raise it using various macros, such as
- $$$THROWONERROR(%sc,%expr) - execute the expression, set into %sc and throw exception
- $$$ThrowOnError(%expr) - execute the expression, set into %sc internally and throw exception
- $$$TOE(%sc,%expr) - Invoke $$$THROWONERROR(%sc,%expr)
- $$$ThrowStatus(%sc) - Directly throw the exception
Most commonly used method to raise this exception is "CreateFromStatus" which accepts the %Status as a argument and convert into StatusException
ClassMethod StatusException()
{
Set sc1 = $$$ERROR($$$UserCTRLC)
#dim sc As %Exception.StatusException = ##class(%Exception.StatusException).CreateFromStatus(sc1)
#; display the error message
Write sc.DisplayString()
#; convert to %Status again
Set st = sc.AsStatus()
Do $SYSTEM.Status.DisplayError(st)
}
Result
ERROR #834: Login aborted
ERROR #834: Login aborted
%Exception.SQL
This Exception handles SQL errors, using SQLCODE and %msg values. There are two methods to create this exception
Example:
either way you can raise an exception
- $$$ThrowSQLCODE(%sqlcode,%message)
- ##class(%Exception.SQL).CreateFromSQLCODE(%sqlcode,%message)
CreateFromSQLCODE : The first parameter is the SQL code, and the second is the message.
ClassMethod SQLExceptionBySQLCODE()
{
Set tSQLException = ##class(%Exception.SQL).CreateFromSQLCODE(-30,"SAMPLE.PERSON1 not found")
Write tSQLException.DisplayString(),!
Set st = tSQLException.AsStatus()
Do $SYSTEM.Status.DisplayError(st)
}
Create object instance: Create an instance of the exception and then handle it.
ClassMethod GeneralException()
{
Set ex1 = ##class(%Exception.General).%New(,5001) ; just for inner exception
Set exGen = ##class(%Exception.General).%New("RegistrationException",5852,,"Invalid MRN",ex1)
Write exGen.DisplayString()
Set sc = exGen.AsStatus()
Do $SYSTEM.OBJ.DisplayError(sc)
}
%Exception.PythonException
This Exception provides Python error information. Here is the simplified sample.
ClassMethod pythonException()
{
Try{
Do ..pyTest()
}
Catch ex {
Write $classname(ex)_" "_ex.DisplayString()
}
}
ClassMethod pyTest() [ Language = python ]
{
print(1/0)
}
Result
%Exception.PythonException <PYTHON EXCEPTION> 246 <class 'ZeroDivisionError'>: division by zero
ERROR #5002: ObjectScript error: <PYTHON EXCEPTION> *<class 'ZeroDivisionError'>: division by zero1
Last but not least
Custom Exception classes
For application-specific errors, it's crucial to handle exceptions precisely. Incorporate string localization on error messages. You can create custom Exception class.
For instance, you can create custom error messages with different translations based on the session's language.
^IRIS.Msg("MyApp","en",62536)="InvalidMRN"
^IRIS.Msg("MyApp","ru",62536)="недействительный MRN"
Simplified custom Exception class sample
Execution of the custom exception
This method demonstrates how to raise and display custom exceptions in different languages, including English and Russian
Include MyApp.Errors
Class MyApp.Utils Extends %RegisteredObject
{
ClassMethod CustomExpcetionInEng()
{
Set tmyappException = ##class(MyApp.Exception).%New(,$$$InvalidMRN)
wWritetmyappException.DisplayString()
}
ClassMethod CustomExpcetionInRussian()
{
Do ##class(%MessageDictionary).SetSessionLanguage("ru")
Set tmyappException = ##class(MyApp.Exception).%New(,$$$InvalidMRN)
write tmyappException.DisplayString()
}
}
Results
InvalidMRN 62536
LEARNING>d ##Class(MyApp.Utils).CustomExpcetionInRussian()
недействительный MRN 62536
LEARNING>
Conclusion
In these ways you can handle the exceptions and %Status errors efficiently in your application code. Handling the errors effectively extremely helps in many ways!
.jpg)
.png)

.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)