Skip to main content
The Copper API defines the measures and hierarchies of an Atoti cube in Java code. It assumes familiarity with the Copper introduction.

Atoti cube builder

Copper calculations are declared in the withCalculations(Consumer<ICopperContext>) method of the cube builder. The entry point of the Copper API is the Copper context, or simply the context. The context knows the measures and hierarchies that are already defined. Copper measures and hierarchies are created with the API, then published to the context. The following snippet declares Copper calculations in the cube builder:
The snippet defines all the Copper measures in a single lambda. For brevity, the other examples in the Copper documentation show only the body of this lambda.
The measures and hierarchies declared in the lambda are added to the cube description before the cube starts. The Copper class provides the static methods that create measures and hierarchies. Every Copper measure implements the CopperMeasure interface. These measures are the building blocks of Copper calculations: their methods build more complex calculations. A measure published in the lambda can be reused by the Copper calculations that follow it. The following pseudo-code publishes a measure, then builds a second measure on top of it:
All the measures of a cube can be declared in this lambda, in the same way. This includes Copper measures, native measures, aggregated measures, and legacy post-processors.

How does Copper work in distributed environments?

Copper works in both the data cubes and the query cubes of a distributed Atoti cluster. A cluster is a group of data cubes and query cubes that communicate together. Within a cluster, an application is a group of data cubes that share the same topology: the same hierarchies, levels, and measures. For more information about the distributed architecture of Atoti and its concepts, see Distributed architecture.

Copper in data cubes

Copper works in distributed data cubes without extra properties or calls. Measures behave as intended in a distributed environment, and their computations are distributed when possible.

Copper in query cubes

Copper in a query cube declares measures that build on top of the measures defined in the data cubes. A query cube can combine measures from several applications, even when they do not share the same topology. For example, a query cube connected to a PnL application and a VaR application can define a measure from VaR_95 and PnL.SUM, which neither application defines. The Copper API in a query cube is similar to the API that defines measures in a data cube. The main difference is how a calculation references an existing measure: The following snippet defines a query cube measure from a data cube measure:

Which Copper features are restricted in query cubes?

Any Copper calculation that a query cube supports also works in a data cube, as long as it uses measures from a single application. The reverse is not true: a query cube has no database and no hierarchies of its own. The Copper features that read the database or need information from the cube description, such as the type of a level, cannot be used directly in a query cube. Define them in the data cubes, then reference them in the query cube with Copper.measureFromDataCube(measureName, measureType). Calculations on existing measures, such as arithmetic, per(...).sum(), shift(...), parentValueOn(...), grandTotalExcluding(...), and window functions, work directly in a query cube. For example, the following features must be defined in the data cubes:
  • Field aggregations, such as Copper.sum(fieldName)
  • Copper.storeLookup(...)
  • Joins with Copper.store(...).joinToCube(...)
  • filter(...)
A query cube also cannot publish new hierarchies. It rejects them with the error “Adding new hierarchies is not permitted in Query cubes.” When a measure is published in a query cube, Atoti checks every measure it depends on. If any of these measures needs a data cube, publication fails with the following error: “measure cannot be published because it relies on features that only work in Data cubes.” A supported operation applied to an unsupported measure is therefore also rejected. To fix the error, define the measure that needs a data cube in the data cubes, then reference it in the query cube with Copper.measureFromDataCube(measureName, measureType).
A measure that uses Copper.storeLookup can be defined in a data cube and used from the query cube. Continuous queries on the query cube are not notified of the database updates that affect this measure. The query cube has no access to the database.