Hello Chris,
> -----Ursprüngliche Nachricht-----
> Von: Christopher Schultz <[email protected]>
> Gesendet: Mittwoch, 12. April 2023 20:31
> An: Tomcat Users List <[email protected]>
> Betreff: Getting started with Websocket
>
> 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?
>
> 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.
>
> 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?
>
> 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?
>
> Thanks,
> -chris
>
I used the simple example below.
You need to add a kind of hashmap per user for example. Its just a POC.
public class SseServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
@Override
public void destroy()
{
//
}
@Override
public void service(final HttpServletRequest req, final HttpServletResponse
res) throws ServletException, IOException
{
// https://web.dev/eventsource-basics/
// https://www.howopensource.com/2016/01/java-sse-chat-example/
if ("text/event-stream".equals(req.getHeader("Accept")))
{
AsyncContext actx = req.startAsync();
actx.setTimeout(0);
System.out.println("new connection");
res.setContentType("text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
res.setCharacterEncoding("UTF-8");
Thread t = new Thread(new SseSender(actx, new Random().nextInt()));
t.start();
//save actx and use it when we need sent data to the client.
}
}
class SseSender implements Runnable
{
private AsyncContext ctx;
private int iRnd;
private boolean bRunning = true;
public SseSender(final AsyncContext p, final int i)
{
this.ctx = p;
this.iRnd = i;
// final String id = UUID.randomUUID().toString();
ctx.addListener(new AsyncListener()
{
@Override
public void onComplete(final AsyncEvent event) throws
IOException {
System.out.println(iRnd + " completed");
bRunning = false;
// stop thread or remove ctx from list
}
@Override
public void onError(final AsyncEvent event) throws IOException {
System.out.println(iRnd + " error");
bRunning = false;
// stop thread or remove ctx from list
}
@Override
public void onStartAsync(final AsyncEvent event) throws
IOException {
// Do nothing
}
@Override
public void onTimeout(final AsyncEvent event) throws
IOException {
bRunning = false;
System.out.println(iRnd + " timed out");
// stop thread or remove ctx from list
}
});
}
@Override
public void run()
{
while (bRunning)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if (bRunning)
{
try
{
sendMessage(ctx.getResponse().getWriter(), 123, "test "
+ Integer.toString(iRnd));
}
catch (Exception e)
{
bRunning = false;
System.out.println("Exception on context " + iRnd);
}
}
}
//ctx.complete();
}
private void sendMessage(final PrintWriter writer, final long id, final
String message)
{
writer.print("id: ");
writer.println(id);
writer.print("data: ");
writer.println(message);
writer.println();
writer.println("event");
writer.println("eventname-xx");
writer.flush();
}
}
}
The js-File:
let peer = null;
var source = null;
onconnect = function (ev) {
console.log("on-connect");
let port = ev.ports[0];
port.onmessage = (e) => {
if (e.data.type=='start' && e.data.port){
peer=e.data.port;
} else if (e.data.type=='msg' && peer){
setInterval(()=>{
peer.postMessage({type:'msg',msg:'greetings!'});
},2000);
}
}
if (source == null)
{
source = new EventSource('/inventar/sse/events?user=th');
}
source.addEventListener('message', function(e) {
console.log(e.data); // Notification
}, false);
source.addEventListener('open', function(e) {
console.log("open");
}, false);
source.addEventListener('error', function(e) {
if (e.readyState == EventSource.CLOSED) {
console.log("closed");
}
}, false);
port.start();
}
And the html:
<html>
<head>
<script>
var worker = new SharedWorker('./test.js');
worker.port.start();
</script>
</head>
<body>
ok
</body>
</html>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]