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?
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)?
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.
You say that exceptions can be handled in the same way in Vaadin 7 but I have two questions:
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?
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.
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.
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.
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?
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.