Infinite loop in case of RuntimeException

Hi Vaadin pros,

in my application I am investigating a strange behaviour at the moment. I am currently taking care of general exception handling. Doing so I have overriden function terminalError() in my Application. The implementation is straight forward at the moment:


    @Override
    public void terminalError(final Terminal.ErrorEvent event) {

        super.terminalError(event);
        ExceptionUtils.handleException(getMainWindow(), event.getThrowable());

    }

ExceptionUtils.handleException() is just showing an customized error notification to the user.
To test my error handling i just added some throwing of a RuntimeException to some ClickListener in my app - works as desired.
But when a RuntimeException exception is occuring “inside” some vaadin component (since I am quit new to vaadin I call this “client side error” at the moment) I can see in the stacktrace that
AbstractApplicationServlet.handleServiceException()
is coming into play.

Now I am facing 2 problems with that:
[b]

  1. The critical notification (via SystemMessages) is rendered allthough my application is not null and terminalError() can be called. Actually it is being called but my custom notification is not displayed to the user.

  2. The way bigger problem than 1): When the user clicks on the critical notification the page is being reloaded. Since it is a “client side error” this will execute the exact same code that threw the exception before, throwing the RuntimeException again and trapping the user in an infinite loop.
    [/b]

Any idea how to handle that properly?

thanks,
Sven

Noone? Is any more code / information needed to illustrate the problem?

Was hoping that someone Else knows a solution, as I don’t Know One.

Hi Sven,

For the first problem I can tell you that the SystemErrorMessages that are shown in red in the client browser can be overridden by creating your own implementation of CustomizedSystemMessages and overriding the


public static SystemMessages getSystemMessages()

method in your application class (Vaadin 6 only). You cannot “override” static methods, but if you create your own static method in your application class, Vaadin will use your custom error messages instead of the default ones.



public class MyApp extends Application{
      //Application implementation

      public static MyErrorMessages getSystemMessages(){
          return new MyErrorMessages(); 
      }

      public static class MyErrorMessages extends CustomizedSystemMessages {

        public MyErrorMessages() {
            //Some examples, see CustomizedSystemMessages for full API
            setCommunicationErrorCaption("There was an error communicating with the server");
            // setCookiesDisabledNotificationEnabled(false);
            setCookiesDisabledURL("http://www.google.com");
        }
    }
}

Please note that the error messages are cached on the client side (browser) so that they can be shown even when the server is unreachable. In the CustomizedSystemMessages you can configure which messages are shown and the texts that are shown to the user. You can also enter the redirect URL that will be used when the user clicks on the error message (or immediately if the error message is disabled).

As for the second question, it is quite hard to give any specific solution as I don’t know what causes the RuntimeException in the first place. What Vaadin will do by default when a system error occurs and the user klicks on the error message is a full refresh of the client-side (i.e. all components and their states are refreshed from the server). If your application throws an unhandled exception during the refresh then you could be stuck in an infinite error loop.

Could you provide some code or stack traces of a simple application where this behaviour can be reproduced? Client-side error in this case is a bit undefined as there can also be “client-side” exceptions that are thrown in the java script in the browser.

Have you tried adding ?debug in the URL to see if you get some exceptions to the Vaadin debug console?
Are you using some add-ons that might be causing exceptions on the client-side (browser)?

Kind regards

Hi Petri,

thanks for your reply.

to 1):
I already have overriden the getSystemMessages() Method. I was just wondering why the call of the method terminalError() in my application (which is happening after rendering the criticalNotification) has no impact on the screen. Here is the code of AbstractApplicationServlet that led me to my assumption:


        if (getRequestType(request) == RequestType.UIDL) {
            Application.SystemMessages ci = getSystemMessages();
            criticalNotification(request, response,
                    ci.getInternalErrorCaption(), ci.getInternalErrorMessage(),
                    null, ci.getInternalErrorURL());
            if (application != null) {
                application.getErrorHandler()
                        .terminalError(new RequestError(e));
            } else {
                throw new ServletException(e);
            }
        } else {
            // Re-throw other exceptions
            throw new ServletException(e);
        }

to 2):
Here is one example stacktrace (shortened) which led to an infinite loop:


com.vaadin.event.ListenerMethod$MethodException: Invocation of method valueChange in org.tepi.filtertable.FilterFieldGenerator$2 failed.
        at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:530)
        at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:164)
        at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1219)
        at com.vaadin.ui.AbstractField.fireValueChange(AbstractField.java:897)
        at com.vaadin.ui.AbstractField.setValue(AbstractField.java:529)
        at com.vaadin.ui.AbstractTextField.changeVariables(AbstractTextField.java:242)
        at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.changeVariables(AbstractCommunicationManager.java:1460)
        at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1404)
        at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1329)
        at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:761)
        at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:323)
        at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:501)
        at de.cominto.epad.web.servlet.SpringApplicationServlet.service(SpringApplicationServlet.java:170)
        at javax.servlet.http.HttpServlet.service(Unknown Source)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Unknown Source)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(Unknown Source)
        at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:119)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Unknown Source)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(Unknown Source)
        at org.apache.catalina.core.StandardWrapperValve.invoke(Unknown Source)
        at org.apache.catalina.core.StandardContextValve.invoke(Unknown Source)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(Unknown Source)
        at org.apache.catalina.core.StandardHostValve.invoke(Unknown Source)
        at org.apache.catalina.valves.ErrorReportValve.invoke(Unknown Source)
        at org.apache.catalina.core.StandardEngineValve.invoke(Unknown Source)
        at org.apache.catalina.connector.CoyoteAdapter.service(Unknown Source)
        at org.apache.jk.server.JkCoyoteHandler.invoke(Unknown Source)
        at org.apache.jk.common.HandlerRequest.invoke(Unknown Source)
        at org.apache.jk.common.ChannelSocket.invoke(Unknown Source)
        at org.apache.jk.common.ChannelSocket.processConnection(Unknown Source)
        at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(Unknown Source)
        at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:662)
       [... caused by ...]

The “caused by” part of the stacktrace is some Hibernate Exception (FilterTable backed up by a HbnContainer). The error was caused by a user entering some “invalid” data in one of the filters of the table. Surely we found and fixed exactly this error, but I was wondering how many more errors there are in my application leading to the same infinite loop situation?

Thanks again,
Sven