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 ( |
|
Naming |
File name must match class name: |
|
Loaded by |
Bean loader at startup — registered as Spring beans (singleton) |
|
Bean name |
Class name with first letter lowercased: |
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
// 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:
<to uri="pfx-api:fetch?objectType=P&filter=allProducts"/>
<process ref="activeProductFilter"/>
<to uri="pfx-csv:marshal"/>
Enrich body with header data
// 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:
<setHeader name="targetRegion"><constant>EMEA</constant></setHeader>
<process ref="regionEnricher"/>
Transform keys / rename fields
// 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)
// 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:
<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→ refproductProcessor.