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

Reply via email to