5.2.12.3. Client-Level Exception Handlers

Unhandled exceptions in Web Client and Desktop Client blocks thrown on the client tier or passed from Middleware, are passed to the special handlers mechanism. This mechanism is implemented in the gui module and available for both blocks.

The handler should be a managed bean implementing the GenericExceptionHandler interface, handle processing in its handle() method and return true, or immediately return false, if this handler is not able to handle the passed exception. This behavior enables creating a "chain of responsibility" for handlers.

It is recommended to inherit your handlers from the AbstractGenericExceptionHandler base class, which is able to disassemble the exceptions chain (including ones packed inside RemoteException) and handle specific exception types. Exception types supported by this handler are defined by passing strings array to the base constructor from the handler constructor. Each string of the array should contain one full class name of the handled exception, for example:

@Component("sample_ZeroBalanceExceptionHandler")
public class ZeroBalanceExceptionHandler extends AbstractGenericExceptionHandler {

    public ZeroBalanceExceptionHandler() {
        super(ZeroBalanceException.class.getName());
    }
...

If the exception class is not accessible on the client side, specify its name with the string literal:

@Component("sample_ForeignKeyViolationExceptionHandler")
public class ForeignKeyViolationExceptionHandler extends AbstractGenericExceptionHandler {

    public ForeignKeyViolationExceptionHandler() {
        super("java.sql.SQLIntegrityConstraintViolationException");
    }
...

In the case of using AbstractGenericExceptionHandler as a base class, the processing logic is located in doHandle() method and looks as follows:

@Override
protected void doHandle(String className, String message, @Nullable Throwable throwable, WindowManager windowManager) {
    String msg = messages.getMainMessage("zeroBalance.message");
    windowManager.showNotification(msg, IFrame.NotificationType.ERROR);
}

If the name of the exception class is insufficient to make a decision whether this handler can be applied to the exception, canHandle() method should be defined. This method accepts also the text of the exception. If the handler is applicable for this exception, the method must return true. For example:

@Component("sample_ZeroBalanceExceptionHandler")
public class ZeroBalanceExceptionHandler extends AbstractGenericExceptionHandler {

    public ZeroBalanceExceptionHandler() {
        super(ZeroBalanceException.class.getName());
    }

    @Override
    protected boolean canHandle(String className, String message, @Nullable Throwable throwable) {
        return StringUtils.containsIgnoreCase(message, "Insufficient or zero funds in your account");
    }
...

WindowManager provides a method for showing an exception with its stack trace: showExceptionDialog(). The method has the following parameters:

  • throwable - Throwable instance.

  • caption - dialog caption. It is an optional parameter, if not set, the default caption is used.

  • message - dialog message. It is an optional parameter, if not set, the default caption is used.

An example of using the method in an exception handler:

@Override
protected void doHandle(String className, String message, @Nullable Throwable throwable, WindowManager windowManager) {
    if (throwable != null)
        windowManager.showExceptionDialog(throwable, "Exception is thrown", message);
    else
        windowManager.showNotification(message, IFrame.NotificationType.ERROR);
}

To localize the error messages, you should override the localization keys for the corresponding exception handlers in the main message pack. Below is an example for the RowLevelSecurityExceptionHandler used in case if row-level security constraints violation:

  • rowLevelSecurity.caption.User.create - notification caption for concrete entity and operation,

  • rowLevelSecurity.caption.Group - notification caption for concrete entity,

  • rowLevelSecurity.entityAndOperationMessage.User.create - notification message for concrete entity and operation,

  • rowLevelSecurity.entityAndOperationMessage.Group - notification message for concrete entity.