gwt@jazoon08 - part 4/6 - attention to detail
DESCRIPTION
A presentation about GWT which I presentaed at Jazoon '08Part 4/6 - Attention to DetailTRANSCRIPT
LOGO SPEAKER‘S COMPANY
# 4
attention to detail.
LOGO SPEAKER‘S COMPANYmake quality evident in everything ...
LOGO SPEAKER‘S COMPANY
your Porsche may drive better but ...
LOGO SPEAKER‘S COMPANY
create delightfull experiences ...
LOGO SPEAKER‘S COMPANY
annoying.
ajax stuff you can’t bookmarkbroken back buttonserror type 11page that crashes during submit, what now?
LOGO SPEAKER‘S COMPANY
history.[ for dummies ]
LOGO SPEAKER‘S COMPANY
LISTEN TO HISTORY EVENTS
public class Example implements EntryPoint, HistoryListener {
public void onModuleLoad() {
History.addHistoryListener(this);
}
public void onHistoryChanged(String historyToken) { ... }
}
CREATE HISTORY EVENTS
History.newItem(“profile”); = http://localhost:8080/example#profile
History.newItem(“search”); = http://localhost:8080/example#search
History.newItem(“edit”); = http://localhost:8080/example#edit
LOGO SPEAKER‘S COMPANY
history.[ demystified ]
LOGO SPEAKER‘S COMPANY
BEHIND THE SCENES
browser history does not only effect top level pages browser history also works for iFrames History maintains a stack of applied tokens these tokens can be used to map to specific application state
background timer which check each ¼ of a second if $wnd.location has changed, if so it triggers the History listener (onHistoryChanged)
LOGO SPEAKER‘S COMPANY
error handling.[ best practices ]
LOGO SPEAKER‘S COMPANY
CATCH UNCAUGHT EXCEPTIONS
catch exceptions at the top-level just before they escape to the browser useful for event callbacks, timers, rpc… which are hard to try / catch
GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() { public void onUncaughtException(Throwable e) { Window.alert(“You thought you could get away didn’t you !!!"); } });
LOGO SPEAKER‘S COMPANY
STANDARDIZE EXCEPTION HANDLING
public abstract class ApplicationAsyncCallback<T> implements AsyncCallback<T> {
public final void onSuccess(T object) { onSuccessInternal(object);
}
public final void onFailure(Throwable throwable) { onFailureInternal(throwable);
Window.alert(“KABOEMMMM”); }
protected void onSuccessInternal(T object) {}
protected void onFailureInternal(Throwable throwable) {} }
LOGO SPEAKER‘S COMPANY
LOG, LOG, LOG, LOG EVERYWHERE (1/4)
Log.debug(“Some log message”);
public class Log {
private static final Logger logger = GWT.isScript() ? new com.FireBugLogger() : new HostedModeLogger();
public static void debug(String message) { log(DEBUG, message); }
protected static void log(Level level, String message) { if (enabled && level.getWeight() <= getMaxLevel().getWeight()) { switch (level) { case ERROR: logger.error(message); break; case WARN: logger.warn(message); break; case INFO: logger.info(message); break; case DEBUG: logger.debug(message); break;
LOGO SPEAKER‘S COMPANY
LOG, LOG, LOG, LOG EVERYWHERE (2/4)
// request log level at runtime http://localhost:8080/x.html?log.level=error public static native String getLoglevel() /*-{
var level; var args = $wnd.location.search; var startLang = args.indexOf("log.level"); if (startLang >= 0) { var value = args.substring(startLang); var begin = value.indexOf("=") + 1; var end = value.indexOf("&"); if (end == -1) { end = value.length; } level = value.substring(begin, end); } return level; }-*/;
LOGO SPEAKER‘S COMPANY
LOG, LOG, LOG, LOG EVERYWHERE (3/4)
public class FireBugLogger implements Logger {
private boolean fireBugInstalled = false;
protected FireBugLogger() { checkIfFireBugInstalled(); }
protected native void checkIfFireBugInstalled() /*-{ [email protected]::fireBugInstalled = (typeof console != 'undefined'); }-*/;
public native void debug(String message) /*-{ if ([email protected]::fireBugInstalled) console.debug(message); }-*/;
LOGO SPEAKER‘S COMPANY
LOG, LOG, LOG, LOG EVERYWHERE (4/4)
public class HostedModeLogger implements Logger {
public void debug(String message) { log(toMessageWithLineInformation("DEBUG", message)); }
public void log(String message) { GWT.log(message, null); }
private String toMessageWithLineInformation(String logLevel, String message) { StackTraceElement line = new Throwable().getStackTrace()[4]; return (logLevel + " " + toLine(line) + ": " + message); }
private String toLine(StackTraceElement line) { return line.getClassName() + "(" + line.getLineNumber() + ")"; }
LOGO SPEAKER‘S COMPANY
what’s wrong with the log example?
LOGO SPEAKER‘S COMPANY
AUTOMATED USER ACCEPTANCE TESTS WITH SELENIUM
your code
Label firstnameLabel = new Label(); label.ensureDebugId(“firstnameLabel”); // if not enabled does nothing
enable debug mode – go Selenium gooooo…..
<inherits name=“com.google.gwt.user.Debug”/> // DOM.setElementProperty(…)
under the hood – UIObject
private static DebugIdImpl debugIdImpl = GWT.create(DebugIdImpl.class);
public static void ensureDebugId(Element elem, String id) { debugIdImpl.ensureDebugId(elem, id); }
LOGO SPEAKER‘S COMPANY
MAARTENVOLDERS.comPASSIONATE ABOUT PEOPLE AND TECHNOLOGY