Groovy Expressions in Mappers

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

XML
<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

XML
<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

XML
<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

XML
<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

XML
<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

  1. expression attribute -- contains the Groovy code to evaluate. The result is converted to a String and written to the target field.

  2. out attribute -- the target field name in the output record.

  3. 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.

  4. 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 &lt;, > as &gt;, & as &amp;, and " as &quot; 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 maxLength with <groovy> just like with <body>.