Download - Comparing GWT Transport Mechanisms
![Page 1: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/1.jpg)
Leif ÅstrandSenior Vaadin Expert
Comparing GWT Transport Mechanisms
torsdag 19 december 13
![Page 2: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/2.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/3.jpg)
AJAX
torsdag 19 december 13
![Page 4: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/4.jpg)
Good
• It just works
Bad
• Low level
RequestBuilder
torsdag 19 december 13
![Page 5: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/5.jpg)
Real world usage
11 %torsdag 19 december 13
![Page 6: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/6.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/7.jpg)
Contact
String
torsdag 19 december 13
![Page 8: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/8.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/9.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/10.jpg)
<?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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/11.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/12.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/13.jpg)
{ 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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/14.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/15.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/16.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/17.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/18.jpg)
What about the server?
torsdag 19 december 13
![Page 19: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/19.jpg)
JAX-RS
torsdag 19 december 13
![Page 20: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/20.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/21.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/22.jpg)
ReflectionCode generation
torsdag 19 december 13
![Page 23: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/23.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/24.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/25.jpg)
Using interfaces instead of objects
torsdag 19 december 13
![Page 26: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/26.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/27.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/28.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/29.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/30.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/31.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/32.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/33.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/34.jpg)
Real world usage
7 %torsdag 19 december 13
![Page 35: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/35.jpg)
Why not just send Java objects?
torsdag 19 december 13
![Page 36: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/36.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/37.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/38.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/39.jpg)
Most popular!
53 %torsdag 19 december 13
![Page 40: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/40.jpg)
[-4, 2, 42, [“Foo”, “Bar”]]
2 | Foo | Bar | 42 | 2 | -4
torsdag 19 december 13
![Page 41: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/41.jpg)
What if we put the server in control?
torsdag 19 december 13
![Page 42: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/42.jpg)
torsdag 19 december 13
![Page 43: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/43.jpg)
State synchronization
torsdag 19 december 13
![Page 44: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/44.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/45.jpg)
Events
torsdag 19 december 13
![Page 46: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/46.jpg)
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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/47.jpg)
Good
• Stateful server• Server push
Bad
• Stateful server
Vaadin
torsdag 19 december 13
![Page 48: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/48.jpg)
Real world usage
6 %torsdag 19 december 13
![Page 49: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/49.jpg)
What if we completely hide the transport?
torsdag 19 december 13
![Page 50: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/50.jpg)
Local? Remote? It’s all the same!
torsdag 19 december 13
![Page 51: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/51.jpg)
// 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](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/52.jpg)
Good
• Transparent communication
• Different protocols• Server push
Bad
• Transparent communication
Errai Bus
torsdag 19 december 13
![Page 53: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/53.jpg)
Which one should I use?
torsdag 19 december 13
![Page 54: Comparing GWT Transport Mechanisms](https://reader034.vdocuments.site/reader034/viewer/2022042713/5462769db1af9f92238b4f28/html5/thumbnails/54.jpg)
Did I get some detail wrong?
Questions?
Please rate the talk at gwtcreate.com/agenda? [email protected]
torsdag 19 december 13