/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sample.scatterplot.websockets;
import com.sun.grizzly.tcp.Request;
import com.sun.grizzly.websockets.BaseServerWebSocket;
import com.sun.grizzly.websockets.DataFrame;
import com.sun.grizzly.websockets.WebSocket;
import com.sun.grizzly.websockets.WebSocketApplication;
import com.sun.grizzly.websockets.WebSocketListener;
import com.sun.jersey.api.json.JSONJAXBContext;
import com.sun.jersey.api.json.JSONMarshaller;
import com.sun.jersey.api.json.JSONUnmarshaller;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import javax.xml.bind.JAXBException;
import sample.scatterplot.ejb.PlotQueryEjb;
import sample.scatterplot.jaxb.PlotData;
import sample.scatterplot.persistence.PlotSample;
import sample.scatterplot.persistence.PlotType;
/**
*
*PlotApplication web socket example. Based on:
*
*
* - http://antwerkz.com/glassfish-web-sockets-sample/:
* Post about WebSockets, it comments chat sample application that
* goes with grizzly.
* - http://java.net/projects/grizzly/sources/svn/content/trunk/code/samples/websockets/chat/:
* Source subversion of the chat application that is commented in
* the previous blog.
* - http://grizzly.java.net/nonav/docs/1.9.31/apidocs/:
* Javadoc API for grizzly (Glassfish websockets implementation).
* - http://weblogs.java.net/blog/spericas/archive/2010/09/29/web-sockets-and-html5-glassfish:
* Another blog entry by Santiago Pericas-Geertsen.
*
*
* @author ricky
*
*/
public class PlotApplication extends WebSocketApplication {
/**
* JSON JAXB context to marshall and unmarshall
*/
JSONJAXBContext ctx = null;
/**
* Mappings of the servlet
*/
Collection mappings = null;
/**
* Query ejb
*/
private PlotQueryEjb plotQueryEjb;
/**
* Constructor of the PlotApllication. The EJB must be passed cos Inject
* does not work here (CDI).
* @param plotQueryEjb The EJB to use to access DDBB
* @param mappings THe mappings of the WebSocketsServlet
*/
public PlotApplication(PlotQueryEjb plotQueryEjb, Collection mappings) {
try {
this.plotQueryEjb = plotQueryEjb;
this.mappings = mappings;
// create the JSONJAXBContext for our plot
ctx = new JSONJAXBContext(PlotData.class);
} catch (JAXBException e) {
e.printStackTrace();
}
}
/**
* The request is for the application if it is inside the servlet mappings.
* It is not a thorough check (just an ends with, no wildcards or whatever).
* @param request The request to check
* @return true if some uri ends with some of the mappings
*/
@Override
public boolean isApplicationRequest(Request request) {
final String uri = request.requestURI().toString();
for (String mapping: mappings) {
if (uri.endsWith(mapping)) {
return true;
}
}
return false;
}
/**
* Method to create a new web socket. Just a BaseServerWebSocket is
* needed.
* @param listeners The listeners of the socket
* @return The new websocket created
* @throws IOException Some error
*/
@Override
public WebSocket createSocket(WebSocketListener[] listeners) throws IOException {
return new BaseServerWebSocket(listeners);
}
/**
* The real onMessage method. The JSON data is unmarshall into the
* PlotData object. Then the EJB is called to obtain the samples
* which are added to the PlotData. Finally the filled data is marshall
* again into JSON and returned.
* @param socket The WebScoket
* @param frame The data frame received
* @throws IOException Some error
*/
@Override
public void onMessage(WebSocket socket, DataFrame frame) throws IOException {
System.err.println("PlotApplication - onMessage: " + frame.getTextPayload());
StringReader sr = new StringReader(frame.getTextPayload());
StringWriter sw = new StringWriter();
try {
// unmarshall the json sent data
JSONUnmarshaller unmarshaller = JSONJAXBContext.getJSONUnmarshaller(ctx.createUnmarshaller());
PlotData data = unmarshaller.unmarshalFromJSON(sr, PlotData.class);
System.err.println("unmarshalled!");
// get the dates for the graph
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
Date startDate = null;
Date endDate = null;
// get end
if (data.getEnd() != null) {
endDate = new Date(Long.parseLong(data.getEnd().substring(1)));
} else {
endDate = cal.getTime();
}
// get start
if (data.getStart() != null) {
startDate = new Date(Long.parseLong(data.getStart().substring(1)));
} else {
cal.add(Calendar.DATE, -1);
startDate = cal.getTime();
}
// execute query against data base
data.setStart(formatTimestamp(startDate));
data.setEnd(formatTimestamp(endDate));
PlotType pt = PlotType.valueOf(data.getType());
data.setLegend(pt.getLegend());
data.setDescription(pt.getDescription());
List list = plotQueryEjb.getPlotSamples(
data.getType() + "-findSamplesBetweenDates", startDate, endDate);
if (list != null && !list.isEmpty()) {
for (PlotSample s: list) {
data.getData().put(formatTimestamp(s.getSampleDate()), s.getSampleValue());
}
}
// marshall again and send via websockets
JSONMarshaller marshaller = JSONJAXBContext.getJSONMarshaller(ctx.createMarshaller());
marshaller.marshallToJSON(data, sw);
System.err.println("marshalled!");
socket.send(sw.toString());
} catch (Exception e) {
e.printStackTrace();
throw new IOException(e);
} finally {
sr.close();
sw.close();
}
}
/**
* All timestamps are generated with a T prefix (JSON rules).
* @param date The date to print
* @return The timestamp prefixed by a T
*/
static public String formatTimestamp(Date date) {
return "T" + date.getTime();
}
}