Repository: camel
Updated Branches:
  refs/heads/master a9fe2d94e -> d772b4f59


CAMEL-4576: throwException EIP now allows to create new exception instance with 
message with details from exchange using simple language.


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

Branch: refs/heads/master
Commit: d772b4f59a5ac49ff7046ea673ae16ffb1f5d689
Parents: a9fe2d9
Author: Claus Ibsen <davscl...@apache.org>
Authored: Fri Jul 10 14:38:48 2015 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Fri Jul 10 14:38:48 2015 +0200

----------------------------------------------------------------------
 .../apache/camel/model/ProcessorDefinition.java | 16 +++++-
 .../camel/model/ThrowExceptionDefinition.java   | 47 +++++++++++++--
 .../processor/ThrowExceptionProcessor.java      | 60 ++++++++++++++++++--
 .../processor/ThrowExceptionMessageTest.java    | 55 ++++++++++++++++++
 .../SpringThrowExceptionMessageTest.java        | 33 +++++++++++
 .../SpringThrowExceptionMessageTest.xml         | 33 +++++++++++
 6 files changed, 235 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/d772b4f5/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java 
b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index b7789f7..5a0b79e 100644
--- a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -68,7 +68,6 @@ import org.apache.camel.spi.InterceptStrategy;
 import org.apache.camel.spi.LifecycleStrategy;
 import org.apache.camel.spi.Policy;
 import org.apache.camel.spi.RouteContext;
-import org.apache.camel.util.IntrospectionSupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -2140,6 +2139,21 @@ public abstract class ProcessorDefinition<Type extends 
ProcessorDefinition<Type>
     }
 
     /**
+     * Sets the exception on the {@link org.apache.camel.Exchange}
+     *
+     * @param type the exception class to use
+     * @param message the given message as caused message (supports simple 
language)
+     * @return the builder
+     */
+    public Type throwException(Class<? extends Exception> type, String 
message) {
+        ThrowExceptionDefinition answer = new ThrowExceptionDefinition();
+        answer.setExceptionClass(type);
+        answer.setMessage(message);
+        addOutput(answer);
+        return (Type) this;
+    }
+
+    /**
      * Marks the exchange for rollback only.
      * <p/>
      * Does <b>not</b> set any exception as opposed to {@link #rollback()} 
methods.

http://git-wip-us.apache.org/repos/asf/camel/blob/d772b4f5/camel-core/src/main/java/org/apache/camel/model/ThrowExceptionDefinition.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/ThrowExceptionDefinition.java 
b/camel-core/src/main/java/org/apache/camel/model/ThrowExceptionDefinition.java
index 4279cee..fcddbfb 100644
--- 
a/camel-core/src/main/java/org/apache/camel/model/ThrowExceptionDefinition.java
+++ 
b/camel-core/src/main/java/org/apache/camel/model/ThrowExceptionDefinition.java
@@ -35,11 +35,16 @@ import org.apache.camel.util.ObjectHelper;
 @XmlRootElement(name = "throwException")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class ThrowExceptionDefinition extends 
NoOutputDefinition<ThrowExceptionDefinition> {
-    @XmlAttribute(required = true)
-    // the ref is required from tooling and XML DSL
+    @XmlAttribute
     private String ref;
+    @XmlAttribute
+    private String message;
     @XmlTransient
     private Exception exception;
+    @XmlAttribute
+    private String exceptionType;
+    @XmlTransient
+    private Class<? extends Exception> exceptionClass;
 
     public ThrowExceptionDefinition() {
     }
@@ -64,8 +69,18 @@ public class ThrowExceptionDefinition extends 
NoOutputDefinition<ThrowExceptionD
             this.exception = 
routeContext.getCamelContext().getRegistry().lookupByNameAndType(ref, 
Exception.class);
         }
 
-        ObjectHelper.notNull(exception, "exception or ref", this);
-        return new ThrowExceptionProcessor(exception);
+        if (exceptionType != null && exceptionClass == null) {
+            try {
+                this.exceptionClass = 
routeContext.getCamelContext().getClassResolver().resolveMandatoryClass(exceptionType,
 Exception.class);
+            } catch (ClassNotFoundException e) {
+                throw ObjectHelper.wrapRuntimeCamelException(e);
+            }
+        }
+
+        if (exception == null && exceptionClass == null) {
+            throw new IllegalArgumentException("exception or 
exceptionClass/exceptionType must be configured on: " + this);
+        }
+        return new ThrowExceptionProcessor(exception, exceptionClass, message);
     }
 
     public String getRef() {
@@ -86,4 +101,28 @@ public class ThrowExceptionDefinition extends 
NoOutputDefinition<ThrowExceptionD
     public void setException(Exception exception) {
         this.exception = exception;
     }
+
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * To create a new exception instance and use the given message as caused 
message (supports simple language)
+     */
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public Class<? extends Exception> getExceptionClass() {
+        return exceptionClass;
+    }
+
+    /**
+     * The class of the exception to create using the message.
+     *
+     * @see #setMessage(String)
+     */
+    public void setExceptionClass(Class<? extends Exception> exceptionClass) {
+        this.exceptionClass = exceptionClass;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/d772b4f5/camel-core/src/main/java/org/apache/camel/processor/ThrowExceptionProcessor.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/processor/ThrowExceptionProcessor.java
 
b/camel-core/src/main/java/org/apache/camel/processor/ThrowExceptionProcessor.java
index 728f311..931e064 100644
--- 
a/camel-core/src/main/java/org/apache/camel/processor/ThrowExceptionProcessor.java
+++ 
b/camel-core/src/main/java/org/apache/camel/processor/ThrowExceptionProcessor.java
@@ -16,9 +16,15 @@
  */
 package org.apache.camel.processor;
 
+import java.lang.reflect.Constructor;
+
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.AsyncProcessor;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.CamelExchangeException;
 import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
 import org.apache.camel.Traceable;
 import org.apache.camel.spi.IdAware;
 import org.apache.camel.support.ServiceSupport;
@@ -28,21 +34,47 @@ import org.apache.camel.util.ObjectHelper;
 /**
  * The processor which sets an {@link Exception} on the {@link Exchange}
  */
-public class ThrowExceptionProcessor extends ServiceSupport implements 
AsyncProcessor, Traceable, IdAware {
+public class ThrowExceptionProcessor extends ServiceSupport implements 
AsyncProcessor, Traceable, IdAware, CamelContextAware {
     private String id;
+    private CamelContext camelContext;
+    private Expression simple;
     private final Exception exception;
+    private final Class<? extends Exception> type;
+    private final String message;
 
     public ThrowExceptionProcessor(Exception exception) {
-        ObjectHelper.notNull(exception, "exception", this);
+        this(exception, null, null);
+    }
+
+    public ThrowExceptionProcessor(Exception exception, Class<? extends 
Exception> type, String message) {
         this.exception = exception;
+        this.type = type;
+        this.message = message;
     }
 
     public void process(Exchange exchange) throws Exception {
         AsyncProcessorHelper.process(this, exchange);
     }
 
+    @SuppressWarnings("unchecked")
     public boolean process(Exchange exchange, AsyncCallback callback) {
-        exchange.setException(exception);
+        Exception cause = exception;
+
+        try {
+            if (message != null && type != null) {
+                // create the message using simple language so it can be 
dynamic
+                String text = simple.evaluate(exchange, String.class);
+                // create a new exception of that type, and provide the 
message as
+                Constructor<?> constructor = 
type.getDeclaredConstructor(String.class);
+                cause = (Exception) constructor.newInstance(text);
+                exchange.setException(cause);
+            } else {
+                exchange.setException(cause);
+            }
+        } catch (Throwable e) {
+            exchange.setException(new CamelExchangeException("Error creating 
new instance of " + exception.getClass(), exchange, e));
+        }
+
         callback.done(true);
         return true;
     }
@@ -63,13 +95,33 @@ public class ThrowExceptionProcessor extends ServiceSupport 
implements AsyncProc
         return exception;
     }
 
+    public Class<? extends Exception> getType() {
+        return type;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
     public String toString() {
         return "ThrowException";
     }
 
     @Override
     protected void doStart() throws Exception {
-        // noop
+        ObjectHelper.notNull(camelContext, "camelContext", this);
+
+        if (message != null) {
+            simple = 
camelContext.resolveLanguage("simple").createExpression(message);
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/d772b4f5/camel-core/src/test/java/org/apache/camel/processor/ThrowExceptionMessageTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/processor/ThrowExceptionMessageTest.java
 
b/camel-core/src/test/java/org/apache/camel/processor/ThrowExceptionMessageTest.java
new file mode 100644
index 0000000..f79b725
--- /dev/null
+++ 
b/camel-core/src/test/java/org/apache/camel/processor/ThrowExceptionMessageTest.java
@@ -0,0 +1,55 @@
+/**
+ * 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.processor;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * @version 
+ */
+public class ThrowExceptionMessageTest extends ContextTestSupport {
+
+    public void testThrowExceptionMessage() throws Exception {
+        getMockEndpoint("mock:start").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+
+        try {
+            template.sendBody("direct:start", "Hello World");
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertEquals("Darn Hello World is invalid", 
e.getCause().getMessage());
+        }
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .to("mock:start")
+                        .throwException(IllegalArgumentException.class, "Darn 
${body} is invalid")
+                        .to("mock:result");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/d772b4f5/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.java
 
b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.java
new file mode 100644
index 0000000..fa0687b
--- /dev/null
+++ 
b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.java
@@ -0,0 +1,33 @@
+/**
+ * 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.spring.processor;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.processor.ThrowExceptionMessageTest;
+
+import static 
org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
+
+/**
+ * @version 
+ */
+public class SpringThrowExceptionMessageTest extends ThrowExceptionMessageTest 
{
+
+    protected CamelContext createCamelContext() throws Exception {
+        return createSpringCamelContext(this, 
"org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.xml");
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/d772b4f5/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.xml
----------------------------------------------------------------------
diff --git 
a/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.xml
 
b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.xml
new file mode 100644
index 0000000..cfd0fc4
--- /dev/null
+++ 
b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringThrowExceptionMessageTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+    <camelContext xmlns="http://camel.apache.org/schema/spring";>
+        <route>
+            <from uri="direct:start"/>
+            <to uri="mock:start"/>
+            <throwException exceptionType="java.lang.IllegalArgumentException" 
message="Darn ${body} is invalid"/>
+            <to uri="mock:result"/>
+        </route>
+    </camelContext>
+</beans>

Reply via email to