На стороне сервера у нас есть подкласс RemoteServiceServlet, который мы используем для всех реализаций сервисов. Вы упоминаете, что это кажется трудоемким, но вот как выглядит код. Вы делаете это один раз, и все готово.
@Override
protected void doUnexpectedFailure(Throwable t) {
t.printStackTrace(System.err);
super.doUnexpectedFailure(t);
}
Примечание. На самом деле мы не отправляем его в System.err, и вы, вероятно, тоже не должны этого делать, но вы поняли идею.
На стороне клиента мы используем подкласс AsyncCallback, называемый AsyncSuccessCallback. Он обрабатывает случай onFailure единообразно для большинства наших вызовов RPC. Большая часть нашего кода обратного вызова может работать со случаем onSuccess, зная, что onFailure обрабатывается. Это также предоставляет единственное место для изменения этой реализации позже.
public abstract class AsyncSuccessCallback<T> implements AsyncCallback<T> {
public void onFailure(Throwable t) {
handleException(t);
}
protected void handleException(Throwable t) {
Window.alert(t.getMessage());
}
}
Примечание. На самом деле мы не используем Window.alert, но, опять же, вы поняли идею. В данном случае мы отображаем диалоговое окно GWT DialogBox, которое отображает форму, которая выполняет процедуру POST на другом сервере, который принимает отчеты об ошибках. Форма позволяет пользователю ввести описание того, что он делал, когда произошла ошибка.
На стороне клиента, если вы хотите получить трассировку стека, вам нужно написать немного дополнительного кода:
// for lineEnding, use "<br>" for HTML, "\n" for text
public static final String getStackTrace(Throwable t, String lineEnding) {
Object[] stackTrace = t.getStackTrace();
if (stackTrace != null) {
StringBuilder output = new StringBuilder();
for (Object line : stackTrace) {
output.append(line);
output.append(lineEnding);
}
return output.toString();
} else {
return "[stack unavailable]";
}
}