A simple GWT application that reverses the order of the characters in a string will be used to demonstrate how to build a GWT service. The String Reverser application consists of a simple form-like UI with a text box where the user can enter a string. Users can press a button to have the string reversed. When the button is pressed, the application will make an asynchronous call to a String Reverser Service. The client will send the user-entered string to the service and a callback as the service call parameters. Once the call is made, server-side code will reverse the order of the characters in the string and return the reversed string to the client via the callback. The rest of this tutorial will focus on the String Reverser Service.
Building and calling a GWT service
There are three steps involved in creating a GWT service:
1. Defining the service’s synchronous and asynchronous interface
2. Implementing the service
3. Calling the service
1. Defining a GWT service
Synchronous Interface
The first step in creating the String Reverser Service is defining the service’s client-side interface. The interface must extend the GWT RemoteService interface and contain the signatures of the service methods that should be exposed to the client. Method parameters and return types must be serializable.
The code snippet below shows the client-side class (StringReverserService) which defines the synchronous interface for the String Reverser Service.
public interface StringReverserService extends RemoteService {
public String reverseString(String stringToReverse);
}
Asynchronous Interface
A client-side asynchronous interface, based on the synchronous interface, must be built before a service call can be made. The nature of asynchronous method calls requires the caller to pass in a callback object (AsyncCallback). This callback object is used to notify the caller when an asynchronous call completes. Asynchronous methods cannot have return types, and so they must always return void. After an asynchronous call is made, all communication back to the caller is via the passed-in callback object.
A service’s asynchronous interface must be in the same package and have the same name, but with the suffix “Async”. E.g. if a service interface is called com.example.app.client.RandomService, the asynchronous interface must be called com.example.app.client.RandomServiceAsync.
An asynchronous “sibling” method should be defined for each method in your service’s synchronous interface. The method signature for these asynchronous sibling methods is the same as the synchronous methods signature, but with the addition of an asynchronous callback. If the synchronous interface method is:
public ReturnType methodName(ParamType1 one, ParamType2 two);
the asynchronous sibling method will be:
public void methodName(ParamType1 one, ParamType2 two, AsyncCallback callback);
The code snippet below shows the client-side class (StringReverserServiceAsync) which defines the asynchronous interface for the String Reverser Service.
public interface StringReverserServiceAsync {
void reverseString(String stringToReverse, AsyncCallback async);
}
2. Implementing a GWT service
Now that the service interfaces have been defined, the next step is to implement the service methods. These methods are implemented in a class that extends GWT’s RemoteServiceServlet class. This service implementation can be hosted in any servlet container.
For the String Reverser Service, the service implementation will take the user-entered string that was passed to the service and reverse the order of the characters. Once reversed, the reversed string is returned.
The code snippet below shows the server-side class (StringReverserServiceImpl) which implements the String Reverser Service Interface.
public class StringReverserServiceImpl extends RemoteServiceServlet implements StringReverserService {
/**
* This method is used to reverse a string
* @param stringToReverse The string that you want reversed
* @return The reversed string
*/
public String reverseString(String stringToReverse) {
StringBuffer reverse = new StringBuffer(stringToReverse.length());
for (int i = (stringToReverse.length() - 1); i >= 0; i–)
reverse.append(stringToReverse.charAt(i));
return reverse.toString();
}
}
3. Calling a GWT service
Once a service has been defined and implemented, it can be called from a client. The process of making a GWT RPC call from the client involves the following steps:
a. Instantiate the service interface using GWT.create().
Before we can use the service, we need to instantiate an instance of the service. The following listing demonstrates how to create an instance of StringReverserService. Note that although an instance of the synchronous service interface is being created and then cast to asynchronous version of the interface. The cast is always safe because the generated proxy implements the asynchronous interface automatically.
The code snippet below shows you how to instantiate the String Reverser Service.
1: StringReverserServiceAsync reverserService = (StringReverserServiceAsync) GWT.create(StringReverserService.class);
b.Specify a service entry point URL for the service using ServiceDefTarget.
Once an instance of the service is created, we need to specify the URL at which the service implementation is, or will be, running. The target URL for the service must reside on the same domain and port from which the host page was served. This is due to the fact that most modern browsers implement the “Single Origin Policy” (SOP) security model. The SOP policy makes it so that JavaScript code running in a currently loaded web-page can only interact with resources originating from sites with the same domain name and port as the currently loaded web-page.
The code snippet below shows you how to specify the URL for the String Reverser Service Implementation.
((ServiceDefTarget) reverserService).setServiceEntryPoint( GWT.getModuleBaseURL() +
"/StringReverser/StringReverserService");
c. Create an AsyncCallback object so that the client can be notified when the service call is completed.
The next step is to create an Asynchrounous Callback (AsyncCallback) object. This object will be passed as a parameter to the remote service when it is called. As was mentioned before, all network operation is GWT are asynchronous and non-blocking. When a call to the service is made, there is no immediate value returned. Since the service call is asynchronous and non-blocking, the GWT application will not wait for a response from the service. It will continue executing until it receives an asynchronous callback from the service. This callback informs the GWT application whether or not the service call has been executed successfully.
If the service call is unsuccessful, the onFailure method of the AsyncCallback object is called. If the service call is successful, the onSuccess method of the AsyncCallback object is called. The onSuccess method accepts a value of type java.lang.Object as a parameter. If your service returns data, this result object is it. It is always safe to downcast the parameter to the return type of the service method. Note that if the return type of the synchronous service interface method is a primitive (int, long, etc) then the parameter will be the boxed version of the primitive (for example, an int return type becomes an Integer).
The following code snippet shows you how to create an AsyncCallback object.
AsyncCallback callback = new AsyncCallback() {
// This method will be called if the service call fails
public void onFailure(Throwable caught) {
// Show a message informing the user why the call failed
Window.alert("Failed to get response from server" + caught.getMessage());
}
// This method will be called if the service call succeeds
public void onSuccess(Object result) {
// Get the service call result and cast it to the desired type and display it
String reverse = (String) result;
Window.alert(reverse);
}
};
d. Make the call
The final step is to make the service call. The following code snippet demonstrates how to make the call to the String Reverser Service.
1: reverserService.reverseString(stringToReverse, callback);
Putting it all together
The following code snippet shows the sections of the String Reverser widget (StringReverserWidget.java) where the call to the String Reverser Service is made. Note that AsyncCallback below is created as an Anonymous Inner Class when the String Reverser Service is called.
/**
* Method used to get an instance of the String Reverser Service
*
* @return Reversed String
*/
private StringReverserServiceAsync getReverserServiceInstance() {
if (reverserService == null) {
// Instantiate the service
reverserService = (StringReverserServiceAsync) GWT.create(StringReverserService.class);
// Specify the URL at which the service implementation is running.
// The target URL must reside on the same domain and port from
// which the host page was served.
((ServiceDefTarget) reverserService).setServiceEntryPoint( GWT.getModuleBaseURL() +
"/StringReverser/StringReverserService");
}
return reverserService;
}
/**
* Method used to call the String Reverser Service. The response from the service is displayed in a dialog box after
* it is received.
*
* @param stringToReverse String that you want reversed
*/
public void callStringReverserService(final String stringToReverse) {
// Show the loading message and animation
showLoadingMessageAndAnimation();
// Call the String Reverser Service
// The asynchronous callback used to handle the service response is created inline.
// If the service call fails, a message will be displayed on the client
// If the service call is successful, the reversed string will be displayed
getReverserServiceInstance().reverseString(stringToReverse, new AsyncCallback() {
public void onFailure(Throwable caught) {
// Reset the button text and remove the loading animation
resetWiget();
Window.alert("Failed to get response from server");
}
public void onSuccess(Object result) {
// Reset the button text and remove the loading animation
resetWiget();
// Get the service call response and display it
String reverse = (String) result;
ReversedStringDisplayDialog dlg = new ReversedStringDisplayDialog(stringToReverse, reverse);
dlg.show();
}
});
}
Friday, July 3, 2009
GWT Tutorial - Building a GWT RPC Service
Introduction
If you haven’t already please read our previous tutorials: Introduction to GWT, and Anatomy of a GWT Project.
As you already know, GWT is a Java framework that allows you to easily develop AJAX (Asynchronous JavaScript and XML) based web applications. The difference between GWT (AJAX based web) applications and traditional (non AJAX based) web applications is that GWT applications do not need to fetch new HTML pages from the server when they want to make User Interface (UI) changes. A GWT application behaves like a regular client/server application that happens to be running in a browser. The GWT application can fetch data from the server as it executes and update only the specific parts of the UI that need to be updated.
To learn more about GWT, I recommend reading these good books - GWT Solutions, GWT Applications, AJAX Security.
What is GWT RPC?
One of the most important pieces of the GWT framework is the GWT Remote Procedure Call (RPC) mechanism. This RPC mechanism makes it easy for a GWT application client to make a call to server-side code. GWT RPC makes it simple to get data between the client and the server.
What is a GWT service?
The server-side code that gets called from the client is referred to as a service (not to be confused with SOAP web-services). During a service call, the GWT RPC makes it easy for client and server to pass Java objects back and forth over HTTP.
GWT services can be used to accomplish tasks that are part of your application, but cannot be done on the client computer. Proper use of GWT services can allow you to develop an application where all the UI logic resides on the client, resulting in an application with greatly improved performance, reduced bandwidth, and reduced web server load. This will also result in a user experience that is similar to using a desktop application, and is far more compelling than the experience of visiting a simple web page.
GWT’s RPC mechanism hides all the plumbing necessary to create and consume services. All the proxy classes that handle RPC plumbing for making the server-side code invocation and for converting data back and forth between the client and server are all generated automagically. All you need to do is define your service’s interface and its server-side implementations.
Asynchronous – the A in AJAX
All network operations in GWT are asynchronous, or non-blocking, i.e. they return immediately after they are called, and require the user to use a callback method to handle the results when they are eventually returned from the server.
The reason for using asynchronous operation is that most browsers’ JavaScript engines are single-threaded. A blocking on a call to XMLHTTPRequest (a JavaScript Object defined by browsers to enable a web page to send HTTP requests) in a browser based application, would block the UI thread until a response was received from the server. This would make it appear as though the browser was frozen for the duration of the connection to the server. Some browsers provide a way around this, but there is no clean, universal solution. As a result, GWT does not implement any synchronous network connections.
Sending data back and forth between client and server
Because GWT RPC calls are between JavaScript (on the client) and Java code (on the browser), GWT provides object serialization as part of its RPC mechanism to help bridge the language divide. Please note that GWT serialization is not the same as Java serialization. You need to ensure that any object that needs to be sent between the client and server is of a GWT serializable type. A type is serializable and can be used in a service interface if the type:
• is primitive, such as char, byte, short, int, long, boolean, float, or double;
• is String, Date, or a primitive wrapper such as Character, Byte, Short, Integer, Long, Boolean, Float, or Double;
• is an array of serializable types (including other serializable arrays);
• is a serializable user-defined class; or
• has at least one serializable subclass
This is only a brief overview of GWT serialization. To learn more about the details of GWT object serialization, and how to create complex serializable objects, check out this tutorial.
If you haven’t already please read our previous tutorials: Introduction to GWT, and Anatomy of a GWT Project.
As you already know, GWT is a Java framework that allows you to easily develop AJAX (Asynchronous JavaScript and XML) based web applications. The difference between GWT (AJAX based web) applications and traditional (non AJAX based) web applications is that GWT applications do not need to fetch new HTML pages from the server when they want to make User Interface (UI) changes. A GWT application behaves like a regular client/server application that happens to be running in a browser. The GWT application can fetch data from the server as it executes and update only the specific parts of the UI that need to be updated.
To learn more about GWT, I recommend reading these good books - GWT Solutions, GWT Applications, AJAX Security.
What is GWT RPC?
One of the most important pieces of the GWT framework is the GWT Remote Procedure Call (RPC) mechanism. This RPC mechanism makes it easy for a GWT application client to make a call to server-side code. GWT RPC makes it simple to get data between the client and the server.
What is a GWT service?
The server-side code that gets called from the client is referred to as a service (not to be confused with SOAP web-services). During a service call, the GWT RPC makes it easy for client and server to pass Java objects back and forth over HTTP.
GWT services can be used to accomplish tasks that are part of your application, but cannot be done on the client computer. Proper use of GWT services can allow you to develop an application where all the UI logic resides on the client, resulting in an application with greatly improved performance, reduced bandwidth, and reduced web server load. This will also result in a user experience that is similar to using a desktop application, and is far more compelling than the experience of visiting a simple web page.
GWT’s RPC mechanism hides all the plumbing necessary to create and consume services. All the proxy classes that handle RPC plumbing for making the server-side code invocation and for converting data back and forth between the client and server are all generated automagically. All you need to do is define your service’s interface and its server-side implementations.
Asynchronous – the A in AJAX
All network operations in GWT are asynchronous, or non-blocking, i.e. they return immediately after they are called, and require the user to use a callback method to handle the results when they are eventually returned from the server.
The reason for using asynchronous operation is that most browsers’ JavaScript engines are single-threaded. A blocking on a call to XMLHTTPRequest (a JavaScript Object defined by browsers to enable a web page to send HTTP requests) in a browser based application, would block the UI thread until a response was received from the server. This would make it appear as though the browser was frozen for the duration of the connection to the server. Some browsers provide a way around this, but there is no clean, universal solution. As a result, GWT does not implement any synchronous network connections.
Sending data back and forth between client and server
Because GWT RPC calls are between JavaScript (on the client) and Java code (on the browser), GWT provides object serialization as part of its RPC mechanism to help bridge the language divide. Please note that GWT serialization is not the same as Java serialization. You need to ensure that any object that needs to be sent between the client and server is of a GWT serializable type. A type is serializable and can be used in a service interface if the type:
• is primitive, such as char, byte, short, int, long, boolean, float, or double;
• is String, Date, or a primitive wrapper such as Character, Byte, Short, Integer, Long, Boolean, Float, or Double;
• is an array of serializable types (including other serializable arrays);
• is a serializable user-defined class; or
• has at least one serializable subclass
This is only a brief overview of GWT serialization. To learn more about the details of GWT object serialization, and how to create complex serializable objects, check out this tutorial.
How to setup a GWT Project
Most people will probably use the command line tools that come with GWT to setup their projects. If you use Eclipse, you can use the command line tools to setup an Eclipse project and then import them into Eclipse. There are also plugins for Eclipse that will help to streamline that process. To find out how to use GWT’s built-in tools here.
If you are using IntelliJ IDEA 6 you can download a GWT plugin, and use that to setup your GWT project. IntelliJ IDEA 7 has built-in support for GWT. If you use IDEA 7, you can learn how to setup a GWT Project here.
If you are using IntelliJ IDEA 6 you can download a GWT plugin, and use that to setup your GWT project. IntelliJ IDEA 7 has built-in support for GWT. If you use IDEA 7, you can learn how to setup a GWT Project here.
Module Package Restrictions
While GWT modules may appear anywhere in your classpath and use Java’s package naming convention, there are restrictions as to where source code can be placed inside of a GWT module. If you want to add some new classes, you can’t just add them anywhere. Java classes must be placed in the client sub-package, in a package that is listed in the source path, or in the server sub-package. The placement of code into these packages is not arbitrary, it is dependent on what you intend to do with your classes.
Client-side code must always be included in either the client sub-package or in a package listed in the source path
Client-side code is code that you expect to be translated into JavaScript and executed in a web-browser. For example, if you create a GWT UI for your application, all the GWT UI classes and the classes they interact with are considered to be client-side code since they must be translated to JavaScript before you can access them through a web-browser. Any code that needs to be translated to JavaScript and executed on the client side must always be included in either the client sub-package or in a package listed in the source path. You also need to ensure that this client-side source code is compatible with Java 1.4.2 or older and only uses classes provided by the GWT JRE Emulation library.
Server-side code must always be included in the server sub-package
Server-side code is code that you expect to be executed on a server computer. This code is executed as is. For example, server side implementations of GWT RPC services, or any other classes that interacts with the GWT RPC services are considered to be server-side code since they execute on a server. Any code that executes on a server as part of a GWT application must always be included in the server sub-package. None of the client-side language restrictions apply to server-side code.
NOTE: If you have classes that you wish to use in both client and server-side code, these classes need to be translated to JavaScript for use in the client. Therefore classes that you wish to use in both client and server-side code should be included in either the client sub-package or in a package listed in the source path. All client-side code language restrictions apply to these classes.
Client-side code must always be included in either the client sub-package or in a package listed in the source path
Client-side code is code that you expect to be translated into JavaScript and executed in a web-browser. For example, if you create a GWT UI for your application, all the GWT UI classes and the classes they interact with are considered to be client-side code since they must be translated to JavaScript before you can access them through a web-browser. Any code that needs to be translated to JavaScript and executed on the client side must always be included in either the client sub-package or in a package listed in the source path. You also need to ensure that this client-side source code is compatible with Java 1.4.2 or older and only uses classes provided by the GWT JRE Emulation library.
Server-side code must always be included in the server sub-package
Server-side code is code that you expect to be executed on a server computer. This code is executed as is. For example, server side implementations of GWT RPC services, or any other classes that interacts with the GWT RPC services are considered to be server-side code since they execute on a server. Any code that executes on a server as part of a GWT application must always be included in the server sub-package. None of the client-side language restrictions apply to server-side code.
NOTE: If you have classes that you wish to use in both client and server-side code, these classes need to be translated to JavaScript for use in the client. Therefore classes that you wish to use in both client and server-side code should be included in either the client sub-package or in a package listed in the source path. All client-side code language restrictions apply to these classes.
Configuring a module
The following are all the configuration options that can be specified in a .gwt.xml descriptor file:
GWT descriptor file element Purpose
<inherits name=”logical-module-name“/> Inherits all the settings from the specified module. There is no limit to the number of modules that can be inherited.
<entry-point class=”classname“/> Specifies an entry point class. There is no limit to the number of entry point classes that can be added. The onModuleLoad() for each of the entry point classes will be called one after the other in the in which they are listed here.
<source path=”path“/> Adds packages to the source path by combining the package in which the module XML is found with the specified path to a sub-package. Any Java source files appearing in the source path are assumed to be translatable.
If no <source> element is defined in a module XML file, the client sub-package is added to the source path by default.
<public path=”path“/> Adds packages to the public path by combining the package in which the module XML is found with the specified path to identify the root of a public path entry. Any files appearing in the public path will be treated as a publicly-accessible resource. The <public> element supports pattern-based filtering that allows you to control which resources get copied into the output directory during a GWT compile. It follows the same rules as Ant’s FileSet element.
If no <public> element is defined in a module XML file, the public sub-package is added to the public path by default.
<servlet path=”url-path” class=”classname“/> This element loads a servlet mounted at the specified URL path. This allows for convenient RPC testing. The URL path should be absolute and have the form of a directory, e.g. /example/path. Your client code then specifies this URL mapping in a call to ServiceDefTarget.setServiceEntryPoint(String). There is no limit to the number of servlets that can be loaded.
<script src=”js-url“/> Automatically injects the external JavaScript file located at the location specified. This is a convenient way of automatically associating external JavaScript files with your module.
<stylesheet src=”css-url“/> Automatically injects the external CSS file located at the location specified. This is a convenient way to automatically attach a CSS file to the HTML Host Page.
<extend-property name=”client-property-name” values=”comma-separated-values“/> Allows you to extend existing client properties with specified values. There is no limit to the number of values that can be added. Client property values accumulate through inherited modules. This element is particularly useful for specifying locales in internationalization.
GWT descriptor file element Purpose
<inherits name=”logical-module-name“/> Inherits all the settings from the specified module. There is no limit to the number of modules that can be inherited.
<entry-point class=”classname“/> Specifies an entry point class. There is no limit to the number of entry point classes that can be added. The onModuleLoad() for each of the entry point classes will be called one after the other in the in which they are listed here.
<source path=”path“/> Adds packages to the source path by combining the package in which the module XML is found with the specified path to a sub-package. Any Java source files appearing in the source path are assumed to be translatable.
If no <source> element is defined in a module XML file, the client sub-package is added to the source path by default.
<public path=”path“/> Adds packages to the public path by combining the package in which the module XML is found with the specified path to identify the root of a public path entry. Any files appearing in the public path will be treated as a publicly-accessible resource. The <public> element supports pattern-based filtering that allows you to control which resources get copied into the output directory during a GWT compile. It follows the same rules as Ant’s FileSet element.
If no <public> element is defined in a module XML file, the public sub-package is added to the public path by default.
<servlet path=”url-path” class=”classname“/> This element loads a servlet mounted at the specified URL path. This allows for convenient RPC testing. The URL path should be absolute and have the form of a directory, e.g. /example/path. Your client code then specifies this URL mapping in a call to ServiceDefTarget.setServiceEntryPoint(String). There is no limit to the number of servlets that can be loaded.
<script src=”js-url“/> Automatically injects the external JavaScript file located at the location specified. This is a convenient way of automatically associating external JavaScript files with your module.
<stylesheet src=”css-url“/> Automatically injects the external CSS file located at the location specified. This is a convenient way to automatically attach a CSS file to the HTML Host Page.
<extend-property name=”client-property-name” values=”comma-separated-values“/> Allows you to extend existing client properties with specified values. There is no limit to the number of values that can be added. Client property values accumulate through inherited modules. This element is particularly useful for specifying locales in internationalization.
What is a GWT Module?
According to Google, “A GWT ‘module’ is simply an encapsulation of functionality”. A module bundles together all the configuration needed to use use your code in a GWT project. While a GWT module shares some similarities with a Java package it is not the same thing. GWT modules follow the Java package dotted-path naming convention, e.g. most of the standard GWT modules are located under “com.google.gwt”. The naming convention is where the similarities end. If you want to add new classes, you can’t just add them anywhere.
GWT modules are defined using XML descriptor files ending with the .gwt.xml extension. The concept of a GWT module descriptor is similar to deployment descriptors in Tomcat and other application servers. The contents of the XML descriptor files are use to specify:
• Inherited modules
• An entry point application class name (optional)
• Source Path entries
• Public Path entries
Inherited Modules
Modules from which settings and code will be inherited.
Entry Point Classes
A module entry point is any class that implements the EntryPoint interface. When a module is loaded, each entry point class listed in the .gwt.xml file is instantiated and its onModuleLoad() method is called. It is possible to create a module with more than one entry point. It is also possible to create a module with no entry points. If you wish to make a re-usable GWT code library, you should package it as a GWT module that contains no entry point classes. This module could then be inherited by other GWT modules.
Source Path
Source Path entries can be used to specify which sub-packages contain translatable source code. Only files found on the source path are candidates to be translated into JavaScript. When modules are inherited by other modules, the source paths are combined so that each module will have access to the translatable source it requires. The client sub-package is included in the source path by default.
Public Path
Public Path entries can be used to specify which sub-packages are public. All the files found on the public path will be copied to the module’s output directory when your application is compiled. When modules are inherited by other modules, the public paths are combined so that each module will have access to the static resources it expects. The public sub-package is included in the public path by default.
GWT modules are defined using XML descriptor files ending with the .gwt.xml extension. The concept of a GWT module descriptor is similar to deployment descriptors in Tomcat and other application servers. The contents of the XML descriptor files are use to specify:
• Inherited modules
• An entry point application class name (optional)
• Source Path entries
• Public Path entries
Inherited Modules
Modules from which settings and code will be inherited.
Entry Point Classes
A module entry point is any class that implements the EntryPoint interface. When a module is loaded, each entry point class listed in the .gwt.xml file is instantiated and its onModuleLoad() method is called. It is possible to create a module with more than one entry point. It is also possible to create a module with no entry points. If you wish to make a re-usable GWT code library, you should package it as a GWT module that contains no entry point classes. This module could then be inherited by other GWT modules.
Source Path
Source Path entries can be used to specify which sub-packages contain translatable source code. Only files found on the source path are candidates to be translated into JavaScript. When modules are inherited by other modules, the source paths are combined so that each module will have access to the translatable source it requires. The client sub-package is included in the source path by default.
Public Path
Public Path entries can be used to specify which sub-packages are public. All the files found on the public path will be copied to the module’s output directory when your application is compiled. When modules are inherited by other modules, the public paths are combined so that each module will have access to the static resources it expects. The public sub-package is included in the public path by default.
GWT Compiler Output
The GWT compiler generates a series of, sometimes oddly named, files.
As of GWT version 1.4, you should typically see the following types of files:
•.nocache.js (or -xs.nocache.js for cross-site script inclusion)
•.cache.html
•.gwt.rpc
.no-cache.js File
The “nocache.js” file is where Deferred Binding occurs. Before your GWT application can run, any dynamically-bound code must be resolved. This might include browser-specific versions of classes, Internationalization strings for the user’s selected language, etc. The “nocache.js” file includes a lookup table that maps Deferred Binding permutations to .cache.html filenames, e.g. “Firefox in German” and “Safari in English” would both be entries in the lookup table, pointing to different .cache.html files.
The file is named “.nocache.js” to indicate that it should never be cached, i.e. it must be re-downloaded and executed each time the browser starts your GWT application. The file must be re-downloaded each time is because the GWT Compiler regenerates it each time, but under the same file name. Allowing browsers to cache the file, would result in browsers not always downloading the latest version of the file when your application is recompiled and redeployed.
.cache.html Files
These are the files that actually contain your GWT application’s logic. A .cache.html file contains JavaScript code wrapped in a thin HTML wrapper. The GWT Compiler doesn’t simply output JavaScript (.js) files because certain browsers, under certain circumstances, do not properly handle compression of pure-JavaScript files. Wrapping the JavaScript in an HTML file solves the problem, and allows the GWT’s JavaScript output to be compressed.
Each .cache.html file uses the MD5 sum of its contents as its name. This guarantees deterministic behavior by the GWT Compiler. If you recompile your application without changing code, the output JavaScript code will not change, and so the MD5 sums (and the file names) will not change. If you do change your source code, the output JavaScript code will also change, and so the MD5 sums (and the file names) will change. Since these files will always have unique names, it is safe for browsers to cache them, hence the name “cache.html“.
.gwt.rpc File
As of GWT version 1.4, types that implement the java.io.Serializable interface now also qualify for serialization over RPC, but only if they are included in the .gwt.rpc file generated by the GWT compiler. The .gwt.rpc file serves as a serialization policy and indicates which types implementing java.io.Serializable are allowed to be serialized over the wire.
As of GWT version 1.4, you should typically see the following types of files:
•
•
•
.no-cache.js File
The “nocache.js” file is where Deferred Binding occurs. Before your GWT application can run, any dynamically-bound code must be resolved. This might include browser-specific versions of classes, Internationalization strings for the user’s selected language, etc. The “nocache.js” file includes a lookup table that maps Deferred Binding permutations to .cache.html filenames, e.g. “Firefox in German” and “Safari in English” would both be entries in the lookup table, pointing to different .cache.html files.
The file is named “.nocache.js” to indicate that it should never be cached, i.e. it must be re-downloaded and executed each time the browser starts your GWT application. The file must be re-downloaded each time is because the GWT Compiler regenerates it each time, but under the same file name. Allowing browsers to cache the file, would result in browsers not always downloading the latest version of the file when your application is recompiled and redeployed.
.cache.html Files
These are the files that actually contain your GWT application’s logic. A .cache.html file contains JavaScript code wrapped in a thin HTML wrapper. The GWT Compiler doesn’t simply output JavaScript (.js) files because certain browsers, under certain circumstances, do not properly handle compression of pure-JavaScript files. Wrapping the JavaScript in an HTML file solves the problem, and allows the GWT’s JavaScript output to be compressed.
Each .cache.html file uses the MD5 sum of its contents as its name. This guarantees deterministic behavior by the GWT Compiler. If you recompile your application without changing code, the output JavaScript code will not change, and so the MD5 sums (and the file names) will not change. If you do change your source code, the output JavaScript code will also change, and so the MD5 sums (and the file names) will change. Since these files will always have unique names, it is safe for browsers to cache them, hence the name “cache.html“.
.gwt.rpc File
As of GWT version 1.4, types that implement the java.io.Serializable interface now also qualify for serialization over RPC, but only if they are included in the .gwt.rpc file generated by the GWT compiler. The .gwt.rpc file serves as a serialization policy and indicates which types implementing java.io.Serializable are allowed to be serialized over the wire.
Subscribe to:
Comments (Atom)