There exist cases where you could need to disconnect a user from Lightstreamer Server. For example, if a user logs in multiple times from different clients and you don't want to support multiple push sessions for the same account. Or perhaps you may want to disconnect a user after a given amount of time since login, or when the authentication credentials have expired.
Lightstreamer Server 7.1 has fully addressed this needs with an extension to the Metadata Adapter interface, so that a session can be forcibly closed by the Metadata Adapter instance which is currently serving the session.
In addition to the Java In-Process SDK, this extension has been ported to the Java Remote and Generic Adapter SDKs, but this requires Server version 7.3 or later; it has not been ported to the other Remote Adapter SDKs yet.
The termination is accomplished through the
forceSessionTerminationmethods in the new
MetadataControlListener class. The Server kernel provides its listener object through the new optional
setListener callback, which it invokes upon adapter startup.
The following snippet of Metadata Adapter code exemplifies how you can enforce termination for a session that, for instance, has lasted for more than five minutes.
[SYNTAX="JAVA"]
......................
private final Set<String> concurrentSessionSet = ConcurrentHashMap.newKeySet();
private static final ScheduledExecutorService expirationChecker = Executors.newScheduledThreadPool(1);
private final int expiryTimeMinutes = 5;
private volatile MetadataControlListener kernelListener;
public void setListener(MetadataControlListener listener) {
kernelListener = listener;
}
public void notifyNewSession(String user, String session, Map clientContext)
throws CreditsException, NotificationException {
concurrentSessionSet.add(session);
expirationChecker.schedule(() -> {
if (concurrentSessionSet.contains(session)) {
kernelListener.forceSessionTermination(session);
}
}, expiryTimeMinutes, TimeUnit.MINUTES);
}
public void notifySessionClose(String session) throws NotificationException {
concurrentSessionSet.remove(session);
}
......................
[/SYNTAX]
By the way, for this particular use case the Server also provides a new utility callback, the optional
getSessionTimeToLive, that is invoked for each session just created. So you can have simply:
[SYNTAX="JAVA"]
......................
private final int expiryTimeMinutes = 5;
public int getSessionTimeToLive(String user, String session) {
// requires a time in seconds
return expiryTimeMinutes * 60;
}
......................
[/SYNTAX]
In addition to the Java In-Process SDK, this extension has been ported to the Java Remote and Generic Adapter SDKs, but this requires Server version 7.3 or later; it has not been ported to the other Remote Adapter SDKs yet.
Another particular use case that is handled directly is when you have one instance of Lightstreamer Server only and you don't want to allow more than one session per user.
In this case, you will simply throw a
ConflictingSessionExceptionfrom the
notifyNewSession method of your Metadata Adapter.
This is available for all Lightstreamer versions and all Adapter SDKs.
Apart from the 7.1 extensions, the general way provided to enforce session termination is through the JMX interface. JMX (Java Management eXtensions) is a standard specification that allows an application to be controlled both internally and externally and both manually and automatically.
Lightstreamer Server exposes a set of
MBeans that give full control over the engine and the sessions.
Since Server version 6.0, the simplest way to terminate a session through JMX is by calling the
destroySession(sessionId)method on the
ResourceMBean object.
With previous versions, you just need to call the
destroySession()method on the appropriate
SessionMBean object.
You can access
MBean objects both from inside your Adapter and from any external Java application.
A source code example is provided in a
previous post, where the Metadata Adapter causes a session to be closed after it has lived longer than five minutes. The example is based on the
SessionMBean technique.
Note, however, that JMX interface is an optional feature of the Enterprise edition, which should be purchased separately, and it is not available for the Community edition.
Moreover, the JMX interface requires a Java endpoint.
If the license does not include JMX, or in case of non-java-based Remote Adapters - and for the general problem of terminating a session from anywhere in the back-end - the last resort is to connect to Lightstreamer Server from the client interface.
In practice, you should connect to the instance of Lightstreamer Server serving the involved session and send a special HTTP request to force session termination. The
sessionIdof the session to terminate is sent as a parameter.
SessionIds are random and complex enough to be quite impossible to guess, so no specific authentication is required to send such request.
The protocol to use to express the termination request should match the protocol currently used by the client; but actually there is no such costraint and any supported protocol can be used.
This allows us to use the simplest protocol available, which is the old text protocol (i.e. the
SDK for Generic Clients up to build 1803, before the introduction of the TLCP protocol).
A source code example is provided in a
previous post (see first code snippet), where the Metadata Adapter causes a session to be closed after it has lived longer than five minutes.
This protocol can be used always with Server 7.1. With 7.0 it may not be available for Enterprise licenses which only include the Web and/or Node.js SDKs. With earlier versions, it is available only for Presto and Vivace editions.
For all other cases, you can resort to the old internal javascript protocol. A source code example is provided in the same
previous post (see second code snippet).
The latter solution works with all versions, editions, and licenses, making it a truly general solution.