Conversion of Groovy Closure Type Parameters to Groovy Types

since 10.0 (Bees Knees)

There is a formula sandbox change to increase security: a new Advanced Configuration Option filterGroovyClosureParameterType enforces conversion of Groovy closure type parameters to their respective Groovy types. It is set to true by default for newly created partitions on 10.0 servers.

Before 10.0

Types were not converted for Groovy Sandbox (such as DomainObject to Map) when used as a closure parameter.

In this example the cor parameter is not a Map (as you may expect) but an instance of a DomainObject (in this particular case a CompensationRecord):

List cors = api.find("COR", 0, 1, null, null, Filter.equal("label", "SC_basic_logic"))?.collect() cors.each {def cor -> // work with "cor" }

Note that if you explicitly set the type of cor to Map, the code will fail with an error.

Since 10.0

After upgrade of existing partitions to 10.0, the conversion of types in closure parameters

  • is automatic just for LocalDateTime -> Date (which is safe in terms of backward compatibility).

  • other types will not be converted by default, because the conversion might break the existing Groovy code. Instead, there will be a specific warning in logs, i.e.:

PFUN-16195 groovy closure parameter type possible conversion: source type: net.pricefx.domain.CompensationRecord, target type: java.util.LinkedHashMap, groovy method: each

If you see this kind of log message, you should consider adding an Advanced Configuration Option filterGroovyClosureParameterType=true, which will:

  • enable automatic conversion for Groovy closure parameters to Map

  • will also remove the logging of the message

Then check your Groovy code for possible errors and fix them by using a proper data type, i.e. DomainObject will be converted to Map.

  • When filterGroovyClosureParameterType=true is not set (or is false), then:

    • this code: cors.each {Map cor -> will not work

    • this code: cors.each {def cor -> will work

    • because cor is an instance of some DomainObject class.

  • When filterGroovyClosureParameterType=true is set, then:

    • both codes will work:
      cors.each {Map cor ->
      cors.each {def cor ->

    • but you will not be able to access the DomainObject, because it was converted to a Map.

 

Found an issue in documentation? Write to us.