GWT Basics - AthanasiosPavlou/sandbox-modules Wiki
This report describes the contents of the sample GWT web application created by the GWT command line tool or the Eclipse plugin. The description goes beyond a simple listing of the project’s contents, attempting to provide enough detail for a more complete understanding of the project structure, its contents and their interaction. The report is in essence a restructuring of information already available online (please see references)
The only requirement to follow this report is to create a GWT project using Eclipse (if you have the GWT plugin installed) or the GWT command line tool by executing: webAppCreator -out MyWebApp com.mycompany.mywebapp.MyWebApp
After the successful creation of the sample project MyWebApp a number of folders, packages and files will be generated. These are described below:
File MyWebApp.launch: If you are using Eclipse, you can launch the app in development mode, by running the .launch configuration file created by webAppCreator using the Run or Debug menus.
As of GWT 2.0, development mode uses a regular browser instead of an embedded browser. You can use any supported browser, including ones on other machines, as long as it has the GWT Developer Plugin installed. If you use a browser that does not have the plugin installed, you will get a message with an offer to download the plugin. Browsers are typically opened automatically via the -startupUrl command line option (though GWT will try to find plausible startup URLs if you do not supply any).
File build.xml: To launch a development mode session, from the command line run ant devmode, assuming you have an Ant build.xml file generated by webAppCreator. Let's look behind the scenes when you launch your GWT application in development mode. To run development mode, you start a Java VM using the main class com.google.com.gwt.dev.DevMode. If you look inside a generated ant build.xml, you'll find something like this:
<target name="devmode" depends="javac" description="Run development mode">
<java failonerror="true" fork="true" classname="com.google.gwt.dev.DevMode">
This is similar to running the following command on the command line:
java -Xmx256M -cp "src;war/WEB-INF/classes;\gwt-2.0.0\gwt-user.jar;\gwt-2.0.0\gwt-dev.jar" com.google.gwt.dev.DevMode -startupUrl Hello.html com.google.gwt.sample.hello.Hello
The -startupUrl parameter tells Development Mode which URL(s) to make available for launching. If the value excludes the domain, the domain is assumed to be localhost. The port is assumed to be the port running the embedded server. In the example above, this address is http://localhost:8888/Hello.html (with an additional parameter giving the location of the development mode code server).
Folder war: By default, development mode runs an internal Jetty instance to serve your web application. This embedded Jetty instance serves directly out of your project's war directory. You can disable this internal server by passing the -noserver option to development mode and instead run your own external server.
- MyWebApp.gwt.xml:This is the project configuration file. It describes the project’s inheritances (i.e. what GWT ibraries are used, what is the app’s enty point, what are the source packages to be used.)
Packages com.mycompany.mywebapp.client and com.mycompany.mywebapp.server
These contain the service descriptors as well as the app’s main entry class (MyWebApp.java). The default example is using GWT-RPC for client-server communication. The GWT-RPC mechanism lets you send Java objects between the client and server with little work on both the client and server sides.
There are three parts to the GWT-RPC mechanism. The first is the service that runs on the server as a servlet, the second is the web browser that acts as a client and calls the service, and last are the data objects that pass between the client and server.
In brief the steps are the following:
You first define the service interfaces that will be implemented by the server (GreetingServiceAsync, GreetingService). The interfaces define the methods for executing the services required. But why do we need two interfaces?
GreetingService: This defines your service, you need to create a Java interface and extend the GWT RemoteService interface. There are some additional fairly subtle requirements when defining this interface: i) The interface must extend com.google.gwt.user.client.rpc.RemoteService. ii) All method parameters and return values must be serializable (this includes all primitive Java types, certain objects that are part of the standard Java library, and classes that implement the IsSerializable interface), iii) The interface must live in the client package. With the service interface defined for your service, you need to implement its methods. You do this by creating a servlet that extends GWT’s RemoteServiceServlet and implements the service interface (creation of GreetingServiceImpl that we will describe later on). When the service is called, the underlying RemoteServiceServlet parses the request, converting the serialized data back into Java objects, and calls the service method. When the method returns a value, it is returned to the RemoteServiceServlet that called the method, and it in turn serializes the result and returns it to the client browser.
GreetingServiceAsync: When you call the remote service from the client, GWT does most of the work for you; however, you need to create one last interface. The GWT compiler uses this interface when it generates the service proxy object. A proxy object is an object instance that forwards the request to another target. In this case, you’ll call a local method, and the proxy object is responsible for serializing the parameters, calling the remote service, and handling the deserialization of the return value. You don’t write the code for the proxy class; the GWT compiler handles this for you. In the client-side code, you create the proxy object by writing the following: GWT.create (ServerStatusService.class) Here you call the static method create() of the com.google.gwt.core.client.GWT class, passing it the class object of the remote service interface. This returns a proxy object that you can use to set the service URL and call the remote methods. The proxy object returned (GreetingService_Proxy) implements two interfaces: one that you need to create (GreetingServiceAsync), and one supplied by GWT (ServiceDefTarget). The proxy class is created at compile time, so you can’t reference this class directly in your code. Instead, you need to cast it to each interface separately to be able to call its methods. Of the two interfaces, ServiceDefTarget is part of the GWT library and includes a method setServiceEntryPoint() for specifying the URL of the remote service. The other interface, GreetingServiceAsync, provides asynchronous methods for calling the remote service. You’ll need to write this second asynchronous service interface yourself:
This asynchronous service interface always has the same name as your service, with the name “Async” appended to it. The methods in the interface must match all the method names in your original service interface, but the signatures need to be changed. Specifically, for each method in the original interface, you must do the following: i) Set the return value to void., ii) Add an extra com. google. gwt. user. client. rpc. AsyncCallback parameter.
This interface is used only by the client code and not the server. Because of this, you don’t need to include this interface in any code deployed to the server, and you must place the interface in the client package.
Then you set up the project to use the service by editing the web application deployment descriptor (/war/WEB-INF/web.xml). Starting with GWT 1.6, servlets should be defined in the web application deployment descriptor (web.xml) instead of the GWT module (MyWebApp.gwt.xml). To set this up, add and elements to the web application deployment descriptor (web.xml) and point to the implementation class (GreetingServiceImpl). In the element, the url-pattern can be in the form of an absolute directory path (for example, /spellcheck or /common/login). If you specify a default service path with a @RemoteService RelativePath annotation on the service interface (as you did with GreetingService), then make sure the url-pattern matches the annotation value. Because you've mapped the GreetingService to "greet" and the module rename-to attribute in MyWebApp.gwt.xml is "mywebapp", the full URL will be: http://localhost:8888/mywebapp/greet
Next comes the implementation of the server (GreetingServiceImpl). This implements the interface you defined for your service and extends the RemoteServiceServlet. The RemoteServiceServlet is where all the magic happens. This servlet receives the data from the server, which we already mentioned must be text due to the way the underlying XMLHttpRequest object works, and deserializes the text data into Java objects. The Java objects are then passed to the implemented methods for processing. On the return trip, the RemoteServiceServlet serializes the return value into text, which can then be sent back to the browser.
Finally on the client-side (MyWebApp) to call the services you include an additional AsyncCallback handler. This handles the result that is passed back from the server (explained in GreetingServiceAsync).
e-book GWT in Action