Successfully reported this slideshow.

Comparing GWT Transport Mechanisms

1

Share

Upcoming SlideShare
Introduction to JSON & Ajax
Introduction to JSON & Ajax
Loading in …3
×
1 of 54
1 of 54

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Comparing GWT Transport Mechanisms

  1. 1. Comparing GWT Transport Mechanisms Leif Åstrand Senior Vaadin Expert torsdag 19 december 13
  2. 2. Contact 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 } torsdag 19 december 13
  3. 3. AJAX torsdag 19 december 13
  4. 4. RequestBuilder Good Bad • It just works • Low level torsdag 19 december 13
  5. 5. Real world usage 11 % torsdag 19 december 13
  6. 6. RequestBuilder 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 } torsdag 19 december 13
  7. 7. Contact String torsdag 19 december 13
  8. 8. String conversion String data = contact.getName(); data += "," + contact.getYearOfBirth(); String[] parts = data.split(","); contact.setName(parts[0]); contact.setYearOfBirth(Integer.parseInt(parts[1])); torsdag 19 december 13
  9. 9. String conversion String data = contact.getName(); data += "," + contact.getYearOfBirth(); String[] parts = data.split(","); contact.setName(parts[0]); contact.setYearOfBirth(Integer.parseInt(parts[1])); torsdag 19 december 13
  10. 10. XML <?xml version="1.0" encoding="UTF-8"?> <contact name="John Doe" yearOfBirth="1900"> <address street="HappyStreet 1" city="Turku" /> <email address="john@doe.com" /> <email address="johndoe@gmail.com" /> </contact> torsdag 19 december 13
  11. 11. XML parsing 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")); } torsdag 19 december 13
  12. 12. XML Good Bad • It’s “standard” • Lots of server-side libraries • Verbose data • Verbose code • Document markup language • Not so common in the GWT ecosystem • Not typesafe torsdag 19 december 13
  13. 13. JSON { } name: "John Doe", yearOfBirth: 1900, address: { street: "Happy Street 1", city: "Turku" }, emailAddresses: ["john@doe.com", "johndoe@gmail.com"] torsdag 19 december 13
  14. 14. JSONValue parsing 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()); } } torsdag 19 december 13
  15. 15. JSON Good Bad • It’s “standard” • Extensive library support • Compact format • Not completely typesafe • JSONValue parsing code is verbose torsdag 19 december 13
  16. 16. JavaScriptObject 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"]; }-*/; } torsdag 19 december 13
  17. 17. JavaScriptObject Good Bad • Very efficient • Very little boilerplate • /*-{ ... }-*/; syntax • Can’t share code with the server torsdag 19 december 13
  18. 18. What about the server? torsdag 19 december 13
  19. 19. JAX-RS torsdag 19 december 13
  20. 20. org.json Good Bad • It’s “standard” • Full control • About as verbose as JSONValue • Not suitable for GWT • The Software shall be used for Good, not Evil. torsdag 19 december 13
  21. 21. Jackson on the server ObjectMapper mapper = new ObjectMapper(); try { Contact contact = mapper.readValue(string, Contact.class); } catch (VariousExceptions e) { // Do something sensible } torsdag 19 december 13
  22. 22. Reflection Code generation torsdag 19 december 13
  23. 23. gwt-jackson 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; } torsdag 19 december 13
  24. 24. Jackson Good Bad • Minimal boiler plate • Can share code between server and client • Plugin for JAX-RS • You’re still just sending objects torsdag 19 december 13
  25. 25. Using interfaces instead of objects torsdag 19 december 13
  26. 26. Contact interface 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(); } torsdag 19 december 13
  27. 27. AutoBean 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("john@doe.com", "johndoe@gmail.com")); String json = AutoBeanCodex.encode(contactBean).getPayload(); AutoBean<Contact> bean = AutoBeanCodex.decode(factory, Contact.class, json); contact = bean.as(); } torsdag 19 december 13
  28. 28. AutoBean Good Bad • Flexible foundation for custom implementations of interface methods • Can’t use classes torsdag 19 december 13
  29. 29. Intercepting interface methods allows us to... Use instance methods for RPC Manage entity identity Send partial updates torsdag 19 december 13
  30. 30. RequestFactory setting it up 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); } torsdag 19 december 13
  31. 31. RequestFactory client-side usage 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(); } torsdag 19 december 13
  32. 32. RequestFactory server-side 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(); } } torsdag 19 december 13
  33. 33. RequestFactory Good Bad • Entities do not need to be GWT compatible • Combines RPC and entity management • Automatic request handling • Complex setup • Heavy coupling with the server torsdag 19 december 13
  34. 34. Real world usage 7% torsdag 19 december 13
  35. 35. Why not just send Java objects? torsdag 19 december 13
  36. 36. Send and receive objects public Object[] sendAndReceive(Object[] objects); public interface ContactService { public void saveContact(Contact contact); public List<Contact> getContacts(); } torsdag 19 december 13
  37. 37. Asynchronousity public interface ContactService { public AsyncResult<Void> saveContact(Contact contact); public AsyncResult<List<Contact>> getContacts(); } public interface ContactServiceAsync { public void saveContact(Contact contact, AsyncCallback<Void> callback); public void getContacts(AsyncCallback<List<Contact>> callback); } torsdag 19 december 13
  38. 38. GWT-RPC Good Bad • Simple but powerful concept • The default solution • You (almost) always send the entire object graph torsdag 19 december 13
  39. 39. Most popular! 53 % torsdag 19 december 13
  40. 40. 2 | Foo | Bar | 42 | 2 | -4 [-4, 2, 42, [“Foo”, “Bar”]] torsdag 19 december 13
  41. 41. What if we put the server in control? torsdag 19 december 13
  42. 42. torsdag 19 december 13
  43. 43. State synchronization torsdag 19 december 13
  44. 44. Reacting to state changes public class ContactState extends SharedState { public String name; @DelegateToWidget public int yearOfBirth; } @Override public TextButtonState getState() { return (TextButtonState) super.getState(); } addStateChangeHandler("name", new StateChangeHandler() { @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { String name = getState().name; doSomethingWithTheName(name); } }); torsdag 19 december 13
  45. 45. Events torsdag 19 december 13
  46. 46. RPC public interface ContactRpc extends ServerRpc { public void deleteContact(int id); } // Sending RPC from the client public void sendDelete(int contactId) { getRpcProxy(ContactRpc.class).deleteContact(contactId); } //Registering RPC handler on the server registerRpc(new ContactRpc() { @Override public void deleteContact(int id) { ContactDAO.deleteById(id); } }); torsdag 19 december 13
  47. 47. Vaadin Good Bad • Stateful server • Server push • Stateful server torsdag 19 december 13
  48. 48. Real world usage 6% torsdag 19 december 13
  49. 49. What if we completely hide the transport? torsdag 19 december 13
  50. 50. Local? Remote? It’s all the same! torsdag 19 december 13
  51. 51. Errai CDI events // Fire event from the client or the server @Inject Event<Contact> contactEvent; public void updateContact(Contact contact) { contactEvent.fire(contact); } // Listen to event on the client or the server public void contactUpdateObserver(@Observes Contact contact) { ContactDAO.updateContact(contact); } torsdag 19 december 13
  52. 52. Errai Bus Good Bad • Transparent communication • Different protocols • Server push • Transparent communication torsdag 19 december 13
  53. 53. Which one should I use? torsdag 19 december 13
  54. 54. ? torsdag 19 december 13 Did I get some detail wrong? Questions? Please rate the talk at gwtcreate.com/agenda leif@vaadin.com

×