I’ve released a service, named TwitSaw, that gives you the possibility to place a link to your Twitter profile on a picture hosted on TwitPic.

Its completly written with GWT and hosted on Googles App Engine. Right now it is still a beta. If you find a bug please send me a message.

wordle

Since GWT 1.6 has changed its file structure, GXT wont work by default anymore. You have to “trick” a bit. Just copy the image and the css directory, from the gxt.jar, to your war directory.

Support by default will be available again with GXT 2.0.

Because of the new file structure of GWT 1.6 the Cypal Eclipse plugin doesn’t work properly any more. Since you want at least a bit of comfort while developing, you have to use Googles Eclipse plugin. But that plugin is everything else than a stroke of genius…

If you want to create a new project, you get a complete GWT example project that demonstrates how to use GWT. This might be fine for the first look at GWT, but its annoying to clean that up every time you create a new project.

While Cypal had some functionality to create RPC services with just one click  – including interface, async-handler and the actual implementation – the Google plugin doesn’t offer any help at all. You have to write everything by your one, even the changes in web.xml.

We can only hope, that Google will add these functionalities soon, or Cypal will getcompatible to GWT 1.6.

Marc Englund has developed a GWT widget that allows you to receive user-input via gestures.

For more information about this cool stuff take a look at his blog.

Yesterday I’ve discovered GWTEventService. Today i started to play around with it, after some research in the example-svn and reading the docs, I was able to write my own “Hello World”.

This Hello World is a small chatting application. You are only able to send messages but not set a nickname or something similar.

Here you can see what it will look like:gwteventservice-helloworld1

In this short overview I’ll just show you the parts that are associated with the GWTEventSerice. The whole regular GWT UI/RPC stuff is left out. If you want to see the complete example, you can download it here.

First of all you need an Event:

public class MyEvent implements Event {
	public String message;

	public MyEvent(){}

	public MyEvent(String message) {
		this.setMessage(message);
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

}

This Event gets fired when the server gets a new message from a client.

The next thing you need is a EventListener that gets notified when an Event occures:

public class MyListener implements RemoteEventListener {

	/**
	 * This function gets called by EventService
	 */
	public void apply(Event anEvent) {
		/**
		 * Check if the incoming Event is from the type MyEvent and if so, call the corresponding function
		 */
		if(anEvent instanceof MyEvent)
			onMyEvent((MyEvent)anEvent);
	}

	/**
	 * This function gets called when the incomming Event is from the Type MyEvent
	 *
	 * @param event
	 */
	public void onMyEvent(MyEvent event){}

}

The Listener receives the Events from the server an processes them.

Now on the client-side you need to register your Listener to the server:


	/**
	 * The domain to which we want to register our listener to
	 */
	private static final Domain DOMAIN = DomainFactory.getDomain("my_domain");

	public void onModuleLoad() {

		/**
		 * Create an EventService
		 */
		RemoteEventServiceFactory theEventServiceFactory = RemoteEventServiceFactory.getInstance();
		RemoteEventService theEventService = theEventServiceFactory.getRemoteEventService();

		/**
		 * Register our listener to the domain
		 */
		theEventService.addListener(DOMAIN, new MyListener(){
			public void onMyEvent(MyEvent event){
				/**
				 * Get the message from the event and append it to the allready received messages
				 */
				getIncommingMessages().setText( getIncommingMessages().getText() + event.getMessage() + "n" );
			}
		});

                [.....]
	}

On the client-side we just register our Listener, and tell him what to do when an Event occurs.

The last thing that we need is the Server:

public class HelloWorldServiceImpl extends RemoteEventServiceServlet implements HelloWorldService {

	/**
	 * The Domain that this Service sends Events to.
	 */
	private static final Domain DOMAIN = DomainFactory.getDomain("my_domain");

	/**
	 * A normal function that gets called when a client sends a message to the server.
	 */
	public void sendMessage(String message) {
		/**
		 * We dont save the incomming messages on the server. We just send an MyEvent to all
		 * registered Listeners on the Domain.
		 */
		this.addEvent(DOMAIN, new MyEvent(message));
	}

}

Instead of the default RemoteServiceServlet we extend this one with RemoteEventServiceServlet from the GWTEventService lib. This gives you the ability to send Events to the clients.

Some nasty thing with GWT was, that if you wanted your client to get notified about changes on the server, you had to use polling. Like a Timer that makes  a RPC every 500ms. That isnt very handy or elegant not just because it causes a lot of traffic but also because its long-winded. More clever would be some kind of Events and the corresponding Listeners.

To get rid of that you can use GWTEventService.

GWTEventService is an event-based client-server communication framework. It uses GWT-RPC and the Comet / server-push technique. The client side offers a high-level API with opportunities to register listeners to the server like to a GUI component. Events can be added to a domain on the server side and the listeners on the client side get informed about the incoming events. The server side is completely independent of the client implementation and is highly configurable. Domains can be defined to decide which events are important for the different contexts.

Advantages

  • Encapsulation of the client-server communication
  • High-level API with listeners and events
  • Only one open connection for event listening
  • Reduction of server calls
  • Reduction of connection peaks
  • Events are returned directly when the event has occurred (instead of polling)
  • Events are bundled to reduce server calls
  • Based on the GWT-RPC mechanism
  • Automatic timeout recognition and handling
  • Extensible architecture

If you are you are using GXT and want to add a StoreListener to your ListStore that fires when a new element is added to the ListStore, you probably have encountered this “problem”. After some hours of research i found this thread in the EXT-JS board.

The Add event uses the “models” field (documented in javadocs for ListStore).

After some thinking I realized that this is not some kind of inconsistency, because you are able to add a whole List of elements to the Store.

If you want to create a simple application that needs to store some data in a database, the normal way to do this would be using a database like MySQL. Here you would send the data via RPC to your server and the server would connect to the database and store it. When you ask the server for some data, the server would again connect to the database, fetch the requested data and send it back to the client.

In my opinion this is some kind of overhead for just a simple application. So to avoid that you can use the Java Serialization. All you need to do here, is creating classes for the informations you want to store.

As an example we try to create a phone-book that is able to do:

  • Save entries with name and phone number
  • Organize entries in groups with names (e.g. Friends, Family, Work ..)

As you can see, the classes need to implement the interface Serializable to be store able. Now lets convert the diagram to code…

Phonebook:

public class Phonebook implements Serializable {
	public List groups = new ArrayList();
	public List entries = new ArrayList();

	public List getGroups() {
		return groups;
	}

	public List getEntries() {
		return entries;
	}
}

Entry:

public class Entry implements Serializable {
	public Entry() {}

	public String name;
	public String number;
	public List myGroups = new ArrayList();

	public Entry(String name, String number) {
		this.setName(name);
		this.setNumber(number);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public List getMyGroups() {
		return myGroups;
	}
}

Group:

public class Group implements Serializable {
	public Group(){}

	public String name;
	public List members = new ArrayList();

	public Group(String name) {
		this.setName(name);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List getMembers() {
		return members;}
	}

You may have noticed, that Entry and Group have an empty constructor, this is needed to fulfill GWTs guidelines for serialization.

Now we need a RPC-Service to communicate with our server. This RPC-Service needs a function to save, and a function to load data. We gonna call them “getPhonebook” and “savePhonebook”.

DataHandlerImpl:

public class DataHandlerImpl extends RemoteServiceServlet implements DataHandler {

	public void savePhonebook(String username, Phonebook book) {
		FileOutputStream fos;
		try {	/**
				 * Open a file for this user and write the serialated data to it.
	             */

				fos = new FileOutputStream(username + ".ser");
				ObjectOutputStream oos = new ObjectOutputStream( fos );

				oos.writeObject( book );
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

	}

	public Phonebook getPhonebook(String username) {

		Phonebook root = null;
		FileInputStream fis;

		try {	/**
				 * Take a look, if this user already has saved a Phonebook
				 * if so, transform it back.
				 */

				fis = new FileInputStream( username + ".ser");
				ObjectInputStream ois = new ObjectInputStream( fis );

				root = (Phonebook) ois.readObject();
			} catch (FileNotFoundException e) {
				/** * First time user logs in, so we have to create a new
				* Phonebook for him.
				*/

				root = new Phonebook();

			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}

			/**
			 * Return either his new Phonebook or his saved Phonebook.
			 */return root;}
	}

Now we can call this RPC-Serivce with something like handler.getPhonebook(“johndoe”, callback); and we would get our saved phonebook and can work with it.

Get saved Phonebook:

final DataHandlerAsync handler = DataHandler.Util.getInstance();

public void onModuleLoad() {

	AsyncCallback callback = new AsyncCallback() {

	public void onFailure(Throwable caught) {}

	public void onSuccess(Phonebook result) {createGUI(result);}

};

handler.getPhonebook("johndoe", callback);}

We ask the server for our Phonebook and send it over to the GUI to do something with it. When we want to save our changes, we just send our Phonebook back to the server.

Save Phonebook:

AsyncCallback callback = new AsyncCallback() {

	public void onFailure(Throwable caught) {
		/**
		 * Oh Oh something is wrong here...
         */
	}

	public void onSuccess(Object result) {
		/**
		 * Yep everything is just fine...
		 */
	}
};

handler.savePhonebook("johndoe", book, callback);

Thats all. Now you have everything you need to load/save data. Now you just need to build a nice little GUI for your application. Maybe something like this:

To save some resources I’ve switched to FluxBox with Rox-Filer…