My favorites | English | Sign in

Google Web Toolkit

Communicating with a Server

  1. Why doesn't GWT provide a synchronous server connection option?
  2. What is the Same Origin Policy, and how does it affect GWT?
  3. How do I make a call to the server if I am not using GWT RPC?
  4. Does GWT RPC support java.io.Serializable?
  5. How can I dynamically fetch JSON feeds from other web domains?
  6. How can I coerce a JSON JavaScriptObject into a GWT JSONObject?

Communicating with Servers

Why doesn't GWT provide a synchronous server connection option?

GWT's network operations are all asynchronous, or non-blocking. That is, they return immediately as soon as called, and require the user to use a callback method to handle the results when they are eventually returned from the server. Though in some cases asynchronous operators are less convenient to use than synchronous operators, GWT does not provide synchronous operators.

The reason is that most browsers' JavaScript engines are single-threaded. As a result, blocking on a call to XMLHTTPRequest also blocks the UI thread, making the browser appear to freeze for the duration of the connection to the server. Some browsers provide a way around this, but there is no universal solution. GWT does not implement a synchronous network connection because to do so would be to introduce a feature that does not work on all browsers, violating GWT's commitment to no-compromise, cross-browser AJAX. It would also introduce complexity for developers, who would have to maintain two different versions of their communications code in order to handle all browsers.

What is the Same Origin Policy, and how does it affect GWT?

Modern browsers implement a security model known as the Same Origin Policy (SOP). Conceptually, it is very simple, but the limitations it applies to JavaScript applications can be quite subtle.

Simply stated, the SOP states that JavaScript code running on a web page may not interact with any resource not originating from the same web site. The reason this security policy exists is to prevent malicious web coders from creating pages that steal web users' information or compromise their privacy. While very necessary, this policy also has the side effect of making web developers' lives difficult.

It's important to note that the SOP issues described below are not specific to GWT; they are true of any AJAX application or framework. This FAQ simply details the specific ways in which GWT is affected by this universal limitation.

How the SOP Affects GWT

When you compile a GWT application, it produces JavaScript code and HTML files. Because a GWT application is broken up into multiple files, the browser will make multiple requests from the HTTP server to fetch all the pieces. Previous to GWT 1.4, this meant that all the GWT files must live on the same web server as the page which launches the GWT application so as not to break the SOP. In GWT 1.4, this is no longer an issue thanks to the new cross-site script inclusion bootstrap process mode.

Typically, the bootstrap process will load the GWT application files from the same web server that is serving the HTML host page. That is, supposing the host HTML file was located at http://mydomain.com/index.html, the GWT application files would also be in the same directory (or a subdirectory) as the index.html file. To load the GWT application, the <module>.nocache.js file would be bootstrapped by having the index.html file include a <script> tag referencing the <module>.nocache.js file. This is the standard bootstrap process to load a GWT application. The <script> tag that needs to be included in the main host HTML page is shown below:

<script language="JavaScript" src="http://mydomain.com/<module>.nocache.js"></script>

However, many organizations setup their deployment platform in such a way that their main host HTML page is served up from http://mydomain.com/, but any other resources such as images and JavaScript files are served up from a separate static server under http://static.mydomain.com/. In older versions of GWT, this configuration would not be possible as the SOP prevented the GWT bootstrap process from allowing script from files that were added from a different server to access the iframe in the main host HTML page. The new GWT 1.4 bootstrap model now provides support for this kind of server configuration.

This is possible due to the <module>-xs.nocache.js file generated by the GWT compiler. Basically, this is a cross-site version of the <module>.nocache.js file. To setup the bootstrap process in cross-site mode, the <script> tag in the main HTML host page just needs to refer the <module>-xs.nocache.js file rather than the <module>.nocache.js counterpart. The <module>-xs.nocache.js file, as well as all the other GWT application resources, can reside on a static server, say http://static.mydomain.com/, while the main HTML host page can be hosted on a separate server on http://mydomain.com/. As long as the script tag is referencing the cross-site version of the .nocache.js file and the other application are in the same path as that file, the application can be loaded using the cross-site bootstrap process. The <script> tag including the cross-site JS file is shown below:

<script language="JavaScript" src="http://static.mydomain.com/<module>-xs.nocache.js"></script>

For more details on the GWT 1.4 bootstrap process, see "What's with all the cache/nocache stuff and weird filenames?"

SOP, GWT, and XMLHTTPRequest Calls

The second area where the SOP is most likely to affect GWT users is the use of XMLHTTPRequest -- the heart of AJAX. The SOP limits the XMLHTTPRequest browser call to URLs on the same server from which the host page was loaded. This means that it is impossible to make any kind of AJAX-style request to a different site than the one from which the page was loaded. For example, you might want to have your GWT application served up from http://pages.mydomain.com/ but have it make requests for data to http://data.mydomain.com/, or even a different port on the same server, such as http://pages.mydomain.com:8888/. Unfortunately, both these scenarios are impossible, prevented by the SOP.

This limitation affects all forms of calls to the server, whether JSON, XML-RPC, or GWT's own RPC library. Generally, you must either run your CGI environment on the same server as the GWT application, or implement a more sophisticated solution such as round-robin DNS load balancing or a reverse-proxy mechanism for your application's CGI calls.

In certain cases, it is possible to work around this limitation. For an example, see "How can I dynamically fetch JSON feeds from other web domains?"

SOP and GWT Hosted Mode

The SOP applies to all GWT applications, whether running in web (compiled) mode on a web server, or in hosted mode. For example, it is perfectly possible to launch a GWT application from a file:// URL pointing to a file on your local computer. Though GWT will run in this case, it will be unable to access any resources from a web server because it will be constrained to the "site" from which it was loaded--your computer's filesystem.

This can cause problems if you are attempting to develop a GWT application that uses server-side technologies not supported by the GWT hosted mode, such as EJBs or Python code. In such cases, you can use the -noserver argument for hosted mode to launch your GWT application from the server technology of your choice. For more information, see "How do I use my own server in hosted mode instead of GWT's built-in Tomcat instance?" Even if you choose to use this feature, however, remember that the SOP still applies.

How do I make a call to the server if I am not using GWT RPC?

The heart of AJAX is making data read/write calls to a server from the JavaScript application running in the browser. GWT is "RPC agnostic" and has no particular requirements about what protocol is used to issue RPC requests, or even what language the server code is written in. Although GWT provides a library of classes that makes the RPC communications with a J2EE server extremely easy, you are not required to use them. Instead you can build custom HTTP requests to retrieve, for example, JSON or XML-formatted data.

To communicate with your server from the browser without using GWT RPC:

  1. Create a connection to the server, using the browser's XMLHTTPRequest feature.
  2. Construct your payload according to whatever protocol you wish to use, convert it to a string, and send it to the server over the connection.
  3. Receive the server's response payload, and parse it according to the protocol.

You must use an asynchronous server connection.

The com.google.gwt.http.client.html package

GWT provides a library to largely (though not completely) automate the steps necessary to communicate with the server via HTTP requests. GWT application developers should use the RequestBuilder class and other classes in the com.google.gwt.http.client.html package, which contains a clean asynchronous server request callback implementation.

Note: New users frequently notice the com.google.gwt.user.client.HTTPRequest class and attempt to use it. However, the HTTPRequest class is deprecated and will be removed at some point in the future. You should definitely use RequestBuilder instead.

Troubleshooting

If you are attempting to use the RequestBuilder class and are having problems, first check your module XML file to make sure that the HTTP module is inherited, as follows:

    <inherits name="com.google.gwt.http.HTTP"/>

Learn more

  • To learn more about alternatives to GWT RPC, see the Developer's Guide, Making HTTP Requests.
  • For a working example of making HTTP requests to retrieve JSON-formatted data, see the Tutorial, Get JSON via HTTP.
  • For documentation of the classes and methods you can use to build HTTP requests, see the API Reference, the com.google.gwt.http.client package.

Does GWT RPC support java.io.Serializable?

The GWT 1.4 RPC system does support the use of java.io.Serializable, however only under a certain condition.

Previous to 1.4, the GWT RPC mechanism used an "IsSerializable" marker interface for denoting classes that can be serialized. Many users expressed the wish to reuse code with GWT that they have already written that used the standard java.io.Serializable marker interface. Since both interfaces are empty marker interfaces, there is no technical reason why GWT's RPC mechanism could not use the standard java.io.Serializable. However, there are good reasons to choose not to do so:

  • The semantics of GWT's serialization are much less sophisticated than standard Java serialization, and so to use java.io.Serializable as the marker interface would imply that GWT's serialization system is capable of more than it actually is.
  • Conversely, GWT's serialization mechanism is simpler than standard Java's, and so to use java.io.Serializable would imply that users have more to worry about (such as serialization version IDs) than they actually do.
  • GWT implements only a subset of the full Java JRE classes, and specifically implements nothing in java.io. To use java.io.Serializable as the GWT RPC serialization marker interface dilutes the message that java.io is not usable within a GWT application.

While each of the points above still hold, the GWT Team felt that the community was generally aware of these issues but preferred the convenience of being able to use the standard java.io.Serializable interface rather than to have their classes implement the isSerializable marker interface, although both marker interfaces to denote serializable classes are supported in GWT 1.4. Considering this, the GWT Team made changes to the GWT RPC system to support the use of java.io.Serializable for data transfer objects (commonly referred to as DTOs) that would be transferred over the wire. However, there is one condition to enable support for java.io.Serializable in the new GWT RPC system.

RPC now generates a serialization policy file during GWT compilation. The serialization policy file contains a whitelist of allowed types which may be serialized. Its name is a strong hash name followed by .gwt.rpc. In order to enable support for java.io.Serializable, the types that your application will send over the wire must be included in the serialization policy whitelist. Also, the serialization policy file must be deployed to your web server as a public resource, accessible from a RemoteServiceServlet via ServletContext.getResource(). If it is not deployed properly, RPC will run in 1.3.3 compatibility mode and refuse to serialize types implementing java.io.Serializable.

Another important point to note is that none of the classes that implement java.io.Serializable in the full Java JRE implement java.io.Serializable in GWT's emulated JRE. What this means is that types that implement java.io.Serializable in the JRE like Throwable, or StackTraceElement won't be able to transfer across the wire through GWT RPC since the client won't be able to serialize/deserialize them. However, this isn't an issue for other types like String, Number, etc... that don't implement java.io.Serializable in the emulated JRE but have custom field serializers so that they can be properly serialized.

These differences between types that implement java.io.Serializable in the real and emulated JREs may be reconciled in a future version of GWT, but for the time this is an important point to keep in mind if your application uses GWT RPC.

How can I dynamically fetch JSON feeds from other web domains?

Like all AJAX tools, GWT's HTTP client and RPC libraries are restricted to only accessing data from the same site where your application was loaded, due to the browser Same Origin Policy. If you are using JSON, you can work around this limitation using a

<script>
tag. To accomplish this, though, you must resort to using DOM manipulation methods to inject the tag into your host page dynamically.

First, you need an external JSON service which can invoke user defined callback functions with the JSON data as argument. An example of such a service is GData's "alt=json-in-script&callback=myCallback" support. Then, you can generate a bridge method, which will be used to invoke a GWT JSON callback handler.

Here is an example:

package mypackage;
public class MyJSONUtility
{
   interface JSONHandler
   {
      public void handleJSON(JavaScriptObject obj);
   }

   public static native void makeJSONRequest(String url, JSONHandler handler) /*-{
       $wnd.jsonCallback = function(jsonObj) {
         @mypackage.MyJSONUtility::dispatchJSON(Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/sample/client/JsonTestApp$JSONHandler;)(jsonObj, handler);
       }
      
       // create SCRIPT tag, and set SRC attribute equal to JSON feed URL + callback function name
       var script = $wnd.document.createElement("script");
       script.setAttribute("src", url+"jsonCallback");
       script.setAttribute("type", "text/javascript");
       
       $wnd.document.getElementsByTagName("head")[0].appendChild(script);
   
   }-*/;

   public static void dispatchJSON(JavaScriptObject jsonObj, JSONHandler handler)
   {
      handler.handleJSON(jsonObj);
   }
}

You can then implement the JSONHandler interface as you choose, and call

   MyJSONUtility.makeJSONRequest(
       "http://www.google.com/calendar/feeds/developer-calendar@google.com/public/full?alt=json-in-script&callback=",
       myHandlerInstance);

Of course, the above example doesn't handle multiple concurrent requests. For that, you need an array of bridge methods; you would access them during callbacks using syntax similar to

jsonCallbacks[requestNumber].

If the external feed doesn't support callback function names using array syntax, you can generate uniquely named bridge methods like jsonCallback1, jsonCallback2, etc. Also, don't forget to cleanup in the bridge function after it's been called, such as removing the SCRIPT node that's been added to the DOM, and deleting the bridge method, since they are no longer used once you have the result.

How can I coerce a JSON JavaScriptObject into a GWT JSONObject?

GWT 1.4 and later

GWT 1.4 makes this process a lot easier by providing constructors for JSONObject and JSONArray that take JavaScriptObject values as constructor arguments.

So if you have some JavaScriptObject value object that you want to coerce into a JSONObject, all you need to do is create the JSONObject by passing in the value as a constructor argument, as shown below.

JSONObject jsonValue = new JSONObject(value);

Previous to GWT 1.4

Previous to GWT 1.4, the only way to do this was to convert the JavaScriptObject back into text representation, and then invoke JSONParser.parse(). You would have to incorporate a JSON encoder/stringifier, such as the open source implementation available at http://www.json.org/json.js, and use it to convert the JavaScriptObject back into a text representation. From that point, you would write a JSNI method to invoke the toJSONString() method on the JavaScriptObject, and then pass it to JSONParser.parse().