Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Comparing GWT
Transport Mechanisms
Leif Åstrand
Senior Vaadin Expert

torsdag 19 december 13
Contact
public class Contact {
private String name;
private int yearOfBirth;
private List<String> emailAddresses;
private ...
AJAX

torsdag 19 december 13
RequestBuilder
Good

Bad

• It just works

• Low level

torsdag 19 december 13
Real world usage

11 %
torsdag 19 december 13
RequestBuilder
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
try {
builder.sendRequest(requestData...
Contact
String
torsdag 19 december 13
String conversion
String data = contact.getName();
data += "," + contact.getYearOfBirth();
String[] parts = data.split(","...
String conversion
String data = contact.getName();
data += "," + contact.getYearOfBirth();
String[] parts = data.split(","...
XML
<?xml version="1.0" encoding="UTF-8"?>
<contact name="John Doe" yearOfBirth="1900">
	 <address street="HappyStreet 1" ...
XML parsing
Document document = XMLParser.parse(string);
Element contactElement = document.getDocumentElement();
contact.s...
XML
Good

Bad

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

• Verbose data
• Verbose code
• Document markup
language...
JSON
{
	
	
	
	
	
	
	
}

name: "John Doe",
yearOfBirth: 1900,
address: {
	 street: "Happy Street 1",
	 city: "Turku"
},
ema...
JSONValue parsing
JSONObject json = JSONParser.parseStrict(string).isObject();
contact.setName(json.get("name").isString()...
JSON
Good

Bad

• It’s “standard”
• Extensive library
support
• Compact format

• Not completely
typesafe
• JSONValue pars...
JavaScriptObject
public class ContactJso extends JavaScriptObject {
public native String getName() /*-{
return this["name"...
JavaScriptObject
Good

Bad

• Very efficient
• Very little boilerplate

• /*-{ ... }-*/; syntax
• Can’t share code
with the...
What about the
server?

torsdag 19 december 13
JAX-RS

torsdag 19 december 13
org.json
Good

Bad

• It’s “standard”
• Full control

• About as verbose
as JSONValue
• Not suitable for
GWT
• The Softwar...
Jackson on the server
ObjectMapper mapper = new ObjectMapper();
try {
Contact contact = mapper.readValue(string, Contact.c...
Reflection
Code generation

torsdag 19 december 13
gwt-jackson
public static interface ContactMapper extends
ObjectMapper<Contact> {}
public Contact parseContact(String stri...
Jackson
Good

Bad

• Minimal boiler plate
• Can share code
between server and
client
• Plugin for JAX-RS

• You’re still j...
Using interfaces
instead of objects

torsdag 19 december 13
Contact interface
public interface Contact {
public void setName(String name);
public String getName();
public void setYea...
AutoBean
interface AddressBookFactory extends AutoBeanFactory {
public AutoBean<Contact> contact();
}
public void autobean...
AutoBean
Good

Bad

• Flexible foundation
for custom
implementations of
interface methods

• Can’t use classes

torsdag 19...
Intercepting interface
methods allows us to...
Use instance methods for RPC

Manage entity identity

Send partial updates
...
RequestFactory setting it up
public interface AddressBookRequestFactory
extends RequestFactory {
public ContactRequest con...
RequestFactory client-side usage
public void contactRequest() {
ContactRequest contactRequest = factory.contactRequest();
...
RequestFactory server-side
public class Contact {
// + fields, setters and getters
public Integer getId() {
return this.id...
RequestFactory
Good

Bad

• Entities do not need
to be GWT
compatible
• Combines RPC and
entity management
• Automatic req...
Real world usage

7%
torsdag 19 december 13
Why not just send
Java objects?

torsdag 19 december 13
Send and receive
objects
public Object[] sendAndReceive(Object[] objects);
public interface ContactService {
public void s...
Asynchronousity
public interface ContactService {
public AsyncResult<Void> saveContact(Contact contact);
public AsyncResul...
GWT-RPC
Good

Bad

• Simple but powerful
concept
• The default solution

• You (almost) always
send the entire
object grap...
Most popular!

53 %
torsdag 19 december 13
2 | Foo | Bar | 42 | 2 | -4

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

torsdag 19 december 13
What if we put
the server in
control?

torsdag 19 december 13
torsdag 19 december 13
State
synchronization

torsdag 19 december 13
Reacting to state
changes
public class ContactState extends SharedState {
public String name;
@DelegateToWidget
public int...
Events

torsdag 19 december 13
RPC
public interface ContactRpc extends ServerRpc {
public void deleteContact(int id);
}
// Sending RPC from the client
pu...
Vaadin
Good

Bad

• Stateful server
• Server push

• Stateful server

torsdag 19 december 13
Real world usage

6%
torsdag 19 december 13
What if we
completely hide
the transport?

torsdag 19 december 13
Local? Remote?
It’s all the same!

torsdag 19 december 13
Errai CDI events
// Fire event from the client or the server
@Inject
Event<Contact> contactEvent;
public void updateContac...
Errai Bus
Good

Bad

• Transparent
communication
• Different protocols
• Server push

• Transparent
communication

torsdag...
Which one should
I use?

torsdag 19 december 13
?
torsdag 19 december 13

Did I get some
detail wrong?
Questions?
Please rate the talk at
gwtcreate.com/agenda

leif@vaadi...
Upcoming SlideShare
Loading in …5
×

Comparing GWT Transport Mechanisms

3,602 views

Published on

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

  • @Ilja Hämäläinen I think I mentioned in the actual presentation when talking about the benefits of defining the transmittable data as interfaces, but the actual name was not included in the slides. I might update that for the presentation in Munich today.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • I use AutoBeans (https://code.google.com/p/google-web-toolkit/wiki/AutoBean) + RequestBuilder. Strange that you didn't mention AutoBeans in your presentation.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

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

×