public class DefaultMatsSocketServer extends java.lang.Object implements MatsSocketServer, MatsSocketStatics
MatsSocketServer.ActiveMatsSocketSession, MatsSocketServer.ActiveMatsSocketSessionDto, MatsSocketServer.DataStoreException, MatsSocketServer.IncomingAuthorizationAndAdapter<I,MR,R>, MatsSocketServer.LiveMatsSocketSession, MatsSocketServer.MatsSocketCloseCodes, MatsSocketServer.MatsSocketEndpoint<I,MR,R>, MatsSocketServer.MatsSocketEndpointContext<I,MR,R>, MatsSocketServer.MatsSocketEndpointIncomingContext<I,MR,R>, MatsSocketServer.MatsSocketEndpointReplyContext<I,MR,R>, MatsSocketServer.MatsSocketEnvelopeDto, MatsSocketServer.MatsSocketEnvelopeWithMetaDto, MatsSocketServer.MatsSocketSession, MatsSocketServer.MatsSocketSessionDto, MatsSocketServer.MessageEvent, MatsSocketServer.MessageEventListener, MatsSocketServer.MessageType, MatsSocketServer.ReplyAdapter<I,MR,R>, MatsSocketServer.SessionEstablishedEvent, MatsSocketServer.SessionEstablishedEventListener, MatsSocketServer.SessionRemovedEvent, MatsSocketServer.SessionRemovedEventListener
MatsSocketStatics.DebugStackTrace, MatsSocketStatics.DirectJson, MatsSocketStatics.DirectJsonMessageHandlingDeserializer, MatsSocketStatics.MatsSocketEnvelopeDto_Mixin, MatsSocketStatics.MessageToStringDeserializer, MatsSocketStatics.SocketSendIOException
Modifier and Type | Field and Description |
---|---|
static java.lang.String |
ALPHABET
A-Z, a-z, 0-9, which is 62 chars.
|
static java.lang.String |
ALPHABET_JSON_ID
All chars from 20-7f, except:
Space (32, 0x20) - since spaces are always annoying to use in Ids
" (34, 0x22) - since this is the start and end symbol of a String
\ (92 0x5c) - since this is the escape char
DEL (127, 0x7f) - since this is a control char
This is 92 chars.
|
MAX_FORWARDER_POOL_SIZE, MAX_LENGTH_OF_TOPIC_NAME, MAX_NUMBER_OF_COMPENSATING_TRANSACTIONS_ATTEMPTS, MAX_NUMBER_OF_HELD_ENVELOPES_PER_SESSION, MAX_NUMBER_OF_MESSAGES_PER_FORWARD_LOOP, MAX_NUMBER_OF_OUTBOX_STORE_ATTEMPTS_CSAF, MAX_NUMBER_OF_RECORDED_ENVELOPES_PER_SESSION, MAX_NUMBER_OF_REDELIVERY_ATTEMPTS, MAX_NUMBER_OF_SESSIONS_PER_USER_ID, MAX_NUMBER_OF_TOPICS_PER_SESSION, MAX_SIZE_OF_HELD_ENVELOPE_MSGS, MDC_CLIENT_APP_NAME_AND_VERSION, MDC_CLIENT_LIB_AND_VERSIONS, MDC_CMID, MDC_MESSAGE_TYPE, MDC_PRINCIPAL_NAME, MDC_SESSION_ID, MDC_SMID, MDC_TRACE_ID, MDC_USER_ID, MILLIS_BETWEEN_COMPENSATING_TRANSACTIONS_ATTEMPTS, MILLIS_BETWEEN_LIVELINESS_UPDATE_RUN, MILLIS_BETWEEN_SCAVENGE_SESSION_REMNANTS_RUN, MILLIS_BETWEEN_SESSION_TIMEOUT_RUN, MILLIS_SESSION_TIMEOUT_SUPPLIER, MIN_FORWARDER_POOL_SIZE, NUMBER_OF_OUTGOING_ENVELOPES_SCHEDULER_THREADS, THREAD_PREFIX
Modifier and Type | Method and Description |
---|---|
void |
addMessageEventListener(MatsSocketServer.MessageEventListener listener)
MessageEventListener s will be invoked for every processed incoming and outgoing
message for any session. |
void |
addSessionEstablishedEventListener(MatsSocketServer.SessionEstablishedEventListener listener)
SessionEstablishedEvent listeners will be invoked when an
LiveMatsSocketSession is established on this node of the
MatsSocketServer instance cluster, i.e. |
void |
addSessionRemovedEventListener(MatsSocketServer.SessionRemovedEventListener listener)
MatsSocketServer.SessionRemovedEvent listeners will be invoked when an MatsSocketServer.LiveMatsSocketSession is removed from this
node of the MatsSocketServer instance cluster - this is both when a MatsSocketSession is
DEREGISTERed , in which case the Client can still
RECONNECT to the same MatsSocketSessionId, and when a
MatsSocketSession is CLOSEd or TIMEOUTed . |
void |
closeSession(java.lang.String matsSocketSessionId,
java.lang.String reason)
Closes the specified MatsSocketSession - can be used to forcibly close an active MatsSocketSession (i.e.
|
static MatsSocketServer |
createMatsSocketServer(javax.websocket.server.ServerContainer serverContainer,
io.mats3.MatsFactory matsFactory,
ClusterStoreAndForward clusterStoreAndForward,
AuthenticationPlugin authenticationPlugin,
java.lang.String websocketPath)
Variant of the
full method that uses the appName that the MatsFactory is configured with as
the 'instanceName' parameter. |
static MatsSocketServer |
createMatsSocketServer(javax.websocket.server.ServerContainer serverContainer,
io.mats3.MatsFactory matsFactory,
ClusterStoreAndForward clusterStoreAndForward,
AuthenticationPlugin authenticationPlugin,
java.lang.String instanceName,
java.lang.String websocketPath)
Create a MatsSocketServer, piecing together necessary bits.
|
java.util.SortedMap<java.lang.String,MatsSocketServer.ActiveMatsSocketSessionDto> |
getActiveMatsSocketSessions()
This returns static, frozen-in-time, "copied-out" DTO-variants of the
LiveMatsSocketSessions . |
IncomingSrrMsgHandler |
getIncomingSrrMsgHandler() |
java.util.Map<java.lang.String,MatsSocketServer.LiveMatsSocketSession> |
getLiveMatsSocketSessions()
Imagine that the MatsSocketServer uses a
ConcurrentMap to keep its set of local, live, currently
connected MatsSocketSessions. |
java.util.SortedMap<java.lang.String,MatsSocketServer.MatsSocketEndpoint<?,?,?>> |
getMatsSocketEndpoints() |
java.util.List<MatsSocketServer.MatsSocketSessionDto> |
getMatsSocketSessions(boolean onlyActive,
java.lang.String userId,
java.lang.String appName,
java.lang.String appVersionAtOrAbove)
Unless restricted by the "constraint parameters", this method returns all MatsSocketSessions on this
MatsSocketServer instance, regardless of whether the session currently is connected, and if connected, which node
it is connected to.
|
int |
getMatsSocketSessionsCount(boolean onlyActive,
java.lang.String userId,
java.lang.String appName,
java.lang.String appVersionAtOrAbove)
Like
MatsSocketServer.getMatsSocketSessions(boolean, String, String, String) , only returning the count - this might be
interesting if there are very many sessions, and you do not need the full DTOs of every Session, just the count
for a metric to graph or similar. |
WebSocketOutgoingEnvelopes |
getWebSocketOutgoingEnvelopes() |
<I,MR,R> MatsSocketServer.MatsSocketEndpoint<I,MR,R> |
matsSocketEndpoint(java.lang.String matsSocketEndpointId,
java.lang.Class<I> incomingClass,
java.lang.Class<MR> matsReplyClass,
java.lang.Class<R> msReplyClass,
MatsSocketServer.IncomingAuthorizationAndAdapter<I,MR,R> incomingAuthEval,
MatsSocketServer.ReplyAdapter<I,MR,R> replyAdapter)
Registers a MatsSocket Endpoint, including a
MatsSocketServer.ReplyAdapter which can adapt the reply from the Mats
endpoint before being fed back to the MatsSocket - and also decide whether to resolve or reject the waiting
Client Promise. |
void |
publish(java.lang.String traceId,
java.lang.String topicId,
java.lang.Object messageDto)
Publish a Message to the specified Topic, with the specified TraceId.
|
void |
request(java.lang.String sessionId,
java.lang.String traceId,
java.lang.String clientEndpointId,
java.lang.Object requestDto,
java.lang.String replyToMatsSocketTerminatorId,
java.lang.String correlationString,
byte[] correlationBinary)
Initiates a request to the specified MatsSocketSession, to the specified Client EndpointId, with a replyTo
specified to (typically) a
MatsSocket terminator - which includes a String "correlationString" and byte array "correlationBinary" which can
be used to correlate the reply to the request (available
here and
here for the reply processing). |
void |
send(java.lang.String sessionId,
java.lang.String traceId,
java.lang.String clientTerminatorId,
java.lang.Object messageDto)
Sends a message to the specified MatsSocketSession, to the specified Client TerminatorId.
|
void |
stop(int gracefulShutdownMillis)
Closes all
MatsSocketServer.ActiveMatsSocketSession on this node, closing the WebSocket with
CloseReason.CloseCodes.SERVICE_RESTART (assuming that a MatsSocket service will never truly go down, thus effectively
asking the client to reconnect, hopefully to another instance). |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
matsSocketDirectReplyEndpoint, matsSocketEndpoint, matsSocketTerminator
jacksonMapper, ms, msSince
public static final java.lang.String ALPHABET
public static final java.lang.String ALPHABET_JSON_ID
public static MatsSocketServer createMatsSocketServer(javax.websocket.server.ServerContainer serverContainer, io.mats3.MatsFactory matsFactory, ClusterStoreAndForward clusterStoreAndForward, AuthenticationPlugin authenticationPlugin, java.lang.String websocketPath)
full method
that uses the appName
that the MatsFactory is configured with as
the 'instanceName' parameter.serverContainer
- the WebSocket ServerContainer
, typically gotten from the Servlet Container.matsFactory
- The MatsFactory
which we should hook into for both sending requests and setting up endpoints
to receive replies.clusterStoreAndForward
- an implementation of ClusterStoreAndForward
which temporarily holds replies while finding the
right node that holds the WebSocket connection - and hold them till the client reconnects in case he
has disconnected in the mean time.authenticationPlugin
- the piece of code that turns an Authorization String into a Principal. Must be pretty fast, as it is
invoked synchronously - keep any IPC fast, otherwise all your threads of the container might be used
up. If the function throws or returns null, authorization did not go through.websocketPath
- The path onto which the WebSocket Server Endpoint will be mounted. Suggestion: "/matssocket". If you
need multiple MatsSocketServer
s, e.g. because you need two types of authentication, they need
to be mounted on different paths.ServerContainer
and the
MatsFactory
.public static MatsSocketServer createMatsSocketServer(javax.websocket.server.ServerContainer serverContainer, io.mats3.MatsFactory matsFactory, ClusterStoreAndForward clusterStoreAndForward, AuthenticationPlugin authenticationPlugin, java.lang.String instanceName, java.lang.String websocketPath)
serverContainer
- the WebSocket ServerContainer
, typically gotten from the Servlet Container.matsFactory
- The MatsFactory
which we should hook into for both sending requests and setting up endpoints
to receive replies.clusterStoreAndForward
- an implementation of ClusterStoreAndForward
which temporarily holds replies while finding the
right node that holds the WebSocket connection - and hold them till the client reconnects in case he
has disconnected in the mean time.authenticationPlugin
- the piece of code that turns an Authorization String into a Principal. Must be pretty fast, as it is
invoked synchronously - keep any IPC fast, otherwise all your threads of the container might be used
up. If the function throws or returns null, authorization did not go through.instanceName
- a unique name of this MatsSocketServer setup, at least within the MQ system the MatsFactory is
connected to, as it is used to postfix/uniquify the endpoints that the MatsSocketServer creates on the
MatsFactory. To illustrate: The variant of this factory method that does not take 'instanceName' uses
the appName
that the MatsFactory is configured with.websocketPath
- The path onto which the WebSocket Server Endpoint will be mounted. Suggestion: "/matssocket". If you
need multiple MatsSocketServer
s, e.g. because you need two types of authentication, they need
to be mounted on different paths.ServerContainer
and the
MatsFactory
.public WebSocketOutgoingEnvelopes getWebSocketOutgoingEnvelopes()
public IncomingSrrMsgHandler getIncomingSrrMsgHandler()
public <I,MR,R> MatsSocketServer.MatsSocketEndpoint<I,MR,R> matsSocketEndpoint(java.lang.String matsSocketEndpointId, java.lang.Class<I> incomingClass, java.lang.Class<MR> matsReplyClass, java.lang.Class<R> msReplyClass, MatsSocketServer.IncomingAuthorizationAndAdapter<I,MR,R> incomingAuthEval, MatsSocketServer.ReplyAdapter<I,MR,R> replyAdapter)
MatsSocketServer
MatsSocketServer.ReplyAdapter
which can adapt the reply from the Mats
endpoint before being fed back to the MatsSocket - and also decide whether to resolve or reject the waiting
Client Promise.
NOTE: If you supply MatsObject
as the type 'MR', you will get such an instance, and can decide
yourself what to deserialize it to - it will be like having a Java method taking Object as argument. However,
there is no "instanceof" functionality, so you will need to know what type of object it is by other means, e.g.
by putting some up-flow information on the Mats ProcessContext
as a
TraceProperty
.
NOTE: You need not be specific with the 'R' type being created in the MatsSocketServer.ReplyAdapter
- it can be any
superclass of your intended Reply DTO(s), up to Object
. However, the introspection aspects will take a
hit, i.e. when listing all MatsSocketEndpoints
on some monitoring/introspection
page. This is also a bit like with Java: Methods returning Object as return type are annoying, but can
potentially be of value in certain convoluted scenarios.matsSocketEndpoint
in interface MatsSocketServer
public void send(java.lang.String sessionId, java.lang.String traceId, java.lang.String clientTerminatorId, java.lang.Object messageDto) throws MatsSocketServer.DataStoreException
MatsSocketServer
send
in interface MatsSocketServer
MatsSocketServer.DataStoreException
- if the ClusterStoreAndForward
makes any problems when putting the outgoing message in the
outbox.public void request(java.lang.String sessionId, java.lang.String traceId, java.lang.String clientEndpointId, java.lang.Object requestDto, java.lang.String replyToMatsSocketTerminatorId, java.lang.String correlationString, byte[] correlationBinary) throws MatsSocketServer.DataStoreException
MatsSocketServer
MatsSocket terminator
- which includes a String "correlationString" and byte array "correlationBinary" which can
be used to correlate the reply to the request (available
here
and
here
for the reply processing). Do note that
since you have no control of when the Client decides to close the browser or terminate the app, you have no
guarantee that a reply will ever come - so code accordingly.
Note: the correlationString
and correlationBinary
are not sent over to the client, but stored
server side in the ClusterStoreAndForward
. This both means that you do not need to be afraid of size (but
storing megabytes is silly anyway), but more importantly, this data cannot be tampered with client side - you can
be safe that what you gave in here is what you get out in the
context.getCorrelationString()
and
context.getCorrelationBinary()
.
Note: To check whether the client Resolved or Rejected the request, use
MatsSocketServer.MatsSocketEndpointIncomingContext.getMessageType()
.
Note: If the specified session is closed when this method is invoked, the message will (effectively) silently be
dropped. Even if you just got hold of the sessionId and it was active then, it might asynchronously close while
you invoke this method.
Note: The message is put in the outbox, and if the session is actually connected, it will be delivered ASAP,
otherwise it will rest in the outbox for delivery once the session reconnects. If the session then closes or
times out while the message is in the outbox, it will be deleted.
Note: Given that the session actually is live and the client is connected or connects before the session is
closed or times out, the guaranteed delivery and exactly-once features are in effect, and this still holds in
face of session reconnects.request
in interface MatsSocketServer
MatsSocketServer.DataStoreException
- if the ClusterStoreAndForward
makes any problems when putting the outgoing message in the
outbox.public void publish(java.lang.String traceId, java.lang.String topicId, java.lang.Object messageDto) throws io.mats3.MatsInitiator.MatsBackendRuntimeException
MatsSocketServer
MatsInitiator.MatsInitiate.publish(Object)
on the MatsFactory
, and thus you might get the
MatsInitiator.MatsBackendRuntimeException
which MatsInitiator.initiateUnchecked(InitiateLambda)
raises.
Note: A published message will be broadcast to all nodes in the MatsSocketServer instance (where each instance
then evaluates if it have subscribers to the topic and forwards to those). In addition, a certain number of
messages per topic will be retained in memory to support "replay of lost messages" when a Client looses
connection and must reconnect. You should consider these facts when designing usage of pub/sub. Messages over
topics should generally be of interest to more than one party. While it is certainly feasible to have
user-specific, or even session-specific topics, which could be authorized to only be subscribable by the "owning
user" or even "owning session" (by use of the
AuthenticationPlugin
), the
current implementation of pub/sub will result in quite a bit of overhead with extensive use of such an approach.
Also, even for messages that are of interest to multiple parties, you should consider the size of the messages:
Maybe not send large PDFs or the entire ISO-images of "newly arrived BlueRays" over a topic - instead send a
small notification about the fresh BlueRay availability including just essential information and an id, and then
the client can decide whether he wants to download it.publish
in interface MatsSocketServer
traceId
- traceId for the flow.topicId
- which Topic to Publish on.messageDto
- the message to Publish.io.mats3.MatsInitiator.MatsBackendRuntimeException
- if the Mats implementation cannot connect to the underlying message broker, or are having problems
interacting with it.public java.util.SortedMap<java.lang.String,MatsSocketServer.MatsSocketEndpoint<?,?,?>> getMatsSocketEndpoints()
getMatsSocketEndpoints
in interface MatsSocketServer
SortedMap[endpointId, endpoint]
.public java.util.List<MatsSocketServer.MatsSocketSessionDto> getMatsSocketSessions(boolean onlyActive, java.lang.String userId, java.lang.String appName, java.lang.String appVersionAtOrAbove) throws MatsSocketServer.DataStoreException
MatsSocketServer
data store
, as opposed to
methods MatsSocketServer.getActiveMatsSocketSessions()
and MatsSocketServer.getLiveMatsSocketSessions()
, which returns result
from this node's internal structures - and therefore only returns sessions that are connected right
now, and are connected to this node. This means that you will get returned both connected sessions,
and sessions that are not currently connected (unless restricting this via parameter 'onlyActive'). The latter
implies that they are state=MatsSocketServer.ActiveMatsSocketSession.MatsSocketSessionState.DEREGISTERED
, and the
MatsSocketServer.MatsSocketSession.getNodeName()
returns Optional.empty()
.
The parameters are constraints - if a parameter is null
or false
, that parameter is not
used in the search criteria, while if it is set, that parameter will constrain the search.getMatsSocketSessions
in interface MatsSocketServer
onlyActive
- If true
, only returns "active" MatsSocketSessions, currently being connected to some
node, i.e. having MatsSocketServer.MatsSocketSession.getNodeName()
NOT returning Optional.empty()
.userId
- If non-null
, restricts the results to sessions for this particular userIdappName
- If non-null
, restricts the results to sessions for this particular app-name. Do realize
that it is the Client that specifies this value, there is no restriction and you cannot trust that
this String falls within your expected values.appVersionAtOrAbove
- If non-null
, restricts the results to sessions having app-version at or above the
specified value, using ordinary alphanum comparison. Do realize that it is the Client that specifies
this value, there is no restriction and you cannot trust that this String falls within your expected
values.data store
.MatsSocketServer.DataStoreException
- if the ClusterStoreAndForward
makes any problems when reading sessions from it.public int getMatsSocketSessionsCount(boolean onlyActive, java.lang.String userId, java.lang.String appName, java.lang.String appVersionAtOrAbove)
MatsSocketServer
MatsSocketServer.getMatsSocketSessions(boolean, String, String, String)
, only returning the count - this might be
interesting if there are very many sessions, and you do not need the full DTOs of every Session, just the count
for a metric to graph or similar.getMatsSocketSessionsCount
in interface MatsSocketServer
data store
.public java.util.SortedMap<java.lang.String,MatsSocketServer.ActiveMatsSocketSessionDto> getActiveMatsSocketSessions()
MatsSocketServer
LiveMatsSocketSessions
. Please observe the difference between MatsSocketServer.ActiveMatsSocketSession
and
MatsSocketServer.LiveMatsSocketSession
. If you have a massive amount of sessions, and only need the sessions for
appName="MegaCorpWebBank", then you should consider not employing this method, but instead do a variant of what
this method does, where you restrict the "copy out" to the relevant sessions:
SortedMap<String, ActiveMatsSocketSessionDto> ret = new TreeMap<>(); for (LiveMatsSocketSession liveSession : getLiveMatsSocketSessions().values()) { // === HERE YOU MAY ADD CRITERIA on the LiveMatsSocketSession, doing 'continue' if not matched === // :: "Copy it out" ActiveMatsSocketSessionDto activeSession = liveSession.toActiveMatsSocketSession(); // ?: Check that the LiveSession is still SESSION_ESTABLISHED if (liveSession.getState() != MatsSocketSessionState.SESSION_ESTABLISHED) { // -> No, it changed during copying, so then we drop this. continue; } // Add to result Map ret.put(activeSession.getMatsSocketSessionId(), activeSession); } return ret;
getActiveMatsSocketSessions
in interface MatsSocketServer
ActiveMatsSocketSession
s - these are the
active MatsSocketSessions which are active right now on this node of the set of
nodes (i.e. cluster) that represents this instance of MatsSocketServer. Notice that all returned
instances had state=SESSION_ESTABLISHED
at the time of
capture.MatsSocketServer.ActiveMatsSocketSession
,
MatsSocketServer.getLiveMatsSocketSessions()
public java.util.Map<java.lang.String,MatsSocketServer.LiveMatsSocketSession> getLiveMatsSocketSessions()
MatsSocketServer
ConcurrentMap
to keep its set of local, live, currently
connected MatsSocketSessions. This method then returns an unmodifiable view of this Map. This means that you can
get session instances, and iterate over it, but the contents will change over time as Clients come and go, i.e.
connects and disconnects. It also means that you can get this Map instance once, and keep a local copy of it, and
it will always be current. It again also means that if you want a "static list" of these sessions, either use
MatsSocketServer.getActiveMatsSocketSessions()
which gives you a snapshot, "frozen-in-time" view of the active sessions,
where both the sessions, and the contents of the sessions, are static. Or you may copy the values of this
returned Map into another container - but in the latter case, the contents of those LiveMatsSocketSession
instances are still live. Please observe the difference between MatsSocketServer.ActiveMatsSocketSession
and
MatsSocketServer.LiveMatsSocketSession
.getLiveMatsSocketSessions
in interface MatsSocketServer
LiveMatsSocketSession
s - these are
the live MatsSocketSessions which are active right now on this node of the set of
nodes (i.e. cluster) that represents this instance of MatsSocketServer.MatsSocketServer.getActiveMatsSocketSessions()
public void closeSession(java.lang.String matsSocketSessionId, java.lang.String reason)
MatsSocketServer
SessionRemoved
listeners
with type CLOSE
will be issued.
Note: This can be done on any node of the MatsSocketServer-instance cluster, as the instruction will be forwarded
to the active node if the MatsSocketSession is not active on this node. If it is not active on any node, it will
nevertheless be closed in the data store
(i.e. the session cannot reconnect
again).closeSession
in interface MatsSocketServer
matsSocketSessionId
- the id of the Session to close.reason
- a short descriptive String of why it was closed.public void addSessionEstablishedEventListener(MatsSocketServer.SessionEstablishedEventListener listener)
MatsSocketServer
SessionEstablishedEvent
listeners will be invoked when an
LiveMatsSocketSession
is established on this node of the
MatsSocketServer
instance cluster, i.e. the authentication/authorization is accepted, HELLO message from
Client is processed and MatsSocketSessionId is established. Note that this means that in a fairly load balanced
3-node MatsSocketServer cluster, you should get approximately 1/3 of the SessionEstablishedEvents on "this" node,
while 2/3 of them will come on the "other" two nodes.
Note: A specific MatsSocketSession with a specific MatsSocketSessionId can be established multiple times, due to
RECONNECT
.
NOTE: You are advised against keeping hold of the LiveMatsSocketSession
instance
that is provided in the SessionEstablishedEvent
. You can instead get a view
of the currently live sessions for this node by means of MatsSocketServer.getLiveMatsSocketSessions()
. If you still
decide to hold on to these active sessions instances, you must be very certain to remove it from
your held instances when getting any SessionRemovedEvent
, meaning that you must remove it for any of the DEREGISTER
, CLOSE
and TIMEOUT
event types: The live session instance is dead for all of these events. If you were to remove it only on
CLOSE or TIMEOUT, believing that a DEREGISTER is a "softer" removal, you have basically misunderstood! You could
then get a DEREGISTER (which actually is the server informing you that it has ditched this LiveMatsSocketSession
and the session is now solely represented in the data store
, while you still
stubbornly hold on to it!), and then not get a corresponding TIMEOUT for the same MatsSocketSessionId until many
hours, or days, later. If you fail to remove it at all, you will eventually get an OutOfMemory situation. The
reason here is that a MatsSocketSession instance is never "reanimated", even if the MatsSocketSession is just
DEREGISTERed: A new LiveMatsSocketSession instance is always created upon a SessionEstablishedEvent
, both for NEW
and
RECONNECT
addSessionEstablishedEventListener
in interface MatsSocketServer
listener
- the SessionEstablishedListener
that shall get invoked when
MatsSocketSessions are established.MatsSocketServer.addSessionRemovedEventListener(SessionRemovedEventListener)
,
MatsSocketServer.getLiveMatsSocketSessions()
,
MatsSocketServer.getActiveMatsSocketSessions()
public void addSessionRemovedEventListener(MatsSocketServer.SessionRemovedEventListener listener)
MatsSocketServer
MatsSocketServer.SessionRemovedEvent
listeners will be invoked when an MatsSocketServer.LiveMatsSocketSession
is removed from this
node of the MatsSocketServer
instance cluster - this is both when a MatsSocketSession is
DEREGISTERed
, in which case the Client can still
RECONNECT
to the same MatsSocketSessionId, and when a
MatsSocketSession is CLOSEd
or TIMEOUTed
. In the latter cases, any information of the MatsSocketSession and its MatsSocketSessionId are deleted
from the MatsSocketServer, and the session cannot be reconnected again.
Note: A specific MatsSocketSession can DEREGISTER
multiple times, due
to it can RECONNECT
again after each DEREGISTER. However, once it
has CLOSE
or TIMEOUT
, the session
cannot RECONNECT ever again, and hence those events are terminal wrt. to that specific MatsSocketSessionId.addSessionRemovedEventListener
in interface MatsSocketServer
listener
- the SessionEstablishedListener
that shall get invoked when
MatsSocketSessions are removed (either deregistered, closed or timed out).MatsSocketServer.addSessionEstablishedEventListener(SessionEstablishedEventListener)
public void addMessageEventListener(MatsSocketServer.MessageEventListener listener)
MatsSocketServer
MessageEventListener
s will be invoked for every processed incoming and outgoing
message for any session. It will be invoked after the message is processed OK on incoming, and
after the message is sent for outgoing. Note that the MatsSocketServer.MatsSocketEnvelopeWithMetaDto
contains more
information than is sent over the wire, this is the "WithMeta" aspect which holds processing metadata - the
wire-part is what is contained in MatsSocketServer.MatsSocketEnvelopeDto
.
Note wrt. modifications on the MatsSocketEnvelopeWithMetaDto
! All fields are public and
non-final, so you can modify it before e.g. sending it over Mats (e.g. nulling out the 'msg' field). However,
read the JavaDoc comment on the class: There is only one single instance for all listeners and
MatsSocketServer.ActiveMatsSocketSession.getLastEnvelopes()
"last envelopes"}, so clone it before modifying!
Note: The last messages per MatsSocketServer.ActiveMatsSocketSession
is available via
MatsSocketServer.ActiveMatsSocketSession.getLastEnvelopes()
.addMessageEventListener
in interface MatsSocketServer
listener
- the MatsSocketServer.MessageEventListener
that will be invoked for every processed incoming and outgoing
envelope for any session.MatsSocketServer.ActiveMatsSocketSession.getLastEnvelopes()
,
MatsSocketServer.MatsSocketEnvelopeWithMetaDto
public void stop(int gracefulShutdownMillis)
MatsSocketServer
MatsSocketServer.ActiveMatsSocketSession
on this node, closing the WebSocket with
CloseReason.CloseCodes.SERVICE_RESTART
(assuming that a MatsSocket service will never truly go down, thus effectively
asking the client to reconnect, hopefully to another instance). Should be invoked at application shutdown.stop
in interface MatsSocketServer