Tutorial: Creating a Remote Service with GWT Designer

This tutorial demonstrates how to create a Remote service with GWT and GWT Designer. It takes the GWT Tutorial on RPC and adapt it for GWT Designer. Since this is a continuation of the Stock Watcher tutorial, you might want to read through that first or download the project here.

Prerequisites: 

Note: This tutorial was created using Eclipse 3.4, Java 1.6, GWT v1.5 and GWT Designer v5.1. 
Special thanks to Chad Lung for creating this tutorial.

First, have a look at the GWT Getting Started Tutorial on RPC.

In the Stock Watcher tutorial, we built the Stock Watcher web app. It worked fine but did ignore one major thing: The stock data is generated in the browser via JavaScript. In a real world web application we would pull our stock data from a server - whether it was from our own server or from some other server out in the cloud. We are going to modify the Stock Watcher app to use RPC (Remote Procedure Call) to update the stock information. The really cool thing is we can reuse the logic we wrote (well, actually the GWT Team wrote it first!) to randomly generate the stock prices since its all in Java and we can do so with very minor changes. We will host that logic in a Java Servlet which is a pretty standard place to do such a thing and is very common in the Java world.

To create the RPC service while following the GWT RPC Tutorial takes a few steps, using GWT Designer is much less work for us. If you haven't opened the StockWatcher project do so now. Once its open expand the project items out like the following:

Right-click on the com.google.gwt.sample.stockwatcher.client.StockWatcher.client package and choose: Google Web Toolkit -> GWT remote service. 

On the next windows that pop up we are going to use the name: StockPriceService.

Lets see what happened now. The GWT Designer basically did a lot of work for us. First, three files were created. 

  • StockPriceService.java
  • StockPriceServiceAsync.java
  • StockPriceServiceImpl.java

Also, in the StockWatcher.gwt.xml file you will see an entry for our servlet was added:

<servlet path="/StockPriceService" class="com.google.gwt.sample.stockwatcher.client.StockWatcher.server.StockPriceServiceImpl"/>

Lets move into the StockPriceService.java first. Open up that file in the source editor and have a look around. We need to add the following code (notice how the method signature is just like the function of the same name in the first tutorial - but that one is executed on the client, this one will be executed on the server):


StockPrice[] getPrices(String[] symbols);

So our code then looks like this:


package com.google.gwt.sample.stockwatcher.client.StockWatcher.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("StockPriceService")
public interface StockPriceService extends RemoteService
{
    StockPrice[] getPrices(String[] symbols);
   
    /**
     * Utility class for simplifying access to the instance of async service.
     */

    public static class Util
    {
        private static StockPriceServiceAsync instance;

        public static StockPriceServiceAsync getInstance()
        {
            if (instance == null)
            {
                instance = GWT.create(StockPriceService.class);
            }
            return instance;
        }
    }
}

Once you've done that hit the "Save" button in Eclipse. Now, a surprise happened behind our backs. Perhaps if you watched the RPC video I mentioned before you know what happened already. Give up? Well when we added that code to StockPriceService.java file and hit "Save" GWT Designer being smart went out and made some modifications to the following files:
1. StockPriceServiceImpl.java
2. StockPriceServiceAsync.java

But what happened? Take a look at those files. Notice anything? GWT Designer added that method we defined to those two files for us. Obviously this is something we could have done ourselves, but its certainly helpful that GWT Designer is smart enough to just do this by itself. In fact if we were to rename this method or change it's signature, GWT Designer will make the appropriate changes for us.

Lets fill in the implementation method for our service. You will notice that the logic in the original tutorial "refreshWatchList()" function is very similar to the logic we are now putting in the "getPrices()" function. Move into the StockPriceServiceImpl.java file and modify it to look like this:


package com.google.gwt.sample.stockwatcher.client.StockWatcher.server;

import com.google.gwt.sample.stockwatcher.client.StockWatcher.client.StockPrice;
import com.google.gwt.sample.stockwatcher.client.StockWatcher.client.StockPriceService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import java.util.Random;

public class StockPriceServiceImpl extends RemoteServiceServlet implements
        StockPriceService
{
    private static final double MAX_PRICE = 100.0;
    private static final double MAX_PRICE_CHANGE = 0.02;

    @Override
    public StockPrice[] getPrices(String[] symbols)
    {
        Random rnd = new Random();

        StockPrice[] prices = new StockPrice[symbols.length];
        for (int i = 0; i <symbols.length; i++)
        {
            double price = rnd.nextDouble() * MAX_PRICE;
            double change = price * MAX_PRICE_CHANGE
                    * (rnd.nextDouble() * 2f - 1f);

            prices[i] = new StockPrice(symbols[i], price, change);
        }

        return prices;
    }
}

So the logic is very similar to the "refreshWatchList()" function, but what about this:

import java.util.Random;

Since we are now running this code on the server vs. the client we make use of the java.util.Random library rather than the emulated GWT version in com.google.gwt.user.client.Random.

Now up until now we haven't talked about Asynchronous calls - which is what we are going to be doing. I'll point you to the GWT RPC Tutorial for a great explanation and say this: Asynchronous calls help with performance since they don't block the application waiting for a return call. You can also make multiple calls and do other things while awaiting for replies to your calls. In today's web applications asynchronous calls have become a standard practice for many developers.

We now need to open the StockPrice.java file and make some modifications. We need to make this class serializable so the data can go across the wire via RPC. We'll need to add an import in order to have the serialization support:

import com.google.gwt.user.client.rpc.IsSerializable;

We can now change the following code from this:

public class StockPrice

To this:

public class StockPrice implements IsSerializable

Ok believe it or not we are done with the server piece of this project. We are going to move on to the client code now. Open up the StockWatcher.java file and add this import:

import com.google.gwt.user.client.rpc.AsyncCallback;
Remove this import since it is going to be unused soon (remember we moved the logic that uses the random numbers stuff to the server):

import com.google.gwt.user.client.Random;

This next step you need to keep in mind that there are different ways to do this. I'm going to take an easy route for the sake of simplicity. Go into the "refreshWatchList()" function and remove the code in there and replace it with our call to the Asynchronous RPC call to our servlet:

protected void refreshWatchList()
    {
        StockPriceService.Util.getInstance().getPrices(stocks.toArray(new String[0]), new AsyncCallback<StockPrice[]>() {
            public void onSuccess(StockPrice[] result)
            {
                updateTable(result);
            }

            public void onFailure(Throwable caught)
            {
                // Error: Whoops!
            }
        });
    }

Assuming everything went well we can now run this and hopefully you will see something similar to this:

It sure looks like the same old web app we built in the first tutorial, but how do we really know its getting its "fake" data from the server via RPC? We can verify this by pressing the "Compile/Browse" button on the GWT Browser which will open up your default web browser, in my case it is Firefox 3 which has Firebug 1.2 installed.

Then I can open Firebug and drill into the browser traffic to see that indeed I'm talking to the server.

That concludes this tutorial. You can download the source file from here.

You can post your comments, questions, corrections in the GWT Designer forum.

Related topics: