A chat room example
On this page we will explain how to create an application using SON with a GWT interface. We are using Eclipse Helios (3.6), SON 1.6.2 and GWT 2.2.0.
The SON Component
Let's first create a simple component capable of sending a message and receiving a message.
We define a component named chat, which is able of sending a receiving a string.
CDML File
Below is the CDML of the chat component.
<component name="chat" type="component" extends="abstractContainer" ns="chat"> <containerclass name="ChatContainer"/> <facadeclass name="ChatFacade" userclassname="Chat"/> <input name="message" method="receiveMessage"> <attribute name="content" javatype="java.lang.String"/> </input> <output name="message" method="sendMessage"> <attribute name="content" javatype="java.lang.String"/> </output> </component>
Different chat components can communicate with messages, as they can send (output of the component) and receive (input) them. We aim to build the web interface for one component. A user will be able to send a message to all chat components connected to him, and messages sent from other users will be displayed on his screen.
To do that, we define listeners and events on the receive and send methods of the component, in an Observer/Observable way.
Listening to component's changes
The event contains the source and the destination of the message, and the content of this message. It also contains the type, which defines if the event was triggered when the message is sent or is received.
package chat.event; public class ChatCommunicationEvent { public enum Type { RECEIVED, SENT } private String expeditor; private String destination; private String message; private Type type; public ChatCommunicationEvent(Type type, String expeditor, String destination, String message) { this.type = type; this.expeditor = expeditor; this.destination = destination; this.message = message; } public String getDestination() { return destination; } public String getExpeditor() { return expeditor; } public String getMessage() { return message; } public Type getType() { return type; } }
A listener on these events is defined with two methods which can be triggered depending on the type of the event.
package chat.event; import java.util.EventListener; public interface ChatCommunicationListener extends EventListener { public void messageReceived(ChatCommunicationEvent event); public void messageSent(ChatCommunicationEvent event); }
Finally, in the main component's class Chat, we define when the listeners will be notified about events.
It is possible to add and remove listeners from the component.
package chat; import javax.swing.event.EventListenerList; import chat.event.ChatCommunicationEvent; import chat.event.ChatCommunicationListener; public abstract class Chat { private EventListenerList listeners = new EventListenerList(); public void addCommunicationListener( ChatCommunicationListener listener) { listeners.add(ChatCommunicationListener.class, listener); } public void removeCommunicationListener( ChatCommunicationListener listener) { listeners.remove(ChatCommunicationListener.class, listener); } ... }
Each time the Chat component receives or sends a message, it will notify the listeners by firing the event. Thanks to the CDML file of the component, there is one method that will be invoked when receiving a message, and 2 for sending one. In the receiveMessage method, we simply fire the event:
public void receiveMessage(String expeditor, java.lang.String content) { fireCommunicationReceived(new ChatCommunicationEvent( ChatCommunicationEvent.Type.RECEIVED, expeditor, getIdName(), content)); System.out.println(expeditor + " send a message: " + content); }
The sendMessage methods are abstract because they will be generated in the Facade by the Smarttools generator. We will add methods which will explicitly fire events and call the send methods, and use them instead of the usual sending methods. We also mark the sendMessage methods as deprecated to remember no to call them directly.
public void sendMessageAndNotify(String content) { fireCommunicationSent(new ChatCommunicationEvent( ChatCommunicationEvent.Type.SENT, getIdName(), null, content)); sendMessage(content); } /** * @deprecated Use sendMessageAndNotify instead to notify the listeners. */ public abstract void sendMessage(String content); public void sendMessageAndNotify(String destination, String content) { fireCommunicationSent(new ChatCommunicationEvent( ChatCommunicationEvent.Type.SENT, getIdName(), destination, content)); sendMessage(destination, content); } /** * @deprecated Use sendMessageAndNotify instead to notify the listeners. */ public abstract void sendMessage(String destination, String content);