An Oracle blog about Oracle Coherence

Running Tabular Reports with Coherence 12.1.3 Reporter

Tim Middleton
Solution Architect


With the latest release of Coherence 12.1.3, we introduced the Coherence JVisualVM Plug-in as part of the product. As part of the internal development of the plug-in, we needed a way of running "Reporter" reports and retrieving the output directly from the operation return value.  The current runReport operation (which is useful for writing out reports to disk) takes in a report name and then writes the output to the filesystem using the OutputPath defined on the MBean.

Based upon this requirement, we introduced the runTabularReport operation on the Reporter MBean which takes either a report name or report XML and returns a TabularData object containing the report output. We exposed this on the MBean as we knew this would be useful for customers.


The following operations were added in 12.1.3

  • runTabularReport(String sReportFile)
  • runTabularGroupReport(String sReportName, Map mapXmlReports)

We are going to focus on the runTabularReport which is the easiest to understand and use.


Startup JVisualVM and connect to a JMX enabled cluster. Select the Reporter MBean and select one of the nodes. Enter the following report name as an argument and click runTabularReport. (Make sure you have at least one cache defined, otherwise null will be returned).

  • reports/report-cache-size.xml 

 The following will be displayed. If you have more than one cache then you can scroll through the results of the report.

 To view the full list of reports available out of the box you can issue the following command against coherence.jar.

 timmiddleton$ jar tvf coherence.jar | grep reports
     0 Thu Apr 03 14:49:54 WST 2014 reports/
  2272 Thu Apr 03 14:49:52 WST 2014 reports/report-all.xml
 17745 Thu Apr 03 14:49:52 WST 2014 reports/report-cache-effectiveness.xml
  2629 Thu Apr 03 14:49:52 WST 2014 reports/report-cache-size.xml
  2152 Thu Apr 03 14:49:52 WST 2014 reports/report-flashjournal.xml
  1672 Thu Apr 03 14:49:52 WST 2014 reports/report-group.xml
  1368 Thu Apr 03 14:49:52 WST 2014 reports/report-management.xml
  4652 Thu Apr 03 14:49:52 WST 2014 reports/report-memory-status.xml
  4541 Thu Apr 03 14:49:52 WST 2014 reports/report-network-health-detail.xml
  7743 Thu Apr 03 14:49:52 WST 2014 reports/report-network-health.xml
  1656 Thu Apr 03 14:49:52 WST 2014 reports/report-node.xml
  2638 Thu Apr 03 14:49:52 WST 2014 reports/report-persistence-detail.xml
  2929 Thu Apr 03 14:49:52 WST 2014 reports/report-persistence.xml
  4270 Thu Apr 03 14:49:52 WST 2014 reports/report-proxy.xml
  1715 Thu Apr 03 14:49:52 WST 2014 reports/report-ramjournal.xml
  4588 Thu Apr 03 14:49:52 WST 2014 reports/report-service.xml
 18473 Thu Apr 03 14:49:52 WST 2014 reports/report-web-cache-overflow.xml
 18456 Thu Apr 03 14:49:52 WST 2014 reports/report-web-cache-sessions.xml
  1771 Thu Apr 03 14:49:52 WST 2014 reports/report-web-group.xml
  4625 Thu Apr 03 14:49:52 WST 2014 reports/report-web-service.xml
 16907 Thu Apr 03 14:49:52 WST 2014 reports/report-web-sessions.xml
  3856 Thu Apr 03 14:49:52 WST 2014 reports/report-web.xml

This is well and good, but the main reason you would want to do this is to directly run a report given a MBeanServer connection and retrieve the results.  

Programatic Access to Reports Output 

All you need to run a report is an MBeanServer connection. This can be obtained via either using the MBeanHelper as per below, or there are a couple of code examples out there you could utilise such as here or here. (Thanks to Ben and Aleks)

Then you can invoke the runTabularReport using that connection.

In my example below, i'm doing the following:

  1. Setting system properties to ensure we have JMX management set
  2. Connect to / create a Coherence Cluster
  3. Get the MBeanServer using the helper
  4. Create some caches and insert data 
  5. Run the report
  6. Navigate the TabularData and output the values.

The full code example is below. 

import com.tangosol.net.CacheFactory;
import com.tangosol.net.Cluster;
import com.tangosol.net.NamedCache;
import com.tangosol.net.management.MBeanHelper;
import java.util.Collection;
import java.util.Set;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.TabularData;
public class ReporterExample
public static void main(String[] args)
throws InstanceNotFoundException, MalformedObjectNameException,
ReflectionException, MBeanException
// enable management before we start/join a cluster
System.setProperty("tangosol.coherence.management", "all");
System.setProperty("tangosol.coherence.log.level", "2");
Cluster cluster = CacheFactory.ensureCluster();
MBeanServer server = MBeanHelper.findMBeanServer();
// create caches and add some data
NamedCache nc1 = CacheFactory.getCache("dist-tim1");
NamedCache nc2 = CacheFactory.getCache("dist-tim2");
nc1.put("key1", "value1");
nc2.put("key1", "value1");
// get the local member to run the report on
int nLocalMemberId = cluster.getLocalMember().getId();
TabularData reportData = (TabularData) server.invoke(
new ObjectName("Coherence:type=Reporter,nodeId=" + nLocalMemberId),
new Object[] {"reports/report-cache-size.xml"},
new String[] {"java.lang.String"});
// navigate the data
if (reportData != null)
Set<?> setKeys = reportData.keySet();
if (setKeys.size() > 0)
// loop through each key, which is actually the row of data
for (Object oKey : setKeys)
// get the columns as an array
Object[] aoColumns = ((Collection<Object>) oKey).toArray();
for (int i = 0; i < aoColumns.length; i++)
System.out.print(aoColumns[i].toString() + "\t");

Running this for my cluster and two caches gives the following output:

 Oracle Coherence Version 
 Grid Edition: Development mode
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
1 0 DistributedCache dist-tim 100000.0 3.1776896E7 30.3048095703125 317.76896

2 0 DistributedCache dist-tim1 1.0 224.0 2.13623046875E-4 224.0

3 0 DistributedCache dist-tim2 1.0 224.0 2.13623046875E-4 224.0

You can also pass in report XML rather than an actual report file, so you can build up your reporter XML on the fly or manipulate the XML before you run it, e.g. parameterise it!

If you have a report group, it can be a little trickier to navigate,  but here is some guidance. Execute the specified report file or report XML defined in the sReport argument. If the report XML file or XML content defines a single report, the returned TabularData will have a CompositeData for each row of values from the report. It will also include a rowId attribute for indexing. For example:

        TabularData(sReportFile) =
                TabularData[ CompositeData { attribute1 -> value1,
                                             attribute2 -> value2,
                                             rowId      -> 1},
                             CompositeData { attribute1 -> value1,
                                             attribute2 -> value2,
                                             rowId      -> 2} ]

If the specified file or XML content defines a report group, the returned TabularData will have a single CompositeData with report-names as keys and TabularDatas of the reports as values. For example:

        TabularData[ CompositeData { report1 -> TabularData(report1),
                                 report2 -> TabularData(report2) } ]


Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.