Hi
assuming you asked for an example based on JMX (i.e. option 2), we show you a code snippet that, added to the Metadata Adapter code, listens to the notifications for session initiation and termination and causes each session to be closed after it has lived longer than five minutes.
There are several ways to access Lightstreamer MBeans server from the Metadata Adapter.
We use the simplest one, which takes advantage of the fact that Lightstreamer Server loads all the Adapters in its main ClassLoader;
so we access the MBeans server via static references, through the MBeanServerFactory.findMBeanServer method.
[SYNTAX="JAVA"]
private final Set currSessions = new HashSet();
private final Timer timer = new Timer();
private final long expiryTime = 5 * 60 * 1000;
private final MBeanServer server;
{
ObjectName serverMBeanName = null;
try {
serverMBeanName = new ObjectName("com.lightstreamer", "type", "Server");
// this MBean is always defined by Lightstreamer MBean server;
// we use it as a mean to identify Lightstreamer MBean server
} catch (MalformedObjectNameException e1) {
// TODO
}
if (serverMBeanName != null) {
ArrayList servers = MBeanServerFactory.findMBeanServer(null);
MBeanServer found = null;
for (int i = 0; i < servers.size(); i++) {
found = (MBeanServer) servers.get(i);
if (found.isRegistered(serverMBeanName)) {
break;
} else {
found = null;
}
}
if (found == null) {
// TODO
}
server = found;
} else {
server = null;
}
}
public void notifyNewSession(String user, final String session) throws CreditsException, NotificationException {
synchronized (currSessions) {
currSessions.add(session);
}
timer.schedule(new TimerTask() {
public void run() {
synchronized (currSessions) {
if (! currSessions.contains(session)) {
return;
}
}
killSession(session);
// this also causes notifySessionClose to be called
}
}, expiryTime);
}
public void notifySessionClose(String session) throws NotificationException {
synchronized (currSessions) {
currSessions.remove(session);
}
}
private void killSession(String session) {
if (server == null) {
// TODO
return;
}
ObjectName sessionMBeanName = null;
Hashtable props = new Hashtable();
props.put("type", "Session");
props.put("sessionId", session);
try {
sessionMBeanName = new ObjectName("com.lightstreamer", props);
} catch (MalformedObjectNameException e1) {
// TODO
return;
}
Object ret;
try {
ret = server.invoke(sessionMBeanName, "destroySession", null, null);
} catch (InstanceNotFoundException e) {
// it is still possible that the session has just ended
return;
} catch (MBeanException e) {
// TODO
return;
} catch (ReflectionException e) {
// TODO
return;
}
if (((Boolean) ret).booleanValue() == false) {
// it is still possible that the session has just ended
return;
}
}
[/SYNTAX]
Old note (until Web Client Library version 4.2.1)
Note that this closure strategy is entirely server-side and the client receives no notice of the closure reason.
The client only sees an unexpected closure.
This means that, if the client is a web page based on the Web Client Library, the client will enter stalled state and, eventually, an attempt to create a new session will be performed.
In this sense, option 3 may be preferrable to both 1 and 2.
New note (since Web Client Library version 4.2.2)
Note that, in case a session is forcibly closed by the Server, the Web Client Library enters in "DISCONNECTED" state and does not try to recover the session; it just notifies application code through the "onServerError" event handler, with proper error codes.
About getting extended information on the sessions by taking advantage of the JMX interface:
Old note (for LS Server up to and including 3.6)
It has to be considered that many of the SessionMBean methods (and getUserAgent in particular) have not been implemented yet.
This is not reported in the MBeanInfo interface, but is shown in the javadoc-style interface description.
New note (for LS Server 4.0 and later, still to be released at time of writing)
All the information available on the SessionMBean is reported in the javadoc-style interface description.
Note that the same information is available dynamically through the MBeanInfo interface.
Dario