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ď

Reply via email to