Sw4   >   Errorhandler   >   Error Handler (All Contents)

Error Handler

The error handler object is an important part of the StudioWorks framework.

In Object-Oriented Programming you need to make a clear distinction between visual classes and non-visual classes. (See Coding Conventions > Visual vs. Non-Visual Classes)

StudioWorks provides you with an error handler object which makes it easy to respect the visual vs. non-visual class rule.

When an error occurs in any method you immediately log the error to the error handler and then at the end of the method you return false or null depending on the type of method. (See Coding Conventions > Quit method return Something) The logged error becomes the current error in the error handler.

When an error condition is returned to a $construct, $control, $event, $print, or $timer method that method is responsible to send a $promptonceLastError message to the error handler object. The error handler opens a prompt window with the last error that was logged.

The error handler is instantiated by the Startup_Task task variable, errhndlr.

To view the error handler's public methods right-click the errhndlr task variable and select Interface Manager. Click on the various $log... methods and review the method description in the Description tab of the Interface Manager .

errhndlrinterface.gif

Click the Run Demo button to try out the various error handler object methods.

Error Handler Coding

The following is a set of recommended coding conventions for writing code which uses the error handler.

  1. Never use the built in OK messages for error prompts. It only takes a few seconds longer to write the code to use the error handler and you will end up spending way more time going back cleaning up your OK messages later on.
  2. Always declare the local variables Mssg and Dtls, then calculate the error message and details to those variables, and send them with the $log... message to the error handler.

    Calculate Mssg as "The error message text."
    Calculate Dtls as "Additional details about the error."
    Do errhndlr.$logError($cmethod,Mssg,Dtls)



    Even if you don't need the Dtls variable, declare it anyway and calculate it as empty. This keeps your code consistent and makes it easier to add error details text later on.

    Tip

    Always enclose your text in double quotes so that you can use single quotes in the text string.



    Calculate Mssg as "The error message text"
    Calculate Dtls as ''
    Do errhndlr.$logError($cmethod,Mssg,Dtls)

  3. Only call the $promptonceLastError method from $construct, $control, $event, $print, $timer methods. If any of these methods call other methods they must check the return flag and send a $promptonceLastError message to the error handler if the flag is false.

    ; Sample code for $construct, $control, $event, or $timer method
    Do $cinst.$someMethodName() Returns FlagOK
    If not(FlagOK)
       Do errhndlr.$promptonceLastError()
    End If



    This takes the guesswork out of deciding when and where to prompt the user. All method execution in Omnis Studio begins in one of these method, so your code is always going to return to one of these methods where you can then check the flag and $promptonceLastError if the flag is false.
Tip

I don't like to include a lot of code in the $event methods because On ev... indents all of the code that follows making it harder to read more than a screen full of $event method code. I find it easer to immediately call an event_evCode method which executes the code for that event and returns the flag. The called method does not need to test pEventCode. Following this convention keeps the $event methods short and simple.


; $event method of a treelist.
On evDrop
Do method event_evDrop Returns FlagOK
If not(FlagOK)
Do errhndlr.$promptonceLastError()
End If

On evTreeExpand
Do method event_evTreeExpand Returns FlagOK
If not(FlagOK)
Do errhndlr.$promptonceLastError()
End If

On evTreeListEditFinishing
Do method event_evTreeListEditFinishing Returns FlagOK
If not(FlagOK)
Do errhndlr.$promptonceLastError()
End If

Debug Error Prompts

If a developer version of Omnis is being used, the error handler will open an OK message prompt as soon as an error is logged. You will see DEBUG ERROR in the title of the OK message. Runtime users will not receive this OK message.

The DEBUG ERROR OK message allows the developer to break into the code (Mac: Cmnd+Opt+Delete, Win: Break) Using the Stack toolbar menu you can then step back to the method where the error was logged and debug your code.

If instead of breaking into the code you press the OK button, the code will finish executing and all going well a visual class public method in the method stack will send a $promptonceLastError message to the error handler and the StudioWorks error prompt dialog window will be opened.

The developer debug error prompts can be turned off by setting $:DeveloperErrorPrompts to false.

Do errhndlr.$:DeveloperErrorPrompt.$assign(kFalse)

Note

If the application mode is set to web, the developer debug error prompts are automatically turned off. See Web App Mode for more details.

Log Errors Destination

The oErrorHandler object has a property method $:LogErrorsDestination which returns 3 possible values:

The error handler defaults to using the tracelog until either the logfile on the client computer, or the Errorlog table in the database, has been successfully set.

By default the log errors destination is set to logfile by StudioWorks when the error handler is initialized. This changes the state of $:LogErrorsDestination property from tracelog to logfile. The $:LogFilePath property gives you the path to the error log file.

If you want the errors from all of the users logged to a central location, an Errorlog table in the main database, you will need to make the following changes to the Startup_Task of your main library.

  1. Add a setErrorHandlerDatabaseSession method to the Startup_Task if it doesn't already exist.

    Note

    You can copy the method from the main library Startup_Task of StartNewApp

  2. Add the following code to the setErrorHandlerDatabaseSession method. (You can copy the code from StartNewApp)

    ; Get the refs DBSessionObjectRef from the refs object.
    Do refs.$:DBSessionObjectRef Returns ObjRef
    If ObjRef.$validref
       
       ; Set the error handler to use the refs session for logging errors to the database.
       Do errhndlr.$setDatabaseSession(SessionRow) Returns FlagOK
    End If

    Quit method FlagOK

  3. In the $signInOKContinue method call the setErrorHandlerDatabaseSession method just after successfully calling the default $signInOKContinue method.

    ; Redirect to the startup task default methods object.
    Do redirect ioStartupTaskDefaultMethods Returns FlagOK
    If FlagOK
       Do method setErrorHandlerDatabaseSession Returns FlagOK
    End If

If the user successfully signs in, they will have successfully logged on to the database. We then send a $setDatabaseSession message to the error handler which points the error handler to the database, checks for an Errorlog server table, creates one if it doesn't exist, and then changes the state of $:LogErrorsDestination to database. From this point on, errors will be logged to the database.

If you want the system administrator to be able to view all of the errors in the error log, you need to make the following changes to your SysAdmin module:

  1. Add the following code to the $addNavigationMenuLines method of oMenusList in your SysAdmin module. (You can copy the code from mySysAdmin)

    ; Add the ErrorlogListView wininst to the nav list if the error handler uses the database for the error log.
    If errhndlr.$:LogErrorsDestination.$cando
       If errhndlr.$:LogErrorsDestination='database'
          Do $cinst.$_addNavigationMenuLine(GroupID,SubgroupID,'ErrorlogListView')
       End If
    End If

  2. Close your app and open it again in order to set the error handler to use the database. The Errorlog table will automatically be created in your database if it doesn't already exist.
  3. Rebuild all lists. All going well an Error Log child node will appear in the main window navigation tree list under the System Administration node.
  4. Click on the node to view the current errors in the Errorlog table.

The SysAdmin view of the Errorlog table allows the administrator to view all errors and to delete errors.

Non-SysAdmin users view their own errors by selecting View Log File from the main menu. They are not able to delete errors.

If you want to customize the error log windows you can copy or subclass them to your main library from swGui4 > Windows Custom (wErrorLogEdit, wErrorLogList, wErrorLogListView)

Error Handler Coding for Prompt Methods

Error handler coding is fairly straight forward for non-visual classes... if an error occurs, you log an error and return flag... the $event method at the start of the sequence of calls gets a false return flag and sends the error handler a $promptonceLastError message.

What isn't so simple is if you have a long method that require gather data, prompting the user, then doing some more work, possibly prompting the user again, and then doing more work. This might be batch process that needs the user to confirm things at different stages of the process.

To avoid having one huge long method, you'll need to break the code into several smaller methods. These methods might be scattered among different object classes. The user prompts can't all be excecuted in the $event method of the push button in the window class, so you are going to have some $prompt... methods which you call along the way.

The trouble you run into with those $prompt... methods is that there are 3 things that could happen:

  1. An error occurs in the method before or after the user is prompted.
  2. No error occurs and the user clicks okay or some other positive response to continue.
  3. No error occurs but the user clicks cancel or some other negative response to stop the process.

What do you return to the sender to communicate the 3 options?

  1. Flag false - error occurred.
  2. Flag true - no error and the user wants to continue.
  3. Flag ??? - the user cancelled.

Returning false if the user cancelled won't work, because the sender will interpret that as an error and send a $promptonceLastError message to the error handler.

The recommended solution is to create a PromptFlag integer variable and return a value of 2 of the user cancelled. To make your code easy to read create the following class variables in any class which deals with prompt flags.

The following sample code shows what the sender method might look like.

; Get all the active vendors and prompt the user to select the vendors to include.
Do method promptselectVendorsToIncludeInReport (VendorsList) Returns PromptFlag
Calculate FlagOK as PromptFlag
If PromptFlag=ckPrompt_continue
   
   ; Get all the inventory items for the selected vendors.
   Do method getInventoryItemsForSelectedVendors (VendorsList,ItemsList) Returns FlagOK
   If FlagOK
      
      ; Prompt the user to select the inventory items they wish to include in the report.
      Do method promptselectInventoryItemsToIncludeInReport (ItemsList) Returns PromptFlag
      Calculate FlagOK as PromptFlag
      If PromptFlag=ckPrompt_continue
         
         ; Print the report.
         Do method printInventoryItemsReport (ItemsList) Returns FlagOK
         
      End If
   End If
End If
Quit method FlagOK

The method will only return flag false if an error occurs. The method will halt execution after a call to a prompt method if the method returns a PromptFlag=ckPrompt_stop. (ckPrompt_stop is a class variable with an init value of 2.)