Add Exception Handler

In Cuba 7.X, the exception dialog had a button that would allow the user to report an exception to the admin. This was removed in Jmix (unless I am wrong). I am looking at recreating this.

It seems the correct way to do this would be to add a new UiExceptionHandler (so that all exceptions can be handled by my new dialog) but I don’t see where in my project I should add this. I am unsure if this is a Spring thing or a Jmix thing so I am also unsure how to delve further to try and solve this myself.

Help?

Jmix has a special extension point for providing custom unhandled exception dialogs (UPDATE 2023-12-20: see the docs).

  1. Create a prototype bean extending ExceptionDialog class and override the base class methods to customize your dialog:

    package com.company.demo.exception;
    
    import com.vaadin.flow.component.button.Button;
    import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
    import io.jmix.flowui.exception.ExceptionDialog;
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    @Component
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public class MyExceptionDialog extends ExceptionDialog {
    
        public MyExceptionDialog(Throwable throwable) {
            super(throwable);
        }
    
        @Override
        protected HorizontalLayout createButtonsPanel() {
            HorizontalLayout buttonsPanel = super.createButtonsPanel();
            Button button = uiComponents.create(Button.class);
            button.setText("Report to admin");
            button.addClickListener(e -> {
                // ...
            });
            buttonsPanel.add(button);
            return buttonsPanel;
        }
    }
    
  2. Create a bean implementing ExceptionDialogProvider interface which is a factory creating your dialog instances:

    package com.company.demo.exception;
    
    import io.jmix.flowui.exception.ExceptionDialog;
    import io.jmix.flowui.exception.ExceptionDialogProvider;
    import org.springframework.beans.factory.ObjectProvider;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyExceptionDialogProvider implements ExceptionDialogProvider {
    
        // using ObjectProvider because MyExceptionDialog is a prototype bean
        private final ObjectProvider<MyExceptionDialog> myExceptionDialogProvider;
    
        public MyExceptionDialogProvider(ObjectProvider<MyExceptionDialog> myExceptionDialogProvider) {
            this.myExceptionDialogProvider = myExceptionDialogProvider;
        }
    
        @Override
        public boolean supports(Throwable throwable) {
            return true; // works for all exception types
        }
    
        @Override
        public ExceptionDialog getExceptionDialogOpener(Throwable throwable) {
            // return new instance of MyExceptionDialog
            return myExceptionDialogProvider.getObject(throwable);
        }
    }
    

That’s it. You dialog will be shown for all unhandled exceptions instead of the default one.

Oh, excellent.

What would be the non-flow equivalent of the ExceptionDialogProvider? Nearest analog I can find is ExceptionDialogBuilderImpl.

Unfortunately there is no such an extension point in Classic UI.
You have to extend DefaultExceptionHandler class and provide its instance to the framework as follows:

public class MainScreen extends Screen implements Window.HasWorkArea {

    @Subscribe
    public void onInit(final InitEvent event) {
        App.getInstance().getExceptionHandlers().setDefaultHandler(
                new DefaultExceptionHandler(getApplicationContext()));
    }