четверг, 3 января 2013 г.

Exception handling in GWT

1) Global exception handling
     При разработке GWT приложения временами происходят непонятные вещи, и вы понятия не мееете, почему такое происходит. Вы можете тратить часы напролет в дебаге пытаясь найти критическую область, что часто зависит от многих факторов. Наверное, многие сталкивались с такой ситуацией, когда в режиме разработки(development mode) работает все отлично, но не после того, как все скомпилируется, соберется и разверернется на сервере. И это почти неизбежно, но если вы вооружены несколькими простыми приемами, то можно сэкономить много времени.
     Хорошим местом для добавления глобального обработчика исключений будет EntryPoint класс. Он позволит на клиентской стороне перехватывать все выброшенные исключения. Давайте зарегистрируем UncaughtExceptionHandler.
public void onModuleLoad() {
  GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
    @Override
    public void onUncaughtException(Throwable e) {
      // some exception handling logic
    }
  });
  // module loading...
}


* This source code was highlighted with Source Code Highlighter.
     Что произойдет, если не добавить UncaughtExceptionHandler в приложение? В режиме отладки(hosted mode), по умолчанию обработчик будет логировать исключения и выводить на консоль. В веб-режиме(web mode) обработчик является null и исключения будут выводиться в браузер, что не очень дружественно к пользователю.
     Также не стоит забывать, что UncaughtExceptionHandler начнет работать только после того, как отработает onModuleLoad() метод. Другими словами, если произойдет исключение во время загрузки модуля, то пользовательский обработчки событий еще не успеет проинициализироваться и это исключение не будет обработано. Это известная проблема, у которой, пока что нет решения, но есть небольшой обходной путь. Если вы ожидаете, что при выполнении метода onModuleLoad() может быть выброшено исключение, то можно извлечь содержимое метода в другой метод onModuleLoad2() и вызвать его используя Scheduler.
public void onModuleLoad() {
  GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
    @Override
    public void onUncaughtException(Throwable e) {
      // some exception handling logic
    }
  });
  
  Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
    @Override
    public void execute() {
      onModuleLoad2();
    }
  });

  private void onModuleLoad2() {
    // module loading logic
  }
}


* This source code was highlighted with Source Code Highlighter.
2) UmbrellaException
     Иногда работая с GWT мы получаем UmbrellaException исключение:
com.google.gwt.event.shared.UmbrellaException: One or more exceptions caught, see full set in UmbrellaException#getCauses
  at com.google.gwt.event.shared.HandlerManager.fireEvent(HandlerManager.java:129)
  at com.google.gwt.user.client.ui.Widget.fireEvent(Widget.java:129)
  at com.google.gwt.event.dom.client.DomEvent.fireNativeEvent(DomEvent.java:116)
  at com.google.gwt.user.client.ui.Widget.onBrowserEvent(Widget.java:177)
  at com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1351)
  at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1307)
  at sun.reflect.GeneratedMethodAccessor57.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.lang.reflect.Method.invoke(Unknown Source)
  …


* This source code was highlighted with Source Code Highlighter.
    Он появился в GWT 2.1.1, вот что про него написано в документации:
A RuntimeException that collects a Set of child Throwables together. Typically thrown after loop, with all of the exceptions thrown during that loop, but delayed so that the loop finishes executing.

* This source code was highlighted with Source Code Highlighter.
     Класс UmbrellaException наследует RuntimeException и является простым набором исключений(Throwable на самом деле). Название скорее всего происходит от слова “зонтик”, обозначающее объект, которые охватывает различные вещи. В текущем случае, это исключение, которое охватывает множество других исключений.
     Для упрощения отладки и более точной обработки ошибок бывает очень полезно развернуть выброшеные исключения.
GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
  @Override
  public void onUncaughtException(Throwable e) {
    verifyNotUmbrellaException(e);
  }
});

private void verifyNotUmbrellaException(Throwable e) {
  for (Throwable th : ((UmbrellaException) e).getCauses()) {
    if (th instanceof UmbrellaException) {
      verifyNotUmbrellaException(th);
    } else {
      th.printStackTrace();
    }
  }
}


* This source code was highlighted with Source Code Highlighter.

Комментариев нет:

Отправить комментарий