You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2014/12/02 13:15:16 UTC

[1/2] camel git commit: CAMEl-8104: rest-dsl should allow custom error messages as-is without attempting output binding.

Repository: camel
Updated Branches:
  refs/heads/camel-2.14.x 500a6635a -> be560320d
  refs/heads/master 3817962c8 -> d33319fab


CAMEl-8104: rest-dsl should allow custom error messages as-is without attempting output binding.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/d33319fa
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/d33319fa
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/d33319fa

Branch: refs/heads/master
Commit: d33319fab93bc29f20d329b25264c6bf62fc90a9
Parents: 3817962
Author: Claus Ibsen <da...@apache.org>
Authored: Tue Dec 2 13:02:21 2014 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Tue Dec 2 13:14:41 2014 +0100

----------------------------------------------------------------------
 .../camel/model/rest/RestBindingDefinition.java | 17 ++++-
 .../model/rest/RestConfigurationDefinition.java | 22 ++++++
 .../apache/camel/model/rest/RestDefinition.java | 15 ++++
 .../apache/camel/model/rest/VerbDefinition.java | 11 +++
 .../processor/binding/RestBindingProcessor.java | 12 +++-
 .../org/apache/camel/spi/RestConfiguration.java | 19 +++++
 .../rest/FromRestGetHttpErrorCodeTest.java      | 66 +++++++++++++++++
 ...RestletPojoInOutCustomErrorResponseTest.java | 76 ++++++++++++++++++++
 .../component/restlet/UserErrorService.java     | 28 ++++++++
 9 files changed, 263 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
index 396243f..3a120c4 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
@@ -51,6 +51,9 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit
     @XmlAttribute
     private String outType;
 
+    @XmlAttribute
+    private Boolean skipBindingOnErrorCode;
+
     @Override
     public String toString() {
         return "RestBinding";
@@ -72,9 +75,12 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit
             mode = bindingMode.name();
         }
 
+        // skip by default
+        boolean skip = skipBindingOnErrorCode == null || skipBindingOnErrorCode;
+
         if (mode == null || "off".equals(mode)) {
             // binding mode is off, so create a off mode binding processor
-            return new RestBindingProcessor(null, null, null, null, consumes, produces, mode);
+            return new RestBindingProcessor(null, null, null, null, consumes, produces, mode, skip);
         }
 
         // setup json data format
@@ -161,7 +167,7 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit
             context.addService(outJaxb);
         }
 
-        return new RestBindingProcessor(json, jaxb, outJson, outJaxb, consumes, produces, mode);
+        return new RestBindingProcessor(json, jaxb, outJson, outJaxb, consumes, produces, mode, skip);
     }
 
     private void setAdditionalConfiguration(CamelContext context, DataFormat dataFormat) throws Exception {
@@ -214,4 +220,11 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit
         this.outType = outType;
     }
 
+    public Boolean getSkipBindingOnErrorCode() {
+        return skipBindingOnErrorCode;
+    }
+
+    public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
index 531fbc8..7cd175b 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
@@ -59,6 +59,9 @@ public class RestConfigurationDefinition {
     private RestBindingMode bindingMode;
 
     @XmlAttribute
+    private Boolean skipBindingOnErrorCode;
+
+    @XmlAttribute
     private String jsonDataFormat;
 
     @XmlAttribute
@@ -132,6 +135,14 @@ public class RestConfigurationDefinition {
         this.bindingMode = bindingMode;
     }
 
+    public Boolean getSkipBindingOnErrorCode() {
+        return skipBindingOnErrorCode;
+    }
+
+    public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+    }
+
     public String getJsonDataFormat() {
         return jsonDataFormat;
     }
@@ -251,6 +262,14 @@ public class RestConfigurationDefinition {
     }
 
     /**
+     * To specify whether to skip binding output if there is a custom HTTP error code
+     */
+    public RestConfigurationDefinition skipBindingOnErrorCode(boolean skipBindingOnErrorCode) {
+        setSkipBindingOnErrorCode(skipBindingOnErrorCode);
+        return this;
+    }
+
+    /**
      * To use a specific json data format
      *
      * @param name  name of the data format to {@link org.apache.camel.CamelContext#resolveDataFormat(java.lang.String) resolve}
@@ -347,6 +366,9 @@ public class RestConfigurationDefinition {
         if (bindingMode != null) {
             answer.setBindingMode(bindingMode.name());
         }
+        if (skipBindingOnErrorCode != null) {
+            answer.setSkipBindingOnErrorCode(skipBindingOnErrorCode);
+        }
         if (jsonDataFormat != null) {
             answer.setJsonDataFormat(jsonDataFormat);
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index 83a78a5..adc0df9 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -53,6 +53,9 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
     @XmlAttribute
     private RestBindingMode bindingMode;
 
+    @XmlAttribute
+    private Boolean skipBindingOnErrorCode;
+
     @XmlElementRef
     private List<VerbDefinition> verbs = new ArrayList<VerbDefinition>();
 
@@ -281,6 +284,18 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         return this;
     }
 
+    public RestDefinition skipBindingOnErrorCode(boolean skipBindingOnErrorCode) {
+        if (getVerbs().isEmpty()) {
+            this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+        } else {
+            // add on last verb as that is how the Java DSL works
+            VerbDefinition verb = getVerbs().get(getVerbs().size() - 1);
+            verb.setSkipBindingOnErrorCode(skipBindingOnErrorCode);
+        }
+
+        return this;
+    }
+
     /**
      * Routes directly to the given endpoint.
      * <p/>

http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
index ea90c4f..4ba401c 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
@@ -48,6 +48,9 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     private RestBindingMode bindingMode;
 
     @XmlAttribute
+    private Boolean skipBindingOnErrorCode;
+
+    @XmlAttribute
     private String type;
 
     @XmlAttribute
@@ -118,6 +121,14 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
         this.bindingMode = bindingMode;
     }
 
+    public Boolean getSkipBindingOnErrorCode() {
+        return skipBindingOnErrorCode;
+    }
+
+    public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+    }
+
     public String getType() {
         return type;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java b/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java
index 429c005..dcf4e0d 100644
--- a/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java
+++ b/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java
@@ -48,10 +48,11 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess
     private final String consumes;
     private final String produces;
     private final String bindingMode;
+    private final boolean skipBindingOnErrorCode;
 
     public RestBindingProcessor(DataFormat jsonDataFormat, DataFormat xmlDataFormat,
                                 DataFormat outJsonDataFormat, DataFormat outXmlDataFormat,
-                                String consumes, String produces, String bindingMode) {
+                                String consumes, String produces, String bindingMode, boolean skipBindingOnErrorCode) {
 
         if (jsonDataFormat != null) {
             this.jsonUnmarshal = new UnmarshalProcessor(jsonDataFormat);
@@ -82,6 +83,7 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess
         this.consumes = consumes;
         this.produces = produces;
         this.bindingMode = bindingMode;
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
     }
 
     @Override
@@ -240,6 +242,14 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess
                 return;
             }
 
+            if (skipBindingOnErrorCode) {
+                Integer code = exchange.hasOut() ? exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class) : exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
+                // if there is a custom http error code then skip binding
+                if (code != null && code >= 300) {
+                    return;
+                }
+            }
+
             if (bindingMode == null || "off".equals(bindingMode)) {
                 // binding is off
                 return;

http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java
index 7767ee2..d945aac 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java
@@ -39,6 +39,7 @@ public class RestConfiguration {
     private String contextPath;
     private RestHostNameResolver restHostNameResolver = RestHostNameResolver.localHostName;
     private RestBindingMode bindingMode = RestBindingMode.off;
+    private boolean skipBindingOnErrorCode = true;
     private String jsonDataFormat;
     private String xmlDataFormat;
     private Map<String, Object> componentProperties;
@@ -194,6 +195,24 @@ public class RestConfiguration {
     }
 
     /**
+     * Whether to skip binding output if there is a custom HTTP error code, and instead use the response body as-is.
+     * <p/>
+     * This option is default <tt>true</tt>.
+     */
+    public boolean isSkipBindingOnErrorCode() {
+        return skipBindingOnErrorCode;
+    }
+
+    /**
+     * Whether to skip binding output if there is a custom HTTP error code, and instead use the response body as-is.
+     * <p/>
+     * This option is default <tt>true</tt>.
+     */
+    public void setSkipBindingOnErrorCode(boolean skipBindingOnErrorCode) {
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+    }
+
+    /**
      * Gets the name of the json data format.
      *
      * @return the name, or <tt>null</tt> to use default

http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetHttpErrorCodeTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetHttpErrorCodeTest.java b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetHttpErrorCodeTest.java
new file mode 100644
index 0000000..0ae4b61
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetHttpErrorCodeTest.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.rest;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.JndiRegistry;
+
+public class FromRestGetHttpErrorCodeTest extends ContextTestSupport {
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndi = super.createRegistry();
+        jndi.bind("dummy-rest", new DummyRestConsumerFactory());
+        return jndi;
+    }
+
+    public void testFromRestModel() throws Exception {
+        String out = template.requestBody("seda:get-say-bye", "I was here", String.class);
+        assertEquals("Bye World", out);
+
+        Exchange reply = template.request("seda:get-say-bye", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Kaboom");
+            }
+        });
+        assertNotNull(reply);
+        assertEquals(404, reply.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+        assertEquals("text/plain", reply.getOut().getHeader(Exchange.CONTENT_TYPE));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                rest("/say/bye")
+                    .get().route()
+                        .choice()
+                            .when(body().contains("Kaboom"))
+                                .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(404))
+                                .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
+                                .setBody(constant("The data is invalid"))
+                            .otherwise()
+                                .transform().constant("Bye World");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletPojoInOutCustomErrorResponseTest.java
----------------------------------------------------------------------
diff --git a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletPojoInOutCustomErrorResponseTest.java b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletPojoInOutCustomErrorResponseTest.java
new file mode 100644
index 0000000..6cae362
--- /dev/null
+++ b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletPojoInOutCustomErrorResponseTest.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.restlet;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.rest.RestBindingMode;
+import org.junit.Test;
+
+/**
+ * @version 
+ */
+public class RestRestletPojoInOutCustomErrorResponseTest extends RestletTestSupport {
+
+    @Test
+    public void testRestletPojoInOutOk() throws Exception {
+        String body = "{\"id\": 123, \"name\": \"Donald Duck\"}";
+        String out = template.requestBody("http://localhost:" + portNum + "/users/lives", body, String.class);
+
+        assertNotNull(out);
+        assertEquals("{\"iso\":\"EN\",\"country\":\"England\"}", out);
+    }
+
+    @Test
+    public void testRestletPojoInOutError() throws Exception {
+        final String body = "{\"id\": 77, \"name\": \"John Doe\"}";
+        Exchange reply = template.request("http://localhost:" + portNum + "/users/lives?throwExceptionOnFailure=false", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody(body);
+            }
+        });
+
+        assertNotNull(reply);
+        assertEquals("id value is too low", reply.getOut().getBody(String.class));
+        assertEquals(400, reply.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+        String type = reply.getOut().getHeader(Exchange.CONTENT_TYPE, String.class);
+        assertTrue(type.contains("text/plain"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.json);
+
+                // use the rest DSL to define the rest services
+                rest("/users/")
+                    .post("lives").type(UserPojo.class).outType(CountryPojo.class)
+                        .route()
+                            .choice()
+                                .when().simple("${body.id} < 100")
+                                    .bean(new UserErrorService(), "idToLowError")
+                                .otherwise()
+                                    .bean(new UserService(), "livesWhere");
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/d33319fa/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/UserErrorService.java
----------------------------------------------------------------------
diff --git a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/UserErrorService.java b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/UserErrorService.java
new file mode 100644
index 0000000..7a71d70
--- /dev/null
+++ b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/UserErrorService.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.restlet;
+
+import org.apache.camel.Exchange;
+
+public class UserErrorService {
+
+    public void idToLowError(Exchange exchange) {
+        exchange.getIn().setBody("id value is too low");
+        exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
+        exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
+    }
+}


[2/2] camel git commit: CAMEl-8104: rest-dsl should allow custom error messages as-is without attempting output binding.

Posted by da...@apache.org.
CAMEl-8104: rest-dsl should allow custom error messages as-is without attempting output binding.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/be560320
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/be560320
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/be560320

Branch: refs/heads/camel-2.14.x
Commit: be560320d5a44a70cae787273674fbfd4e75c037
Parents: 500a663
Author: Claus Ibsen <da...@apache.org>
Authored: Tue Dec 2 13:02:21 2014 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Tue Dec 2 13:15:05 2014 +0100

----------------------------------------------------------------------
 .../camel/model/rest/RestBindingDefinition.java | 17 ++++-
 .../model/rest/RestConfigurationDefinition.java | 22 ++++++
 .../apache/camel/model/rest/RestDefinition.java | 15 ++++
 .../apache/camel/model/rest/VerbDefinition.java | 11 +++
 .../processor/binding/RestBindingProcessor.java | 12 +++-
 .../org/apache/camel/spi/RestConfiguration.java | 19 +++++
 .../rest/FromRestGetHttpErrorCodeTest.java      | 66 +++++++++++++++++
 ...RestletPojoInOutCustomErrorResponseTest.java | 76 ++++++++++++++++++++
 .../component/restlet/UserErrorService.java     | 28 ++++++++
 9 files changed, 263 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
index 396243f..3a120c4 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java
@@ -51,6 +51,9 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit
     @XmlAttribute
     private String outType;
 
+    @XmlAttribute
+    private Boolean skipBindingOnErrorCode;
+
     @Override
     public String toString() {
         return "RestBinding";
@@ -72,9 +75,12 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit
             mode = bindingMode.name();
         }
 
+        // skip by default
+        boolean skip = skipBindingOnErrorCode == null || skipBindingOnErrorCode;
+
         if (mode == null || "off".equals(mode)) {
             // binding mode is off, so create a off mode binding processor
-            return new RestBindingProcessor(null, null, null, null, consumes, produces, mode);
+            return new RestBindingProcessor(null, null, null, null, consumes, produces, mode, skip);
         }
 
         // setup json data format
@@ -161,7 +167,7 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit
             context.addService(outJaxb);
         }
 
-        return new RestBindingProcessor(json, jaxb, outJson, outJaxb, consumes, produces, mode);
+        return new RestBindingProcessor(json, jaxb, outJson, outJaxb, consumes, produces, mode, skip);
     }
 
     private void setAdditionalConfiguration(CamelContext context, DataFormat dataFormat) throws Exception {
@@ -214,4 +220,11 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit
         this.outType = outType;
     }
 
+    public Boolean getSkipBindingOnErrorCode() {
+        return skipBindingOnErrorCode;
+    }
+
+    public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
index 531fbc8..7cd175b 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
@@ -59,6 +59,9 @@ public class RestConfigurationDefinition {
     private RestBindingMode bindingMode;
 
     @XmlAttribute
+    private Boolean skipBindingOnErrorCode;
+
+    @XmlAttribute
     private String jsonDataFormat;
 
     @XmlAttribute
@@ -132,6 +135,14 @@ public class RestConfigurationDefinition {
         this.bindingMode = bindingMode;
     }
 
+    public Boolean getSkipBindingOnErrorCode() {
+        return skipBindingOnErrorCode;
+    }
+
+    public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+    }
+
     public String getJsonDataFormat() {
         return jsonDataFormat;
     }
@@ -251,6 +262,14 @@ public class RestConfigurationDefinition {
     }
 
     /**
+     * To specify whether to skip binding output if there is a custom HTTP error code
+     */
+    public RestConfigurationDefinition skipBindingOnErrorCode(boolean skipBindingOnErrorCode) {
+        setSkipBindingOnErrorCode(skipBindingOnErrorCode);
+        return this;
+    }
+
+    /**
      * To use a specific json data format
      *
      * @param name  name of the data format to {@link org.apache.camel.CamelContext#resolveDataFormat(java.lang.String) resolve}
@@ -347,6 +366,9 @@ public class RestConfigurationDefinition {
         if (bindingMode != null) {
             answer.setBindingMode(bindingMode.name());
         }
+        if (skipBindingOnErrorCode != null) {
+            answer.setSkipBindingOnErrorCode(skipBindingOnErrorCode);
+        }
         if (jsonDataFormat != null) {
             answer.setJsonDataFormat(jsonDataFormat);
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index 83a78a5..adc0df9 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -53,6 +53,9 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
     @XmlAttribute
     private RestBindingMode bindingMode;
 
+    @XmlAttribute
+    private Boolean skipBindingOnErrorCode;
+
     @XmlElementRef
     private List<VerbDefinition> verbs = new ArrayList<VerbDefinition>();
 
@@ -281,6 +284,18 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         return this;
     }
 
+    public RestDefinition skipBindingOnErrorCode(boolean skipBindingOnErrorCode) {
+        if (getVerbs().isEmpty()) {
+            this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+        } else {
+            // add on last verb as that is how the Java DSL works
+            VerbDefinition verb = getVerbs().get(getVerbs().size() - 1);
+            verb.setSkipBindingOnErrorCode(skipBindingOnErrorCode);
+        }
+
+        return this;
+    }
+
     /**
      * Routes directly to the given endpoint.
      * <p/>

http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
index ea90c4f..4ba401c 100644
--- a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java
@@ -48,6 +48,9 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
     private RestBindingMode bindingMode;
 
     @XmlAttribute
+    private Boolean skipBindingOnErrorCode;
+
+    @XmlAttribute
     private String type;
 
     @XmlAttribute
@@ -118,6 +121,14 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition>
         this.bindingMode = bindingMode;
     }
 
+    public Boolean getSkipBindingOnErrorCode() {
+        return skipBindingOnErrorCode;
+    }
+
+    public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+    }
+
     public String getType() {
         return type;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java b/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java
index 429c005..dcf4e0d 100644
--- a/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java
+++ b/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java
@@ -48,10 +48,11 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess
     private final String consumes;
     private final String produces;
     private final String bindingMode;
+    private final boolean skipBindingOnErrorCode;
 
     public RestBindingProcessor(DataFormat jsonDataFormat, DataFormat xmlDataFormat,
                                 DataFormat outJsonDataFormat, DataFormat outXmlDataFormat,
-                                String consumes, String produces, String bindingMode) {
+                                String consumes, String produces, String bindingMode, boolean skipBindingOnErrorCode) {
 
         if (jsonDataFormat != null) {
             this.jsonUnmarshal = new UnmarshalProcessor(jsonDataFormat);
@@ -82,6 +83,7 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess
         this.consumes = consumes;
         this.produces = produces;
         this.bindingMode = bindingMode;
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
     }
 
     @Override
@@ -240,6 +242,14 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess
                 return;
             }
 
+            if (skipBindingOnErrorCode) {
+                Integer code = exchange.hasOut() ? exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class) : exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
+                // if there is a custom http error code then skip binding
+                if (code != null && code >= 300) {
+                    return;
+                }
+            }
+
             if (bindingMode == null || "off".equals(bindingMode)) {
                 // binding is off
                 return;

http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java
index 7767ee2..d945aac 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java
@@ -39,6 +39,7 @@ public class RestConfiguration {
     private String contextPath;
     private RestHostNameResolver restHostNameResolver = RestHostNameResolver.localHostName;
     private RestBindingMode bindingMode = RestBindingMode.off;
+    private boolean skipBindingOnErrorCode = true;
     private String jsonDataFormat;
     private String xmlDataFormat;
     private Map<String, Object> componentProperties;
@@ -194,6 +195,24 @@ public class RestConfiguration {
     }
 
     /**
+     * Whether to skip binding output if there is a custom HTTP error code, and instead use the response body as-is.
+     * <p/>
+     * This option is default <tt>true</tt>.
+     */
+    public boolean isSkipBindingOnErrorCode() {
+        return skipBindingOnErrorCode;
+    }
+
+    /**
+     * Whether to skip binding output if there is a custom HTTP error code, and instead use the response body as-is.
+     * <p/>
+     * This option is default <tt>true</tt>.
+     */
+    public void setSkipBindingOnErrorCode(boolean skipBindingOnErrorCode) {
+        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
+    }
+
+    /**
      * Gets the name of the json data format.
      *
      * @return the name, or <tt>null</tt> to use default

http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetHttpErrorCodeTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetHttpErrorCodeTest.java b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetHttpErrorCodeTest.java
new file mode 100644
index 0000000..0ae4b61
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetHttpErrorCodeTest.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.rest;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.JndiRegistry;
+
+public class FromRestGetHttpErrorCodeTest extends ContextTestSupport {
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndi = super.createRegistry();
+        jndi.bind("dummy-rest", new DummyRestConsumerFactory());
+        return jndi;
+    }
+
+    public void testFromRestModel() throws Exception {
+        String out = template.requestBody("seda:get-say-bye", "I was here", String.class);
+        assertEquals("Bye World", out);
+
+        Exchange reply = template.request("seda:get-say-bye", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Kaboom");
+            }
+        });
+        assertNotNull(reply);
+        assertEquals(404, reply.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+        assertEquals("text/plain", reply.getOut().getHeader(Exchange.CONTENT_TYPE));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                rest("/say/bye")
+                    .get().route()
+                        .choice()
+                            .when(body().contains("Kaboom"))
+                                .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(404))
+                                .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
+                                .setBody(constant("The data is invalid"))
+                            .otherwise()
+                                .transform().constant("Bye World");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletPojoInOutCustomErrorResponseTest.java
----------------------------------------------------------------------
diff --git a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletPojoInOutCustomErrorResponseTest.java b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletPojoInOutCustomErrorResponseTest.java
new file mode 100644
index 0000000..6cae362
--- /dev/null
+++ b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletPojoInOutCustomErrorResponseTest.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.restlet;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.rest.RestBindingMode;
+import org.junit.Test;
+
+/**
+ * @version 
+ */
+public class RestRestletPojoInOutCustomErrorResponseTest extends RestletTestSupport {
+
+    @Test
+    public void testRestletPojoInOutOk() throws Exception {
+        String body = "{\"id\": 123, \"name\": \"Donald Duck\"}";
+        String out = template.requestBody("http://localhost:" + portNum + "/users/lives", body, String.class);
+
+        assertNotNull(out);
+        assertEquals("{\"iso\":\"EN\",\"country\":\"England\"}", out);
+    }
+
+    @Test
+    public void testRestletPojoInOutError() throws Exception {
+        final String body = "{\"id\": 77, \"name\": \"John Doe\"}";
+        Exchange reply = template.request("http://localhost:" + portNum + "/users/lives?throwExceptionOnFailure=false", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody(body);
+            }
+        });
+
+        assertNotNull(reply);
+        assertEquals("id value is too low", reply.getOut().getBody(String.class));
+        assertEquals(400, reply.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
+        String type = reply.getOut().getHeader(Exchange.CONTENT_TYPE, String.class);
+        assertTrue(type.contains("text/plain"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.json);
+
+                // use the rest DSL to define the rest services
+                rest("/users/")
+                    .post("lives").type(UserPojo.class).outType(CountryPojo.class)
+                        .route()
+                            .choice()
+                                .when().simple("${body.id} < 100")
+                                    .bean(new UserErrorService(), "idToLowError")
+                                .otherwise()
+                                    .bean(new UserService(), "livesWhere");
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/be560320/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/UserErrorService.java
----------------------------------------------------------------------
diff --git a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/UserErrorService.java b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/UserErrorService.java
new file mode 100644
index 0000000..7a71d70
--- /dev/null
+++ b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/UserErrorService.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.restlet;
+
+import org.apache.camel.Exchange;
+
+public class UserErrorService {
+
+    public void idToLowError(Exchange exchange) {
+        exchange.getIn().setBody("id value is too low");
+        exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
+        exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
+    }
+}