Developing Reports

AEM provides a selection of standard reports most of which are based on a reporting framework.

Using the framework you can either extend these standard reports, or develop your own, completely new, report(s). The reporting framework integrates tightly with existing CQ5 concepts and principles so that developers can use their existing knowledge of CQ5 as a springboard for developing reports.

For the standard reports delivered with AEM:

NOTE

The tutorial Creating Your Own Report - An Example also shows how many of the principles below can be used.

You can also refer to the standard reports to see other examples of implementation.

NOTE

In the examples and definitions below the following notation is used :

  • Each line defines a node or a property where:
    N:<name> [<nodeType>] : Describes a node with the name of <*name*> and node type of <*nodeType*>.
    P:<name> [<propertyType] : Describes a property with the name of <*name*> and a property type of <*propertyType*>.
    P:<name> = <value> : Describes a property <name> that must be set to the value of <value>.

  • Indentation shows the hierarchical dependencies between the nodes.

  • Items separated by | denotes a list of possible items; for example, types or names; e.g. String|String[] means that the property can be either String or String[].

  • [] depicts an array; such as String[] or an array of nodes as in the Query Definition.

Unless otherwise stated the default types are:

  • Nodes - nt:unstructured
  • Properties - String

Reporting Framework

The reporting framework works on the following principles:

The reporting framework (illustrated by the structure of a standard report) uses the following building blocks, fed by the processing queue:

Report Page

The report page:

Report Base

The reportbase component forms the basis of any report as it:

Column Base

Each column is an instance of the columnbase component that:

The Query and Data Retrieval

The query:

This specifies the sub-tree of the repository to be searched.

To help minimize the performance impact, it is advisable to (try to) restrict the query to a specific sub-tree of the repository. The root path can be either predefined in the report template or set by the user in the Configuration (Edit) dialog.

These are imposed to produce the (initial) result set; they include for example, restrictions on the node type, or property constraints.

The developer has to ensure that the query defined for a report returns a node set appropriate for that report. However, the node itself need not hold all the required information, this can also be derived from parent and/or child nodes. For example, the query used for the User Report. However, most columns on this report do not take their data directly from these nodes, but from the child nodes profile.

Processing Queue

The query returns a result set of data to be displayed as rows on the report. Each row in the result set is processed (server-side), in several phases, before being transferred to the client for display on the report.

This allows:

For example, it allows you to process two property values as a single value by calculating the difference between the two.

For example, paths can be mapped to a title (as in the more human-readable content of the respective jcr:title property).

For example, consisting of a text that is displayed to the user, a value to be used for sorting and an additional URL that is used (on the client side) for creating a link.

Workflow of the Processing Queue

The following workflow represents the processing queue:

Phases of the Processing Queue

Where the detailed steps and elements are:

  1. Transforms the results returned by the initial query (reportbase) into the basic result set using value extractors.

    Value extractors are automatically chosen depending on the column type. They are used for reading values from the underlying JCR Query and creating a result set from them; after which further processing may then be applied. For example, for the diff type, the value extractor reads two properties, calculates the single value that is then added to the result set. The value extractors cannot be configured.

  2. To that initial result set, containing raw data, initial filtering (raw phase) is applied.

  3. Values are preprocessed; as defined for the apply phase.

  4. Filtering (assigned to the preprocessed phase) is executed on the preprocessed values.

  5. Values are resolved; according to the defined resolver.

  6. Filtering (assigned to the resolved phase) is executed on the resolved values.

  7. Data is grouped and aggregated.

  8. Array data is resolved by converting it into a (string-based) list.

    This is an implicit step that converts a multi-value result into a list that can be displayed; it is required for (unaggregated) cell values that are based on multi-value JCR properties.

  9. Values are again preprocessed; as defined for the afterApply phase.

  10. Data is sorted.

  11. The processed data is transferred to the client.

NOTE

The initial query returning the basis data result set is defined on the reportbase component.

Other elements of the processing queue are defined on the columnbase components.

Report Construction and Configuration

The following are needed to construct and configure a report:

Location of Report Components

The default reporting components are held under /libs/cq/reporting/components.

However, it is strongly recommended that you do not update these nodes, but create your own component nodes under /apps/cq/reporting/components or if more appropriate /apps/<yourProject>/reports/components.

Where (as an example):

N:apps
    N:cq [nt:folder]
        N:reporting|reports [sling:Folder]
            N:components [sling:Folder]

Under this you create the root for your report and under this, the report base component and the column base components:

N:apps
    N:cq [nt:folder]
        N:reporting|reports [sling:Folder]
            N:components [sling:Folder]
                N:<reportname> [sling:Folder]
                        N:<reportname> [cq:Component]  // report base component
                        N:<columnname> [cq:Component]  // column base component

Page Component

A report page must use the sling:resourceType of /libs/cq/reporting/components/reportpage.

A customized page component should not be necessary (in most cases).

Report Base Component

Each report type requires a container component derived from /libs/cq/reporting/components/reportbase.

This component acts as a container for the report as a whole and provides information for:

N:<reportname> [cq:Component]
    P:sling:resourceSuperType = "cq/reporting/components/reportbase"
    N:charting
    N:dialog [cq:Dialog]
    N:queryBuilder

Query Definition

N:queryBuilder
    N:propertyConstraints
    [
        N:<name> // array of nodes (name irrelevant), each with the following properties:
            P:name
            P:value
    ]
    P:nodeTypes [String|String[]]
    P:mandatoryProperties [String|String[]
  ]

Can be used to limit the result set to nodes that have specific properties with specific values. If multiple constraints are specified, the node must satisfy all of them (AND operation).

For example:

  N:propertyConstraints
   [
   N:0
   P:sling:resourceType
   P:foundation/components/textimage
   N:1
   P:jcr:modifiedBy
   P:admin
   ]

Would return all textimage components that were last modified by the admin user.

Used to limit the result set to the specified node types. Multiple node types can be specified.

Can be used to limit the result set to nodes that have all of the specified properties. The value of the properties is not taken into account.

All are optional and can be combined as necessary, but you must define at least one of them.

Chart Definitions

N:charting
    N:settings
        N:active [cq:WidgetCollection]
        [
            N:<name> // array of nodes, each with the following property
                P:id   // must match the id of a child node of definitions
        ]
    N:definitions [cq:WidgetCollection]
    [
        N:<name> // array of nodes, each with the following properties
            P:id
            P:type
            // additional, chart type specific configurations
    ]

Holds definitions for the active charts.

As multiple settings can be defined, you can use this to define which are currently active. These are defined by an array of nodes (there is no compulsory naming convention for these nodes, but the standard reports often use 0, 1x), each having the following property:

Identification for the active charts. This must match the id of one of the chart definitions.

Defines the chart types that are potentially available for the report. The definitions to be used will be specified by the active settings.

The definitions are specified using an array of nodes (again often named 0, 1x), each having the following properties:

The chart identification.

The type of chart available. Select from:

Pie chart. Generated from current data only.

Series of lines (connecting dots representing the actual snapshots). Generated from historic data only.

The maximum radius allowed for the pie chart; therefore the maximum size allowed for the chart (without legend). Ignored if fixedRadius is defined.

The minimum radius allowed for the pie chart. Ignored if fixedRadius is defined.

Defines a fixed radius for the pie chart.

True if an additional line showing the Total should be shown.
default: false

Number of lines/series to be shown.
default: 9 (this is also the maximum allowed)

Maximum number of aggregated snapshots (dots shown on each horizontal line, representing distinct values) for which popups are to be displayed i.e. when the user does mouse-over on a distinct value or corresponding label in the chart legend.

default: 35 (i.e. no popups at all are shown if more than 35 distinct values are applicable for the current chart settings).

There is an additional limit of 10 popups that can be shown in parallel (multiple popups can be shown when mouse-over is made over the legend texts).

Configuration Dialog

Every report can have a configuration dialog, allowing the user to specify various parameters for the report. This dialog is accessible through the Edit button when the report page is open.

This dialog is a standard CQ dialog.

An example dialog can look as follows:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="https://www.day.com/jcr/cq/1.0" xmlns:jcr="https://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Dialog"
    height="{Long}424">
    <items jcr:primaryType="cq:WidgetCollection">
        <props jcr:primaryType="cq:Panel">
            <items jcr:primaryType="cq:WidgetCollection">
                <title
                    jcr:primaryType="cq:Widget"
                    path="/libs/cq/reporting/components/commons/title.infinity.json"
                    xtype="cqinclude"/>
                <description
                    jcr:primaryType="cq:Widget"
                    path="/libs/cq/reporting/components/commons/description.infinity.json"
                    xtype="cqinclude"/>
                <rootPath
                    jcr:primaryType="cq:Widget"
                    fieldLabel="Root path"
                    name="./report/rootPath"
                    rootPath=""
                    rootTitle="Repository root"
                    xtype="pathfield"/>
                <processing
                    jcr:primaryType="cq:Widget"
                    path="/libs/cq/reporting/components/commons/processing.infinity.json"
                    xtype="cqinclude"/>
                <scheduling
                    jcr:primaryType="cq:Widget"
                    path="/libs/cq/reporting/components/commons/scheduling.infinity.json"
                    xtype="cqinclude"/>
            </items>
        </props>
    </items>
</jcr:root>

Several preconfigured components are provided; these can be referenced in the dialog, using the xtype property with a value of cqinclude:

/libs/cq/reporting/components/commons/title

Textfield to define the report title.

/libs/cq/reporting/components/commons/description

Textarea to define the report description.

/libs/cq/reporting/components/commons/processing

Selector for the report’s processing mode (manually/automatically load data).

/libs/cq/reporting/components/commons/scheduling

Selector for scheduling snapshots for the historic chart.

NOTE

The referenced components must be included using the .infinity.json suffix (see example above).

Root Path

Additionally a root path can be defined for the report:

This limits the report to a certain section (tree or subtree) of the repository, which is recommended for performance optimization. The root path is specified by the rootPath property of the report node of each report page (taken from the template upon page creation).

It can be specified by:

Column Base Component

Each column type requires a component derived from /libs/cq/reporting/components/columnbase.

A column component defines a combination of the following:

N:<columnname> [cq:Component]
    P:componentGroup
    P:jcr:title
    P:sling:resourceSuperType = "cq/reporting/components/columnbase"
    N:cq:editConfig [cq:EditConfig] // <a href="#events-and-actions">Events and Actions</a>
    N:defaults // <a href="#column-default-values">Column Default Values</a>
    N:definitions
      N:queryBuilder // <a href="#column-specific-query">Column Specific Query</a>
        P:property [String|String[]] // Column Specific Query
        P:subPath // Column Specific Query
        P:secondaryProperty [String|String[]] // Column Specific Query
        P:secondarySubPath // Column Specific Query
      N:data
        P:clientFilter [String] // <a href="#client-filter">Client Filter</a>
        P:resolver // <a href="#resolvers-and-preprocessing">Resolvers and Preprocessing</a>
        N:resolverConfig // Resolvers and Preprocessing
        N:preprocessing // Resolvers and Preprocessing
      P:type // <a href="#column-specific-definitions">Column Specific Definitions</a>
      P:groupable [Boolean] // Column Specific Definitions
      N:filters [cq:WidgetCollection] // Column Specific Definitions
      N:aggregates [cq:WidgetCollection] // Column Specific Definitions

See also Defining Your New Report.

Column Specific Query

This defines the specific data extraction (from the report data result set) for use in the individual column.

N:definitions
    N:queryBuilder
        P:property [String|String[]]
        P:subPath
        P:secondaryProperty [String|String[]]
        P:secondarySubPath

Defines the property to be used for calculating the actual cell value.

If property is defined as String[] multiple properties are scanned (in sequence) to find the actual value.

For example, in the case of:

property = [ "jcr:lastModified", "jcr:created" ]

The corresponding value extractor (which is in control here) will:

If the result is not located on the node that is returned by the query, subPath defines where the property is actually located.

Defines a second property that must also be used for calculating the actual cell value; this will only be used for certain column types (diff and sortable).

For example, in the case of the Workflow Instances Report, the property specified is used to store the actual value of the time difference (in milliseconds) between start and end times.

Similar to subPath, when secondaryProperty is used.

In most cases, only property will be used.

Client Filter

The client filter extracts the information to be displayed, from the data returned by the server.

NOTE

This filter is executed clientside, after the entire serverside processing has been applied.

N:definitions
    N:data
        P:clientFilter [String]

clientFilter is defined as a JavaScript function that:

The following example extracts the corresponding page path from a component path:

function(v) {
    var sepPos = v.lastIndexOf('/jcr:content');
    if (sepPos < 0) {
        return v;
    }
    return v.substring(sepPos + '/jcr:content'.length, v.length);
}

Resolvers and Preprocessing

The processing queue defines the various resolvers and configures the preprocessing:

N:definitions
    N:data
        P:resolver
        N:resolverConfig
        N:preprocessing
            N:apply
            N:applyAfter

Defines the resolver to be used. The following resolvers are available:

Maps values to other values; for example, this is used to resolve constants such as en to its equivalent value English.

The default resolver. This is a dummy resolver that actually resolves nothing.

Resolves a path value to the path of the appropriate page; more precisely, to the corresponding jcr:content node. For example, /content/.../page/jcr:content/par/xyz is resolved to /content/.../page/jcr:content.

Resolves a path value by optionally appending a sub path and taking the actual value from a property of the node (as defined by resolverConfig) at the resolved path. For example, a path of /content/.../page/jcr:content can be resolved to the content of the jcr:title property, this would mean that a page path is resolved to the page title.

Resolves a value by prepending a path and taking the actual value from a property of the node at the resolved path. For example, a value de might be prepended by a path such as /libs/wcm/core/resources/languages, taking the value from the property language, to resolve the country code de to the language description German.

Provides definitions for the resolver; the options available are dependent on the resolver selected:

Use properties to specify the constants for resolving. The name of the property defines the constant to be resolved; the value of the property defines the resolved value.

For example a property with Name= 1 and Value =One will resolve 1 to One.

No configuration available.

Defines the name of the property that should be used for resolving the value. If not specified, the default value of jcr:title (the page title) is used; for the page resolver, this means that first the path is resolved to the page path, then further resolved to the page title.

Specifies the name of the property that should be used for resolving the value. If not specified, the default value of jcr:title is used.

This property can be used to specify a suffix to be appended to the path before the value is resolved.

Defines the path to be prepended.

Defines the property on the resolved path where the actual value is located.

Determines whether the resolved value should be internationalized (i.e. using CQ5’s internationalization services.

Preprocessing is optional and can be bound (separately) to the processing phases apply or applyAfter:

The initial preprocessing phase (step 3 in the representation of the processing queue).

Apply after preprocessing (step 9 in the representation of the processing queue).

Resolvers

The resolvers are used to extract the information required. Examples of the various resolvers are:

The following will resolve a contant value of VersionCreated to the string New version created.

See /libs/cq/reporting/components/auditreport/typecol/definitions/data.

N:data
    P:resolver=const
    N:resolverConfig
        P:VersionCreated="New version created"

Resolves a path value to the jcr:description property on the jcr:content (child) node of the corresponding page.

See /libs/cq/reporting/components/compreport/pagecol/definitions/data.

N:data
    P:resolver=page
    N:resolverConfig
        P:propertyName="jcr:description"

The following resolves a path of /content/.../page to the content of the jcr:title property, this would mean that a page path is resolved to the page title.

See /libs/cq/reporting/components/auditreport/pagecol/definitions/data.

N:data
    P:resolver=path
    N:resolverConfig
        P:propertyName="jcr:title"
        P:subPath="/jcr:content"

The following prepends a value de with the path extension /libs/wcm/core/resources/languages, then takes the value from the property language, to resolve the country code de to the language description German.

See /libs/cq/reporting/components/userreport/languagecol/definitions/data.

N:data
    P:resolver=pathextension
    N:resolverConfig
        P:path="/libs/wcm/core/resources/languages"
        P:propertyName="language"

Preprocessing

The preprocessing definition can be applied to either the:

The preprocessing definition for the original value is specified on apply and/or applyAfter directly.

If necessary, a separate definition can be provided for each aggregation.

To specify explicit preprocessing for aggregated values, the preprocessing definitions have to reside on a respective aggregated child node ( apply/aggregated, applyAfter/aggregated). If explicit preprocessing for distinct aggregates is required, the preprocessing definition is located on a child node with the name of the respective aggregate (for example apply/aggregated/min/max or other aggregates).

You can specify either of the following to be used during preprocessing:

When found, the specified pattern (which is defined as a regular expression) is replaced by another pattern; for example, this can be used to extract a substring of the original.

Converts a numeric value into a relative string; for example, the value ``representing a time difference of 1 hour would be resolved to a string such as 1:24PM (1 hour ago).

For example:

N:definitions
    N:data
        N:preprocessing
            N:apply|applyAfter
                P:pattern         // regex
                P:replace         // replacement for regex
                // and/or
                P:format          // data type formatter

Preprocessing - Find and Replace Patterns

For preprocessing you can specify a pattern (defined as a regular expression or regex) that is located and then substituted by the replace pattern:

The regular expression used to locate a substring.

The string, or representation of the string, that will be used as a replacement for the original string. Often this represents a substring of the string located by the regular expression pattern.

An example replacement can be broken down as:

Preprocessing - Data Type Formatters

These formatters convert a numeric value into a relative string.

For example, this can be used for a time column that allows min, avg and max aggregates. As min/ avg/ max aggregates are displayed as a time difference (e.g. 10 days ago), they require a data formatter. For this, a datedelta formatter is applied to the min/ avg/ max aggregated values. If a count aggregate is also available then this does not need a formatter, neither does the original value.

Currently the available data type formatters are:

Data type formatter:

Duration is the time span between two defined dates. For example, the start and end of a workflow action that took 1 hour, starting at 2/13/11 11:23h and ending one hour later at 2/13/11 12:23h.

It converts a numeric value (interpreted as milliseconds) into a duration string; for example, 30000 is formatted as * 30s.*

Datadelta is the time span between a date in the past until “now” (so it will have a different result if the report is viewed at a later point in time).

t converts the numeric value (interpreted as a time difference in days) into a relative date string. For example, 1 is formatted as 1 day ago.

The following example defines datedelta formatting for min and max aggregates:

N:definitions
    N:data
        N:preprocessing
            N:apply
                N:aggregated
                    N:min
                        P:format = "datedelta"
                    N:max
                        P:format = "datedelta"

Column Specific Definitions

The column specific definitions define the filters and aggregates available for that column.

N:definitions
    P:type
    P:groupable [Boolean]
    N:filters [cq:WidgetCollection]
    [
        N:<name> // array of nodes (names irrelevant) with the following properties:
            P:filterType
            P:id
            P:phase
    ]
    N:aggregates [cq:WidgetCollection]
    [
        N:<name> // array of nodes (names irrelevant) with the following properties:
            P:text
            P:type
    ]

The following are available as standard options:

Is used for extracting parts of a date needed for aggregation (for example, group by year to get data aggregated for each year).

Is used for values that use different values (as taken from different properties) for sorting and displaying.

In addition. any of the above can be defined as multi value; for example, string[] defines an array of strings.

The value extractor is chosen by the column type. If a value extractor is available for a column type, then this extractor is used. Otherwise, the default value extractor is used.

A type may (optionally) take a parameter. For example, timeslot:year extracts the year from a date field. Types with their parameters:

Defines whether the report can be grouped by this column.

Filter definitions.

Available filters are:

A string based filter.

Filter identifier.

Available phases:

Filter is applied on raw data.

Aggregate definitions.

Textual name of the aggregate. If text is not specified, then it will take the default description of the aggregate; for example, minimum will be used for the min aggregate.

Column Default Values

This is used to define default values for the column:

N:defaults
    P:aggregate

Valid aggregate values are the same as for type under aggregates (see Column Specific Definitions (definitions - filters / aggregates) ).

Events and Actions

Edit Configuration defines the necessary events for the listeners to detect and the actions to be applied after those events occurs. See the introduction to component development for background information.

The following values must be defined to ensure that all required actions are catered for:

N:cq:editConfig [cq:EditConfig]
    P:cq:actions [String[]] = "insert", "delete"
    P:cq:dialogMode = "floating"
    P:cq:layout = "auto"
    N:cq:listeners [cq:EditListenersConfig]
        P:aftercreate = "REFRESH_INSERTED"
        P:afterdelete = "REFRESH_SELF"
        P:afteredit = "REFRESH_SELF"
        P:afterinsert = "REFRESH_INSERTED"
        P:aftermove = "REFRESH_SELF"
        P:afterremove = "REFRESH_SELF"

Generic Columns

Generic columns are an extension where (most of) the column definitions are stored on the instance of the column node (rather than the component node).

They use a (standard) dialog, that you customize, for the individual generic component. This dialog allows the report user to define the column properties of a generic column on the report page (using the menu option Column properties…).

An example is the Generic column of the User Report; see /libs/cq/reporting/components/userreport/genericcol.

To make a column generic:

See /libs/cq/reporting/components/userreport/genericcol/definitions

See /libs/cq/reporting/components/userreport/genericcol/definitions/dialog

For example, if you want to make the type of the generic column configurable through the dialog, use a field with the name of ./definitions/type.

See /libs/cq/reporting/components/userreport/genericcol/cq:editConfig

Note that for properties that are defined on both the component and column instances, the value on the column instance takes precedence.

Properties available for a generic column are:

In the case of a new instance of the generic column on the User Report the properties defined with the dialog are persisted under:

/etc/reports/userreport/jcr:content/report/columns/genericcol/settings/generic

Report Design

The design defines which column types are available for creating a report. It also defines the paragraph system to which the columns are added.

You are strongly recommended to create an individual design for each report. This ensures full flexibility. See also Defining Your New Report.

The default reporting components are held under /etc/designs/reports.

The location for your reports can depend on where you have located your components:

Required design properties are registered on jcr:content/reportpage/report/columns (for example, /etc/designs/reports/<reportName>/jcr:content/reportpage/report/columns):

Any components and/or component groups that are allowed on the report.

Property with value cq/reporting/components/repparsys.

An example design snippet (taken from the design of the component report) is:

<!-- ... -->
    <jcr:content
        jcr:primaryType="nt:unstructured"
        jcr:title="Component Report"
        sling:resourceType="wcm/core/components/designer">
        <reportpage jcr:primaryType="nt:unstructured">
            <report jcr:primaryType="nt:unstructured">
                <columns
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="cq/reporting/components/repparsys"
                    components="group:Component Report"/>
            </report>
        </reportpage>
    </jcr:content>
<!-- ... -->

Specifying designs for individual columns is not required. Available columns can be defined in design mode.

NOTE

It is recommended that you do not make any changes to the standard report designs. This is to ensure that you do not lose any changes when upgrading or installing hotfixes.

Please copy the report and its design if you want to customize a standard report.

NOTE

Default columns can be created automatically when a report is created. These are specified in the template.

Report Template

Each report type must provide a template. These are standard CQ Templates and can be configured as such.

The template must:

An example template snippet (taken from the component report template) is:

<!-- ... -->
    <jcr:content
        cq:designPath="/etc/designs/reports/compreport"
        jcr:primaryType="cq:PageContent"
        sling:resourceType="cq/reporting/components/reportpage">
        <report
            jcr:primaryType="nt:unstructured"
            sling:resourceType="cq/reporting/components/compreport/compreport"/>
    </jcr:content>
<!-- .. -->

An example template snippet, showing the definition of the root path (taken from the user report template), is:

<!-- ... -->
    <jcr:content
        cq:designPath="/etc/designs/reports/userreport"
        jcr:primaryType="cq:PageContent"
        sling:resourceType="cq/reporting/components/reportpage">
        <report
            jcr:primaryType="nt:unstructured"
            rootPath="/home/users"
            sling:resourceType="cq/reporting/components/compreport/compreport"/>
    </jcr:content>
<!-- .. -->

The default reporting templates are held under /libs/cq/reporting/templates.

However, it is strongly recommended that you do not update these nodes, but create your own component nodes under /apps/cq/reporting/templates or if more appropriate /apps/<yourProject>/reports/templates.

Where, as an example (see also Location of Report Components):

N:apps
    N:cq [nt:folder]
        N:reporting|reports [sling:Folder]
            N:templates [sling:Folder]

Under this you create the root for your template:

N:apps
    N:cq [nt:folder]
        N:reporting|reports [sling:Folder]
            N:templates [sling:Folder]
                N:<reportname> [sling:Folder]

Creating Your Own Report - An Example

Defining Your New Report

To define a new report you must create and configure:

  1. The root for your report components.
  2. The report base component.
  3. One, or more, column base components.
  4. The report design.
  5. The root for your report template.
  6. The report template.

To illustrate these steps, the following example defines a report that lists all OSGi configurations within the repository; i.e. all instances of the sling:OsgiConfig node.

NOTE

Copying an existing report, then customizing the new version, is an alternative method.

  1. Create the root node for your new report.

    For example, under /apps/cq/reporting/components/osgireport.

    N:cq [nt:folder]
        N:reporting [sling:Folder]
            N:components [sling:Folder]
                N:osgireport [sling:Folder]
    
  2. Define your report base. For example osgireport[cq:Component] under /apps/cq/reporting/components/osgireport.

    N:osgireport [sling:Folder]
        N:osgireport [cq:Component]
            P:sling:resourceSuperType [String] = "cq/reporting/components/reportbase"
            N:charting [nt:unstructured]
                N:settings [nt:unstructured]
                    N:active [cq:WidgetCollection]
                        N:0 [nt:unstructured]
                            P:id [String] = "pie"
                        N:1 [nt:unstructured]
                            P:id [String] = "lineseries"
                N:definitions [cq:WidgetCollections]
                    N:0 [nt:unstructured]
                        P:id [String] = "pie"
                        P:maxRadius [Long] = 180
                        P:type [String] = "pie"
                    N:1 [nt:unstructured]
                        P:id [String] = "lineseries"
                        P:type [String] = "lineseries"
            N:dialog [cq:Dialog]
                P:height [Long] = 424
                N:items [cq:WidgetCollection]
                    N:props [cq:Panel]
                        N:items [cq:WidgetCollection]
                            N:title [cq:Widget]
                                P:path [String] = "/libs/cq/reporting/components/commons/title.infinity.json"
                                P:xtype [String] = "cqinclude"
                            N:description [cq:Widget]
                                P:path [String] = "/libs/cq/reporting/components/commons/description.infinity.json"
                                P:xtype [String] = "cqinclude"
                            N:rootPath [cq:Widget]
                                P:fieldLabel [String] = "Root path"
                                P:name [String] = "./report/rootPath"
                                P:xtype [String] = "pathfield"
                            N:processing [cq:Widget]
                                P:path [String] = "/libs/cq/reporting/components/commons/processing.infinity.json"
                                P:xtype [String] = "cqinclude"
                            N:scheduling [cq:Widget]
                                P:path [String] = "/libs/cq/reporting/components/commons/scheduling.infinity.json"
                                P:xtype [String] = "cqinclude"
            N:queryBuilder [nt:unstructured]
                P:nodeTypes [String[]] = "sling:OsgiConfig"
    

    This defines a report base component that:

  3. Define your first column (columnbase) component. For example bundlecol[cq:Component] under /apps/cq/reporting/components/osgireport.

    N:osgireport [sling:Folder]
        N:bundlecol [cq:Component]
            P:componentGroup [String] = "OSGi Report"
            P:jcr:title = "Bundle"
            P:sling:resourceSuperType [String] = "cq/reporting/components/columnbase"
            N:cq:editConfig [cq:EditConfig]
                P:cq:actions [String[]] = "insert", "delete"
                P:cq:dialogMode [String] = "floating"
                P:cq:layout [String] = "auto"
                N:cq:listeners [cq:EditListenersConfig]
                    P:aftercreate [String] "REFRESH_INSERTED"
                    P:afterdelete [String] "REFRESH_SELF"
                    P:afteredit [String] "REFRESH_SELF"
                    P:afterinsert [String] "REFRESH_INSERTED"
                    P:aftermove [String] "REFRESH_SELF"
                    P:afterremove [String] "REFRESH_SELF"
            N:defaults [nt:unstructured]
                P:aggregate [String] = "count"
            N:definitions [nt:unstructured]
                P:groupable [Boolean] = false
                P:type [String] = "string"
                N:queryBuilder [nt:unstructured]
                    P:property [String] = "jcr:path"
    

    This defines a column base component that:

    NOTE

    In this example there are no definitions of N:data and P:clientFilter. This is because the value received from the server is returned on a 1:1 basis - which is the default behavior.

    This is the same as the definitions:

    N:data [nt:unstructured]
      P:clientFilter [String] = "function(v) { return v; }"
    

    Where the function simply returns the value it receives.

  4. Define your report design. For example osgireport[cq:Page] under /etc/designs/reports.

    N:osgireport [cq:Page]
        N:jcr:content [nt:unstructured]
            P:jcr:title [String] = "OSGi report"
            P:sling:resourceType [String] = "wcm/core/components/designer"
            N:reportpage [nt:unstructured]
                N:report [nt:unstructured]
                    N:columns [nt:unstructured]
                        P:components [String] = "group:OSGi Report"
                        P:sling:resourceType [String] = "cq/reporting/components/repparsys"
    
  5. Create the root node for your new report template.

    For example, under /apps/cq/reporting/templates/osgireport.

    N:cq [nt:folder]
        N:reporting [sling:Folder]
            N:templates [sling:Folder]
                N:osgireport [cq:Template]
    
  6. Define your report template. For example osgireport[cq:Template] under /apps/cq/reporting/templates.

    N:osgireport [cq:Template]
        P:allowedPaths [String[]] = "/etc/reports(/.*)?"
        P:jcr:description [String] = "Use this report generator to create a new OSGi report."
        P:jcr:title [String] = "OSGi Report Template"
        P:ranking [Long] = 100
        P:shortTitle [String] = "OSGi Report"
        N:jcr:content [cq:PageContent]
            P:cq:designPath [String] = "/etc/designs/reports/osgireport"
            P:sling:resourceType [String] = "cq/reporting/components/reportpage"
            N:report [nt:unstructured]
                P:rootPath [String] = "/"
                P:sling:resourceType [String] = "cq/reporting/components/osgireport/osgireport"
        N:thumbnail.png [nt:file]
    

    This defines a template that:

Creating an Instance of Your New Report

An instance of your new report can now be created:

  1. Open the Tools console.

  2. Select Reports in the left-hand pane.

  3. Then New… from the toolbar. Define a Title and Name, select your new report type (the OSGi Report Template) from the list of templates, then click Create.

  4. Your new report instance will appear in the list. Double-click this to open.

  5. Drag a component (for this example, Bundle in the OSGi Report group) from the sidekick to create the first column and start the report definition.

    NOTE

    As this example does not have any groupable columns the charts will not be available. To see charts, set groupable to true:

    N:osgireport [sling:Folder]
     N:bundlecol [cq:Component]
     N:definitions [nt:unstructured]
     P:groupable [Boolean] = true
    

Configuring the Report Framework Services

This section describes advanced configuration options for the OSGi services that implement the report framework.

These can be viewed using the Configuration menu of the web console (available for example at http://localhost:4502/system/console/configMgr). When working with AEM there are several methods of managing the configuration settings for such services; see Configuring OSGi for more details and the recommended practices.

Basic Service (Day CQ Reporting Configuration)

As the data is fake it must only be used for testing and debugging purposes.

Using the fakedata selector will finish the report implicitly, so all existing data will be lost; data can be restored manually, but this can be a time-consuming process.

Basically, snapshots are taken for the user that has finished the report. There might be situations (for example on a publish system, where this user is non-existant as their account has not been replicated) where you want specify a fallback user that is used instead.

Additionally, specifying a user might impose a security risk.

Cache Settings (Day CQ Reporting Cache)

NOTE

Report data may be different for each user and language. Therefore report data is cached per report, user and language. This means that a Max entries value of 2 actually caches data for either:

  • one report for two users with different language settings
  • one user and two reports

On this page