Custom Exception Handling
In addition to throwing exceptions when ProcScript errors occur, you can define your own exceptions using the throw or throw/list statements.
These commands enable you to define an error number that is returned in $procerror, and a brief error description and additional information that is returned in $procerrorcontext, just like Uniface ProcScript errors.
To ensure that custom error numbers do not conflict with Uniface error numbers, use negative integers outside the range -1..-9999
.
Example: Throwing a Custom Exception
For example, the following example includes a custom check to ensure that profile data is provided (not ""
), because that would make the function always return True
.
entry dataExists throws ; Declares that this module throws an exception on any $procerror returns Boolean params string pEntityName: in string pProfileData: in ; “fieldname1=profile1{;...}” endparams variables string vFieldName, vFieldProfile numeric vIndex endvariables clear/e pEntityName forlist/id vFieldName, vFieldProfile, vIndex in pProfileData ; 1. Populates fields with profile data if (vFieldProfile != "") ; 2. Custom check for empty profile @("%%(vFieldName).%%(pEntityName)")/init = vFieldProfile else ; 3. Throw a custom exception. See Note 3 throw -10000, "Profile data not allowed to be null", "PARAM_INDEX=%%(vIndex);PARAM_NAME=%%(pProfileData);FIELD_NAME=%%(vFieldName)" endif endfor try ; introduces code that may result in an error retrieve/e pEntityName catch -2, -4 ; catches specific errors and handles them return "F" endtry return "T" end
Notes:
- Loop that populates the fields with the profile data.
- Custom check for null or
""
. - If the check fails, the throw statement throws a custom error with the following arguments:
- ErrorNumber, a negative integer that is put in $procerror and the
ERROR
item of $procerrorcontext. - Description, a short error description that is put in the
DESCR
item of $procerrorcontext. For code readability, define a hard-coded message here. - AdditionalInfo, an associative list with more error details that is put in the
ADDITIONAL
item of $procerrorcontext.
- ErrorNumber, a negative integer that is put in $procerror and the
For more information, see throw.
Generalizing Custom Exceptions
Checking for null or empty values is a common requirement, so it makes sense to centralize the exception for general use.
The following example demonstrates how you can use a Global ProcScript to assemble the error information for the exception and then use it in another code module.
entry notNull ; 1. Global ProcScript in Library 'myExceptions' throws ; 2. Declares that this module throws an exception on any $procerror. See Note 2 returns string ; 3. Exception details as an associated list params numeric pParamIndex : in string pParamName : in string pFieldName : in endparams variables string vException ; The exception details as an associative list endvariables putitem/id vException, "ERROR", -10000 putitem/id vException, "DESCRIPTION", "Profile data not allowed to be null" putitem/id vException, "ADDITIONAL", "PARAM_INDEX=%%(pParamIndex);PARAM_NAME=%%(pProfileData);FIELD_NAME=%%(pFieldName)" return vException end
-
The
notNull
entry is defined in a Global ProcScript in Library calledmyExceptions
.Tip: It is good practice to create a dedicated Global Proc library for all your custom exceptions.
- It is also good practice to always add a throws declaration to script modules. This ensures that if you have made a mistake in writing the code, it is reported as soon as you test it.
- The Global ProcScript returns a string that holds an associative list of format with the error information which can be passed as the argument with a throw/list statement
- The code uses the IN parameters passed by the calling module to construct the associative list for the exception details. These IN parameters are specific to this
notNull
exception.
The entry dataExists
can now use the notNull
Global ProcScript in a throw/list command. The throw/list statement takes the return value of the myException::notNull()
Global ProcScript as argument. (Remember that the entries can be used as functions).
entry dataExists throws ; Declares that this module throws an exception on any $procerror returns Boolean params string pEntityName: in string pProfileData: in ; “fieldname1=profile1{;...}” endparams variables string vFieldName, vFieldProfile endvariables clear/e pEntityName forlist/id vFieldName, vFieldProfile, vIndex in pProfileData if (vFieldProfile != "") ; 2. Custom check for empty profile. @("%%(vFieldName).%%(pEntityName)")/init = vFieldProfile else ; Throw a custom exception throw/list myExceptions::notNull(2, vFieldProfile, vFieldName) endif endfor try ; Introduces code that may result in an error retrieve/e pEntityName catch -2, -4 ; Catches specific errors and handles them return "F" endtry return "T" end
For more information, see throw/list.