Handling uncaught exceptions

Hello,

I need a way to handle all uncaught exceptions and present a custom UI in response. The Vaadin Book
here
gives an example for V6. It uses getMainWindow() which does not apply to V7. What is the proper way to catch all exceptions and present a custom feedback component?

Thanks.

/Daryl

You can use the static Root.getCurrentRoot() method instead of getMainWindow().

The new approach also has the added benefit of showing the message in the right place if multiple browser windows are used.

Thanks, but I don’t think I’m asking the right question. I have a button on the page like so:

addComponent(new Button("Throw error", new Button.ClickListener() {
	public void buttonClick(ClickEvent event) {
		Integer.parseInt("asdf");
	}
}));

And I have an Application with this override:


@Override
public void terminalError(ErrorEvent event) {
	System.out.println("*** UNCAUGHT exception: " + event.getThrowable());
	Root.getCurrentRoot().showNotification("An uncaught exception occured!", event.getThrowable().toString(), Notification.TYPE_ERROR_MESSAGE);
}

What’s printed out is “*** UNCAUGHT exception: java.lang.RuntimeException: Unable to invoke method click in com.vaadin.terminal.gwt.client.ui.button.ButtonServerRpc” (and the notification doesn’t show). So now I think I understand what a “terminal error” is, an error on the client side. I’m looking for a way to catch all server side exceptions and present a custom feedback form.

If I use Application.CustomizedSystemMessages and setInternalErrorURL() is there a way to get access to the exception at the destination URL (suppose it’s another Vaadin root)?

Thanks.

/Daryl

The missing notification is a regression. Similar code in Vaadin 6.7 shows the expected notification. I’ve created
ticket #8778
for this issue.

No, a terminal error is any uncaught server side exception. The exception only happens in the server side code. In Vaadin 7, that exception is apparently not properly handled, so that a generic error message is sent to the client instead of the results of running the terminalError method.

If you reload the page in the browser (without ?restartApplication in the URL), the notification will be displayed there instead because it has remained in the server side queue over changes that should be sent to the client.

That is what Application.terminalError is designed for, though it’s apparently broken in Vaadin 7.

Sending the user to another Vaadin Root when an internal error happens feels like a quite dangerous path - the user may end up in an infinite loop if an error occurs when showing that Root. Otherwise it might however work if you store the last exception on the server side, e.g. as a field in your Application class from where the error form root can find it. I would still suggest waiting for the regression to be fixed and handle it the “proper” way instead.

Ok, thanks. I’ll try it in V6. I noticed the ticket states “If a Notification is added to the current Root…” Attempts to add components also fails.


public void terminalError(ErrorEvent event) {
	Window window = new Window("Error");
	window.addComponent(new Label("Something bad happened."));
	window.center();
	Root.getCurrentRoot().addComponent(window);
}

/Daryl

Now that Vaadin 7 beta 3 is out, what is the Vaadin 7 way to handle uncaught exceptions?

Same question.

The same thing can be done in Vaadin 7 using VaadinServiceSession.setErrorHandler

You say that exceptions can be handled in the same way in Vaadin 7 but I have two questions:

  1. Terminal has been deprecated and there is a new VaadinServiceSession.ApplicationError but it doesn’t appear to be used. There is still a setErrorHandler method that takes a Terminal. The method itself is not deprecated. Is this still the right method to use even though Terminal is deprecated?

  2. Do exceptions triggered during initial UI construction get handled by this error handler? If so, then it seems logical that my first line of UI.init() should be to set me error handler.

Thanks,
-mike

In Vaadin 7.0 beta 10,
Terminal has been eliminated
.

Currently in Vaadin 7.0.0+ you must use
VaadinSession.getCurrent().setErrorHandler
:

	VaadinSession.getCurrent().setErrorHandler(new ErrorHandler() {

	    @Override
	    public void error(ErrorEvent event) {
		// ...
	    }

	});

handleExceptionDuringRequest method in VaadinService does not allow the errorHandler to handle the request. After calling errorHandler.error(new ErrorEvent(t));, a ServiceException is still thrown. This does not allow the handler to prevent an exception being thrown to the client. Is this a bug?

More like a missing feature, IMHO. The logic in handleExceptionDuringRequest is a bit weird, but it’s meant only for cases where something critical happens in Vaadin core code. However, currently exceptions thrown from connector resource request handling (possibly from user code) are passed there and this could be considered a bug (they should be handled via the regular connector exception handling). Please see
ticket #12269
which will probably be implemented for Vaadin 7.2.

Was this ever fixed? We are using Vaadin 7.3.6… We override the setErrorHandler this way:

VaadinSession.getCurrent.setErrorHandler(new DefaultErrorHandler() { override def error(event: com.vaadin.server.ErrorEvent) {…

When I purposely throw a Runtime Exception I get logging going to the Console of the stack trace but not being logged with log4j, and it does not go into our custom error method. Note we are using Scala and the runtime exception happens in a Spring transaction (which rollsback first). I have tried upgrading to 7.3.10 but that did not help.

Note changed new DefaultErrorHandler to new ErrorHandler() as seen in previous posts but it doesn’t help.

Where is the best place to register session error handler? I would like to have it for all my UI. Does it mean that I have to introduce some parent UI?

VaadinSession.getCurrent().setErrorHandler

I think the best way would be to use UI.setErrorHandler.
so for example in your Ui’s init method you can do:

[code]
setErrorHandler(new ErrorHandler() {

        @Override
        public void error(com.vaadin.server.ErrorEvent event) {
            System.out.println(event.getThrowable().getMessage());
        }
    });

[/code]Instead of the sysout you of course do something more sensible like display a Window explaining the User there was a problem and/or a way to submit a Bug to the Dev.

FYI,

To catch and log all errors, you have to invoke both UI.setErrorHandler() and VaadinSession.setErrorHandler().

Plus you should also register a servlet filter that logs exceptions, e.g., [ExceptionLoggingFilter]
(http://archiecobbs.github.io/dellroad-stuff/site/apidocs/index.html?org/dellroad/stuff/servlet/ExceptionLoggingFilter.html).

Could You explain a little bit Your solution ?
Tks
Tullio