Sometimes a chart is worth a thousand words.

If you’re developing a business app with an administrative console, it’s likely that you’ll want to show your admins one or more charts. That way, they can get a quick overview of key metrics.

As a Spring Boot developer who’s focused heavily on back-end code, you might struggle to produce quality charts on the UI. That doesn’t have to be the case.

With Highcharts, you have a great way to add slick, even three-dimensional, charts to your app.

In this article, we’ll go over how to integrate Highcharts with Spring Boot. As is usually the case, you can view the complete source code on GitHub.
 

The Use Case

The use case for this tutorial is that you have a Spring Boot e-commerce app that sells saltwater fishing tackle online. You’ve just been given a requirement to add charts to the admin console.

In this case, you’re going to draw a couple of charts that show info about sales between May and July. Specifically, you need to draw two charts:

  • A stacked column chart that breaks down sales by lure type (inshore, nearshore, and offshore) for each month
  • A pie chart that breaks down sales by U.S. region (Northeast, South, Midwest, and West)

 

Get the Highcharts Code

Start by grabbing the Highcharts code. For the purposes of this use case, you just need two files: highcharts.js and highcharts-3d.js.

Just copy and paste the contents of those files into your own local file of the same name. To follow the Metronic pattern, it’s best to put them in the /static/assets/global/plugins/highcharts/js folder under /src/main/resources.

So you’re tree should look like this:

highcharts

 

 

Create the Controller

As with most Spring Boot apps, you’re going to need a controller class that will not only forward the user to the correct HTML file, but also set up the data you want to display on the charts.

To make things simple here, just hardcode the data directly into the controller. In a real-life situation, of course, you’d grab the data from a database and maybe even do some number-crunching on the business logic side.

Here’s what your controller class should look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Controller
public class ChartController {
 
    @RequestMapping(value = "/chart", method=RequestMethod.GET)
    public String chart(Model model) {
         
        //first, add the regional sales
        Integer northeastSales = 17089;
        Integer westSales = 10603;
        Integer midwestSales = 5223;
        Integer southSales = 10111;
         
        model.addAttribute("northeastSales", northeastSales);
        model.addAttribute("southSales", southSales);
        model.addAttribute("midwestSales", midwestSales);
        model.addAttribute("westSales", westSales);
         
        //now add sales by lure type
        List<Integer> inshoreSales = Arrays.asList(4074, 3455, 4112);
        List<Integer> nearshoreSales = Arrays.asList(3222, 3011, 3788);
        List<Integer> offshoreSales = Arrays.asList(7811, 7098, 6455);
         
        model.addAttribute("inshoreSales", inshoreSales);
        model.addAttribute("nearshoreSales", nearshoreSales);
        model.addAttribute("offshoreSales", offshoreSales);
         
        return "chart";
    }
     
     
    //redirect to demo if user hits the root
    @RequestMapping("/")
    public String home(Model model) {
        return "redirect:chart";
    }
}

As you can see, the code begins by mapping the /chart URL path to the chart() method.

Then, the method starts off by hardcoding the sales figures per region and adding them to the Model object.

After that, the code creates three lists: one for inshore sales, one for nearshore sales, and one for offshore sales. Each list contains three integers that represent the sales for May, June, and July respectively.

Those lists are all added to the model with intuitive attribute names.

Finally, the method returns the string “chart.” In this case, that means the UI will display the contents of chart.html in the templates folder under /src/main/resources.

Let’s look at that HTML file next.

 

The HTML File

Recall that your requirement is to draw two charts: one stacked column chart and a pie chart. With Highcharts, that means you need to create a <div> element that basically acts as a placeholder for each chart.

So the relevant HTML code will look something like this:

1
2
3
4
5
6
7
8
<div class="row" style="margin-bottom:30px">
    <div class="col-md-6" style="margin-top:20px">
        <div id="salesByType" style="width:100%; height:400px;"></div>
    </div>
    <div class="col-md-6" style="margin-top:20px">
        <div id="salesByRegion" style="width:100%; height:400px;"></div>
    </div>
</div>

While there are several <div> elements in that code block, you can clearly see the two that will hold the charts. The id of the first one is salesByType and the id of the second one is salesByRegion.

So how does Highcharts populate those <div> elements with beautiful graphs? That magic happens with the help of jQuery.

More specifically: it happens with the help of jQuery and Thymeleaf.

 

The jQuery Code

Within your HTML file, add some jQuery code that will draw your graphs. In this case, you’ll need to add a function that executes when the DOM is ready.

The standard jQuery notation for that is this:

1
2
3
4
$(function () {
 
...
});

But wait. There’s more.

You’re going to do some shorthand Thymeleaf notation in this jQuery code. As a result, you need to “tell” Thymeleaf that you’re doing some script inlining.

Here’s what that looks like:

1
2
3
4
5
6
<script th:inline="javascript">
/*<![CDATA[*/
 
...
 
/*]]>*/

Keep in mind: that goes around the entire JavaScript block. You can see the whole thing in the HTML file on GitHub as well as later on in this article.

 

Configure Highcharts

As with so many other third-party tools, Highcharts has some configuration options. You’ll need to set a couple of those options here.

1
2
3
4
5
6
Highcharts.setOptions({
    lang: {
        decimalPoint: '.',
        thousandsSep: ','
    }
});

That’s pretty self-explanatory. You’re telling Highcharts to use a period for a decimal point and to separate thousands with a comma. You’ll get a space between thousands by default if you don’t set that second option.

 

Draw the Stacked Column Chart

It’s finally time to write code that actually draws a chart. Start by creating a function that will draw the stacked column chart.

Remember, that’s the graph that shows sales by lure type for each of the three months. Here’s what the code looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
function drawSalesByTypeChart() {
    var salesByTypeChart = Highcharts.chart('salesByType', {
        chart: {
            type: 'column',
            margin: 75,
            options3d: {
                enabled: true,
                alpha: 15,
                beta: 15,
                depth: 110
            }
        },
        title: {
            text: 'Sales by Lure Type'
        },
        xAxis: {
            categories: ['May', 'June', 'July']
        },
        yAxis: {
            title: {
                text: 'Sales (US $)'
            }
        },
        tooltip: {
            pointFormat: "${point.y:,.0f}"
        },
        plotOptions: {
            column: {
                depth: 60,
                stacking: true,
                grouping: false,
                groupZPadding: 10
            }
        },
        series: [{
            name: 'Inshore',
            data: /**/ []
        }, {
            name: 'Nearshore',
            data: /**/ []
        }, {
            name: 'Offshore',
            data: /**/ []
        }]
    });
}

It’s beyond the scope of this article to go into too much detail about how to use Highcharts. If you want to know more about it, consult the documentation.

There are some important points to cover in the code block above, though.

First, pay particular attention to the salesByType parameter in the Highcharts.chart function call. That parameter must match the id of one of the <div> elements you created above.

Happily enough, it does.

Also note that the code is specifying the options3d object. That’s going to give us a pretty, three-dimensional graph.

The pointformat setting in the tooltip object specifies what users will see in the tooltip when they hover over certain parts of the chart. That awkward syntax basically says “precede the value of the y coordinate with a dollar sign and don’t show any decimal points.”

Towards the bottom, you’ll see the series array of name/data pairs. That bizarre structure you see for the value of data is actually grabbing info from the model.

Yes, it looks like it’s commented out, but it’s really doing some work.

For example, /**/ [] is telling Thymeleaf to get the request attribute named “inshoreSales” and assign it to the value of data on that line. In the event that there’s no request attribute named “inshoreSales,” the system will use the default setting of an empty array.

By the way, recall that the “inshoreSales” request attribute is actually a List object. Thymeleaf is cool enough to format that object in a way that JavaScript understands.

 

Draw the Pie Chart

Now that you’re done with the stacked column chart, it’s time to draw the pie chart. The code for that looks fairly similar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function drawSalesByRegionChart() {
    var salesByRegionChart = Highcharts.chart('salesByRegion', {
        chart: {
            type: 'pie',
            margin: 40,
            options3d: {
                enabled: true,
                alpha: 45,
                beta: 0
            }
        },
        title: {
            text: 'Sales by Region'
        },
        tooltip: {
            pointFormat: "${point.y:,.0f}"
        },
        plotOptions: {
            pie: {
                allowPointSelect: true,
                depth: 35
            }
        },
        series: [{
            name: 'Regions',
            colorByPoint:true,
            data: [{
                name: 'Northeast',
                y: /**/ 0
            },{
                name: 'South',
                y: /**/ 0
            },{
                name: 'Midwest',
                y: /**/ 0
            },{
                name: 'West',
                y: /**/ 0
            }]
        }]
    });
}

As you can see, you once again need to specify the id of the <div> element where the chart will appear.

Of course, the type of chart has also changed. You’re now drawing a pie chart instead of a column chart.

The series array uses the exact same kind of notation you used in the previous section.

 

Test It Out

When everything is completed, your entire JavaScript block should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<script th:inline="javascript">
/*<![CDATA[*/
    $(function () {
        Highcharts.setOptions({
            lang: {
                decimalPoint: '.',
                thousandsSep: ','
            }
        });
 
        drawSalesByTypeChart();
        drawSalesByRegionChart();
    });
     
     
    function drawSalesByRegionChart() {
        var salesByRegionChart = Highcharts.chart('salesByRegion', {
            chart: {
                type: 'pie',
                margin: 40,
                options3d: {
                    enabled: true,
                    alpha: 45,
                    beta: 0
                }
            },
            title: {
                text: 'Sales by Region'
            },
            tooltip: {
                pointFormat: "${point.y:,.0f}"
            },
            plotOptions: {
                pie: {
                    allowPointSelect: true,
                    depth: 35
                }
            },
            series: [{
                name: 'Regions',
                colorByPoint:true,
                data: [{
                    name: 'Northeast',
                    y: /**/ 0
                },{
                    name: 'South',
                    y: /**/ 0
                },{
                    name: 'Midwest',
                    y: /**/ 0
                },{
                    name: 'West',
                    y: /**/ 0
                }]
            }]
        });
    }
     
    function drawSalesByTypeChart() {
        var salesByTypeChart = Highcharts.chart('salesByType', {
            chart: {
                type: 'column',
                margin: 75,
                options3d: {
                    enabled: true,
                    alpha: 15,
                    beta: 15,
                    depth: 110
                }