Created
August 24, 2016 09:00
-
-
Save john77eipe/95805440a3b8f94a266bf69ee11ee67a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Basic version | |
* @author johne | |
* | |
*/ | |
@WebServlet(urlPatterns = "/Weather/v1", asyncSupported = true) | |
public class WeatherDataStream extends HttpServlet { | |
private static final long serialVersionUID = 1L; | |
// Keeps all open connections from browsers | |
private Set<AsyncContext> asyncContexts = new HashSet<AsyncContext>(); | |
protected void doGet(HttpServletRequest request, HttpServletResponse response) | |
throws ServletException, IOException { | |
// Check that it is SSE request | |
if ("text/event-stream".equals(request.getHeader("Accept"))) { | |
log("--SSE REQUEST--"); | |
// send streaming data to all open connections | |
// Set header fields | |
response.setContentType("text/event-stream"); | |
response.setHeader("Cache-Control", "no-cache"); | |
response.setHeader("Connection", "keep-alive"); | |
response.setCharacterEncoding("UTF-8"); | |
// Start asynchronous context and add listeners to remove it in case | |
// of errors | |
final AsyncContext ac = request.startAsync(); | |
ac.addListener(new AsyncListener() { | |
@Override | |
public void onComplete(AsyncEvent event) throws IOException { | |
log("--ASYNC EVENT COMPLETE-- "); | |
asyncContexts.remove(event.getAsyncContext()); | |
} | |
@Override | |
public void onError(AsyncEvent event) throws IOException { | |
log("--ASYNC EVENT ERROR--"); | |
asyncContexts.remove(event.getAsyncContext()); | |
} | |
@Override | |
public void onStartAsync(AsyncEvent event) throws IOException { | |
log("--ASYNC EVENT START--"); | |
} | |
@Override | |
public void onTimeout(AsyncEvent event) throws IOException { | |
log("--ASYNC EVENT TIMEOUT--"); | |
asyncContexts.remove(event.getAsyncContext()); | |
} | |
}); | |
// Put context in a map | |
asyncContexts.add(ac); | |
log("Event Registration for connection obj: "+ac.toString()); | |
} | |
} | |
protected void doPost(HttpServletRequest request, HttpServletResponse response) | |
throws ServletException, IOException { | |
log("--WEATHER POST DATA RECEIVED--"); | |
log("Current set of connections: " + asyncContexts); | |
WeatherToken token = new WeatherToken(request.getParameter("city"), request.getParameter("temp")); | |
// Sends the message to all the asyncContext's response | |
for (AsyncContext asyncContext : asyncContexts) { | |
log("Sending MSG to connection obj: " + asyncContext); | |
boolean errorStatus = sendMessage(asyncContext.getResponse().getWriter(), token); | |
if (errorStatus) { | |
throw new RuntimeException("Connection closed by client"); | |
} | |
} | |
} | |
private boolean sendMessage(PrintWriter writer, WeatherToken token) { | |
writer.println("event: city"); | |
writer.print("data: "); | |
writer.println(token.getType()+":"+token.getData()); | |
writer.println(); //new line marks an event boundary | |
return writer.checkError(); //checkError() calls writer.flush(); | |
} | |
@Override | |
public void destroy() { | |
log("--SERVLET DESTROYED--"); | |
for(AsyncContext asyncContext: asyncContexts){ | |
asyncContext.complete(); | |
} | |
super.destroy(); | |
} | |
@Override | |
public void init(ServletConfig config) throws ServletException { | |
log("--SERVLET INITIALIZED--"); | |
super.init(config); | |
} | |
public void log(String output) { | |
System.out.println(LocalDateTime.now() +" [" + Thread.currentThread().getName() + "]" + output); | |
} | |
} | |
class WeatherToken { | |
private String tokenType; | |
private String tokenValue; | |
public WeatherToken(String data, String type) { | |
this.tokenValue = data; | |
this.tokenType = type; | |
} | |
public String getType() { | |
return tokenType; | |
} | |
public String getData() { | |
return tokenValue; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment