com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

Custom Report Sample

This sample explains how to create a Custom Report for Services in WSO2 Governance Registry in few easy steps. We will be reusing the code of the Handler Sample in this example. This sample requires Apache Maven. See Installation Prerequisites for links on how to install it.

Alternatives

This sample includes two different alternatives that would in return produce two different types of reports:

  1. A list of all services including details of name, version along with a brief description.
  2. A side-by-side comparison between two services.

The instructions below explain how to run the first alternative. For the second alternative you have make a few changes to the first alternative. Read more under Instructions 2.

Instructions 1

  1. Navigate to GREG_HOME/ samples/handler/src to find the source code of the Handler Sample.
  2. Add the following dependency to your POM file. Make sure you update the current version of the registry (e.g. 4.4.3) and carbon governance (e.g. 4.5.1). 

    Project Object Model (POM) is an XML representation of a Maven project held in a file named pom.xml. You should find POM file by the name pom.xml inside GREG_HOME/ samples/handler/src.

    <dependency>
    <groupId>org.wso2.carbon.registry</groupId>
    <artifactId>org.wso2.carbon.registry.reporting</artifactId>
    <version>${carbon.registry.version}</version>
    </dependency>
    <dependency>
    <groupId>org.wso2.carbon.commons</groupId>
    <artifactId>org.wso2.carbon.reporting.api</artifactId>
    <version>${carbon.commons.version}</version>
    </dependency>
    <dependency>
    <groupId>org.wso2.carbon.commons</groupId>
    <artifactId>org.wso2.carbon.reporting.util</artifactId>
    <version>${carbon.commons.version}</version>
    </dependency>
    <dependency>
    <groupId>org.wso2.carbon.governance</groupId>
    <artifactId>org.wso2.carbon.governance.api</artifactId>
    <version>${carbon.governance.version}</version>
    </dependency>
  3. Add a new Java Class named ServiceReportGenerator at GREG_HOME/samples/handler/src/src/main/java/org/wso2/carbon/registry/samples/reporting/ServiceReportGenerator.java with the following source:

    package org.wso2.carbon.registry.samples.reporting;
     
    import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
    import org.wso2.carbon.governance.api.services.ServiceManager;
    import org.wso2.carbon.governance.api.services.dataobjects.Service;
    import org.wso2.carbon.governance.api.util.GovernanceUtils;
    import org.wso2.carbon.registry.core.Registry;
    import org.wso2.carbon.registry.core.session.CurrentSession;
    import org.wso2.carbon.registry.core.utils.RegistryUtils;
    import org.wso2.carbon.registry.reporting.AbstractReportGenerator;
    import org.wso2.carbon.reporting.util.JasperPrintProvider;
    import org.wso2.carbon.reporting.util.ReportParamMap;
    import org.wso2.carbon.reporting.util.ReportStream;
     
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.LinkedList;
    import java.util.List;
     
    public class ServiceReportGenerator extends AbstractReportGenerator {
     
        public ByteArrayOutputStream execute(String template, String type)
                throws IOException {
     
            try {
                Registry registry = getRegistry();
     
                // Read Template
                String templateContent = RegistryUtils.decodeBytes(
                        (byte[]) registry.get(template).getContent());
     
                // Create Report Bean Collection
                ServiceManager manager = new ServiceManager(
                        GovernanceUtils.getGovernanceUserRegistry(registry, CurrentSession.getUser()));
                List<ReportBean> beanList = new LinkedList<ReportBean>();
                for (Service artifact : manager.getAllServices()) {
                    beanList.add(new ReportBean(artifact.getAttribute("overview_name"),
                            artifact.getAttribute("overview_version"),
                            artifact.getAttribute("overview_description")));
                }
     
                // Generate Report Stream
                return new ReportStream().getReportStream(new JasperPrintProvider().createJasperPrint(
                        new JRBeanCollectionDataSource(beanList), templateContent,
                        new ReportParamMap[0]), type);
     
            } catch (Exception e) {
                e.printStackTrace();
            }
     
            return new ByteArrayOutputStream(0);
        }
     
        public static class ReportBean {
            private String overview_name;
            private String overview_version;
            private String overview_description;
     
            public ReportBean(String overview_name, String overview_version,
                              String overview_description) {
                this.overview_name = overview_name;
                this.overview_version = overview_version;
                this.overview_description = overview_description;
            }
     
            public String getOverview_name() {
                return overview_name;
            }
     
            public String getOverview_version() {
                return overview_version;
            }
     
            public String getOverview_description() {
                return overview_description;
            }
        }
     
    }

     

    The WSO2 Governance Registry uses the Jasper Reporting Engine. Learn more on Jasper Reporting APIs to generate more elegant reports.

     

  4. Compile the source code by running the following command inside GREG_HOME/ samples/handler/src:

    mvn clean install

     

    The command mvn clean install will trigger an Apache Maven Build in your command line. This requires you having installed Apache Maven. See Installation Prerequisites for links on how to install it.

     A successful run of Apache Maven will generate a report similar to the following:

  5. Copy the GREG_HOME/ samples/handler/src/target/ org.wso2.carbon.registry.samples.handler-4.5.0.jar into GREG_HOME/repository/components/dropins.
  6. Start the WSO2 Governance Registry. See Running the Product for more information.
  7. Navigate to the Resource Browser of Governance Registry and add a new resource as text content with the following parameters:
    1. Name - /_system/governance/repository/components/org.wso2.carbon.governance/templates/service_template.jrxml
    2. Media Type - application/xml
    3. Content - (Copy the content below)

      <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Service List Report" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
      	<property name="ireport.zoom" value="1.3310000000000068"/>
      	<property name="ireport.x" value="0"/>
      	<property name="ireport.y" value="0"/>
              <field name="overview_name" class="java.lang.String"/>
              <field name="overview_version" class="java.lang.String"/>
              <field name="overview_description" class="java.lang.String"/>
      	<background>
      		<band height="802" splitType="Stretch"/>
      	</background>
      	<title>
      		<band height="52" splitType="Stretch">
      			<staticText>
      				<reportElement x="0" y="9" width="555" height="27"/>
      				<textElement textAlignment="Center" verticalAlignment="Middle">
      					<font fontName="SansSerif" size="20"/>
      				</textElement>
      				<text><![CDATA[Service List Report]]></text>
      			</staticText>
      		</band>
      	</title>
      	<pageHeader>
      		<band splitType="Stretch"/>
      	</pageHeader>
      	<columnHeader>
      		<band height="29" splitType="Stretch">
      			<staticText>
      				<reportElement x="0" y="0" width="150" height="21"/>
      				<textElement textAlignment="Left" verticalAlignment="Middle">
      					<font fontName="SansSerif" size="12" isBold="true"/>
      				</textElement>
      				<text><![CDATA[Name]]></text>
      			</staticText>
      			<staticText>
      				<reportElement x="150" y="0" width="305" height="21"/>
      				<textElement textAlignment="Center" verticalAlignment="Middle">
      					<font fontName="SansSerif" size="12" isBold="true"/>
      				</textElement>
      				<text><![CDATA[Version]]></text>
      			</staticText>
      			<line>
      				<reportElement x="0" y="21" width="555" height="1"/>
      			</line>
      			<staticText>
      				<reportElement x="455" y="0" width="100" height="21"/>
      				<textElement textAlignment="Center" verticalAlignment="Middle">
      					<font fontName="SansSerif" size="12" isBold="true"/>
      				</textElement>
      				<text><![CDATA[Description]]></text>
      			</staticText>
      		</band>
      	</columnHeader>
      	<detail>
      		<band height="30" splitType="Stretch">
      			<textField>
      				<reportElement x="0" y="4" width="305" height="20"/>
      				<textElement textAlignment="Center" verticalAlignment="Middle"/>
      				<textFieldExpression class="java.lang.String"><![CDATA[$F{overview_name}]]></textFieldExpression>
      			</textField>
      			<textField>
      				<reportElement x="305" y="4" width="150" height="20"/>
      				<textElement textAlignment="Left" verticalAlignment="Middle"/>
      				<textFieldExpression class="java.lang.String"><![CDATA[$F{overview_version}]]></textFieldExpression>
      			</textField>
      			<textField>
      				<reportElement x="455" y="4" width="100" height="20"/>
      				<textElement textAlignment="Center" verticalAlignment="Middle"/>
      				<textFieldExpression class="java.lang.String"><![CDATA[$F{overview_description}]]></textFieldExpression>
      			</textField>
      		</band>
      	</detail>
      	<columnFooter>
      		<band splitType="Stretch"/>
      	</columnFooter>
      	<pageFooter>
      		<band height="29" splitType="Stretch">
      			<staticText>
      				<reportElement x="0" y="3" width="204" height="18"/>
      				<textElement verticalAlignment="Top">
      					<font size="8"/>
      				</textElement>
      				<text><![CDATA[Created with WSO2 Governanace Registry]]></text>
      			</staticText>
      			<line>
      				<reportElement x="0" y="1" width="555" height="1"/>
      			</line>
      			<textField>
      				<reportElement x="246" y="2" width="80" height="20"/>
      				<textElement textAlignment="Right">
      					<font size="8"/>
      				</textElement>
      				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
      			</textField>
      			<textField evaluationTime="Report">
      				<reportElement x="327" y="2" width="69" height="20"/>
      				<textElement>
      					<font size="8"/>
      				</textElement>
      				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
      			</textField>
      			<textField pattern="dd/MM/yyyy HH.mm.ss">
      				<reportElement x="456" y="3" width="99" height="18"/>
      				<textElement textAlignment="Center">
      					<font size="8"/>
      				</textElement>
      				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
      			</textField>
      		</band>
      	</pageFooter>
      	<summary>
      		<band splitType="Stretch"/>
      	</summary>
      </jasperReport>
  8. Click the "Add" button to finish adding the text content.

    Read more on Text Content Creation.

    The WSO2 Governance Registry uses the Jasper Reporting Engine. The Template File that you created is a Jasper Report Template (.jrxml). Learn more on how to use tools like iReport to generate these template files.

  9. Now, you need to Add a new Report using the following parameters:
    1. Report Name - Service Report
    2. Template - /_system/governance/repository/components/org.wso2.carbon.governance/templates/service_template.jrxml
    3. Report Type - PDF
    4. Report Class - org.wso2.carbon.registry.samples.reporting.ServiceReportGenerator
  10. Click the "Add" button to finish adding the report.

    See the section on Reports to learn how to add reports and manage existing reports.
  11. Add a few Services to Governance Registry. Read more on /wiki/spaces/~yohanna@wso2.com/pages/21233672.
  12. Go to the Manage Reports screen, and select "Generate" to open the Generate Report Screen.
  13. Finally, click on the "Generate" button to generate the report.

    You should now find a PDF file named "Service Report.pdf" getting downloaded.

Instructions 2

Create two new services called "CXFService" and "Axis2service" before generating the report. For information on adding a service, see Managing Services.

In step 3 of the example above, use the following code in ServiceReportGenerator at GREG_HOME/samples/handler/src/src/main/java/org/wso2/carbon/registry/samples/reporting/ServiceReportGenerator.java:

package org.wso2.carbon.registry.samples.reporting;
  
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.wso2.carbon.governance.api.exception.GovernanceException;
import org.wso2.carbon.governance.api.services.ServiceFilter;
import org.wso2.carbon.governance.api.services.ServiceManager;
import org.wso2.carbon.governance.api.services.dataobjects.Service;
import org.wso2.carbon.governance.api.util.GovernanceUtils;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.session.CurrentSession;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.registry.reporting.AbstractReportGenerator;
import org.wso2.carbon.registry.reporting.annotation.Property;
import org.wso2.carbon.reporting.util.JasperPrintProvider;
import org.wso2.carbon.reporting.util.ReportParamMap;
import org.wso2.carbon.reporting.util.ReportStream;
  
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
  
public class ServiceReportGenerator extends AbstractReportGenerator {
  
    private String service1;
    private String service2;
  
    @Property(mandatory = true)
    public void setService1(String service1) {
        this.service1 = service1;
    }
  
    @Property(mandatory = true)
    public void setService2(String service2) {
        this.service2 = service2;
    }
  
    public ByteArrayOutputStream execute(String template, String type)
            throws IOException {
  
        try {
            Registry registry = getRegistry();
  
            // Read Template
            String templateContent = RegistryUtils.decodeBytes(
                    (byte[]) registry.get(template).getContent());
  
            // Create Report Bean Collection
            ServiceManager manager = new ServiceManager(
                    GovernanceUtils.getGovernanceUserRegistry(registry, CurrentSession.getUser()));
	        GovernanceUtils.loadGovernanceArtifacts((UserRegistry) GovernanceUtils.getGovernanceUserRegistry(registry, CurrentSession.getUser()));
            List<ReportBean> beanList = new LinkedList<ReportBean>();
            Service s1 = findService(manager, service1);
            Service s2 = findService(manager, service2);
            String s1_name = s1.getQName().getLocalPart();
            String s2_name = s2.getQName().getLocalPart();
            for (String key : s1.getAttributeKeys()) {
                String[] s1_attributes = s1.getAttributes(key);
                String[] s2_attributes = s2.getAttributes(key);
                if (s2_attributes != null) {
                    if (s1_attributes.length > 1 || s2_attributes.length > 1) {
                        beanList.add(new ReportBean(s1_name, s2_name, key,
                                getAttributeString(s1_attributes),
                                getAttributeString(s2_attributes)));
                    } else {
                        beanList.add(new ReportBean(s1_name, s2_name, key,
                                s1_attributes[0], s2_attributes[0]));
                    }
                }
            }
  
            // Generate Report Stream
            return new ReportStream().getReportStream(new JasperPrintProvider().createJasperPrint(
                    new JRBeanCollectionDataSource(beanList), templateContent,
                    new ReportParamMap[0]), type);
  
        } catch (Exception e) {
            e.printStackTrace();
        }
  
        return new ByteArrayOutputStream(0);
    }
  
    private String getAttributeString(String[] attributes) {
        StringBuilder s1_attrString = new StringBuilder();
        for (String attribute : attributes) {
            s1_attrString.append(attribute).append(";");
        }
        return s1_attrString.toString();
    }
  
    private Service findService(ServiceManager manager, final String serviceStr)
            throws GovernanceException {
        Service[] temp = manager.findServices(new ServiceFilter() {
            public boolean matches(Service service) throws GovernanceException {
                String[] parts = serviceStr.split(";");
                return parts[0].equals(service.getQName().getLocalPart()) &&
                        (parts.length <= 1 ||
                                parts[1].equals(service.getQName().getNamespaceURI())) &&
                        (parts.length <= 2 ||
                                parts[2].equals(service.getAttribute("overview_version")));
            }
        });
        return (temp == null || temp.length == 0) ? null : temp[0];
    }
  
    public static class ReportBean {
        private String name1;
        private String name2;
        private String attr_name;
        private String attr_value1;
        private String attr_value2;
  
        public ReportBean(String name1, String name2, String attr_name, String attr_value1,
                          String attr_value2) {
            this.name1 = name1;
            this.name2 = name2;
            this.attr_name = attr_name;
            this.attr_value1 = attr_value1;
            this.attr_value2 = attr_value2;
        }
  
        public String getName1() {
            return name1;
        }
  
        public String getName2() {
            return name2;
        }
  
        public String getAttr_name() {
            return attr_name;
        }
  
        public String getAttr_value1() {
            return attr_value1;
        }
  
        public String getAttr_value2() {
            return attr_value2;
        }
    }
  
}

Report Generator classes can optionally accept attributes. To define attributes, you need to include a method that starts with set along with the @Property annotation. Set mandatory = true to indicate that this is a mandatory attribute. The Load Attributes button can be used to load these attributes.

In step 7 of the example above, use the following template:

<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Service-Service Comparison" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
	<property name="ireport.zoom" value="1.3310000000000068"/>
	<property name="ireport.x" value="0"/>
	<property name="ireport.y" value="0"/>
        <field name="name1" class="java.lang.String"/>
        <field name="name2" class="java.lang.String"/>
        <field name="attr_name" class="java.lang.String"/>
        <field name="attr_value1" class="java.lang.String"/>
        <field name="attr_value2" class="java.lang.String"/>
	<background>
		<band height="802" splitType="Stretch"/>
	</background>
	<title>
		<band height="52" splitType="Stretch">
			<staticText>
				<reportElement x="0" y="9" width="555" height="27"/>
				<textElement textAlignment="Center" verticalAlignment="Middle">
					<font fontName="SansSerif" size="20"/>
				</textElement>
				<text><![CDATA[Service-Service Comparison]]></text>
			</staticText>
		</band>
	</title>
	<pageHeader>
		<band splitType="Stretch"/>
	</pageHeader>
	<columnHeader>
		<band height="29" splitType="Stretch">
			<textField>
				<reportElement x="155" y="0" width="200" height="21"/>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="SansSerif" size="12" isBold="true"/>
				</textElement>
				<textFieldExpression class="java.lang.String"><![CDATA[$F{name1}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="355" y="0" width="200" height="21"/>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="SansSerif" size="12" isBold="true"/>
				</textElement>
				<textFieldExpression class="java.lang.String"><![CDATA[$F{name2}]]></textFieldExpression>
			</textField>
		</band>
	</columnHeader>
	<detail>
		<band height="30" splitType="Stretch">
			<textField>
				<reportElement x="0" y="4" width="155" height="20"/>
				<textElement textAlignment="Left" verticalAlignment="Middle"/>
				<textFieldExpression class="java.lang.String"><![CDATA[$F{attr_name}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="155" y="4" width="200" height="20"/>
				<textElement textAlignment="Left" verticalAlignment="Middle"/>
				<textFieldExpression class="java.lang.String"><![CDATA[$F{attr_value1}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="355" y="4" width="200" height="20"/>
				<textElement textAlignment="Left" verticalAlignment="Middle"/>
				<textFieldExpression class="java.lang.String"><![CDATA[$F{attr_value2}]]></textFieldExpression>
			</textField>
		</band>
	</detail>
	<columnFooter>
		<band splitType="Stretch"/>
	</columnFooter>
	<pageFooter>
		<band height="29" splitType="Stretch">
			<staticText>
				<reportElement x="0" y="3" width="204" height="18"/>
				<textElement verticalAlignment="Top">
					<font size="8"/>
				</textElement>
				<text><![CDATA[Created with WSO2 Governanace Registry]]></text>
			</staticText>
			<line>
				<reportElement x="0" y="1" width="555" height="1"/>
			</line>
			<textField>
				<reportElement x="246" y="2" width="80" height="20"/>
				<textElement textAlignment="Right">
					<font size="8"/>
				</textElement>
				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
			</textField>
			<textField evaluationTime="Report">
				<reportElement x="327" y="2" width="69" height="20"/>
				<textElement>
					<font size="8"/>
				</textElement>
				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
			</textField>
			<textField pattern="dd/MM/yyyy HH.mm.ss">
				<reportElement x="456" y="3" width="99" height="18"/>
				<textElement textAlignment="Center">
					<font size="8"/>
				</textElement>
				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
			</textField>
		</band>
	</pageFooter>
	<summary>
		<band splitType="Stretch"/>
	</summary>
</jasperReport>

The WSO2 Governance Registry uses the Jasper Reporting Engine. The Template File that you created is a Jasper Report Template (.jrxml). Learn more on how to use tools like iReport to generate these template files.

com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.