On 12/04/2023 20:39, Christopher Schultz wrote:
Mark,
On 4/12/23 15:21, Mark Thomas wrote:
On 12/04/2023 19:31, Christopher Schultz wrote:
All,
I'm finally dipping my toes into Websocket-based communication with
my Tomcat-based applications. Is it possible to do everything with
"real" code and not any annotations?
I was looking for something like the Servlet Async model where you
take an existing request and put it into async mode:
final AsyncContext ac = request.startAsync(request, response);
ac.start(new Runnable() {
@Override
public void run() {
// Do some stuff
// Write the response
ac.complete();
}
});
All the tutorials I see use annotations to set up the Websocket
endpoint, etc.
Is it possible and/or recommended to use pure-code registration of
such endpoints and/or post-HTTP-request upgrade?
Configure an endpoint with code:
ServerContainer.addEndpoint(ServerEndpointConfig)
or
Upgrade an existing connection to WebSocket:
ServerContainer.upgradeHttpToWebSocket(...)
ACK
How do I get a reference to a ServerContainer instance?
ServletContext attribute:
jakarta.websocket.server.ServerContainer
I'm wanting to do things like verify that the request belongs to an
authenticated user with certain privileges, etc. and only then allow
that user to connect using Websocket to trade data across the wire.
There are various ways to do that. Either the upgrade call above or a
custom ServerEndpointConfig.Configurator.modifyHandshake. The former
has more access to the Servlet objects so is probably what you want.
I think so.
How can I relate a Websocket session to an authenticated user? Can I
communicate back and forth between the Websocket world and the
HTTP-based world like websocket.session <-> HttpSession?
Not easily. The lifecycles of the sessions diverge at the point of
upgrade. It is possible for the HttpSession to expire but the
WebvSocket session doesn't get notified.
You really need to set up everything at the point of the upgrade
including retaining a reference to the HttpSession if you wish.
There are various discussions of this - and how to keep them in sync -
on line.
It is less than ideal but there is no simple fix.
Sounds reasonable. So one thing I could to is inject a reference to the
HttpSession during the upgrade process. I would just have to be very
careful about accessing things in that session just in case it expires.
I could also copy whatever I need.
In this particular use-case, I don't actually need that, but I was
curious about the future.
It looks like there is a significant hole in these APIs that the WG
needs to think about fixing in a generalizable way.
Yes. So far the independent lifecycles have made this rather tricky.
Solutions tend to require creating dependencies between the Servlet and
WebSocket specs neither really wants.
A lot of the discussion (or references to it) can be found at
https://github.com/jakartaee/websocket/issues/175
If I want to send a fire-and-forget message to the client from the
server, can I just:
session.getAsyncRemote().sendText("hello world");
and ignore the Future<?> object returned, or will I need to verify
that message was sent before attempting to send another one?
No. You need to make sure the previous message completed before you
send the next one.
So I would probably then want to use:
session.getBasicRemote().sendText("hello world");
and then move-on with my life?
You'd need to wait before you moved on because that blocks but yes.
Note that the whole wait for the last message to finish before you send
the next is a grey area that might get cleaned up in the next version of
the spec.
What about a ws Session which can be accessed by multiple threads that
might want to write? How do I coordinate them so that they don't
conflict? Would a simple:
synchronized(session) {
session.getBasicRemote().sendText("Message N");
}
be sufficient?
Sufficient? Yes. Efficient? Possibly not ;)
Mark
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org