prague gwt

Upload: bac-le-phuong-

Post on 29-May-2018

222 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/9/2019 Prague GWT

    1/39

    Real GWT ApplicationsJeff DwyerAuthor: Pro Web 2.0 Applications with GWT

    Founder: ToCollege.net & MyHippocampus.com

    Currently: (rails)

  • 8/9/2019 Prague GWT

    2/39

    Today

    What and Why GWT?

    Demo ToCollege.net

    Real Apps Integration Patterns

    Hibernate Security

    Gears

  • 8/9/2019 Prague GWT

    3/39

    Goal

    Rich web experiences. Speed and responsiveness of desktop.

    Benefits of the web.

  • 8/9/2019 Prague GWT

    4/39

    Landscape

    JavaScript+ Server RichClient

    YUI

    Dojo

    Rico

    Script.aclo.us

    jMaki

    Flex

    Silverlight

    Echo

    Lazlo

    JSF

    GWT

  • 8/9/2019 Prague GWT

    5/39

    Why GWT

    GWT Brings Java Software DevelopmentBest Practices to AJAX HTML

    GWT is DHTML + JavaScript JavaScript doesnt scale... with increased

    development staff.

    Best Practices: i18n, History, ImageBundle

  • 8/9/2019 Prague GWT

    6/39

    Features

    Easy RPC: Single domain for client & server

    History Mechanism Extremely Cacheability

    Browser Compatibility

    Real Debugging & JUnit & I18N

  • 8/9/2019 Prague GWT

    7/39

    Benefits & Joys

    One Domain Model

    Static Typing

    IDE Refactoring, Code Completion FindBugs, PMD, Checkstyle, Metrics

    Hosted Mode. Real Debugging. Maven

  • 8/9/2019 Prague GWT

    8/39

    Tradeoffs? Code Size? Think HttpRequests > size

    Cache Forever Debugable w/ Firebug? Use pretty mode or real debugger

    Script.aculo.us? JSNI is great, or whip together yourself.

    SEO...

  • 8/9/2019 Prague GWT

    9/39

    How it Works

    Swing + CSS

    Java to JavaScript compiler Compressed and Obfuscated by default

    Include in HTML with and

    Locale Specific Compilation

  • 8/9/2019 Prague GWT

    10/39

    Demo

    www.ToCollege.net http://code.google.com/p/tocollege-net/

    http://code.google.com/p/tocollege-net/http://code.google.com/p/tocollege-net/http://code.google.com/p/tocollege-net/
  • 8/9/2019 Prague GWT

    11/39

    ToCollege.net Stack

    MySQL / Hibernate

    Compass

    Spring MVC 2.5 Acegi & OpenID

    SiteMesh & FreeMarker GWT 1.5 Integration SEO, Security

    Also: Facebook, Maven

  • 8/9/2019 Prague GWT

    12/39

    VerticalLabel

  • 8/9/2019 Prague GWT

    13/39

    public class VerticalLabel extends Composite {public interface LetterImages extends ImageBundle {

    AbstractImagePrototype A();

    AbstractImagePrototype B();AbstractImagePrototype sY();

    AbstractImagePrototype sZ();

    AbstractImagePrototype SPACE();

    }

    private FlowPanel mainPanel;

    private HashMap allImages;private static final LetterImages images =

    (LetterImages) GWT.create(LetterImages.class);

    public VerticalLabel(String text) {

    if (allImages == null) {

    createMap();

    }

    mainPanel = new FlowPanel();

    mainPanel.setStylePrimaryName("vertical-label");

    setText(text);

    initWidget(mainPanel);

    }private void setText(String text) {

    mainPanel.clear();

    for (int i = text.length() - 1; i >= 0; i--) {

    char c = text.charAt(i);

    mainPanel.add(getImage(c));

    }

    }

    }

    VerticalLabel.java

  • 8/9/2019 Prague GWT

    14/39

    The Joy of IE6 w/ Apologies to Joel Webber

    Interface:

    public abstract boolean compare(Element e1, Element e2);Standard:

    public native boolean compare(Element e1, Element e2) /*-{return (e1 == e2);

    }-*/;IE6:

    public native boolean compare(Element e1, Element e2) /*-{if (!e1 && !e2)

    return true;else if (!e1 || !e2)

    return false;return (e1.uniqueID == e2.uniqueID);

    }-*/;

    Deferred Binding

  • 8/9/2019 Prague GWT

    15/39

    public class ForumApp extends GWTApp implements

    HistoryListener {

    public ForumApp(int pageID) {if (initToken.length() > 0) {

    onHistoryChanged(initToken);

    }History.addHistoryListener(this);

    }

    // #School~486~20

    // #UserForumPost~12~0// #UserForumPost~12

    public void onHistoryChanged(String historyToken) {ForumCommand fc = new ForumCommand();

    String[] tok = historyToken.split(ForumTopic.SEP);

    fc.setId(Long.parseLong(tok[1]));if (tok.length == 3) {

    fc.setStart(Integer.parseInt(tok[2]));

    }

    fc.setType(tok[0]);load(fc);

    }

    }

    History(Back Button)

    http://www.tocollege.net/forums.html#SchoolForumPost~112

    http://www.tocollege.net/forums.html#http://www.tocollege.net/forums.html#http://www.tocollege.net/forums.html#http://www.tocollege.net/forums.html#
  • 8/9/2019 Prague GWT

    16/39

    SampleApp.java1.5 Source

    JREEmulation

    GWTCompiler

    Gecko(Fr)

    Gecko(En)

    IE (En)

    IE (Fr)function gGd(a){return (this==null?null:this)===(a==null?null:a)}function hGd(){return gmb}function iGd(){return this.$H||(this.$H=++Cvc)}

    ... (...)

  • 8/9/2019 Prague GWT

    17/39

    SampleApp.java1.5 Source

    JREEmulation

    GWTCompiler

    Gecko Gecko

    IE (En)

    IE (Fr)function gGd(a){return (this==null?null:this)===(a==null?null:a)}function hGd(){return gmb}function iGd(){return this.$H||(this.$H=++Cvc)}

    IE

    ... (...)

    Spring MVC, PHP, Rails, etc

    ?

  • 8/9/2019 Prague GWT

    18/39

    SampleApp.java1.5 Source

    JREEmulation

    GWTCompiler

    Gecko Gecko

    IE (En)

    IE (Fr)function gGd(a){return (this==null?null:this)===(a==null?null:a)}function hGd(){return gmb}function iGd(){return this.$H||(this.$H=++Cvc)}

    IE

    ... (...)

    SpringMVCPHP

    Rails

  • 8/9/2019 Prague GWT

    19/39

    Simple GWT Integration

    protectedvoid loadError(Exception e) {

    VerticalPanel panel = new VerticalPanel();

    panel.add(new Label("Error"));

    panel.add(new Label(e.getMessage()));

    RootPanel.get(gwt-preload).setVisible(false);

    RootPanel.get(gwt-slot).add(panel);}

  • 8/9/2019 Prague GWT

    20/39

    Real Applications

    Integration

    JavaScript & FreeMarker Macros

    Hibernate Command Pattern

    Security XSRF & Command Pattern

    Gears

  • 8/9/2019 Prague GWT

    21/39

    Integration

    div id == Java Code What about multiple component talking to

    each other?

    What about re-use?

    This is where people screw up. Manymodules, etc.

    Solution? Leverage JavaScript.

  • 8/9/2019 Prague GWT

    22/39

    Spring MVC Integration

    Macros are your friend

    Component-ization GWT-RPC

    SEO w/ Bootstrapping &

  • 8/9/2019 Prague GWT

    23/39

    Using GWT: Macros

  • 8/9/2019 Prague GWT

    24/39

    Using GWT: JavaScript

    FreeMarker

    GWTDispatcher

    VerticalImageApp ToCollegeApp ImageBundleApp

    Vars['widgetCount'] = "2"

    Vars['widget_1'] = "ImageBundle"

    Vars['widget_2'] = "VerticalImage"Vars['widget_2_text'] = "Make Me Vertical!"

  • 8/9/2019 Prague GWT

    25/39

    Hiberate: Architecture

  • 8/9/2019 Prague GWT

    26/39

    Hibernate4GWT

    User

    Application

    School

    Hib4GWTProxy

    1..1

    GWT Client

    User

    Application

    School

    Reviews (Lazy)

    1..1

    ServerGWTRPC

    &

    Hib4GWT

  • 8/9/2019 Prague GWT

    27/39

    Hibernate w/GWTHibernateFilter

    User

    Application

    School

    Null

    1..1

    GWT Client

    User

    Application

    School

    Reviews (Lazy)

    1..1

    ServerGWTRPC

    &GWTHibernateFilter

  • 8/9/2019 Prague GWT

    28/39

    Pro & Cons

    Hibernate4GWT GWTHibernateFilter

    Pros Can use save(Object) No change to objects

    ConsOverhead.Must implementHibernate4GWT

    Cant simply call save()Lazy collections != null

  • 8/9/2019 Prague GWT

    29/39

    RPC Servicepublicinterface GWTSchoolService extends RemoteService {

    SiteCommand executeAndSaveCommand(SiteCommand comm)

    throws SiteException;

    List getAllSchools() throws SiteException;

    PostsList getForum(String tagname, int start, int max)

    throws SiteException;

    School getSchoolDetails(String schoolName);

    List getSchoolsMatching(String match) throws SiteException;

    List matchProcessType(String queryString)

    throws SiteException;

    }

  • 8/9/2019 Prague GWT

    30/39

    Get Idempotent

    SOFE

    Spring Security

    ServerPostsList getForum(String tagname, int start, int max)

    throws SiteException;

    School getSchoolDetails(String schoolName);

  • 8/9/2019 Prague GWT

    31/39

    PostSOFE

    Spring Security

    Server

    SiteCommand executeAndSaveCommand(SiteCommand comm)

    throws SiteException;

    Command

    XSRF Protection

  • 8/9/2019 Prague GWT

    32/39

    Command Pattern

    Hibernate Integration

    Authorization XSRF

    Gears / Offline

  • 8/9/2019 Prague GWT

    33/39

    save(Object o)

    Dangerous Client can modify anything.

  • 8/9/2019 Prague GWT

    34/39

    Command Pattern

    G (1)

  • 8/9/2019 Prague GWT

    35/39

    publicclass SimpleGearsDatabase extends Database implements ClientDB {

    public SimpleGearsDatabase(String databaseName) throws GearsException { super(databaseName);

    } public ResultSet execute(String statement, Object... args) {

    String[] strs = new String[args.length];//convert args -> strs

    return execute(statement, strs);}

    publicvoid createKeyedStringStore(String tableName) {

    execute("drop table if exists " + tableName);execute("create table if not exists " + tableName

    + " (key varchar(255), json text )");

    } publicvoid addToKeyedStringStore(String tableName, String key,

    String value) {execute("insert into " + tableName + " values (?, ?)", key, value);

    }

    public List getFromKeyedStringStore(String tableName,String key, GearsRowMapper mapper) {

    return query("select json from " + tableName + " where key = ?",mapper, key);

    }}

    Gears (1)

  • 8/9/2019 Prague GWT

    36/39

    Gears (2) public List query(String sql, GearsRowMapper mapper,

    Object... args) {

    ResultSet rs = execute(sql, args);

    List rtn = new ArrayList();

    for (int i = 0; rs.isValidRow(); ++i, rs.next()) {

    rtn.add(mapper.mapRow(rs, i));

    }

    rs.close();

    return rtn;

    }publicinterface GearsRowMapper {

    T mapRow(ResultSet rs, int rowNum) throws DatabaseException;

    }

    G (3)

  • 8/9/2019 Prague GWT

    37/39

    Gears (3)public ServiceCache(GWTApp gwtApp) {

    this.schoolService = gwtApp.getSchoolService();

    this.userService = gwtApp.getUserService();

    if (Gears.isInstalled()) {

    try {

    db = new SimpleGearsDatabase("tocollege.net"); db.createKeyedStringStore(MATCH);

    db.createKeyedStringStore(PROCESSTYPE);

    } catch (GearsException e) {

    Log.warn("No Gears " + e.getMessage());

    }

    } if (db == null) {

    Log.info("Creating Empty Client DB");

    db = new EmptyClientDB();

    }

    }

  • 8/9/2019 Prague GWT

    38/39

    publicvoid matchSchool(final String query,

    final AsyncCallback origCallback) {

    List stored = db.getFromKeyedStringStore(MATCH, query,

    stringMapper);

    if (stored != null && !stored.isEmpty()) {

    origCallback.onSuccess(stored);

    return;

    } else {

    schoolService.getSchoolsMatching(query,

    new AsyncCallback() {

    publicvoid onFailure(Throwable caught) {

    origCallback.onFailure(caught);

    }

    publicvoid onSuccess(List result) {

    origCallback.onSuccess(result);

    for (String string : result) {

    db.addToKeyedStringStore(MATCH, query,

    string);

    }

    }

    });

    }

    }

  • 8/9/2019 Prague GWT

    39/39

    Thanks!

    ToCollege.net &

    http://code.google.com/p/tocollege-net/

    http://code.google.com/p/tocollege-net/http://code.google.com/p/tocollege-net/