• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
GWT@Jazoon08 - Part 2/6 - Attentive Service
 

GWT@Jazoon08 - Part 2/6 - Attentive Service

on

  • 3,558 views

A presentation about GWT which I presentaed at Jazoon '08

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

Statistics

Views

Total Views
3,558
Views on SlideShare
3,554
Embed Views
4

Actions

Likes
4
Downloads
71
Comments
0

1 Embed 4

http://www.slideshare.net 4

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

GWT@Jazoon08 - Part 2/6 - Attentive Service GWT@Jazoon08 - Part 2/6 - Attentive Service Presentation Transcript

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