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