Overview
The <groovy> element in mapper definitions lets you write inline Groovy expressions to transform, compute, or conditionally set field values. The expression has access to the body variable (the current row as a Map), as well as exchange, headers, and properties from the Camel context.
Complete XML Examples
String Manipulation
<mappers>
<loadMapper id="stringManipulationMapper">
<!-- Uppercase a field -->
<groovy expression="body.name?.toUpperCase()" out="label"/>
<!-- Concatenate two fields -->
<groovy expression="body.firstName + ' ' + body.lastName" out="attribute1"/>
<!-- Substring extraction -->
<groovy expression="body.code?.substring(0, Math.min(body.code?.length() ?: 0, 10))" out="attribute2"/>
<!-- Trim and normalize whitespace -->
<groovy expression="body.description?.trim()?.replaceAll('\\s+', ' ')" out="attribute3"/>
</loadMapper>
</mappers>
Null Handling
<mappers>
<loadMapper id="nullSafeMapper">
<!-- Safe navigation operator (?.) prevents NullPointerException -->
<groovy expression="body.optionalField?.trim() ?: 'N/A'" out="attribute1"/>
<!-- Default value when field is null or empty -->
<groovy expression="body.status ?: 'UNKNOWN'" out="attribute2"/>
<!-- Explicit null check -->
<groovy expression="body.price != null ? body.price : '0'" out="attribute3"/>
</loadMapper>
</mappers>
Conditional Logic
<mappers>
<loadMapper id="conditionalMapper">
<!-- Ternary operator for simple conditions -->
<groovy expression="body.quantity?.toInteger() > 100 ? 'BULK' : 'STANDARD'" out="attribute1"/>
<!-- Multi-condition logic -->
<groovy expression="body.region == 'EU' ? 'EUR' : (body.region == 'US' ? 'USD' : 'OTHER')" out="attribute2"/>
<!-- Boolean flag based on field value -->
<groovy expression="body.active == 'Y' ? '1' : '0'" out="attribute3"/>
</loadMapper>
</mappers>
Arithmetic and Date Formatting
<mappers>
<loadMapper id="arithmeticMapper">
<!-- Sum of two numeric fields -->
<groovy expression="body.price.toInteger() + body.vat.toInteger()" out="attribute1"/>
<!-- Percentage calculation -->
<groovy expression="String.valueOf(body.price.toBigDecimal() * 1.21)" out="attribute2"/>
<!-- Date formatting (parse and reformat) -->
<groovy expression="java.time.LocalDate.parse(body.dateStr, java.time.format.DateTimeFormatter.ofPattern('dd/MM/yyyy')).format(java.time.format.DateTimeFormatter.ofPattern('yyyy-MM-dd'))" out="attribute3"/>
<!-- Current timestamp -->
<groovy expression="new java.text.SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(new Date())" out="attribute4"/>
</loadMapper>
</mappers>
Accessing Exchange Properties and Headers
<mappers>
<loadMapper id="contextAwareMapper">
<body in="sku"/>
<!-- Use an exchange property set earlier in the route -->
<groovy expression="exchange.properties['batchId']" out="attribute1"/>
<!-- Combine body field with a header value -->
<groovy expression="body.sku + '-' + exchange.in.headers['region']" out="attribute2"/>
</loadMapper>
</mappers>
How It Works
-
expressionattribute -- contains the Groovy code to evaluate. The result is converted to a String and written to the target field. -
outattribute -- the target field name in the output record. -
Available variables:
-
body-- a Map representing the current row (keys are field names). -
exchange-- the full Camel Exchange object. -
headers/exchange.in.headers-- message headers. -
properties/exchange.properties-- exchange properties.
-
-
Groovy expressions run inside a sandboxed environment. Not all Java/Groovy classes are available; standard String, Math, Date, and collection operations work.
Common Pitfalls
-
NullPointerException: Always use the safe navigation operator (
?.) or null checks. Source data frequently has missing fields. -
Type coercion: Body values are typically Strings. Use
.toInteger(),.toBigDecimal(), or.toDouble()explicitly before arithmetic. -
String escaping in XML: Because the expression lives inside an XML attribute, you must escape
<as<,>as>,&as&, and"as"within expressions. -
Performance: Complex Groovy expressions are compiled and cached, but extremely long expressions can be harder to debug. Consider moving very complex logic into a separate Groovy script or processor.
-
maxLength with Groovy: You can combine
maxLengthwith<groovy>just like with<body>.