Server Side Comet Publish Application Tutorial
This tutorial demonstrates the simplicity in publishing events from the Server.
To demonstrate the ease of using Comet (AJAX push, reverse AJAX) functionality on the Server within a OfficeFloor web application the following simple chat application will be used for this tutorial.

The application will:
The application in this tutorial is deliberately simple to allow focus on the Comet functionality.
The below is the content of the Template.html.
<html> <body> <p>Chat:</p> <center><big> <p id="chat"></p> </big></center> </body> </html>
The template logic object is as follows.
public class TemplateLogic {
public void login(@Parameter String userName, User user,
AsyncCallback<Void> callback) {
user.setName(userName);
callback.onSuccess(null);
}
public void message(@Parameter CometEvent event, User user,
ConversationSubscription publisher, AsyncCallback<Long> callback) {
ConversationMessage message = (ConversationMessage) event.getData();
publisher.message(new ConversationMessage(user.getName(), message
.getText()));
callback.onSuccess(Long.valueOf(1));
}
}
The above provides two methods, that respectively:
The following demonstrates the configuration necessary to add the template.

For manually handling the published event the method name is specified. This allows the Server code to intercept all published events from the clients and manually handle them. In the case of this tutorial, adding the user name to the message before publishing the event. The parameter to this specified method is always a CometEvent. It also follows the GWT RPC handling pattern and therefore must notify that successfully serviced the GWT RPC request via the AsyncCallback.
The typical reason for manually handling the published events is to push them onto a queue for a cluster of web servers. This enables multiple web servers to be notified of the published event and subsequently publish the event to all the Comet clients. This is necessary as the Comet client establishes a connection to only one web server in the cluster.
The Comet event is published by the server via the following interface.
@CometPublisherInterface
public interface ConversationSubscription extends CometSubscriber {
void message(ConversationMessage message);
}
The annotation informs WoOF to dependency inject an implementation of the interface that will allow the server code to publish the CometEvent.
An interface with this annotation must adhere to the same rules of a CometSubscriber (e.g. single method with a single parameter).
OfficeFloor will publish the event with the following details:
The reason for using the interface is to allow type safe publishing of events.
The following POJO is the event data sent.
public class ConversationMessage implements IsSerializable {
private String name;
private String text;
public ConversationMessage(String name, String text) {
this.name = name;
this.text = text;
}
public ConversationMessage(String text) {
this(null, text);
}
public ConversationMessage() {
}
public String getName() {
return this.name;
}
public String getText() {
return this.text;
}
}
The user name is stored in the HTTP session with the following object.
@HttpSessionStateful
public class User implements Serializable {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
The following GWT RPC interfaces are used to send the user name to the server.
@RemoteServiceRelativePath("username")
public interface UserNameService extends RemoteService {
void login(String userName);
}
public interface UserNameServiceAsync {
void login(String userName, AsyncCallback<Void> callback);
}
The GWT client side code is included as follows for completeness of this tutorial.
public class CometManualAppEntryPoint implements EntryPoint {
/**
* {@link UserNameService}.
*/
private final UserNameServiceAsync userNameService = GWT
.create(UserNameService.class);
@Override
public void onModuleLoad() {
// Vertically align contents
RootPanel panel = RootPanel.get("chat");
VerticalPanel chatPanel = new VerticalPanel();
panel.add(chatPanel);
// Provide dialog box for user name
final DialogBox dialogBox = new DialogBox();
dialogBox.setModal(true);
HorizontalPanel userNamePanel = new HorizontalPanel();
dialogBox.add(userNamePanel);
userNamePanel.add(new Label("Enter user name: "));
final TextBox userNameTextBox = new TextBox();
userNamePanel.add(userNameTextBox);
Button userNameSubmit = new Button("submit");
userNamePanel.add(userNameSubmit);
dialogBox.show();
dialogBox.center();
userNameSubmit.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
CometManualAppEntryPoint.this.userNameService.login(
userNameTextBox.getText(), new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
dialogBox.hide();
}
@Override
public void onFailure(Throwable caught) {
Window.alert("Failed to specify user name");
}
});
}
});
// Provide the text area to contain conversation
final TextArea conversation = new TextArea();
conversation.setReadOnly(true);
conversation.setSize("100%", "300px");
chatPanel.add(conversation);
// Handle listening for messages
OfficeFloorComet.subscribe(ConversationSubscription.class,
new ConversationSubscription() {
@Override
public void message(ConversationMessage message) {
conversation.setText(conversation.getText() + "\n"
+ message.getName() + ": " + message.getText());
}
}, null);
// Provide means to add message
HorizontalPanel messagePanel = new HorizontalPanel();
chatPanel.add(messagePanel);
final TextBox message = new TextBox();
message.setWidth("80%");
messagePanel.add(message);
Button send = new Button("send");
messagePanel.add(send);
// Handle submitting a message
final ConversationSubscription publisher = OfficeFloorComet
.createPublisher(ConversationSubscription.class);
send.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
String messageText = message.getText();
publisher.message(new ConversationMessage(messageText));
}
});
}
}
See the other tutorials for further functionality.