CometD 2 Oort Seti
CometD 2 Oort Seti
Seti is the Oort clustering component that tracks clients connected to any comet in the cloud, and allows an application to send messages to particular client(s) in the cloud transparently, as if they were in the local comet.
Configuration
An org.cometd.oort.Seti instance must be configured with an associated org.cometd.oort.Oort instance, either via code, or by configuring an org.cometd.oort.SetiServlet in web.xml, for example:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>cometd</servlet-name>
<servlet-class>org.cometd.server.CometdServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cometd</servlet-name>
<url-pattern>/cometd/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>oort</servlet-name>
<servlet-class>org.cometd.oort.OortServlet</servlet-class>
<load-on-startup>2</load-on-startup>
<init-param>
<param-name>oort.url</param-name>
<param-value>http://host:port/context/cometd</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>seti</servlet-name>
<servlet-class>org.cometd.oort.SetiServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
</web-app>
Note how the load-on-startup parameter of the SetiServlet must be greater than that of the OortServlet.
SetiServlet does not have any configuration init parameter.
Associating Users
Seti allows to associate a unique string representation of a user with one or more ServerSession (see the CometD concepts for more details on ServerSession).
This is normally done when the user first logs in into the application, and the unique string representation of the user can be anything that the user provides to authenticate itself (a user name, a token, a database id, etc). For brevity, we will call this unique string representation of the user simply userId.
Note that the same userId may login multiple times (for example from a desktop computer and from a mobile device), so it will be associated to multiple ServerSessions.
In practice, the best way of associating a userId with a ServerSession is in a SecurityPolicy during authentication, for example:
public class MySecurityPolicy extends DefaultSecurityPolicy
{
private final Seti seti;
public MySecurityPolicy(Seti seti)
{
this.seti = seti;
}
@Override
public boolean canHandshake(BayeuxServer server, ServerSession session, ServerMessage message)
{
if (session.isLocalSession())
return true;
// Authenticate
String userId = performAuthentication(session, message);
if (userId == null)
return false;
// Associate
seti.associate(userId, session);
return true;
}
}
Alternatively, you can perform the association in an BayeuxServer.Extension or in a CometD service, in response to a specific message that it is always sent by the client after a successful handshake.
When Seti associates a userId with a session, it broadcasts an internal message on the cloud (on channel /seti/all) that tells to all the other comets where this userId is.
In this way, all the comets in the cloud know where a particular userId resides.
The same userId may be associated in different comets (for example, the desktop computer logs in - and therefore is associated - in comet1, while the mobile device is associated in comet2).
Similarly, you can disassociate a userId at any time by calling Seti.disassociate(userId, session).
If the user disconnects or "disappears" (for example, it crashed or its network dropped), its session will be removed or expired by the server and Seti will automatically disassociate the userId.
Sending Messages
After users have been associated, sending a message to a particular user in the cloud can be done via Seti.sendMessage(String userId, String channel, Object data).
@Service("seti_forwarder");
public class SetiForwarder
{
private final Seti seti;
private SetiService(Seti seti)
{
this.seti = seti;
}
@Listener("/service/forward")
public void forward(ServerSession session, ServerMessage message)
{
Map data = message.getDataAsMap();
String targetUserId = (String)data.get("targetUserId");
seti.sendMessage(targetUserId, message.getChannel(), data);
}
}
In the example below, clientA wants to send a message to clientC but not to clientB.
Therefore clientA sends a message to the server it is connected to using a service channel (so that the message is not broadcasted), and then a specialized CometD service will route the message to the appropriate user using Seti (see above). The Seti on cometA knows that the target user is on cometC (thanks to the association) and forwards the message to cometC which will in turn deliver the message to clientC.

- Printer-friendly version
- Login to post comments