Hello Camel experts
I’m structuring a Camel Spring Boot application as a pipeline of reusable
routes, each following the Single Responsibility Principle. Each route type has
its own abstract `RouteBuilder`, and concrete routes describe only the happy
path. Common error handling should live in the abstract base classes.
### Pipeline
`technical-sender → sender → process → receiver → technical-receiver`
* **technical-sender**: REST entry point (e.g.
`rest().post("/demo").to("seda:demo-sender")`)
* **sender**: unmarshalling + auth + validation + call process + marshal
response
* **process**: map request/response, call receiver
* **receiver**: add headers/auth, retries, call technical-receiver
* **technical-receiver**: low-level producer (HTTP/SOAP/etc.)
### Goal
If an exception happens in any route (validation/mapping/unmarshalling or
external call failure), I want to:
1. Catch it **in the route where it occurs**
2. Wrap it into a domain exception (e.g. `IntegrationException`)
3. Propagate it **backwards** through the route pipeline
4. Allow intermediate routes to optionally enrich it (e.g. process adds context)
5. Finally, the sender maps it to the external API contract (status code + body)
Importantly, I want to avoid cluttering happy paths with `doTry()` / `choice()`
blocks.
### Problems I’m hitting
1. `onException` runs only once per Exchange. If I use `handled(false)` and the
exchange returns to the caller route, `onException` is not triggered again in
the caller.
2. Rethrowing or setting `Exchange.setException(...)` inside `onException`
triggers `FatalFallbackErrorHandler` and terminates processing.
3. Using `errorHandler(noErrorHandler())` allows propagation to the caller, but
disables route-level `onException` (including redelivery).
4. `onCompletion` ordering is FIFO, not LIFO. When the failure happens in the
receiver, callbacks run sender → process → receiver, but I would need receiver
→ process → sender for backward enrichment.
### Expected behavior
The technical receiver simulates an HTTP 500. I want the client to receive
**502 Bad Gateway** and:
```json
{
"errors": [
{ "code": "500", "message": "Something wrong occurred in external system" }
]
}
```
Demo project (repro):
[https://github.com/bvv-jmedved/error-hanling-demo](https://github.com/bvv-jmedved/error-hanling-demo)
Any advice on the recommended Camel pattern to achieve “wrap per route +
backward propagation + optional enrichment” without polluting the happy path?
Jíří Medveď