comparing gwt transport mechanisms

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

Upload: lastrand

Post on 11-Nov-2014

1.879 views

Category:

Technology


0 download

DESCRIPTION

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

TRANSCRIPT

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