This is an automated email from the ASF dual-hosted git repository.

lburgazzoli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k-runtime.git


The following commit(s) were added to refs/heads/master by this push:
     new b86aefd  yaml-loader: add support for OnException
b86aefd is described below

commit b86aefd2c264ae1160a3bf273d5ee17ddae79151
Author: lburgazzoli <lburgazz...@gmail.com>
AuthorDate: Tue May 26 19:59:26 2020 +0200

    yaml-loader: add support for OnException
---
 .../camel/k/loader/yaml/parser/FromStepParser.java |   2 +-
 .../loader/yaml/parser/OnExceptionStepParser.java  | 173 +++++++++++++++++++++
 .../camel/k/loader/yaml/parser/RestStepParser.java |   2 +-
 .../camel/k/loader/yaml/spi/StartStepParser.java   |   1 -
 .../apache/camel/k/loader/yaml/spi/StepParser.java |  17 +-
 .../camel/k/loader/yaml/YamlSourceLoader.java      |  42 +----
 .../apache/camel/k/loader/yaml/RoutesTest.groovy   |  61 +++++---
 .../apache/camel/k/loader/yaml/TestSupport.groovy  |  17 +-
 .../k/loader/yaml/parser/OnExceptionTest.groovy    | 138 ++++++++++++++++
 .../k/loader/yaml/support/MyException.groovy}      |  17 +-
 .../loader/yaml/support/MyFailingProcessor.groovy} |  19 +--
 .../routes/RoutesTest_onExceptionHandled.yaml      |  28 ++++
 .../k/knative/yaml/parser/KnativeStepParser.java   |   2 +-
 13 files changed, 418 insertions(+), 101 deletions(-)

diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/FromStepParser.java
 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/FromStepParser.java
index 22f846f..47e95fc 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/FromStepParser.java
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/FromStepParser.java
@@ -37,7 +37,7 @@ public class FromStepParser implements StartStepParser {
     public ProcessorDefinition<?> toStartProcessor(Context context) {
         final FromStepDefinition definition = 
context.node(FromStepDefinition.class);
         final String uri = definition.getEndpointUri();
-        final RouteDefinition route = new RouteDefinition().from(uri);
+        final RouteDefinition route = context.builder().from(uri);
 
         // as this is a start converter, steps are mandatory
         StepParserSupport.notNull(definition.steps, "steps");
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/OnExceptionStepParser.java
 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/OnExceptionStepParser.java
new file mode 100644
index 0000000..6e12643
--- /dev/null
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/OnExceptionStepParser.java
@@ -0,0 +1,173 @@
+/*
+ * 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.k.loader.yaml.parser;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import org.apache.camel.k.annotation.yaml.YAMLNodeDefinition;
+import org.apache.camel.k.annotation.yaml.YAMLStepParser;
+import org.apache.camel.k.loader.yaml.model.Step;
+import org.apache.camel.k.loader.yaml.spi.ProcessorStepParser;
+import org.apache.camel.k.loader.yaml.spi.StartStepParser;
+import org.apache.camel.k.loader.yaml.spi.StepParserSupport;
+import org.apache.camel.model.ExpressionSubElementDefinition;
+import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.RedeliveryPolicyDefinition;
+import org.apache.camel.model.WhenDefinition;
+import org.apache.camel.model.language.ConstantExpression;
+import org.apache.camel.model.language.ExpressionDefinition;
+import org.apache.camel.reifier.OnExceptionReifier;
+
+import static org.apache.camel.util.ObjectHelper.ifNotEmpty;
+
+@YAMLStepParser("on-exception")
+public class OnExceptionStepParser implements StartStepParser, 
ProcessorStepParser {
+    @SuppressWarnings("unchecked")
+    @Override
+    public ProcessorDefinition<?> toStartProcessor(Context context) {
+        final Definition definition = context.node(Definition.class);
+        final OnExceptionDefinition onException = 
context.builder().onException();
+
+        if (definition.exceptions == null) {
+            definition.exceptions = List.of(Exception.class.getName());
+        }
+
+        onException.setExceptions(definition.exceptions);
+        onException.setRouteScoped(false);
+
+        mapToOnException(context, definition, onException);
+
+        return StepParserSupport.convertSteps(
+            context,
+            onException,
+            definition.steps);
+    }
+
+    @Override
+    public ProcessorDefinition<?> toProcessor(Context context) {
+        final Definition definition = context.node(Definition.class);
+        final OnExceptionDefinition onException = new OnExceptionDefinition();
+
+        if (definition.exceptions == null) {
+            definition.exceptions = List.of(Exception.class.getName());
+        }
+
+        onException.setExceptions(definition.exceptions);
+        onException.setRouteScoped(true);
+
+        mapToOnException(context, definition, onException);
+
+        return StepParserSupport.convertSteps(
+            context,
+            onException,
+            definition.steps);
+    }
+
+    private static void mapToOnException(Context context, Definition 
definition, OnExceptionDefinition onException) {
+        ifNotEmpty(definition.retryWhile, onException::setRetryWhile);
+        ifNotEmpty(definition.handled, onException::setHandled);
+        ifNotEmpty(definition.continued, onException::setContinued);
+        ifNotEmpty(definition.continued, onException::setContinued);
+        ifNotEmpty(definition.redeliveryPolicyType, 
onException::setRedeliveryPolicyType);
+        ifNotEmpty(definition.redeliveryPolicyRef, 
onException::setRedeliveryPolicyRef);
+        ifNotEmpty(definition.onRedeliveryRef, 
onException::setOnRedeliveryRef);
+        ifNotEmpty(definition.onExceptionOccurredRef, 
onException::setOnExceptionOccurredRef);
+        ifNotEmpty(definition.useOriginalMessage, val -> 
onException.setUseOriginalMessage(Boolean.toString(val)));
+        ifNotEmpty(definition.useOriginalBody, val -> 
onException.setUseOriginalBody(Boolean.toString(val)));
+
+        if (definition.onWhen != null) {
+            StepParserSupport.notNull(definition.onWhen.steps, "onWhen.steps");
+
+            StepParserSupport.convertSteps(
+                context,
+                definition.onWhen,
+                definition.onWhen.steps
+            );
+
+            onException.setOnWhen(definition.onWhen);
+        }
+    }
+
+    @YAMLNodeDefinition(reifiers = OnExceptionReifier.class)
+    public static final class Definition {
+        public List<Step> steps;
+
+        @JsonAlias("exceptions")
+        public List<String> exceptions;
+
+        @JsonAlias({"when", "on-when"})
+        public When onWhen;
+        @JsonAlias("retry-while")
+        public ExpressionElement retryWhile;
+        @JsonAlias("handled")
+        public MaybeBooleanExpressionElement handled;
+        @JsonAlias("continued")
+        public MaybeBooleanExpressionElement continued;
+
+        @JsonAlias("redelivery-policy")
+        public RedeliveryPolicyDefinition redeliveryPolicyType;
+        @JsonAlias("redelivery-policy-ref")
+        public String redeliveryPolicyRef;
+
+        @JsonAlias("on-redelivery-ref")
+        public String onRedeliveryRef;
+        @JsonAlias("on-exception-occurred-ref")
+        public String onExceptionOccurredRef;
+        @JsonAlias("use-original-message")
+        public boolean useOriginalMessage;
+        @JsonAlias("use-original-body")
+        public boolean useOriginalBody;
+
+        public static final class When extends WhenDefinition implements 
HasExpression {
+            public List<Step> steps;
+        }
+
+        public static final class ExpressionElement extends 
ExpressionSubElementDefinition implements HasExpression {
+            @Override
+            public void setExpression(ExpressionDefinition 
expressionDefinition) {
+                super.setExpressionType(expressionDefinition);
+            }
+
+            @Override
+            public ExpressionDefinition getExpression() {
+                return super.getExpressionType();
+            }
+        }
+
+        public static final class MaybeBooleanExpressionElement extends 
ExpressionSubElementDefinition implements HasExpression {
+            public MaybeBooleanExpressionElement() {
+            }
+
+            public MaybeBooleanExpressionElement(boolean argument) {
+                setExpression(new 
ConstantExpression(Boolean.toString(argument)));
+            }
+
+            @Override
+            public void setExpression(ExpressionDefinition 
expressionDefinition) {
+                super.setExpressionType(expressionDefinition);
+            }
+
+            @Override
+            public ExpressionDefinition getExpression() {
+                return super.getExpressionType();
+            }
+        }
+    }
+}
+
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/RestStepParser.java
 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/RestStepParser.java
index 99cb057..936f556 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/RestStepParser.java
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/parser/RestStepParser.java
@@ -41,7 +41,7 @@ public class RestStepParser implements StartStepParser {
         StepParserSupport.notNull(definition.verb, "verb");
         StepParserSupport.notNull(definition.steps, "steps");
 
-        RestDefinition rest = new RestDefinition().verb(definition.verb, 
definition.uri);
+        RestDefinition rest = context.builder().rest().verb(definition.verb, 
definition.uri);
 
         ObjectHelper.ifNotEmpty(definition.apiDocs, rest::apiDocs);
         ObjectHelper.ifNotEmpty(definition.enableCORS, rest::enableCORS);
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
index f80bcdb..10426a2 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
@@ -22,7 +22,6 @@ import org.apache.camel.model.ProcessorDefinition;
 public interface StartStepParser extends StepParser {
     /**
      * @param context
-     * @return
      */
     ProcessorDefinition<?> toStartProcessor(Context context);
 
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StepParser.java
 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StepParser.java
index 2fab5f2..42099ee 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StepParser.java
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StepParser.java
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.camel.CamelContext;
 import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.spi.HasCamelContext;
 import org.apache.camel.util.ObjectHelper;
 
@@ -35,12 +36,12 @@ public interface StepParser {
      */
     class Context implements HasCamelContext {
         private final ObjectMapper mapper;
-        private final CamelContext camelContext;
+        private final RouteBuilder builder;
         private final JsonNode node;
         private final Resolver resolver;
 
-        public Context(CamelContext camelContext, ObjectMapper mapper, 
JsonNode node, Resolver resolver) {
-            this.camelContext = camelContext;
+        public Context(RouteBuilder builder, ObjectMapper mapper, JsonNode 
node, Resolver resolver) {
+            this.builder = builder;
             this.mapper = mapper;
             this.node = node;
             this.resolver = ObjectHelper.notNull(resolver, "resolver");
@@ -48,7 +49,11 @@ public interface StepParser {
 
         @Override
         public CamelContext getCamelContext() {
-            return camelContext;
+            return builder.getContext();
+        }
+
+        public RouteBuilder builder() {
+            return builder;
         }
 
         public JsonNode node() {
@@ -75,7 +80,7 @@ public interface StepParser {
         }
 
         public <T extends StepParser> T lookup(Class<T> type, String stepId) {
-            StepParser parser = resolver.resolve(camelContext, stepId);
+            StepParser parser = resolver.resolve(builder.getContext(), stepId);
             if (type.isInstance(parser)) {
                 return type.cast(parser);
             }
@@ -85,7 +90,7 @@ public interface StepParser {
 
         public static Context of(Context context, JsonNode step) {
             return new Context(
-                context.camelContext,
+                context.builder,
                 context.mapper,
                 step,
                 context.resolver
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml/src/main/java/org/apache/camel/k/loader/yaml/YamlSourceLoader.java
 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/main/java/org/apache/camel/k/loader/yaml/YamlSourceLoader.java
index 1c1b4cd..a300fe1 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml/src/main/java/org/apache/camel/k/loader/yaml/YamlSourceLoader.java
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/main/java/org/apache/camel/k/loader/yaml/YamlSourceLoader.java
@@ -19,7 +19,6 @@ package org.apache.camel.k.loader.yaml;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -31,7 +30,6 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategy;
 import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
 import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
-import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.k.Runtime;
 import org.apache.camel.k.Source;
@@ -40,11 +38,6 @@ import org.apache.camel.k.annotation.Loader;
 import org.apache.camel.k.loader.yaml.model.Step;
 import org.apache.camel.k.loader.yaml.spi.StartStepParser;
 import org.apache.camel.k.loader.yaml.spi.StepParser;
-import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.rest.RestDefinition;
-import org.apache.camel.model.rest.RestsDefinition;
 
 @Loader("yaml")
 public class YamlSourceLoader implements SourceLoader {
@@ -94,41 +87,12 @@ public class YamlSourceLoader implements SourceLoader {
             @Override
             public void configure() throws Exception {
                 final StepParser.Resolver resolver = 
StepParser.Resolver.caching(new YamlStepResolver());
-                final CamelContext camelContext = getContext();
-                final List<RouteDefinition> routes = new ArrayList<>();
-                final List<RestDefinition> rests = new ArrayList<>();
 
                 try (is) {
                     for (Step step : mapper.readValue(is, Step[].class)) {
-                        final StepParser.Context context = new 
StepParser.Context(camelContext, mapper, step.node, resolver);
-                        final ProcessorDefinition<?> root = 
StartStepParser.invoke(context, step.id);
-
-                        if (root == null) {
-                            throw new IllegalStateException("No route 
definition");
-                        }
-                        if (!(root instanceof RouteDefinition)) {
-                            throw new IllegalStateException("Root definition 
should be of type RouteDefinition");
-                        }
-
-                        RouteDefinition r = (RouteDefinition) root;
-                        if (r.getRestDefinition() == null) {
-                            routes.add(r);
-                        } else {
-                            rests.add(r.getRestDefinition());
-                        }
-                    }
-
-                    if (!routes.isEmpty()) {
-                        RoutesDefinition definition = new RoutesDefinition();
-                        definition.setRoutes(routes);
-
-                        setRouteCollection(definition);
-                    }
-                    if (!rests.isEmpty()) {
-                        RestsDefinition definition = new RestsDefinition();
-                        definition.setRests(rests);
-
-                        setRestCollection(definition);
+                        StartStepParser.invoke(
+                            new StepParser.Context(this, mapper, step.node, 
resolver),
+                            step.id);
                     }
                 }
             }
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/RoutesTest.groovy
 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/RoutesTest.groovy
index 3fc24b0..cde4540 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/RoutesTest.groovy
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/RoutesTest.groovy
@@ -17,6 +17,7 @@
 package org.apache.camel.k.loader.yaml
 
 import org.apache.camel.component.mock.MockEndpoint
+import org.apache.camel.k.loader.yaml.support.MyFailingProcessor
 import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy
 import org.apache.camel.support.processor.idempotent.MemoryIdempotentRepository
 
@@ -26,15 +27,15 @@ class RoutesTest extends TestSupport {
         setup:
             def context = startContext()
 
-            
org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context,'mock:split') {
+            mockEndpoint(context,'mock:split') {
                 expectedMessageCount = 3
                 expectedBodiesReceived 'a', 'b', 'c'
             }
-            
org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context,'mock:route') {
+            mockEndpoint(context,'mock:route') {
                 expectedMessageCount = 1
                 expectedBodiesReceived 'a,b,c'
             }
-            
org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context,'mock:flow') {
+            mockEndpoint(context,'mock:flow') {
                 expectedMessageCount = 3
                 expectedBodiesReceived 'a', 'b', 'c'
             }
@@ -53,15 +54,15 @@ class RoutesTest extends TestSupport {
         setup:
             def context = startContext()
 
-            org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context, 
'mock:route') {
+            mockEndpoint(context, 'mock:route') {
                 expectedMessageCount 2
                 expectedBodiesReceived 'a', 'b'
             }
-            org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context, 
'mock:filter') {
+            mockEndpoint(context, 'mock:filter') {
                 expectedMessageCount 1
                 expectedBodiesReceived 'a'
             }
-            
org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context,'mock:flow') {
+            mockEndpoint(context,'mock:flow') {
                 expectedMessageCount 1
                 expectedBodiesReceived 'a'
             }
@@ -84,7 +85,7 @@ class RoutesTest extends TestSupport {
                 'aggregatorStrategy': new UseLatestAggregationStrategy()
             ])
 
-            org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context, 
'mock:route') {
+            mockEndpoint(context, 'mock:route') {
                 expectedMessageCount 2
                 expectedBodiesReceived '2', '4'
             }
@@ -103,30 +104,42 @@ class RoutesTest extends TestSupport {
 
     def 'idempotentConsumer'() {
         setup:
-        def context = startContext([
+            def context = startContext([
                 'myRepo': new MemoryIdempotentRepository()
-        ])
+            ])
 
-        
org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context,'mock:idempotent')
 {
-            expectedMessageCount = 3
-            expectedBodiesReceived 'a', 'b', 'c'
-        }
-        
org.apache.camel.k.loader.yaml.TestSupport.mockEndpoint(context,'mock:route') {
-            expectedMessageCount = 5
-            expectedBodiesReceived 'a', 'b', 'a2', 'b2', 'c'
-        }
+            mockEndpoint(context,'mock:idempotent') {
+                expectedMessageCount = 3
+                expectedBodiesReceived 'a', 'b', 'c'
+            }
+            mockEndpoint(context,'mock:route') {
+                expectedMessageCount = 5
+                expectedBodiesReceived 'a', 'b', 'a2', 'b2', 'c'
+            }
         when:
-        context.createProducerTemplate().with {
-            sendBodyAndHeader('direct:route', 'a', 'id', '1')
-            sendBodyAndHeader('direct:route', 'b', 'id', '2')
-            sendBodyAndHeader('direct:route', 'a2', 'id', '1')
-            sendBodyAndHeader('direct:route', 'b2', 'id', '2')
-            sendBodyAndHeader('direct:route', 'c', 'id', '3')
-        }
+            context.createProducerTemplate().with {
+                sendBodyAndHeader('direct:route', 'a', 'id', '1')
+                sendBodyAndHeader('direct:route', 'b', 'id', '2')
+                sendBodyAndHeader('direct:route', 'a2', 'id', '1')
+                sendBodyAndHeader('direct:route', 'b2', 'id', '2')
+                sendBodyAndHeader('direct:route', 'c', 'id', '3')
+            }
         then:
             MockEndpoint.assertIsSatisfied(context)
         cleanup:
             context?.stop()
     }
 
+    def 'onExceptionHandled'() {
+        setup:
+            def context = startContext([
+                'myFailingProcessor' : new MyFailingProcessor()
+            ])
+        when:
+            def out = 
context.createProducerTemplate().requestBody('direct:start', 'Hello World');
+        then:
+            out == 'Sorry'
+        cleanup:
+            context?.stop()
+    }
 }
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/TestSupport.groovy
 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/TestSupport.groovy
index 597d429..7a0f17a 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/TestSupport.groovy
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/TestSupport.groovy
@@ -19,6 +19,7 @@ package org.apache.camel.k.loader.yaml
 import com.fasterxml.jackson.databind.JsonNode
 import groovy.util.logging.Slf4j
 import org.apache.camel.CamelContext
+import org.apache.camel.builder.RouteBuilder
 import org.apache.camel.component.mock.MockEndpoint
 import org.apache.camel.impl.DefaultCamelContext
 import org.apache.camel.k.loader.yaml.spi.ProcessorStepParser
@@ -36,13 +37,23 @@ class TestSupport extends Specification {
 
     static StepParser.Context stepContext(String content) {
         def node = MAPPER.readTree(content.stripMargin())
-        def cctx = new DefaultCamelContext()
+        def builder = new RouteBuilder(new DefaultCamelContext()) {
+            @Override
+            void configure() throws Exception {
+            }
+        }
 
-        return new StepParser.Context(cctx, MAPPER, node, RESOLVER)
+        return new StepParser.Context(builder, MAPPER, node, RESOLVER)
     }
 
     static StepParser.Context stepContext(JsonNode content) {
-        return new StepParser.Context(new DefaultCamelContext(), MAPPER, 
content, RESOLVER)
+        def builder = new RouteBuilder(new DefaultCamelContext()) {
+            @Override
+            void configure() throws Exception {
+            }
+        }
+
+        return new StepParser.Context(builder, MAPPER, content, RESOLVER)
     }
 
     static CamelContext startContext(String content) {
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/parser/OnExceptionTest.groovy
 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/parser/OnExceptionTest.groovy
new file mode 100644
index 0000000..4f286f8
--- /dev/null
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/parser/OnExceptionTest.groovy
@@ -0,0 +1,138 @@
+/*
+ * 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.k.loader.yaml.parser
+
+import org.apache.camel.k.loader.yaml.TestSupport
+import org.apache.camel.model.OnExceptionDefinition
+import org.apache.camel.model.ToDefinition
+import org.apache.camel.model.language.ConstantExpression
+
+class OnExceptionTest extends TestSupport {
+    def "definition (route)"() {
+        given:
+            def stepContext = stepContext('''
+                 exceptions: 
+                   - java.lang.Exception
+                   - java.io.IOException
+                 when:
+                   constant: "when"
+                   steps:
+                     - to: 'log:when'
+                 retry-while:                 
+                   constant: "while"
+                 handled:                 
+                   constant: "handled"
+                 continued:                 
+                   constant: "continued"
+                 
+            ''')
+        when:
+            def processor = new 
OnExceptionStepParser().toProcessor(stepContext)
+        then:
+            with(processor, OnExceptionDefinition) {
+                exceptions.contains('java.lang.Exception')
+                exceptions.contains('java.io.IOException')
+
+                with(onWhen) {
+                    outputs.size() == 1
+
+                    with(outputs[0], ToDefinition) {
+                        endpointUri == 'log:when'
+                    }
+                    with(expression, ConstantExpression) {
+                        expression == 'when'
+                    }
+                }
+                with(retryWhile.expressionType, ConstantExpression) {
+                    expression == 'while'
+                }
+                with(handled.expressionType, ConstantExpression) {
+                    expression == 'handled'
+                }
+                with(continued.expressionType, ConstantExpression) {
+                    expression == 'continued'
+                }
+            }
+    }
+
+    def "definition with maybe-booleans"() {
+        when:
+            def processor = toProcessor(OnExceptionStepParser, '''
+                 handled: true
+                 continued: false                 
+            ''')
+        then:
+            with(processor, OnExceptionDefinition) {
+                with(handled.expressionType, ConstantExpression) {
+                    expression == 'true'
+                }
+                with(continued.expressionType, ConstantExpression) {
+                    expression == 'false'
+                }
+            }
+    }
+
+    def "definition (global)"() {
+        given:
+            def stepContext = stepContext('''
+                 exceptions: 
+                   - java.lang.Exception
+                   - java.io.IOException
+                 when:
+                   constant: "when"
+                   steps:
+                     - to: 'log:when'
+                 retry-while:                 
+                   constant: "while"
+                 handled:                 
+                   constant: "handled"
+                 continued:                 
+                   constant: "continued"
+            ''')
+        when:
+            def processor = new 
OnExceptionStepParser().toStartProcessor(stepContext)
+        then:
+            stepContext.builder().routeCollection.onExceptions.size() == 1
+            
stepContext.builder().routeCollection.onExceptions[0].exceptions.contains("java.lang.Exception")
+            
stepContext.builder().routeCollection.onExceptions[0].exceptions.contains("java.io.IOException")
+
+            with(processor, OnExceptionDefinition) {
+                exceptions.contains('java.lang.Exception')
+                exceptions.contains('java.io.IOException')
+
+                with(onWhen) {
+                    outputs.size() == 1
+
+                    with(outputs[0], ToDefinition) {
+                        endpointUri == 'log:when'
+                    }
+                    with(expression, ConstantExpression) {
+                        expression == 'when'
+                    }
+                }
+                with(retryWhile.expressionType, ConstantExpression) {
+                    expression == 'while'
+                }
+                with(handled.expressionType, ConstantExpression) {
+                    expression == 'handled'
+                }
+                with(continued.expressionType, ConstantExpression) {
+                    expression == 'continued'
+                }
+            }
+    }
+}
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/support/MyException.groovy
similarity index 64%
copy from 
camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
copy to 
camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/support/MyException.groovy
index f80bcdb..5b573b3 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/support/MyException.groovy
@@ -14,19 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.k.loader.yaml.spi;
+package org.apache.camel.k.loader.yaml.support
 
-import org.apache.camel.model.ProcessorDefinition;
-
-@FunctionalInterface
-public interface StartStepParser extends StepParser {
-    /**
-     * @param context
-     * @return
-     */
-    ProcessorDefinition<?> toStartProcessor(Context context);
-
-    static ProcessorDefinition<?> invoke(Context context, String stepId) {
-        return context.lookup(StartStepParser.class, 
stepId).toStartProcessor(context);
+class MyException extends Exception {
+    MyException(String message) {
+        super(message)
     }
 }
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/support/MyFailingProcessor.groovy
similarity index 64%
copy from 
camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
copy to 
camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/support/MyFailingProcessor.groovy
index f80bcdb..3904351 100644
--- 
a/camel-k-loader-yaml/camel-k-loader-yaml-common/src/main/java/org/apache/camel/k/loader/yaml/spi/StartStepParser.java
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/groovy/org/apache/camel/k/loader/yaml/support/MyFailingProcessor.groovy
@@ -14,19 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.k.loader.yaml.spi;
+package org.apache.camel.k.loader.yaml.support
 
-import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.Exchange
+import org.apache.camel.Processor
 
-@FunctionalInterface
-public interface StartStepParser extends StepParser {
-    /**
-     * @param context
-     * @return
-     */
-    ProcessorDefinition<?> toStartProcessor(Context context);
-
-    static ProcessorDefinition<?> invoke(Context context, String stepId) {
-        return context.lookup(StartStepParser.class, 
stepId).toStartProcessor(context);
+class MyFailingProcessor implements Processor {
+    @Override
+    void process(Exchange exchange) throws Exception {
+        throw new MyException('Sorry you cannot do this')
     }
 }
diff --git 
a/camel-k-loader-yaml/camel-k-loader-yaml/src/test/resources/routes/RoutesTest_onExceptionHandled.yaml
 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/resources/routes/RoutesTest_onExceptionHandled.yaml
new file mode 100644
index 0000000..3bd3bcb
--- /dev/null
+++ 
b/camel-k-loader-yaml/camel-k-loader-yaml/src/test/resources/routes/RoutesTest_onExceptionHandled.yaml
@@ -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.
+#
+- on-exception:
+    exceptioons:
+      - org.apache.camel.k.loader.yaml.support.MyException
+    handled: true
+    steps:
+      - transform:
+          constant: "Sorry"
+- from:
+    uri: "direct:start"
+    steps:
+      - process:
+          ref: "myFailingProcessor"
\ No newline at end of file
diff --git 
a/camel-k-runtime-knative/src/main/java/org/apache/camel/k/knative/yaml/parser/KnativeStepParser.java
 
b/camel-k-runtime-knative/src/main/java/org/apache/camel/k/knative/yaml/parser/KnativeStepParser.java
index 48c07f8..b1d4c75 100644
--- 
a/camel-k-runtime-knative/src/main/java/org/apache/camel/k/knative/yaml/parser/KnativeStepParser.java
+++ 
b/camel-k-runtime-knative/src/main/java/org/apache/camel/k/knative/yaml/parser/KnativeStepParser.java
@@ -37,7 +37,7 @@ public class KnativeStepParser implements 
ProcessorStepParser, StartStepParser {
     public ProcessorDefinition<?> toStartProcessor(Context context) {
         final Definition definition = context.node(Definition.class);
         final String uri = definition.getEndpointUri();
-        final RouteDefinition route = new RouteDefinition().from(uri);
+        final RouteDefinition route = context.builder().from(uri);
 
         // steps are mandatory
         ObjectHelper.notNull(definition.steps, "from steps");

Reply via email to