Configuration Tips - Groovy

Dos and Don'ts

Topic

Tip

Details

Topic

Tip

Details

api.global over 16 MB not persisted

Do not put more than 16 MB into the api.global variable – if the size exceeds, it is not persisted.

Calculation Flow Management

Loading more than 200 rows

When loading more than 200 rows, it is recommended to use the sortBy field.

Data Reading Functions

Storing data for all nodes and api.global

If you need to store the data for all nodes in the calculation flow (in Distributed Mode), do not use api.global as it will be different for all nodes and threads; use a shared cache instead.

Performance Improvements (Batching, api.getBatchInfo)

Declaring variables

Do not declare variables inside loops.

Important Limitations and Known Issues

itemThreshold should not be lower than 1000

Do not set itemThreshold to values lower than 1000.

The following example is wrong:

<calculationSlave>     <itemThreshold>1</itemThreshold> </calculationSlave>

The itemThreshold drives the minimum number of items required to qualify for distributed processing. Setting this too low simply makes no sense as the effort to build the distribution framework becomes more costly than the calculations themselves.

https://pricefx.atlassian.net/wiki/spaces/PERF/pages/2057011701

Tips and Notes

Topic

Tip

Details

Topic

Tip

Details

Best practices for Groovy libraries

In Libraries, the following is recommended:

  • The names of the function parameter should be self-explaining.

  • The types of the parameters should be specified.

  • The return types of the library functions should be specified.

  • The functions should be documented using GroovyDoc (similar to JavaDoc).

Libraries

Global variables and api.retainGlobal

If you use global variables, you need to check the settings of api.retainGlobal.

  • If the option api.retainGlobal defaults to TRUE is enabled, then using api.global is enough.

  • If it is disabled, the calculation engine resets this variable to false in the beginning of each record calculation and that causes that the api.global map with all gathered data is lost. If you want to enable it for a particular logic, set api.retainGlobal to true in the first element in the first line of code.

Groovy Cheatsheet

api.global per node

During the distributed calculations (Price List, LPG, CFS), the process is executed across several server nodes, each sub-process calculating small part of the lines/rows. Each sub-process has its own api.global content, i.e. it is not shared across the sub-processes. So, if you run a PL calculation distributed across 3 nodes, the system will hold the 3 instances of api.global in total in the memory.

Caching

Maps instead of real objects

Calculation logic implicitly converts an object to a Map. This is a security feature. In Groovy you always get a map. Returning a specific type would allow you to call something that was not designed to be used in exposed Groovy API.

For example, rr.getClass() returns java.util.LinkedHashMap instead of RebateRecord, even though the type RebateRecord was specified beforehand.

 

api.addOrUpdate in Test Drive

When debugging a logic using Test Drive, the api.addOrUpdate function will NOT perform the write operation – it will skip it. However, there is a checkbox (in Test Drive) to allow execution of write operations.

This operation will ONLY work in contexts that allow object modification (CFS, CalculationFlow and direct logic execution via JSON API).

Groovy Cheatsheet

api.addOrUpdate cannot be used in distributed calculation

The method api.addOrUpdate() cannot be used in distributed calculation and there is a workaround: api.boundCall() which can be called including batches, but it is not recommended to use.

However, if you do it safely, it will make sense (addOrUpdate only specific sort of keys, not the same).

Distributed Calculation

Why not to use api.boundCall

api.boundCall is a super powerful function, however, try to avoid it as much as you can. It makes the code more complex and there is a high risk for the project – you never know if the bound call you design will work in future releases. It runs in a different thread, so there may be clashes.

Avoid api.boundCall

Using functions with fields parameter

When using this form of the function: find(String typeCode, int startRow, int maxRows, String sortBy, List<String> fields, Filter ... filters), i.e. the one with the "fields" parameter, you get back "full objects" which are transferred through type conversion. If you do not use the "fields" parameter, you get only raw data for attributeXX fields which is always a string. That means you will get a hashmap where all values are strings – if you have numbers in the table, you will get back a string.

Data Reading Functions

'float' and 'double' should not be used

The types 'float' and 'double' should not be used in Groovy because the result of the logic element can ultimately end up in a 'double' which is currently serialized in JSON as a string. Therefore ensure you use 'BigDecimal' whenever dealing with a decimal point number and force the type when initially getting data back from a function call.

Why NOT to Use 'float' or 'double' Types in Groovy

Return type BigDecimal

The return type is not guaranteed to be of type BigDecimal. Therefore, always cast to BigDecimal when you read the input value.

Numbers

Data modification of Products, Extensions and Company Parameters

Data modification functions work only in certain logic contexts, and they do nothing in the other cases, without any warning.

https://pricefx.atlassian.net/wiki/spaces/KB/pages/3668770846

Why formula language is deprecated

Formula language should not be used, it is no longer supported.

https://pricefx.atlassian.net/wiki/spaces/KB/pages/2344190022

Found an issue in documentation? Write to us.