54
Leif Åstrand Senior Vaadin Expert Comparing GWT Transport Mechanisms torsdag 19 december 13

Comparing GWT Transport Mechanisms

Embed Size (px)

DESCRIPTION

Presentation about transport mechanisms in GWT, held at GWT.create 2013 in San Francisco and Frankfurt.

Citation preview

Page 1: Comparing GWT Transport Mechanisms

Leif ÅstrandSenior Vaadin Expert

Comparing GWT Transport Mechanisms

torsdag 19 december 13

Page 2: Comparing GWT Transport Mechanisms

public class Contact { private String name; private int yearOfBirth;

private List<String> emailAddresses;

private Address address; public static class Address { private String street; private String city; }

// + Getters and setters

}

Contact

torsdag 19 december 13

Page 3: Comparing GWT Transport Mechanisms

AJAX

torsdag 19 december 13

Page 4: Comparing GWT Transport Mechanisms

Good

• It just works

Bad

• Low level

RequestBuilder

torsdag 19 december 13

Page 5: Comparing GWT Transport Mechanisms

Real world usage

11 %torsdag 19 december 13

Page 6: Comparing GWT Transport Mechanisms

RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);try { builder.sendRequest(requestData, new RequestCallback() {

@Override public void onResponseReceived(Request request, Response response) { int statusCode = response.getStatusCode(); String text = response.getText(); }

@Override public void onError(Request request, Throwable exception) { // TODO Handle asynchronous problems

} });} catch (RequestException e) { // TODO Handle synchronous problems}

RequestBuilder

torsdag 19 december 13

Page 7: Comparing GWT Transport Mechanisms

Contact

String

torsdag 19 december 13

Page 8: Comparing GWT Transport Mechanisms

String data = contact.getName();data += "," + contact.getYearOfBirth();

String[] parts = data.split(",");contact.setName(parts[0]);contact.setYearOfBirth(Integer.parseInt(parts[1]));

String conversion

torsdag 19 december 13

Page 9: Comparing GWT Transport Mechanisms

String data = contact.getName();data += "," + contact.getYearOfBirth();

String[] parts = data.split(",");contact.setName(parts[0]);contact.setYearOfBirth(Integer.parseInt(parts[1]));

String conversion

torsdag 19 december 13

Page 10: Comparing GWT Transport Mechanisms

<?xml version="1.0" encoding="UTF-8"?><contact name="John Doe" yearOfBirth="1900"> <address street="HappyStreet 1" city="Turku" /> <email address="[email protected]" /> <email address="[email protected]" /></contact>

XML

torsdag 19 december 13

Page 11: Comparing GWT Transport Mechanisms

Document document = XMLParser.parse(string);Element contactElement = document.getDocumentElement();

contact.setName(contactElement.getAttribute("name"));contact.setYearOfBirth(Integer.parseInt(

contactElement.getAttribute("yearOfBirth")));contact.setAddress(parseAddress(

contactElement.getElementsByTagName("address").item(0)));

NodeList emailTags = contactElement.getElementsByTagName("email");for (int i = 0; i < emailTags.getLength(); i++) { contact.getEmailAddresses().add(

((Element) emailTags.item(i)).getAttribute("address"));

}

XML parsing

torsdag 19 december 13

Page 12: Comparing GWT Transport Mechanisms

Good

• It’s “standard”• Lots of server-side

libraries

Bad

• Verbose data• Verbose code• Document markup

language• Not so common in

the GWT ecosystem• Not typesafe

XML

torsdag 19 december 13

Page 13: Comparing GWT Transport Mechanisms

{ name: "John Doe", yearOfBirth: 1900, address: { street: "Happy Street 1", city: "Turku" }, emailAddresses: ["[email protected]", "[email protected]"]}

JSON

torsdag 19 december 13

Page 14: Comparing GWT Transport Mechanisms

JSONObject json = JSONParser.parseStrict(string).isObject();

contact.setName(json.get("name").isString().stringValue());contact.setYearOfBirth(

(int) json.get("yearOfBirth").isNumber().doubleValue());contact.setAddress(

parseAddress(json.get("address").isObject()));

JSONArray emailAddresses = json.get("emailAddresses").isArray(); for (int i = 0; i < emailAddresses.size(); i++) { contact.getEmailAddresses().add(

emailAddresses.get(i).isString().stringValue()); }}

JSONValue parsing

torsdag 19 december 13

Page 15: Comparing GWT Transport Mechanisms

Good

• It’s “standard”• Extensive library

support• Compact format

Bad

• Not completely typesafe

• JSONValue parsing code is verbose

JSON

torsdag 19 december 13

Page 16: Comparing GWT Transport Mechanisms

public class ContactJso extends JavaScriptObject { public native String getName() /*-{ return this["name"]; }-*/;

public native int getYearOfBirth() /*-{ return this["yearOfBirth"]; }-*/;

public native AddressJso getAddress() /*-{ return this["address"]; }-*/;

public native JsArrayString getEmailAddresses() /*-{ return this["emailAddresses"]; }-*/;}

JavaScriptObject

torsdag 19 december 13

Page 17: Comparing GWT Transport Mechanisms

Good

• Very efficient• Very little boilerplate

Bad

• /*-{ ... }-*/; syntax• Can’t share code

with the server

JavaScriptObject

torsdag 19 december 13

Page 18: Comparing GWT Transport Mechanisms

What about the server?

torsdag 19 december 13

Page 19: Comparing GWT Transport Mechanisms

JAX-RS

torsdag 19 december 13

Page 20: Comparing GWT Transport Mechanisms

Good

• It’s “standard”• Full control

Bad

• About as verbose as JSONValue

• Not suitable for GWT

• The Software shall be used for Good, not Evil.

org.json

torsdag 19 december 13

Page 21: Comparing GWT Transport Mechanisms

ObjectMapper mapper = new ObjectMapper();try { Contact contact = mapper.readValue(string, Contact.class);} catch (VariousExceptions e) { // Do something sensible}

Jackson on the server

torsdag 19 december 13

Page 22: Comparing GWT Transport Mechanisms

ReflectionCode generation

torsdag 19 december 13

Page 23: Comparing GWT Transport Mechanisms

public static interface ContactMapper extends ObjectMapper<Contact> {}

public Contact parseContact(String string) { ContactMapper mapper = GWT.create(ContactMapper.class); Contact contact = mapper.read(string); return contact;}

gwt-jackson

torsdag 19 december 13

Page 24: Comparing GWT Transport Mechanisms

Good

• Minimal boiler plate• Can share code

between server and client

• Plugin for JAX-RS

Bad

• You’re still just sending objects

Jackson

torsdag 19 december 13

Page 25: Comparing GWT Transport Mechanisms

Using interfaces instead of objects

torsdag 19 december 13

Page 26: Comparing GWT Transport Mechanisms

public interface Contact { public void setName(String name); public String getName();

public void setYearOfBirth(int yearOfBirth); public int getYearOfBirth();

public void setAddress(Address address); public Address getAddress();

public void setEmailAddresses(List<String> addresses); public List<String> getEmailAddresses();}

Contact interface

torsdag 19 december 13

Page 27: Comparing GWT Transport Mechanisms

interface AddressBookFactory extends AutoBeanFactory { public AutoBean<Contact> contact(); }

public void autobeanExample() { AddressBookFactory factory = GWT.create(AddressBookFactory.class); AutoBean<Contact> contactBean = factory.contact(); Contact contact = contactBean.as();

contact.setName("John Doe"); contact.setYearOfBirth(1900); contact.setEmailAddresses(Arrays.asList("[email protected]", "[email protected]"));

String json = AutoBeanCodex.encode(contactBean).getPayload();

AutoBean<Contact> bean = AutoBeanCodex.decode(factory, Contact.class, json);

contact = bean.as(); }

AutoBean

torsdag 19 december 13

Page 28: Comparing GWT Transport Mechanisms

Good

• Flexible foundation for custom implementations of interface methods

Bad

• Can’t use classes

AutoBean

torsdag 19 december 13

Page 29: Comparing GWT Transport Mechanisms

Intercepting interface methods allows us to...

Send partial updates

Manage entity identity

Use instance methods for RPC

torsdag 19 december 13

Page 30: Comparing GWT Transport Mechanisms

public interface AddressBookRequestFactory extends RequestFactory { public ContactRequest contactRequest();}

@Service(Contact.class)public interface ContactRequest extends RequestContext { public Request<List<ContactProxy>> getContacts(); public InstanceRequest<ContactProxy, Void> update();}

public void setupRequestFactory() { this.factory = GWT.create(AddressBookRequestFactory.class); this.eventBus = new SimpleEventBus(); this.factory.initialize(this.eventBus);}

RequestFactory - setting it up

torsdag 19 december 13

Page 31: Comparing GWT Transport Mechanisms

public void contactRequest() { ContactRequest contactRequest = factory.contactRequest(); contactRequest.getContacts().with("address").fire( new Receiver<List<ContactProxy>>() { @Override public void onSuccess(List<ContactProxy> contacts) { updateUI(contacts); } });}

public void updateContact(ContactProxy proxy) { ContactRequest contactRequest = factory.contactRequest(); contactRequest.update().using(proxy).fire();}

RequestFactory -client-side usage

torsdag 19 december 13

Page 32: Comparing GWT Transport Mechanisms

public class Contact { // + fields, setters and getters public Integer getId() { return this.id; }

public Integer getVersion() { return this.version; }

public void update() { ContactDAO.update(this); }

public static List<Contact> getContacts() { return ContactDAO.fetchContacts(); }}

RequestFactory - server-side

torsdag 19 december 13

Page 33: Comparing GWT Transport Mechanisms

Good

• Entities do not need to be GWT compatible

• Combines RPC and entity management

• Automatic request handling

Bad

• Complex setup• Heavy coupling with

the server

RequestFactory

torsdag 19 december 13

Page 34: Comparing GWT Transport Mechanisms

Real world usage

7 %torsdag 19 december 13

Page 35: Comparing GWT Transport Mechanisms

Why not just send Java objects?

torsdag 19 december 13

Page 36: Comparing GWT Transport Mechanisms

public Object[] sendAndReceive(Object[] objects);

Send and receive objects

public interface ContactService { public void saveContact(Contact contact); public List<Contact> getContacts();}

torsdag 19 december 13

Page 37: Comparing GWT Transport Mechanisms

public interface ContactService { public AsyncResult<Void> saveContact(Contact contact); public AsyncResult<List<Contact>> getContacts();}

Asynchronousity

public interface ContactServiceAsync { public void saveContact(Contact contact, AsyncCallback<Void> callback); public void getContacts(AsyncCallback<List<Contact>> callback);}

torsdag 19 december 13

Page 38: Comparing GWT Transport Mechanisms

Good

• Simple but powerful concept

• The default solution

Bad

• You (almost) always send the entire object graph

GWT-RPC

torsdag 19 december 13

Page 39: Comparing GWT Transport Mechanisms

Most popular!

53 %torsdag 19 december 13

Page 40: Comparing GWT Transport Mechanisms

[-4, 2, 42, [“Foo”, “Bar”]]

2 | Foo | Bar | 42 | 2 | -4

torsdag 19 december 13

Page 41: Comparing GWT Transport Mechanisms

What if we put the server in control?

torsdag 19 december 13

Page 42: Comparing GWT Transport Mechanisms

torsdag 19 december 13

Page 43: Comparing GWT Transport Mechanisms

State synchronization

torsdag 19 december 13

Page 44: Comparing GWT Transport Mechanisms

public class ContactState extends SharedState { public String name;

@DelegateToWidget public int yearOfBirth;}

@Overridepublic TextButtonState getState() { return (TextButtonState) super.getState();}

addStateChangeHandler("name", new StateChangeHandler() { @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { String name = getState().name; doSomethingWithTheName(name); }});

Reacting to state changes

torsdag 19 december 13

Page 45: Comparing GWT Transport Mechanisms

Events

torsdag 19 december 13

Page 46: Comparing GWT Transport Mechanisms

public interface ContactRpc extends ServerRpc { public void deleteContact(int id);}

// Sending RPC from the clientpublic void sendDelete(int contactId) { getRpcProxy(ContactRpc.class).deleteContact(contactId);}

//Registering RPC handler on the serverregisterRpc(new ContactRpc() { @Override public void deleteContact(int id) { ContactDAO.deleteById(id); }});

RPC

torsdag 19 december 13

Page 47: Comparing GWT Transport Mechanisms

Good

• Stateful server• Server push

Bad

• Stateful server

Vaadin

torsdag 19 december 13

Page 48: Comparing GWT Transport Mechanisms

Real world usage

6 %torsdag 19 december 13

Page 49: Comparing GWT Transport Mechanisms

What if we completely hide the transport?

torsdag 19 december 13

Page 50: Comparing GWT Transport Mechanisms

Local? Remote? It’s all the same!

torsdag 19 december 13

Page 51: Comparing GWT Transport Mechanisms

// Fire event from the client or the server @InjectEvent<Contact> contactEvent;

public void updateContact(Contact contact) { contactEvent.fire(contact);}

// Listen to event on the client or the serverpublic void contactUpdateObserver(@Observes Contact contact) { ContactDAO.updateContact(contact);}

Errai CDI events

torsdag 19 december 13

Page 52: Comparing GWT Transport Mechanisms

Good

• Transparent communication

• Different protocols• Server push

Bad

• Transparent communication

Errai Bus

torsdag 19 december 13

Page 53: Comparing GWT Transport Mechanisms

Which one should I use?

torsdag 19 december 13

Page 54: Comparing GWT Transport Mechanisms

Did I get some detail wrong?

Questions?

Please rate the talk at gwtcreate.com/agenda? [email protected]

torsdag 19 december 13