Category: GWT


Just a short post to say that I recently had this problem – I needed to get my event web service pushing messages to my GWT server side code. But how to expose the GWT server side code like a web service? The solution I found was using the GwtRpcCommLayer library. Using this library you can expose your GWT server side methods to any Java application (Swing or command line) or in my case a Java web service. It’s very straightforward to use and there is an example Eclipse project which you can easily get up and running. For my purposes I then used the gwt-comet library to push the event messages from the GWT server side code (without polling) to my GWT client side code/browser for presentation. Very cool!

If you took a look at my previous post GWT and NetBeans you should know how to set up the bare minimum for a GWT project in NetBeans. In this post, we are going to see how to consume a free online web service LyricsWikia from our GWT project. The SOAP based LyricsWikia web service allows you to search their database to return song lyrics for a given song title, album or music artist.

You can use another web service of your choice instead of LyricsWikia if you prefer, just do some googling for free web services. Some examples are Amazon (AWS), weather services, YouTube, post-code/location finders etc.

Normally when I consume web services in NetBeans, I go for JAX-WS style because it is the successor to JAX-RPC. Unfortunately in this case the WSDL we are going to use is old and is an RPC style one. So to accomodate this you need to do the following:

Open NetBeans (I’m using 6.8) and select Tools –> Plugins then navigate to the Available Plugins tab. Check JAX-RPC Web Services and install. We’ll get back to the web service later, for now we need to set up the project. If you haven’t done so already, you need to create a GWT project in NetBeans, see this post GWT and NetBeans for how to set up a basic project. The first thing we are going to do to extend this project is create a GWT RPC Service. Using this architecture the GWT client side code will call the GWT server side code using asynchronous RPC calls. The GWT server side code will act as a web service client and consume the web service, then it will return the results to our GWT client side code for presentation in the browser.

In your NetBeans project go to New –> GWT RPC Service… and make the service name something really original like GwtRpcService. Make sure the Create Usage Example Class checkbox is checked, this will make our life easier. Next, have a look at the generated classes. In the com.client package you should now have GWTRPCService.java, GWTRPCServiceAsync.java and GWTRPCServiceUsageExample.java. In the com.server package you should now have GWTRPCServiceImpl.java. An RPC service method has been created for us myMethod(String s) we will modify this method to something more suitable for our requirements.

Open GWTRPCService.java and replace:

public String myMethod(String s);
with:
public String getLyrics(String artist, String song);

Open GWTRPCServiceAsync.java and replace:

public void myMethod(String s, AsyncCallback<String> callback);

with:

public void getLyrics(String artist, String song, AsyncCallback<String> callback);

Open GWTRPCServiceImpl.java and replace:

public String myMethod(String s) {
    // Do something interesting with 's' here on the server.
    return "Server says: " + s;
}

with:

public String getLyrics(String artist, String song)
{
    return null;
}

I’m not going to go into great detail about what we just did because you can google that yourself, basically we have an RPC service method getLyrics(…) and we will be calling this method asynchronously. In the implementation class we don’t just want to return null, we want to call a suitable LyricsWikia web service operation and return the result.

OK next problem. The LyricsWikia WSDL will not work out of the box for us Java heads. You might think, oh great example. But this is reality. In my experience this happens a lot and small changes need to be made to get things working in your preferred IDE – or more specifically whatever you are using to generate client stubs. To overcome this, we need to download the WSDL to our local machine and make a couple of changes then use this local version to generate our client stubs instead of the URL for the deployed WSDL.

Get the LyricsWikia WSDL here. If you are are using Safari like me and you browse to this you might think this doesn’t look like a WSDL. It must be the way Safari renders WSDL files or something but I had to go View –> View Source then Select AllCopy and Paste the selection into a text editor and Save it. I saved the file as LyricsWikia.wsdl.

Open LyricsWikia.wsdl and replace:

<xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="AlbumResult[]"/>

with:

<xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="tns:AlbumResult[]"/>

Replace:

<xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="AlbumData[]"/>

with:

<xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="tns:AlbumData[]"/>

Save the file.

In the NetBeans project go to New –> Web Service Client… Select Local File and browse to the local copy of the WSDL that we just edited. Specify a Package name, I will use com.lyricsWikia. For this particular web service, the client style must be JAX-RPC Style. Select Finish.

In NetBeans 6.8, if I try and build the project at this point, I will see the following error message:

../nbproject/build-impl.xml:422: taskdef class com.sun.xml.rpc.tools.ant.Wscompile cannot be found
BUILD FAILED (total time: 0 seconds)

Well that is not cool. To fix it, in the NetBeans Files view locate your projects root folder –> nbproject folder –> project.properties and right click Edit.

Replace:

wscompile.classpath=${wscompile.tools.classpath}:${j2ee.platform.wscompile.classpath}

with:

wscompile.classpath=${wscompile.tools.classpath}:${j2ee.platform.wscompile.classpath}:${javac.classpath}

If you open GWTRPCServiceUsageExample.java and comment out the following line of code you should now be able to build the project successfully:

getService().myMethod(txtUserInput.getText(), callback);

It’s now time to implement our getLyrics(…) method now that we have generated our web service client stubs (they should be visible under Generated Sources (jax-rpc)).

Open GWTRPCServiceImpl.java and replace:

public String getLyrics(String artist, String song)
{
      return null;
}

with:

public String getLyrics(String artist, String song)
{
      LyricWiki service = new LyricWiki_Impl();
      LyricWikiPortType port = null;
      String lyrics = "";
      try
      {
            port = service.getLyricWikiPort();
            ((Stub)port)._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, "http://lyrics.wikia.com/server.php");
      }
      catch(ServiceException ex)
      {
            ex.printStackTrace();
      }
      boolean exists = false;
      try
      {
            exists = port.checkSongExists(artist, song);
            if(exists)
            {
                  LyricsResult result = port.getSong(artist, song);
                  lyrics = result.getLyrics();
            }
            else
            {
                  lyrics = "Sorry, no lyrics available";
            }
      }
      catch(RemoteException ex)
      {
            ex.printStackTrace();
      }
      return lyrics;
}

You will also need to add the following import statements to the top of the class:

import com.lyricsWikia.LyricWiki;
import com.lyricsWikia.LyricWikiPortType;
import com.lyricsWikia.LyricWiki_Impl;
import com.lyricsWikia.LyricsResult;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;

We are nearly done. Now, we just need to modify our GWT client side code to call our RPC service method. We will create a very simple form that allows the user to pass in a music artist and a song title as a parameter and press a button to retrieve the lyrics.

Modify GWTRPCServiceUsageExample.java so it looks like this:

package com.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.TextArea;

/**
 * Example class using the GWTRPCService service.
 *
 * @author nes
 */
public class GWTRPCServiceUsageExample extends VerticalPanel {

    private TextArea txtAreaServerReply = new TextArea();
    private TextBox txtArtistInput = new TextBox();
    private TextBox txtSongInput = new TextBox();
    private Button btnSend = new Button("Get Lyrics!");

    public GWTRPCServiceUsageExample() {
        add(new Label("Music Artist: "));
        add(txtArtistInput);
        add(new Label("Song: "));
        add(txtSongInput);
        add(btnSend);
        txtAreaServerReply.setSize("500px", "500px");
        add(txtAreaServerReply);
        // Create an asynchronous callback to handle the result.
        final AsyncCallback<String> callback = new AsyncCallback<String>() {
            public void onSuccess(String result) {
                txtAreaServerReply.setText(result);
            }
            public void onFailure(Throwable caught) {
                txtAreaServerReply.setText("Communication failed");
            }
        };
        // Listen for the button clicks
        btnSend.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event) {
                // Make remote call. Control flow will continue immediately and later
                // 'callback' will be invoked when the RPC completes.
                getService().getLyrics(txtArtistInput.getText(), txtSongInput.getText(), callback);
            }
        });
    }

    public static GWTRPCServiceAsync getService() {
        // Create the client proxy. Note that although you are creating the
        // service interface proper, you cast the result to the asynchronous
        // version of the interface. The cast is always safe because the
        // generated proxy implements the asynchronous interface automatically.
        return GWT.create(GWTRPCService.class);
    }

}

Modify codenesEntryPoint.java (or your entry point class) so it looks like this:

package com.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Main entry point.
 *
 * @author nes
 */
public class testEntryPoint implements EntryPoint {

    /**
     * Creates a new instance of testEntryPoint
     */
    public testEntryPoint() {
    }

    /**
     * The entry point method, called automatically by loading a module
     * that declares an implementing class as an entry-point
     */
    public void onModuleLoad() {
        RootPanel.get().add(new GWTRPCServiceUsageExample());
    }

}

Now Build, Deploy and Run the project. If you are having any problems check your Glassfish server log for errors or debug the project in NetBeans. To debug the project in NetBeans, GWT Development Mode needs a browser plugin. You can also use Firebug (Mozilla plugin) to debug inside your browser.

Run the Project

Run the Project

Note. The LyricsWikia web service will only return a small portion of the song lyrics if they are available. This is due to licensing restrictions/fair use policy.

GWT and NetBeans

In this post we will set up Netbeans to support a GWT Project using the gwt4nb plugin. Note that there is also the Google plugin for Eclipse.

First off, download and install the gwt4nb plugin.

In Netbeans, create a new Java Web –> Web Application. Name your application and hit Next until you get to the Frameworks tab. If you have successfully installed the gwt4nb plugin you should see Google Web Toolkit listed. Select the Google Web Toolkit framework. Then, if you haven’t already, download the GWT SDK. Next, browse to the GWT SDK installation folder. Name your GWT module and hit Finish.

The plug-in will create a gwt.xml file which references the GWT entry point implementation class.

For example, if I used the module name com.codenes then I would see the file codenes.gwt.xml created in the com package under Source Packages. The entry point implementation class reference would read as:

<entry-point class=”com.client.codenesEntryPoint”/>

We can locate the entry point implementation class within the newly created com.client package. Inspecting this class, we can see the entry point method onModuleLoad() which is where we will be adding our own code later. Inside the method we can see a button and a label are being created and added to the RootPanel.

Run the project, your browser should launch and the button “Click me!” and the text “Hello, GWT!!!” should be visible.

:)

I’m currently porting an AJAX style web application written entirely in Javascript, to a Google Web Toolkit (GWT) web application written in Java.  I’m doing this because I am no Javascript guru and I wanted to further extend the original project so it was either now or never to make the more comfortable switch to Java. The other reason is the web application needs to work with a lot of complex XML as it interacts with SOAP web services. To this point, I haven’t found a Javascript equivalent of XMLBeans which does a fine job of binding XML schemas to Java objects.

The original Javascript web application used the following libraries:

  • Ext JS – Javascript framework for UI/widgets (licensed)
  • OpenLayers – Javascript library for displaying dynamic maps (open source)
  • Apache CXFWSDL2JS tool for generating Javascript web service client stubs (open source)

The GWT equivalent libraries that I am using for the ported project are:

  • Ext GWT – Java framework for UI/widgets (licensed)
  • GWT-OpenLayers – GWT wrapper for OpenLayers (open source)
  • Metro/JAX-WS – Wsimport tool for generating Java web service client stubs (open source)

The development environment for the original Javascript project was Netbeans (6.5) for coding, AppServ (Apache web server) for deployment and the Firefox Firebug plugin for debugging.

The ported Java project is being developed entirely in Netbeans (6.7.1), using the bundled Glassfish application server and GWT Hosted Mode within the IDE for debugging.

From an architecture point of view, the GWT project is going to be a little different from the original Javascript application. The Javascript application made client side AJAX/XMLHttpRequest calls to a variety of web services.

Note. To support Javascript cross-site scripting you can configure Apache web server using the mod_rewrite/proxy method detailed in this post http://premshree.livejournal.com/66129.html

The GWT project on the other hand, will utilise GWT’s Remote Procedure Call (RPC) mechanism to decouple GWT client-side and server-side code. The client-side code will be the presentation layer (UI) and will make RPC calls to the server-side code which will consume a variety of web services, returning the response back to the client-side for presentation.