Catching exceptions in 1C:Enterprise script





This article describes the standards that apply to exception handling. All of the listed recommendations are mandatory unless noted otherwise.

In general, we recommend that you do not catch exceptions. In particular, do not catch exceptions solely for displaying error messages, for the platform automatically displays an error message for each uncaught exception.

Still, sometimes you might need to catch exceptions. For example, you might want to modify an error message, making it totally clear for end users. But even if you do, you still have to register the error in the event log to ensure that the system administrator can identify that problem and provide the error details by technical support request.

We recommend that you write the detailed error description to the event log and display the brief description to users.

Examples of incorrect exception handling

1. Some server business logic is called from the client during interactive user work:

&AtServer
Procedure PerformAction()
    // Code that raises an exception
    ...
EndProcedure

Incorrect:

// at client
Try
    PerformAction();
Except
    DoMessageBox("Cannot perform the action.");
EndTry;

Correct:

&AtServer Procedure PerformAction() Try // Code that raises an exception ... Except // Write event log record to be analyzed by system administrator WriteLogEvent(NStr("en = 'Performing action'"), EventLogLevel.Error, , , DetailErrorDescription(ErrorInfo())); Raise; EndTry; EndProcedure

and on the client:

Try
    PerformAction();
Except
    MessageText = BriefErrorDescription(ErrorInfo());
    DoMessageBox(NStr("en = 'Cannot perform the action. Reason:'" + Chars.LF + MessageText);
EndTry;

2. In some client business logic:

&AtClient
Procedure CreateFileOnDisk()
    // Code that raises an exception
    ...
EndProcedure

We recommend that you make an additional server call for registering unsuccessful operation execution in the event log:

Try
    // Code that raises an exception
    CreateFileOnDisk();
Except
    MessageText = BriefErrorDescription(ErrorInfo());
    DoMessageBox(NStr("en = 'Cannot perform the action. Reason:'") + Chars.LF + MessageText);
    WriteFileOperationError(DetailErrorDescription(ErrorInfo()));
EndTry;
 
&AtServer
Procedure WriteFileOperationError(...)
    WriteLogEvent(NStr("en = 'Performing action'"),
        EventLogLevel.Error, , ,
        DetailErrorDescription(ErrorInfo()));
EndProcedure

3. Never catch exceptions without notifying the system administrator:

Try
    // Code that raises an exception
    ...
Except
    // Catch exceptions
EndTry;

As a rule, such script clauses introduce problems that are impossible to locate.

Correct:

Try
    // Code that raises an exception
    ...
Except
    // Comment explaining why the exception is caught without notifying end users.
    // ...
    // And write an event log record to noify the administrator.
    WriteLogEvent(NStr("en = 'Performing action'"),
        EventLogLevel.Error, , ,
        DetailErrorDescription(ErrorInfo()));
EndTry;

4. Do not use exceptions for checking the availability of object attributes, methods, templates, and so on. This might lead to errors that are hard to locate, and this also complicates debugging in the "Stop on errors" mode.

Instead of catching exceptions in this scenario we recommed that you:

  • Use metadata operations for explicit checks whether an attribute, template, or another piece of data is available.
  • If the availability of some data depends on library deployment options, reflect this fact in overridable modules.
  • Revise the logic of the methods that catch exceptions. For example, you can implement parameters that define whether some object method or property is accessed.

Incorrect:

Try
    ContextERPServer.GetTemplate("ExchangeComponent");
    Path = ContextERPServer.PathToObject + ".Template.ExchangeComponent");
Except
EndTry;

Correct:

ExchangeComponentTemplate = ContextERPServer.Metadata().Templates.Find("ExchangeComponent");
If ExchangeComponentTemplate <> Undefined Then
    PathToTemplate = ExchangeComponent.FullName();
EndIf;

5. Within transactions, use the following exception handling format:

BeginTransaction();
Try
    Query = New Query("...");
    Selection = Query.Execute().Select();
    While Selection.Next() Do
        ...
    EndDo;
    CommitTransaction();
Except
    RollbackTransaction();
    WriteLogEvent(NStr("en = 'Performing action'"),
        EventLogLevel.Error, , ,
        DetailErrorDescription(ErrorInfo()));
    Raise;
EndTry;

Since an exception does not roll the transaction back immediately but prohibits committing it, each of the BeginTransaction calls must have a matching CommitTransaction or RollbackTransaction call.


Comments
0
Add comment