Classes (Groovy)

Classes (Groovy)

Custom Groovy classes for advanced processing logic that cannot be expressed in route XML alone.

Attribute

Details

Purpose

Custom processors, aggregation strategies, validators — when XML config is not enough

Format

Groovy source files (.groovy) — compiled at startup

Naming

File name must match class name: ProductProcessor.groovy, CustomAggregator.groovy

Loaded by

Bean loader at startup — registered as Spring beans (singleton)

Bean name

Class name with first letter lowercased: ProductProcessorproductProcessor


Groovy Sandbox

All Groovy classes run inside a security sandbox — always enabled on provisioned instances, cannot be disabled.

Execution time limit: Groovy scripts have a configurable timeout (default set by PlatformManager). If a script exceeds the time limit, it is aborted with a GroovyEvaluationException. The timeout is controlled by integration.groovy-sandbox.timeout (in seconds) — this cannot be changed on provisioned instances.

The sandbox restricts which Java classes and methods can be used. Only whitelisted types are permitted — see the Groovy Sandbox page for the full whitelist, blacklist, and how to add custom allowed types.

If your code uses a class that is not whitelisted, it throws GroovyEvaluationException at runtime.


Supported Interfaces

A class must implement one of:

  • org.apache.camel.Processor — arbitrary body/header manipulation

  • org.apache.camel.AggregationStrategy — custom aggregation logic

  • net.pricefx.integration.csv.schema.validators.Validator — CSV/XLSX row validation


Processor Examples

Filter records by field value

Groovy
// classes/ActiveProductFilter.groovy
import org.apache.camel.Exchange
import org.apache.camel.Processor

class ActiveProductFilter implements Processor {

    @Override
    void process(Exchange exchange) throws Exception {
        def body = exchange.in.body as List<Map>
        exchange.in.body = body.findAll { it.status == 'ACTIVE' }
    }
}

Usage:

XML
<to uri="pfx-api:fetch?objectType=P&amp;filter=allProducts"/>
<process ref="activeProductFilter"/>
<to uri="pfx-csv:marshal"/>

Enrich body with header data

Groovy
// classes/RegionEnricher.groovy
import org.apache.camel.Exchange
import org.apache.camel.Processor

class RegionEnricher implements Processor {

    @Override
    void process(Exchange exchange) throws Exception {
        def region = exchange.in.getHeader('targetRegion', String)
        def body = exchange.in.body as List<Map>
        body.each { row -> row.region = region }
        exchange.in.body = body
    }
}

Usage:

XML
<setHeader name="targetRegion"><constant>EMEA</constant></setHeader>
<process ref="regionEnricher"/>

Transform keys / rename fields

Groovy
// classes/FieldRenamer.groovy
import org.apache.camel.Exchange
import org.apache.camel.Processor

class FieldRenamer implements Processor {

    private static final Map<String, String> MAPPING = [
        'product_id'  : 'sku',
        'product_name': 'label',
        'list_price'  : 'attribute1'
    ]

    @Override
    void process(Exchange exchange) throws Exception {
        def body = exchange.in.body as List<Map>
        exchange.in.body = body.collect { row ->
            MAPPING.collectEntries { from, to -> [(to): row[from]] }
        }
    }
}

Set headers from body (for routing decisions)

Groovy
// classes/EventRouter.groovy
import org.apache.camel.Exchange
import org.apache.camel.Processor

class EventRouter implements Processor {

    @Override
    void process(Exchange exchange) throws Exception {
        def body = exchange.in.body as Map
        exchange.in.setHeader('eventType', body?.eventType)
        exchange.in.setHeader('targetName', body?.data?.getAt(0)?.targetName)
    }
}

Usage:

XML
<process ref="eventRouter"/>
<choice>
    <when>
        <simple>${header.targetName} == 'DMDS.Product'</simple>
        <to uri="direct:handleProductLoad"/>
    </when>
</choice>

Common Pitfalls

  • Sandbox timeout — Groovy scripts exceeding the execution time limit are aborted. Break up long-running operations across multiple route steps instead of doing everything in one processor.

  • Sandbox restrictions — Only whitelisted classes/methods are allowed. See Groovy Sandbox for the full list.

  • No anonymous inner classes — The sandbox blocks anonymous classes. Use named classes (as shown above) instead.

  • Cannot use external dependencies — Classes are compiled with the IM classpath only. No additional JARs can be added.

  • Compilation errors are non-fatal — If a class fails to compile, it is skipped with an error log. Other classes still load normally.

  • Bean name — The Spring bean name is always the class name with the first letter lowercased. ProductProcessor → ref productProcessor.