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
ERRORitem of $procerrorcontext. - Description, a short error description that is put in the
DESCRitem of $procerrorcontext. For code readability, define a hard-coded message here. - AdditionalInfo, an associative list with more error details that is put in the
ADDITIONALitem 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
notNullentry 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
notNullexception.
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.