Reputation: 131
I have problems setting up a SSE environment with Jetty. I use Chrome (44.0.2403.107 m) and FF (39.0) as client browsers.
I created a servlet in Jetty (see below) and used a WebAppContext to make it available programatically. I also tried to use the EventSourceServlet
provided by Jetty, however, this didn't work either.
On the client side I created a simple EventSource
and tried to get the messages. While curl
delivers the correct output (see output below), FF and Chrome do not fire the event as expected. After killing the server, the events seem to pop up in the browsers (after the timeout of the request).
Can anyone point out my error while implementing SSE with Jetty?
I also recognized that jetty uses special write
methods with respect to async writing. However, in the EventSourceServlet
these methods are not used. Do I have to use those for SSE to work? Also, at which points in my servlet can I omit the flush
?
The servlet I created:
package de.rub.lps.sophie.agenten.sample.webui.servlet;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AsyncContextState;
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = -8049945594360149181L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getSession(true).getId());
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("text/event-stream");
resp.setCharacterEncoding(StandardCharsets.UTF_8.name());
resp.flushBuffer();
AsyncContextState async = (AsyncContextState) req.startAsync();
System.out.println(async);
new Thread() {
public void run() {
try {
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ServletOutputStream outputStream = async.getResponse().getOutputStream();
if (outputStream.isReady()) {
String message = "data: refresh\n\n";
outputStream.write(message.getBytes(StandardCharsets.UTF_8), 0, message.length());
outputStream.flush();
async.getResponse().flushBuffer();
} else {
System.out.println("not ready!");
}
System.out.println("wrote!");
}
} catch (IOException e) {
async.complete();
e.printStackTrace();
}
};
}.start();
}
}
An excerpt of how I start the Jetty and add the WebAppContext with the servlet (included in a big try/catch...):
HandlerCollection handlerCollection = new HandlerCollection(true);
server = new Server(8888);
server.setHandler(handlerCollection);
server.start();
WebAppContext context = new WebAppContext();
handlerCollection.addHandler(context);
context.setContextPath("/test");
context.setResourceBase("/myPath");
ServletHolder servletHolder = new ServletHolder(new TestServlet());
servletHolder.setAsyncSupported(true);
context.addServlet(servletHolder, "/test");
context.start()
The output by curl
:
> GET /[email protected]:1099/JADE/test HTTP/1.1
> Host: 127.0.0.1:8888
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Jul 2015 09:08:05 GMT
< Set-Cookie: JSESSIONID=aw6ro34htalm1uf5huix9bxo6;Path=/test/test
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Content-Type: text/event-stream;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(9.3.1.v20150714)
<
data: refresh
data: refresh
data: refresh
[... and so on...]
And the test.html
I use in the browsers:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<script>
var eventSource = new EventSource('test');
eventSource.onmessage = function(event) {
console.log(event);
window.alert(event.data);
};
</script>
</body>
</html>
Upvotes: 3
Views: 3907
Reputation: 56
I suspect the issue is with jetty. I have noticed, that when trying to consume Marathon
events (via /v2/events
) with a jersey2 client, that it was separating the events with \r\n
instead of \n\n
so it is just sitting there filling up the buffer and never returning control.
Upvotes: 1