finally

Declares ProcScript inside a try-endtry block that must be executed, regardless of whether an exception occurs or not.

finally

For example:

try
    <ProcScript that might throw an exception>
catch {Error1 {,ErrorN}}
    <ProcScript that will execute for the specified Error(s)>
finally
    <ProcScript that will always execute, regardless of whether an error occurred or not>
endtry

Use

Allowed in all component types.

Description

The finally statement is used to declare code inside a try-endtry block that is always executed, irrespective of whether an exception occurs or not.

It is typically used to execute cleanup activities, such as data cleanup or closing a connection. The finally statement allows you to write this code in just one place in your module, enabling more readable and maintainable code.

The finally statement and its corresponding code must be the last block inside a try-endtry block.

It is possible for a finally block to throw an exception, for example by calling an entry that throws an exception. In this case, the finally block is executed up to and including the code that throws the exception. The rest of the finally block is not executed, and the process continues with the new exception. However, this is considered bad practice and care should be taken to avoid code that causes an error in the finally block.

The goto statement and ProcScript label are not allowed inside a finally block, and will result in a compilation error.

Example

The following module retrieves an occurrence with a specific key and returns the value of one of its fields when the retrieve is successful.

If an error -2 or -4 is returned (no data is found), the exception is caught and no data is returned. All other errors are considered fatal and throw an exception. In all cases, the entity should not leave any data behind, therefore the finally block is used to clear it:

entry getData
throws
params
  string pProfile: in
  string pResult: out
endparams
  clear/e "MYENTITY"
  FIELD1.MYENTITY/init = pProfile
  try
    retrieve/e "MYENTITY"
    pResult = FIELD2.MYENTITY
  catch -2, -4
    ; No data, return nothing
    pResult = ""
  finally
    clear/e "MYENTITY"
  endtry
end

Using return in a finally block

If the finally block contains a return statement, this will overwrite any return statements in the try or catch block(s). However, a return statement in the finally block is considered bad practice, as finally should be used for cleanup operations rather than for communication back to the caller.

When finally is not executed

There are some cases when the finally block does not execute, namely when using self-destructing statements in the try block delete an instance (deleteinstance <$instancename>, or exit) or exit an application (apexit), causing the current runtime context to be deleted:

Deleting an instance

If the code inside a try block of a try-finally-endtry construct causes the current instance to get deleted (for example, by using deleteinstance <$instancename> or exit), further code execution stops because the current runtime context has been deleted. The finally block is not executed in this case. The cleanup operation is still executed, but should not be used to clean up exception related context.

It is best practice to delete an instance from outside the current instance, to ensure all context stays available while handling any exceptions. If deleting the current instance cannot be avoided, place any module-related cleanup logic just before the deleteinstance <$instancename> or exit statement, and not in the finally block.

Exiting the application

If the code inside a try block of a try-finally-endtry construct causes the application to exit (using an apexit statement), further code execution stops because the current runtime context has been deleted, therefore the finally block is not executed.

It is best to practice to avoid terminating the whole application using ProcScript. Instead, terminate all instances in a controlled way to allow Uniface to exit the application naturally when all instances are gone. If this cannot be avoided, place any module-related cleanup logic just before the apexit statement, and not in the finally block.

Related Topics