Your SlideShare is downloading. ×
0
<ul><ul><li># 2 </li></ul></ul><ul><ul><li>attentive service. </li></ul></ul>
the doorman hailing a cab ...
the waiter refilling your glass ...
opening a new line at the checkout ...
<ul><ul><li>annoying. </li></ul></ul><ul><ul><li>hit search button 10 times before match found </li></ul></ul><ul><ul><li>...
<ul><ul><li>intuitive. </li></ul></ul><ul><ul><li>act as a user not as a system </li></ul></ul><ul><ul><li>take all the ne...
<ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ for dummies ] </li></ul></ul>
<ul><ul><li>overview. </li></ul></ul><ul><ul><li>moves Java instances between client and server </li></ul></ul><ul><ul><li...
<ul><ul><li>DEFINE REMOTE SERVICE </li></ul></ul><ul><ul><li>  @RemoteServiceRelativePath(“wishlistService.do”)  // module...
<ul><ul><li>DEFINE ASYNC SERVICE </li></ul></ul><ul><ul><li>  public interface WishlistService Async  { </li></ul></ul><ul...
<ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ best practices ] </li></ul></ul>
<ul><ul><li>use stateless servers – better handling / scaling </li></ul></ul><ul><ul><li>keep conversational state on the ...
<ul><ul><li>PROBLEM: NESTED INNER CALLBACK SYNDROME </li></ul></ul><ul><ul><li>  // async call #1 </li></ul></ul><ul><ul><...
<ul><ul><li>BAD SOLUTION: NESTED CALLBACKS BECOME CLASSES </li></ul></ul><ul><ul><li>  </li></ul></ul><ul><ul><li>  myServ...
<ul><ul><li>SOLUTION: REFACTOR NESTED CALLBACKS INTO METHODS </li></ul></ul><ul><ul><li>myService. doFirstRequest (“foo”, ...
<ul><ul><li>real world issues. </li></ul></ul><ul><ul><li>GWT + JPA = KABOOMMM !!! </li></ul></ul><ul><ul><li>back to the ...
<ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ demystified ] </li></ul></ul>
<ul><li>WishlistServiceAsync  service = (...)  GWT.create (WishlistService.class); </li></ul><ul><ul><li>service.findMatch...
RequestBuilder RemoteServiceProxy <ul><li>WishlistServiceAsync  service = (...)  GWT.create (WishlistService.class); </li>...
<ul><ul><li>WishlistService_Proxy.java [generated] </li></ul></ul><ul><ul><li>public class WishlistService_Proxy extends  ...
<ul><ul><li>RemoteServiceProxy.java  </li></ul></ul><ul><ul><li>public abstract class RemoteServiceProxy implements ... { ...
<ul><ul><li>RequestCallbackAdapter.java  </li></ul></ul><ul><ul><li>  public class RequestCallbackAdapter<T> implements  R...
<ul><ul><li>RemoteServiceServlet.java  </li></ul></ul><ul><ul><li>  public class RemoteServiceServlet extends  HttpServlet...
<ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ rocked science ] </li></ul></ul>
<ul><ul><li>CUSTOMIZING RPC SERIALIZATION </li></ul></ul><ul><ul><li>PURPOSE </li></ul></ul><ul><ul><li>  Null out lazy co...
<ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ new features ] </li></ul></ul>
ACCESSING THE REQUEST OBJECT <ul><ul><li>PURPOSE </li></ul></ul><ul><ul><li>  useful for canceling the HTTP request used b...
ACCESSING THE REQUESTBUILDER OBJECT <ul><ul><li>PURPOSE </li></ul></ul><ul><ul><li>  provides access to HTTP timeouts and ...
INLINE PRESERIALIZED PAYLOADS (1/3) <ul><ul><li>PURPOSE   </li></ul></ul><ul><ul><li>  replace an RPC call that  always  t...
INLINE PRESERIALIZED PAYLOADS (2/3) <ul><ul><li>CREATE REMOTE SERVICE INTERFACE AS USUAL </li></ul></ul><ul><ul><li>  publ...
INLINE PRESERIALIZED PAYLOADS (3/3) <ul><ul><li>READ PRESERIALIZED STRING IN THE CLIENT   </li></ul></ul><ul><ul><li>  Ser...
<ul><ul><li>events. </li></ul></ul>
<ul><ul><li>ASYNC CALLBACK EVENTS </li></ul></ul><ul><ul><li>act upon success / failure of asynchronous callbacks </li></u...
<ul><ul><li>EVENT LISTENERS </li></ul></ul><ul><ul><li>listen upon events being triggered </li></ul></ul><ul><ul><li>imple...
<ul><ul><li>NATIVE DOM EVENTS </li></ul></ul><ul><ul><li>  public class MyWidget extends Widget { </li></ul></ul><ul><ul><...
<ul><ul><li>MEMORY LEAK </li></ul></ul><ul><ul><li>in some browsers any reference cycle that involves a JavaScript  </li><...
<ul><ul><li>MAARTENVOLDERS. com </li></ul></ul><ul><ul><li>PASSIONATE ABOUT PEOPLE AND TECHNOLOGY </li></ul></ul>
Upcoming SlideShare
Loading in...5
×

GWT@Jazoon08 - Part 2/6 - Attentive Service

1,832

Published on

A presentation about GWT which I presentaed at Jazoon '08
Part 2/6 - Attentive Service

Published in: Technology, Business
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,832
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
72
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide
  • Transcript of "GWT@Jazoon08 - Part 2/6 - Attentive Service"

    1. 1. <ul><ul><li># 2 </li></ul></ul><ul><ul><li>attentive service. </li></ul></ul>
    2. 2. the doorman hailing a cab ...
    3. 3. the waiter refilling your glass ...
    4. 4. opening a new line at the checkout ...
    5. 5. <ul><ul><li>annoying. </li></ul></ul><ul><ul><li>hit search button 10 times before match found </li></ul></ul><ul><ul><li>click add button for items that already exist </li></ul></ul><ul><ul><li>country dropdowns Belgium = b + 6x down arrow </li></ul></ul>
    6. 6. <ul><ul><li>intuitive. </li></ul></ul><ul><ul><li>act as a user not as a system </li></ul></ul><ul><ul><li>take all the nerdy and techy stuff out </li></ul></ul><ul><ul><li>user laziness is key </li></ul></ul><ul><ul><li>- auto complete </li></ul></ul><ul><ul><li>- smart tabs (members [0] vs members) </li></ul></ul><ul><ul><li>- smart country dropdown (your country on top) </li></ul></ul>
    7. 7. <ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ for dummies ] </li></ul></ul>
    8. 8. <ul><ul><li>overview. </li></ul></ul><ul><ul><li>moves Java instances between client and server </li></ul></ul><ul><ul><li>uses Serializable + IsSerializable marker interface </li></ul></ul><ul><ul><li>polymorphism is supported but at a cost </li></ul></ul><ul><ul><li>generator creates the necessary marshaling code </li></ul></ul><ul><ul><li>supports Java 1.5 language constructs </li></ul></ul><ul><ul><li>built on top of RequestBuilder (XHR) </li></ul></ul>
    9. 9. <ul><ul><li>DEFINE REMOTE SERVICE </li></ul></ul><ul><ul><li> @RemoteServiceRelativePath(“wishlistService.do”) // moduleBaseURL + value </li></ul></ul><ul><ul><li> public interface WishlistService extends RemoteService { </li></ul></ul><ul><ul><li> List<Wish> findMatches(String query); </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li>IMPLEMENT REMOTE SERVICE </li></ul></ul><ul><ul><li> public class WishlistServiceImpl extends RemoteServiceServlet </li></ul></ul><ul><ul><li> implements WishlistService { </li></ul></ul><ul><ul><li> public List<Wish> findMatches(String query) { ... do something ... } </li></ul></ul><ul><ul><li> } </li></ul></ul>
    10. 10. <ul><ul><li>DEFINE ASYNC SERVICE </li></ul></ul><ul><ul><li> public interface WishlistService Async { </li></ul></ul><ul><ul><li> void findMatches(String query, AsyncCallback async ); </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li>CALL SERVICE </li></ul></ul><ul><ul><li> WishlistAsyncServiceAsync service = GWT.create (WishlistService.class); </li></ul></ul><ul><ul><li> service.findMatches(“abc”, new AsyncCallback <List<Wish>>() { </li></ul></ul><ul><ul><li> public void onSuccess (List<Wish> matches) { ... } </li></ul></ul><ul><ul><li> public void onFailure (Throwable caught) { ... } </li></ul></ul><ul><ul><li> }); </li></ul></ul>
    11. 11. <ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ best practices ] </li></ul></ul>
    12. 12. <ul><ul><li>use stateless servers – better handling / scaling </li></ul></ul><ul><ul><li>keep conversational state on the client </li></ul></ul><ul><ul><li>balance your RPC calls, think about latency </li></ul></ul><ul><ul><li>only pull data that is really being used </li></ul></ul><ul><ul><li>paginate on the server </li></ul></ul><ul><ul><li>… </li></ul></ul>
    13. 13. <ul><ul><li>PROBLEM: NESTED INNER CALLBACK SYNDROME </li></ul></ul><ul><ul><li> // async call #1 </li></ul></ul><ul><ul><li> myService. doFirstRequest (“foo”, new AsyncCallback<String>() { </li></ul></ul><ul><ul><li> public void onSuccess(String result) { </li></ul></ul><ul><ul><li> // async call #2 </li></ul></ul><ul><ul><li> myService. doSecondRequest (result, new AsyncCallback<String>() { </li></ul></ul><ul><ul><li> public void onSuccess(String result) { </li></ul></ul><ul><ul><li> // and more and more and moreeee async calls on the way </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> public void onFailure(Throwable caught) { ... } </li></ul></ul><ul><ul><li> }); </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> public void onFailure(Throwable caught) { ... } </li></ul></ul><ul><ul><li> }); </li></ul></ul>
    14. 14. <ul><ul><li>BAD SOLUTION: NESTED CALLBACKS BECOME CLASSES </li></ul></ul><ul><ul><li> </li></ul></ul><ul><ul><li> myService. doFirstRequest (“foo”, new FirstRequestHandler() ); </li></ul></ul><ul><ul><li> class FirstRequestHandler implements AsyncCallback { </li></ul></ul><ul><ul><li> public void onSuccess(String result) { </li></ul></ul><ul><ul><li> myService. doSecondRequest (result, new SecondRequestHandler() ); </li></ul></ul><ul><ul><li> public void onFailure(Throwable caught) { ... } </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> class SecondRequestHandler implements AsyncCallback { </li></ul></ul><ul><ul><li> … </li></ul></ul><ul><ul><li> } </li></ul></ul>
    15. 15. <ul><ul><li>SOLUTION: REFACTOR NESTED CALLBACKS INTO METHODS </li></ul></ul><ul><ul><li>myService. doFirstRequest (“foo”, handleFirstRequest() ); </li></ul></ul><ul><ul><li> protected AsyncCallback handleFirstRequest() { </li></ul></ul><ul><ul><li> return new AsyncCallback<String>() { </li></ul></ul><ul><ul><li> public void onSuccess(String result) { </li></ul></ul><ul><ul><li> myService. doSecondRequest (result, handeSecondRequest() );} </li></ul></ul><ul><ul><li> public void onFailure(Throwable caught) { ... } </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> protected AsyncCallback handleSecondRequest() { … } </li></ul></ul>
    16. 16. <ul><ul><li>real world issues. </li></ul></ul><ul><ul><li>GWT + JPA = KABOOMMM !!! </li></ul></ul><ul><ul><li>back to the future with DTOs ??? </li></ul></ul><ul><ul><li>SpringFramework integration ??? </li></ul></ul>
    17. 17. <ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ demystified ] </li></ul></ul>
    18. 18. <ul><li>WishlistServiceAsync service = (...) GWT.create (WishlistService.class); </li></ul><ul><ul><li>service.findMatches(“abc”, new AsyncCallback<List<Wish>>() { </li></ul></ul><ul><ul><li>public void onSuccess (List<Wish> matches) { ... } </li></ul></ul><ul><ul><li>public void onFailure (Throwable caught) { ... } </li></ul></ul><ul><ul><li>}); </li></ul></ul>WishlistServiceImpl extends RemoteServiceServlet ???
    19. 19. RequestBuilder RemoteServiceProxy <ul><li>WishlistServiceAsync service = (...) GWT.create (WishlistService.class); </li></ul><ul><ul><li>service.findMatches(“abc”, new AsyncCallback<List<Wish>>() { </li></ul></ul><ul><ul><li>public void onSuccess (List<Wish> matches) { ... } </li></ul></ul><ul><ul><li>public void onFailure (Throwable caught) { ... } </li></ul></ul><ul><ul><li>}); </li></ul></ul>WishlistServiceImpl RemoteServiceServlet WishlistServiceAsync service <ul><ul><li>public void onSuccess(List<Wish> matches) { ... } </li></ul></ul><ul><ul><li>public void onFailure(Throwable caught) { ... } </li></ul></ul>WishlistService_Proxy XHR RequestCallbackAdapter RemoteServiceProxy - configure RequestBuilder - method = POST - header = text/x-gwt-rpc - url - data - invoke RequestBuilder send() RemoteServiceServlet - invoke implementation - write response WishlistService_Proxy [Generated] WishlistService_Proxy [Generated] - prepare stream RequestCallbackAdapter RequestCallbackAdapter - trigger client callback for: - onError - onResponseReceived XHR - response found - trigger callback XHR XHR - make request - listen to response RequestBuilder - init XHR callback - open XHR - send data
    20. 20. <ul><ul><li>WishlistService_Proxy.java [generated] </li></ul></ul><ul><ul><li>public class WishlistService_Proxy extends RemoteServiceProxy </li></ul></ul><ul><ul><li> implements WishlistServiceAsync { </li></ul></ul><ul><ul><li> public void findMatches (String text, AsyncCallback async) { </li></ul></ul><ul><ul><li> ... </li></ul></ul><ul><ul><li> ClientSerializationStreamWriter w = createStreamWriter(); // _TypeSerializer </li></ul></ul><ul><ul><li> w.writeString(“WishlistService”); // Remote service I/F name </li></ul></ul><ul><ul><li> w.writeString( &quot;findMatches&quot; ); // MethodName </li></ul></ul><ul><ul><li> w.writeInt(1); // Number of parameters </li></ul></ul><ul><ul><li> w.writeString(&quot;java.lang.String&quot;); // First parameter type </li></ul></ul><ul><ul><li> w.writeString( text ); // First parameter value </li></ul></ul><ul><ul><li> String payload = w.toString(); </li></ul></ul><ul><ul><li> doInvoke(ResponseReader.OBJECT, “WishlistService_Proxy.findMatches&quot;, </li></ul></ul><ul><ul><li> getRequestId(), payload, async); } </li></ul></ul><ul><ul><li> } </li></ul></ul>
    21. 21. <ul><ul><li>RemoteServiceProxy.java </li></ul></ul><ul><ul><li>public abstract class RemoteServiceProxy implements ... { </li></ul></ul><ul><ul><li> protected <T> Request doInvoke (ResponseReader reader, String methodName, </li></ul></ul><ul><ul><li> int invocationCount, String requestData, AsyncCallback<T> async) { </li></ul></ul><ul><ul><li> RequestBuilder rb = new RequestBuilder( RequestBuilder.POST , “WishlistService.rpc” ); </li></ul></ul><ul><ul><li> rb.setHeader(&quot;Content-Type&quot;, &quot;text/x-gwt-rpc; charset=utf-8&quot;); </li></ul></ul><ul><ul><li> rb.setCallback(responseHandler); // RequestCallbackAdapter </li></ul></ul><ul><ul><li> rb.setRequestData( requestData ); </li></ul></ul><ul><ul><li> try { </li></ul></ul><ul><ul><li> rb. send(); </li></ul></ul><ul><ul><li> } catch (RequestException re) { </li></ul></ul><ul><ul><li> callback.onFailure(new InvovationException(re)) </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li> } </li></ul></ul>
    22. 22. <ul><ul><li>RequestCallbackAdapter.java </li></ul></ul><ul><ul><li> public class RequestCallbackAdapter<T> implements RequestCallback { </li></ul></ul><ul><ul><li> public void onError (Request request, Throwable exception) { </li></ul></ul><ul><ul><li> callback.onFailure (exception); </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> </li></ul></ul><ul><ul><li> public void onResponseReceived (Request request, Response response) { </li></ul></ul><ul><ul><li> String encodedResponse = response.getText(); </li></ul></ul><ul><ul><li> int statusCode = response.getStatusCode(); </li></ul></ul><ul><ul><li> if (statusCode != Response.SC_OK) { // + multiple other exception related test !!! </li></ul></ul><ul><ul><li> caught = new StatusCodeException(statusCode, encodedResponse); </li></ul></ul><ul><ul><li> } else { </li></ul></ul><ul><ul><li> result = </li></ul></ul><ul><ul><li>(T) responseReader.read(streamFactory.createStreamReader(encodedResponse)); </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> if (caught == null) { callback.onSuccess (result); } else { callback.onFailure (caught);} </li></ul></ul>
    23. 23. <ul><ul><li>RemoteServiceServlet.java </li></ul></ul><ul><ul><li> public class RemoteServiceServlet extends HttpServlet implements ... { </li></ul></ul><ul><ul><li> public final void doPost (HttpServletRequest request, HttpServletResponse response) { </li></ul></ul><ul><ul><li> perThreadRequest.set(request); </li></ul></ul><ul><ul><li> perThreadResponse.set(response); </li></ul></ul><ul><ul><li> </li></ul></ul><ul><ul><li> String requestPayload = RPCServletUtils.readContentAsUtf8(request); </li></ul></ul><ul><ul><li> RPCRequest rpcRequest = RPC. decodeRequest (requestPayload, …); </li></ul></ul><ul><ul><li> String responsePayload = RPC. invokeAndEncodeResponse (...); </li></ul></ul><ul><ul><li> //  calls remote method on WishListServiceImpl class </li></ul></ul><ul><ul><li> RPCServletUtils. writeResponse (..., responsePayload, ...); </li></ul></ul>
    24. 24. <ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ rocked science ] </li></ul></ul>
    25. 25. <ul><ul><li>CUSTOMIZING RPC SERIALIZATION </li></ul></ul><ul><ul><li>PURPOSE </li></ul></ul><ul><ul><li> Null out lazy collections and load lazy proxy objects </li></ul></ul><ul><ul><li>EXAMPLE (subclass ServerSerializationStreamWriter) </li></ul></ul><ul><ul><li> public void serializableValue(Object value, Class type) ... { </li></ul></ul><ul><ul><li> else if (type == java.util.Set.class) { </li></ul></ul><ul><ul><li> Set hashSet = new HashSet(); </li></ul></ul><ul><ul><li> if (value instanceof PersistentSet) { </li></ul></ul><ul><ul><li> PersistentSet persistentSet = (PersistentSet) value; </li></ul></ul><ul><ul><li> if (persistentSet.wasInitialized()) { hashSet.addAll(persistentSet); </li></ul></ul>
    26. 26. <ul><ul><li>gwt rpc. </li></ul></ul><ul><ul><li>[ new features ] </li></ul></ul>
    27. 27. ACCESSING THE REQUEST OBJECT <ul><ul><li>PURPOSE </li></ul></ul><ul><ul><li> useful for canceling the HTTP request used by RPC </li></ul></ul><ul><ul><li>EXAMPLE </li></ul></ul><ul><ul><li> public interface WishlistServiceAsync { </li></ul></ul><ul><ul><li> Request findMatches(String query, AsyncCallback async); </li></ul></ul><ul><ul><li> } </li></ul></ul>
    28. 28. ACCESSING THE REQUESTBUILDER OBJECT <ul><ul><li>PURPOSE </li></ul></ul><ul><ul><li> provides access to HTTP timeouts and headers </li></ul></ul><ul><ul><li> caller must manually call requestBuilder.send(); </li></ul></ul><ul><ul><li>EXAMPLE </li></ul></ul><ul><ul><li> public interface WishlistServiceAsync { </li></ul></ul><ul><ul><li> RequestBuilder findMatches(String query, AsyncCallback async); </li></ul></ul><ul><ul><li> } </li></ul></ul>
    29. 29. INLINE PRESERIALIZED PAYLOADS (1/3) <ul><ul><li>PURPOSE </li></ul></ul><ul><ul><li> replace an RPC call that always takes place right after startup </li></ul></ul><ul><ul><li> one less call to make to the server (Turbo boost for startup) </li></ul></ul>
    30. 30. INLINE PRESERIALIZED PAYLOADS (2/3) <ul><ul><li>CREATE REMOTE SERVICE INTERFACE AS USUAL </li></ul></ul><ul><ul><li> public interface MyRemoteService extends RemoteService { </li></ul></ul><ul><ul><li> MyPayload aMethod(String var); </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li>CREATE SERIALIZED VALUE ON THE SERVER-SIDE </li></ul></ul><ul><ul><li> String myPayload = RPC.encodeResponseForSuccess(…); </li></ul></ul><ul><ul><li>EMBED PAYLOAD INTO HTML PAGE (SiteMesh / Servlet / …) </li></ul></ul><ul><ul><li> <script>window.myPayload = “MyPayload generated String”</script> </li></ul></ul>
    31. 31. INLINE PRESERIALIZED PAYLOADS (3/3) <ul><ul><li>READ PRESERIALIZED STRING IN THE CLIENT </li></ul></ul><ul><ul><li> SerializationStreamFactory f = GWT.create(MyRemoteService.class); </li></ul></ul><ul><ul><li> MyPayload myPayload = f.createStreamReader(getPayload()).readObject(); </li></ul></ul><ul><ul><li> native String getPayload() /*- { </li></ul></ul><ul><ul><li> return $wnd.myPayload; </li></ul></ul><ul><ul><li> } -*/ </li></ul></ul>
    32. 32. <ul><ul><li>events. </li></ul></ul>
    33. 33. <ul><ul><li>ASYNC CALLBACK EVENTS </li></ul></ul><ul><ul><li>act upon success / failure of asynchronous callbacks </li></ul></ul><ul><ul><li>public interface AsyncCallback<T> { </li></ul></ul><ul><ul><li>void onFailure(Throwable caught); </li></ul></ul><ul><ul><li>void onSuccess(T result); </li></ul></ul><ul><ul><li>} </li></ul></ul>
    34. 34. <ul><ul><li>EVENT LISTENERS </li></ul></ul><ul><ul><li>listen upon events being triggered </li></ul></ul><ul><ul><li>implement EventListener </li></ul></ul><ul><ul><li>adapters available for some </li></ul></ul><ul><ul><li>don’t forget to detach the listeners when destroying the widget </li></ul></ul><ul><ul><li>examples </li></ul></ul><ul><ul><li>History.addHistoryListener(historyListener); </li></ul></ul><ul><ul><li>myButton.addClickListener(clickListener) </li></ul></ul><ul><ul><li>myTextField.addKeyboardListener(keyboardListenerAdapter) </li></ul></ul>
    35. 35. <ul><ul><li>NATIVE DOM EVENTS </li></ul></ul><ul><ul><li> public class MyWidget extends Widget { </li></ul></ul><ul><ul><li> public myWidget() { </li></ul></ul><ul><ul><li> setElement(DOM.createDiv()); </li></ul></ul><ul><ul><li> sinkEvents(Event.ONCLICK()); // event bubbling </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> public void onBrowserEvent(Event event) { </li></ul></ul><ul><ul><li> switch (DOM.eventGetType(event)) { </li></ul></ul><ul><ul><li> case Event.ONCLICK: // do something…; break; </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> } </li></ul></ul><ul><ul><li> } </li></ul></ul>
    36. 36. <ul><ul><li>MEMORY LEAK </li></ul></ul><ul><ul><li>in some browsers any reference cycle that involves a JavaScript </li></ul></ul><ul><ul><li>object and a DOM element has a nasty tendency to never get </li></ul></ul><ul><ul><li>garbage-collected </li></ul></ul><ul><ul><li> hybrid system </li></ul></ul><ul><ul><li> DOM objects are referenced through reference counting </li></ul></ul><ul><ul><li> JS object is using garbage collection </li></ul></ul><ul><ul><li> example </li></ul></ul><ul><ul><li> obj = document.getElementById(&quot;DivElement&quot;); </li></ul></ul><ul><ul><li> document.getElementById(&quot;DivElement&quot;).propertyX = obj; </li></ul></ul><ul><ul><li> </li></ul></ul><ul><ul><li> JS object “obj”  DOM object “DivElement”  obj / propertyX </li></ul></ul>
    37. 37. <ul><ul><li>MAARTENVOLDERS. com </li></ul></ul><ul><ul><li>PASSIONATE ABOUT PEOPLE AND TECHNOLOGY </li></ul></ul>
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×