title: Camel exception handling in Grails
body: <p>I currently have exception handling being done in an abstract class that all my routes inherit.  Something like this:</p>
  
  <pre><code>    onException(SocketException,HttpOperationFailedException)
          .handled(true)
          .maximumRedeliveries(settings.maximumRedeliveries)
          .redeliverDelay(settings.redeliverDelay)
          .useCollisionAvoidance()
          .collisionAvoidanceFactor(settings.collisionAvoidanceFactor)
          .onRedelivery(redeliveryProcessor)
          .log('retry failed, sending to the route failed coordinator')
          .to(routeFailedCoordinator)
  </code></pre>
  
  <p>Now, I want to do some different things based on different response codes.  For all codes other than 200, HttpOperationFailedException get's thrown.  For 4XX codes, I want to send the message on to a failed queue and send an email, if enabled for that particular route.  For all other errors, I want to go through the retry cycle.  Here's what works for the 4XX errors:</p>
  
  <pre><code>    onException(HttpOperationFailedException)
          .handled(true)
          .process { Exchange x -&gt;
              HttpOperationFailedException ex = x.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class)
              log.debug("Caught a HttpOperationFailedException: statusCode=${ex?.statusCode}")
              ProducerTemplate producer = x.getContext().createProducerTemplate()
              if (ex?.statusCode &gt;= 400 &amp;&amp; ex?.statusCode &lt; 500) {
                  log.debug("Skipping retries ...")
  
                  producer.send(routeFailedEndpoint, x)
  
                  x.in.body = "Request:\n${x.in.body}\n\nResponse: ${ex.statusCode}\n${ex.responseBody}".toString()
                  if (sendFailedEmailEnabled)
                      producer.send('direct:routeFailedEmailHandler', x)
              } else {
                  producer.send(routeFailedRetryEndpoint, x)
              }
          }.stop()
  </code></pre>
  
  <p>How do I add code for retrying like in the first code snippet?  I tried using nested choice()...when()...otherwise() clauses and kept getting compile errors.</p>
  
  <p>Anyone had to do something similar?</p>
  
  <p>Here is my code with nested choice()..when()..otherwise() clauses:</p>
  
  <pre><code>    onException(HttpOperationFailedException)
          .handled(true)
          .choice()
              .when { Exchange x -&gt;
                  HttpOperationFailedException ex = x.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class)
                  log.debug("Caught a HttpOperationFailedException: statusCode=${ex?.statusCode}")
                  if (ex?.statusCode &gt;= 400 &amp;&amp; ex?.statusCode &lt; 500) {
                      log.debug("Skipping retries ...")
                      x.in.body = "Request:\n${x.in.body}\n\nResponse: ${ex.statusCode}\n${ex.responseBody}".toString()
                      return true // don't retry
                  }
  
                  log.debug("Performing retries ...")
                  return false // do attempt retries
              }.choice()
                  .when { !sendFailedEmailEnabled }.to(routeFailedEndpoint)
                  .otherwise()
                      .multicast().to(routeFailedEndpoint, 'direct:routeFailedEmailHandler').endChoice()
              .otherwise()
                  .getParent().getParent().getParent()
                  .maximumRedeliveries(settings.maximumRedeliveries)
                  .redeliverDelay(settings.redeliverDelay)
                  .useCollisionAvoidance()
                  .collisionAvoidanceFactor(settings.collisionAvoidanceFactor)
                  .onRedelivery(redeliveryProcessor)
                  .to(routeFailedCoordinator)
  </code></pre>