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
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
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
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
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
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
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
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