Communication Infrastructure
Frame- Module com.google.gwt.user.User provides Frame class
- Pass information to the server by manipulating the URL
- Retrieve responses from the Frame's content or the server can write script tags to be executed
- History and browser compatibility issues to consider
- Load events are not reliable across browsers; specifically in Safari 2
FormPanel
- Module com.google.gwt.user.User provides FormPanel class
- Provides interoperability with servers that accept traditional HTML form encoding
- Data is sent asynchronously
- Any Widget that implements HasName which is part of the FormPanel will have its data sent on submit
- Enables file uploads
final FormPanel form = new FormPanel(); form.setAction("/myFormHandler"); // FileUpload requires the POST method, and multipart MIME // encoding. form.setEncoding(FormPanel.ENCODING_MULTIPART); form.setMethod(FormPanel.METHOD_POST); // Create a FileUpload widget. FileUpload upload = new FileUpload(); upload.setName("uploadFormElement"); form.setWidget(upload); // Get a root panel and add the form and a button RootPanel rootPanel = RootPanel.get(); rootPanel.add(form); rootPanel.add(new Button("Submit", new ClickListener() { public void onClick(Widget sender) { form.submit(); } }));
RequestBuilder (XHR)
- Module com.google.gwt.http.HTTP provides RequestBuilder
- Builder for making HTTP GETs and POSTs requests
- Asynchronous communications only
- Restricted by the same origin policy
- Browsers limit the possible number of simultaneous connections so don’t go crazy firing off requests
public void onModuleLoad() throws RequestException { String url = GWT.getModuleBaseURL() + "get"; RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url); // Create a callback object to handle the result RequestCallback requestCallback = new RequestCallback() { public void onError(Request request, Throwable exception) { //… } public void onResponseReceived(Request request, Response response) { //… } }; // Send the request builder.sendRequest("payload", requestCallback); }
XML Services
XML Encoding/Decoding- Module com.google.gwt.xml.XML declares XML related classes
- XMLParser parses a string containing valid XML into a new Document instance
- Document class can be used to explore and modify the structure of the document
- Document class will also convert the structure back into a string
- Manipulation of XML is somewhat laborious
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, "..."); RequestCallback requestCallback = new RequestCallback() { public void onResponseReceived(Request request, Response response) { // Parse xml response into a Document object Document result = XMLParser.parse(response.getText()); // ... } // Error handling omitted }; // Create Document Document doc = XMLParser.createDocument(); // Add elements to the document as necessary… // Send the XML request rb.sendRequest(doc.toString(), requestCallback);
JSON Services
JSON Encoding/Decoding- Module com.google.gwt.json.JSON declares JSON related classes
- JSONParser converts between strings and JSON objects
- JSON is a fundamental data encoding that does not support cyclic structures
- JSONP, JSONRPC are protocols built on top of the JSON encoding
- Again, the conversion to/from JSON can be somewhat laborious
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, "..."); RequestCallback requestCallback = new RequestCallback() { public void onResponseReceived(Request request, Response response) { // Parse json response into a JSONValue object JSONValue result = JSONParser.parse(response.getText()); // ... } // Error handling omitted }; rb.sendRequest("{...}", requestCallback);
Efficiency Tip: JavaScriptObject Overlays
Overlays result in no runtime overhead; very efficient
/** * Java overlay of a JavaScriptObject, whose JSON * representation is { count: 5 }. */ public class MyJSO extends JavaScriptObject { // Convert a JSON encoded string into a MyJSO instance public static native MyJSO fromJSONString( String jsonString) /*-{ return eval('(' + jsonString + ')'); }-*/; // Returns the count property of this MyJSO public native int getCount() /*-{ return this.count; }-*/; }
GWT RPC
GWT RPC Overview- Designed to move Java instances between client code (in the browser) and a Java servlet
- Uses Serializable and IsSerializable marker interfaces
- Interfaces define the service, a generator creates the necessary marshaling code with built-inversioning and a serialization policy file
- Supports Java 1.5 language constructs
- Built on top of RequestBuilder (XHR)
- Like the rest of GWT, recompile to pick up the latest performance improvements - faster serialization code, etc.
// Implemented by the servlet @RemoteServiceRelativePath("tasks") public interface TaskRemoteService extends RemoteService { List<Task> getTasks(int startIndex, int maxCount) throws TaskServiceException; } // Implemented by generated client proxy, needs to match sync public interface TaskRemoteServiceAsync { void getTasks(int startIndex, int maxCount, AsyncCallback<List<Task>> callback); } // TaskRemoteService servlet public class TaskRemoteServiceImpl extends RemoteServiceServlet implements TaskRemoteService { public List<Task> getTasks(int startIndex, int maxCount) throws TaskServiceException { // Code omitted } }
Invoking GWT RemoteServices
// Get client proxy, annotation causes auto addressing TaskRemoteServiceAsync service = GWT.create(TaskRemoteService.class); // Create a callback object to handle results AsyncCallback<List<Task>> asyncCallback = new AsyncCallback<List<Task>>() { public void onFailure(Throwable caught) { // Deal with TaskServiceException... } public void onSuccess(List<Task> result) { for (Task task : result) { // Process each task... } } }; // Actually call the service service.getTasks(0, 10, asyncCallback);
Accessing the Request Object
- Async method signature changed to return a Request instance
- Useful for canceling the HTTP request used by RPC
// Modified async interface public interface TaskRemoteServiceAsync { // Method returns the underlying HTTP Request instance Request getTasks(int startIndex, int maxCount, AsyncCallback<List<Task>> callback); }
Accessing the RequestBuilder Object
- Change the return type of the async method to RequestBuilder, proxy returns a fully configured RequestBuilder
- Provides access to HTTP timeouts, and headers
- Caller must call RequestBuilder.send()
- Wrap modified async interface to provide your own special manipulation code
// Modified async interface public interface TaskRemoteServiceAsync { // Method returns the underlying HTTP RequestBuilder instance RequestBuilder getTasks(int startIndex, int maxCount, AsyncCallback<List<Task>> callback); }
Raw RPC Serialization
- For pre-serialization of responses or custom transports
* Client accesses the generated SerializationStreamFactory
* Server uses RPC.encodeResponseForSuccess method to encode - Streams are not symmetric
public Object clientDeserializer(String encodedPayload) throws SerializationException { // Create the serialization stream factory SerializationStreamFactory serializationFactory = GWT.create(TaskRemoteService.class); // Create a stream reader SerializationStreamReader streamReader = serializationFactory.createStreamReader(encodedPayload); // Deserialize the instance return streamReader.readObject(); }
Best Practices
- Use stateless servers - better handling, better scalability
- Keep conversational state in the client
- Consider possible failure modes, keep the user’s needs in mind
- Judiciously control the amount of data sent to the client - consider pagination of data instead of one bulk transfer
0 comments:
Post a Comment