Skip to content

Instantly share code, notes, and snippets.

@BohdanLevchenko
Forked from khill/GraphController.java
Created June 16, 2020 18:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BohdanLevchenko/001564b51fa72ae94ad8e6b9b68c55ae to your computer and use it in GitHub Desktop.
Save BohdanLevchenko/001564b51fa72ae94ad8e6b9b68c55ae to your computer and use it in GitHub Desktop.
Example of a Spring MVC Controller which Displays a Graph from JFreeChart
package org.khill.dashboard.controller;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.awt.Color;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import javax.imageio.ImageIO;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.time.Minute;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.RectangleInsets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
/**
* Example controller showing how to display a graph from JFreeChart
*
* @author khill
*
*/
@Controller
public class GraphController {
@Autowired
private ReportDAO reportDao;
@RequestMapping("/minuteGraph.htm")
public ResponseEntity <byte []> getUpdatesByMinuteGraph() {
HttpStatus responseCode = HttpStatus.OK;
byte [] image = new byte[0];
Map <String,Long> updatesByMinute = reportDao.loadUpdateCountsByMinute(15);
try {
image = this.getUpdateCountByMinuteGraph(updatesByMinute);
} catch (Exception e) {
responseCode = HttpStatus.INTERNAL_SERVER_ERROR;
}
return new ResponseEntity<byte[]>(image, responseCode);
}
/*
* Creates a line graph using JFreeChart
*/
private byte [] getGraphFromDataSet(TimeSeriesCollection dataset, String titleText, String xLabel, String yLabel) throws Exception {
// create the chart
JFreeChart chart = ChartFactory.createTimeSeriesChart(
titleText, // title
xLabel, // x-axis label
yLabel, // y-axis label
dataset, // data
true, // create legend?
true, // generate tooltips?
false // generate URLs?
);
TextTitle title = chart.getTitle();
title.setPaint(new Color(0, 84, 148));
title.setFont(new Font("Lucida Sans Unicode", Font.BOLD, 12));
XYPlot plot = (XYPlot) chart.getPlot();
Color fgColor = new Color(46, 110, 158);
Color bgColor = new Color(228, 232, 234);
Color gridColor = new Color(128, 128, 128);
chart.getLegend().setItemPaint(fgColor);
plot.setBackgroundPaint(bgColor);
plot.setDomainGridlinePaint(gridColor);
plot.setRangeGridlinePaint(gridColor);
plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
XYItemRenderer r = plot.getRenderer();
if (r instanceof XYLineAndShapeRenderer) {
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
renderer.setBaseItemLabelPaint(fgColor);
renderer.setSeriesItemLabelPaint(0, fgColor);
renderer.setBaseFillPaint(fgColor);
renderer.setBaseOutlinePaint(fgColor);
renderer.setSeriesPaint(0, fgColor);
renderer.setBaseShapesVisible(false);
renderer.setBaseShapesFilled(false);
renderer.setDrawSeriesLineAsPath(true);
}
BufferedImage img = chart.createBufferedImage(600, 300);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "PNG", baos);
return baos.toByteArray();
}
/**
* Creates a time series graph for a specific frequency
*
* @param updateCounts the update data information which forms the basis of the graph
* @param frequency the period frequency
* @return a chart PNG in byte array form
* @throws Exception
*/
private byte [] getTimeSeriesGraph(Map <String,Long> updateCounts, int frequency) throws Exception {
if(frequency != Calendar.MINUTE && frequency != Calendar.SECOND) {
throw new IllegalArgumentException("Unsupported time series frequency specified - must be minutes or seconds");
}
// build the dataset
TimeSeries ts = new TimeSeries("UpdateCount");
RegularTimePeriod p = null;
Date d = null;
Date start = null;
Date end = null;
DateFormat f = null;
if(frequency == Calendar.MINUTE) {
f = new SimpleDateFormat("MM-dd-yyyy HH:mm");
}
if(frequency == Calendar.SECOND) {
f = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
}
for(String s : updateCounts.keySet()) {
d = f.parse(s);
if(start == null || d.getTime() < start.getTime()) {
start = d;
}
if(end == null || d.getTime() > end.getTime()) {
end = d;
}
if(frequency == Calendar.MINUTE) {
p = RegularTimePeriod.createInstance(Minute.class, d, TimeZone.getDefault());
ts.add(p, updateCounts.get(s));
}
if(frequency == Calendar.SECOND) {
p = RegularTimePeriod.createInstance(Second.class, d, TimeZone.getDefault());
ts.add(p, updateCounts.get(s));
}
}
String chartTitle = null;
String xTitle = null;
if(frequency == Calendar.MINUTE) {
chartTitle = "Updates per Minute";
if(end != null && start != null) {
long minuteDelta = (end.getTime() - start.getTime()) / (60 * 1000);
chartTitle = chartTitle + " (Last " + minuteDelta + " Minutes)";
xTitle = "minutes";
}
}
if(frequency == Calendar.SECOND) {
chartTitle = "Updates per Second";
if(end != null && start != null) {
long delta = (end.getTime() - start.getTime()) / (1000);
chartTitle = chartTitle + " (Last " + delta + " Seconds)";
xTitle = "seconds";
}
}
TimeSeriesCollection dataset = new TimeSeriesCollection();
dataset.addSeries(ts);
return this.getGraphFromDataSet(dataset, chartTitle, xTitle, "updates");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment