Hello Chris, > -----Ursprüngliche Nachricht----- > Von: Christopher Schultz <ch...@christopherschultz.net> > Gesendet: Mittwoch, 12. April 2023 20:31 > An: Tomcat Users List <users@tomcat.apache.org> > 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: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org