The case every integration has: the shop‘s order mapped field by field to the courier’s shipment format, which has different names, a different structure, and values the order does not carry. The mapping is a Groovy script.
INFO ... data-mapping.camel.yaml:27 : Shipment for the courier: {"shipmentRef":"SHIP-1001","recipient":{"customerNo":"C-482","countryCode":"DK"},"parcels":[{"article":"CAMEL-TSHIRT","pieces":2},{"article":"CAMEL-MUG","pieces":1}],"totalPieces":3,"service":"domestic","createdAt":"2026-09-18"}
Install JBang and the Camel CLI as described in the root README; camel --version confirms the install.
camel run *
order.json is parsed with unmarshal and the json data format, so the script works on a map, not on text.setBody with a groovy expression runs shipment-mapping.groovy: resource:file: loads the script from the file next to the route. The script‘s last expression, a map with the courier’s field names, becomes the body.marshal with json writes the shipment out. Renamed fields, a nested recipient, one parcels entry per line, a computed totalPieces, a service chosen from the country, and a createdAt the order never had.order.json, unmarshals it with json, and logs ${body[orderId]}.setBody with an inline groovy expression returning [shipmentRef: body.orderId] and log the body.shipment-mapping.groovy and load it with resource:file:.collect, the total with sum.marshal with json and log the shipment.[DK: 'DOM', SE: 'NORDIC'][order.country].routes quick-start shows a bean.The example comes with a test in the Citrus YAML DSL, test/data-mapping.citrus.it.yaml, which the Camel CLI runs:
camel test run test/data-mapping.citrus.it.yaml
The test starts the route and verifies that the shipment is logged with the courier's fields.
If you hit any problem using Camel or have some feedback, then please let us know.
We also love contributors, so get involved :-)
The Camel riders!