+ All Categories
Home > Technology > GWT@Jazoon08 - Part 2/6 - Attentive Service

GWT@Jazoon08 - Part 2/6 - Attentive Service

Date post: 15-May-2015
Category:
Upload: maarten-volders
View: 1,826 times
Download: 2 times
Share this document with a friend
Description:
A presentation about GWT which I presentaed at Jazoon '08Part 2/6 - Attentive Service
Popular Tags:
37
LOGO SPEAKER‘S COMPANY # 2 attentive service.
Transcript
Page 1: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

# 2

attentive service.

Page 2: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

the doorman hailing a cab ...

Page 3: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

the waiter refilling your glass ...

Page 4: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

opening a new line at the checkout ...

Page 5: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

annoying.

hit search button 10 times before match found

click add button for items that already exist

country dropdowns Belgium = b + 6x down arrow

Page 6: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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)

Page 7: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

gwt rpc.[ for dummies ]

Page 8: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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)

Page 9: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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

}

Page 10: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

DEFINE ASYNC SERVICE

public interface WishlistServiceAsync {

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) { ... }

});

Page 11: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

gwt rpc.[ best practices ]

Page 12: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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

Page 13: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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) { ... }

});

Page 14: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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 {

}

Page 15: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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() { … }

Page 16: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

real world issues.

GWT + JPA = KABOOMMM !!!

back to the future with DTOs ???

SpringFramework integration ???

Page 17: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

gwt rpc.[ demystified ]

Page 18: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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

???

Page 19: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

RequestBuilderRemoteServiceProxy

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) { ... }

RemoteServiceProxy

- configure RequestBuilder - method = POST - header = text/x-gwt-rpc - url - data- invoke RequestBuilder send()

RemoteServiceServlet

- invoke implementation- write response

WishlistService_ProxyWishlistService_Proxy [Generated]WishlistService_Proxy [Generated]

- prepare stream

XHR

RequestCallbackAdapterRequestCallbackAdapterRequestCallbackAdapter

- trigger client callback for: - onError - onResponseReceived

XHR

- response found- trigger callback

XHRXHR

- make request- listen to response

RequestBuilder

- init XHR callback- open XHR- send data

Page 20: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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("findMatches"); // MethodName w.writeInt(1); // Number of parameters w.writeString("java.lang.String"); // First parameter type w.writeString(text); // First parameter value

String payload = w.toString(); doInvoke(ResponseReader.OBJECT, “WishlistService_Proxy.findMatches", getRequestId(), payload, async); } }

Page 21: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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("Content-Type", "text/x-gwt-rpc; charset=utf-8"); rb.setCallback(responseHandler); // RequestCallbackAdapter rb.setRequestData(requestData);

try { rb.send(); } catch (RequestException re) { callback.onFailure(new InvovationException(re))

} }

Page 22: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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);}

Page 23: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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, ...);

Page 24: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

gwt rpc.[ rocked science ]

Page 25: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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

Page 26: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

gwt rpc.[ new features ]

Page 27: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

ACCESSING THE REQUEST OBJECT

PURPOSE

useful for canceling the HTTP request used by RPC

EXAMPLE

public interface WishlistServiceAsync {

Request findMatches(String query, AsyncCallback async);

}

Page 28: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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

}

Page 29: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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)

Page 30: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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>

Page 31: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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;

} -*/

Page 32: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

events.

Page 33: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

ASYNC CALLBACK EVENTS

act upon success / failure of asynchronous callbacks

public interface AsyncCallback<T> { void onFailure(Throwable caught); void onSuccess(T result); }

Page 34: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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)

Page 35: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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;

}

}

}

Page 36: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

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("DivElement"); document.getElementById("DivElement").propertyX = obj; JS object “obj” DOM object “DivElement” obj / propertyX

Page 37: GWT@Jazoon08 - Part 2/6 - Attentive Service

LOGO SPEAKER‘S COMPANY

MAARTENVOLDERS.comPASSIONATE ABOUT PEOPLE AND TECHNOLOGY


Recommended