SlideShare ist ein Scribd-Unternehmen logo
1 von 54
Downloaden Sie, um offline zu lesen
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 Address address;
public static class Address {
private String street;
private String city;
}
// + Getters and setters
}

torsdag 19 december 13
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, 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
Contact
String
torsdag 19 december 13
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
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
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
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
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
JSON
{
	
	
	
	
	
	
	
}

name: "John Doe",
yearOfBirth: 1900,
address: {
	 street: "Happy Street 1",
	 city: "Turku"
},
emailAddresses: ["john@doe.com", "johndoe@gmail.com"]

torsdag 19 december 13
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
JSON
Good

Bad

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

• Not completely
typesafe
• JSONValue parsing
code is verbose

torsdag 19 december 13
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
JavaScriptObject
Good

Bad

• Very efficient
• Very little boilerplate

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

torsdag 19 december 13
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 Software shall
be used for Good,
not Evil.

torsdag 19 december 13
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
Reflection
Code generation

torsdag 19 december 13
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
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
Using interfaces
instead of objects

torsdag 19 december 13
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
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
AutoBean
Good

Bad

• Flexible foundation
for custom
implementations of
interface methods

• Can’t use classes

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

Manage entity identity

Send partial updates

torsdag 19 december 13
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
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
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
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
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 saveContact(Contact contact);
public List<Contact> getContacts();
}

torsdag 19 december 13
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
GWT-RPC
Good

Bad

• Simple but powerful
concept
• The default solution

• You (almost) always
send the entire
object graph

torsdag 19 december 13
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 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
Events

torsdag 19 december 13
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
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 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
Errai Bus
Good

Bad

• Transparent
communication
• Different protocols
• Server push

• Transparent
communication

torsdag 19 december 13
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@vaadin.com

Weitere ähnliche Inhalte

Ähnlich wie Comparing GWT Transport Mechanisms

Drupal 8 configuration system for coders and site builders - Drupalaton 2013
Drupal 8 configuration system for coders and site builders - Drupalaton 2013Drupal 8 configuration system for coders and site builders - Drupalaton 2013
Drupal 8 configuration system for coders and site builders - Drupalaton 2013swentel
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETtdc-globalcode
 
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...swentel
 
Introduction à Dart
Introduction à DartIntroduction à Dart
Introduction à DartSOAT
 
Rust vs. Go: qual è il linguaggio più adatto al tuo progetto?
Rust vs. Go: qual è il linguaggio più adatto al tuo progetto?Rust vs. Go: qual è il linguaggio più adatto al tuo progetto?
Rust vs. Go: qual è il linguaggio più adatto al tuo progetto?Claudio Capobianco
 

Ähnlich wie Comparing GWT Transport Mechanisms (7)

Drupal 8 configuration system for coders and site builders - Drupalaton 2013
Drupal 8 configuration system for coders and site builders - Drupalaton 2013Drupal 8 configuration system for coders and site builders - Drupalaton 2013
Drupal 8 configuration system for coders and site builders - Drupalaton 2013
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NET
 
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
Drupal 8 configuration system for coders and site builders - DrupalCamp Balti...
 
Introduction à Dart
Introduction à DartIntroduction à Dart
Introduction à Dart
 
Rust vs. Go: qual è il linguaggio più adatto al tuo progetto?
Rust vs. Go: qual è il linguaggio più adatto al tuo progetto?Rust vs. Go: qual è il linguaggio più adatto al tuo progetto?
Rust vs. Go: qual è il linguaggio più adatto al tuo progetto?
 
Java 8 to the rescue!?
Java 8 to the rescue!?Java 8 to the rescue!?
Java 8 to the rescue!?
 
Why realm?
Why realm?Why realm?
Why realm?
 

Kürzlich hochgeladen

Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 

Kürzlich hochgeladen (20)

Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 

Comparing GWT Transport Mechanisms

  • 1. Comparing GWT Transport Mechanisms Leif Åstrand Senior Vaadin Expert torsdag 19 december 13
  • 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
  • 4. RequestBuilder Good Bad • It just works • Low level torsdag 19 december 13
  • 5. Real world usage 11 % torsdag 19 december 13
  • 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
  • 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. 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. 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. 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. 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. 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. 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. JSON Good Bad • It’s “standard” • Extensive library support • Compact format • Not completely typesafe • JSONValue parsing code is verbose torsdag 19 december 13
  • 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. JavaScriptObject Good Bad • Very efficient • Very little boilerplate • /*-{ ... }-*/; syntax • Can’t share code with the server torsdag 19 december 13
  • 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. 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
  • 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. 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. Using interfaces instead of objects torsdag 19 december 13
  • 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. 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. AutoBean Good Bad • Flexible foundation for custom implementations of interface methods • Can’t use classes torsdag 19 december 13
  • 29. Intercepting interface methods allows us to... Use instance methods for RPC Manage entity identity Send partial updates torsdag 19 december 13
  • 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. 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. 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. 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. Real world usage 7% torsdag 19 december 13
  • 35. Why not just send Java objects? torsdag 19 december 13
  • 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. 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. GWT-RPC Good Bad • Simple but powerful concept • The default solution • You (almost) always send the entire object graph torsdag 19 december 13
  • 39. Most popular! 53 % torsdag 19 december 13
  • 40. 2 | Foo | Bar | 42 | 2 | -4 [-4, 2, 42, [“Foo”, “Bar”]] torsdag 19 december 13
  • 41. What if we put the server in control? torsdag 19 december 13
  • 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
  • 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. Vaadin Good Bad • Stateful server • Server push • Stateful server torsdag 19 december 13
  • 48. Real world usage 6% torsdag 19 december 13
  • 49. What if we completely hide the transport? torsdag 19 december 13
  • 50. Local? Remote? It’s all the same! torsdag 19 december 13
  • 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. Errai Bus Good Bad • Transparent communication • Different protocols • Server push • Transparent communication torsdag 19 december 13
  • 53. Which one should I use? torsdag 19 december 13
  • 54. ? torsdag 19 december 13 Did I get some detail wrong? Questions? Please rate the talk at gwtcreate.com/agenda leif@vaadin.com