SSE without Jersey

Gert-Jan van de Streek

Gert-Jan van de Streek

Published: 14 April, 2015

Sometimes you are not working on the edge of technology. For example when you have to add something to a project that has not been touched for over 4 years. Or when you are integrating with a product that uses not so up-to-date library dependencies. This is where this blog post starts: in JIRA, with an ancient version of Jersey. And I want to implement Server Side Events (SSE). Ready?

So here I am, stuck with Jersey version 1.0.3. This is when you realize Jersey has made good progress over the years and how much of the heavy lifting it does for you. But now, I'm on my own and I still need to connect an SSE client to JIRA. Luckily since servlet version 3 there is async processing support and while it has been around for a few years, I have never had the chance to play with it. It turns out, it's not too hard to implement sse yourself. Let me share the code, just in case you find yourself working out of sight of the edge of technology one day:

public class IssueCreation extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // First check if your client request SSE
if ("text/event-stream".equals(req.getHeader("Accept"))) {
// Check, handle as SSE request
doSse(req, resp);
}
} protected void doSse(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// It took me a while to find this, but Tomcat needs this for async to work
req.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true); // SSE needs this content type:
resp.setContentType("text/event-stream"); try {
final AsyncContext asyncContext = req.startAsync(); asyncContext.addListener(new AsyncListener() {
// implement the required listener methods here, I trust you know how to do that
} ); asyncContext.start(new Runnable() {
public void run() {
while(true) {
// depending on your use case start writing to the servlets outputstream:
writer = asyncContext.getResponse().getWriter();
writer.write("data: " + "{yourdata}");
writer.write("\n\n");
writer.flush();
}
}
}); } catch(Exception e) {
// ...
}
}

Writing an event is as simple as sending text that starts with "data: ". You end the event with a double new-line. This results in a simple stream for the attached client:

HTTP/1.1 200 OK
Content-Type: text/event-stream data: {yourdata} data: {yourdata} data: {yourdata} ...

The nice part of falling back to basic is that you learn a bit more about a specification, SSE in this case. It turned out to be quite nice and easy!

Related blogs

Did you enjoy reading?

Share this blog with your audience!