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 2021/08/03 12:33:32 UTC

[camel] 02/22: CAMEL-16757: routes configuration for intercept, on completion

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

davsclaus pushed a commit to branch CAMEL-16757b
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 90824ad1050077dca392489f49bc522ee47a2951
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 07:36:50 2021 +0200

    CAMEL-16757: routes configuration for intercept, on completion
---
 .../org/apache/camel/catalog/models.properties     |   5 +-
 ...sConfiguration.json => routeConfiguration.json} |   8 +-
 .../camel/catalog/models/routeConfigurations.json  |  16 ++
 .../camel/catalog/models/routesConfigurations.json |  17 --
 .../camel/catalog/models/templateBeanFactory.json  |  17 --
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  82 ++++----
 .../camel/model/RouteConfigurationDefinition.java  |  60 ++++++
 .../model/RoutesConfigurationBuilderTest.java      | 225 ++++++++++++++++++++-
 8 files changed, 345 insertions(+), 85 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
index fd5fa5c..e0d7e06 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
@@ -145,6 +145,8 @@ rollback
 roundRobin
 route
 routeBuilder
+routeConfiguration
+routeConfigurations
 routeContext
 routeContextRef
 routeTemplate
@@ -152,8 +154,6 @@ routeTemplateContext
 routeTemplateContextRef
 routeTemplates
 routes
-routesConfiguration
-routesConfigurations
 routingSlip
 rss
 saga
@@ -189,7 +189,6 @@ syslog
 tarfile
 template
 templateBean
-templateBeanFactory
 templateParameter
 templateScript
 threadPool
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfiguration.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
similarity index 76%
rename from catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfiguration.json
rename to catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
index c4a5307..515c123 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfiguration.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
@@ -1,12 +1,12 @@
 {
   "model": {
     "kind": "model",
-    "name": "routesConfiguration",
-    "title": "Routes Configuration",
-    "description": "Global configuration for Camel routes",
+    "name": "routeConfiguration",
+    "title": "Route Configuration",
+    "description": "Reusable configuration for Camel route(s).",
     "deprecated": false,
     "label": "configuration",
-    "javaType": "org.apache.camel.model.RoutesConfigurationDefinition",
+    "javaType": "org.apache.camel.model.RouteConfigurationDefinition",
     "input": false,
     "output": false
   },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfigurations.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfigurations.json
new file mode 100644
index 0000000..d9d128f
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfigurations.json
@@ -0,0 +1,16 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "routeConfigurations",
+    "title": "Route Configurations",
+    "description": "A series of route configurations",
+    "deprecated": false,
+    "label": "configuration",
+    "javaType": "org.apache.camel.model.RouteConfigurationsDefinition",
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    
+  }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfigurations.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfigurations.json
deleted file mode 100644
index 8bd9060..0000000
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfigurations.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "model": {
-    "kind": "model",
-    "name": "routesConfigurations",
-    "title": "Routes Configurations",
-    "description": "A series of global configuration for Camel routes",
-    "deprecated": false,
-    "label": "configuration",
-    "javaType": "org.apache.camel.model.RoutesConfigurationsDefinition",
-    "input": false,
-    "output": false
-  },
-  "properties": {
-    "id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
-    "description": { "kind": "element", "displayName": "Description", "required": false, "type": "object", "javaType": "org.apache.camel.model.DescriptionDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" }
-  }
-}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templateBeanFactory.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templateBeanFactory.json
deleted file mode 100644
index 538a54b..0000000
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templateBeanFactory.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "model": {
-    "kind": "model",
-    "name": "templateBeanFactory",
-    "title": "Template Bean Factory",
-    "description": "A route template bean factory (local bean)",
-    "deprecated": false,
-    "label": "configuration",
-    "javaType": "org.apache.camel.model.RouteTemplateBeanFactoryDefinition",
-    "input": false,
-    "output": false
-  },
-  "properties": {
-    "language": { "kind": "attribute", "displayName": "Language", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "bean", "groovy", "joor", "language", "mvel", "ognl" ], "deprecated": false, "autowired": false, "secret": false, "description": "The language to use for creating the bean (such as groovy, joor)" },
-    "script": { "kind": "value", "displayName": "Script", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The script to execute that creates the bean. If the script use the prefix resource: such as resource:classpath:com\/foo\/myscript.groovy, resource:file:\/var\/myscript.groovy, then its loaded from the external resource." }
-  }
-}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 1000a99..a9e8def 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -1265,6 +1265,22 @@ To refer to a Java org.apache.camel.builder.RouteBuilder instance to use.
     </xs:annotation>
   </xs:element>
 
+  <xs:element name="routeConfiguration" type="tns:routeConfigurationDefinition">
+    <xs:annotation>
+      <xs:documentation xml:lang="en"><![CDATA[
+Reusable configuration for Camel route(s).
+      ]]></xs:documentation>
+    </xs:annotation>
+  </xs:element>
+
+  <xs:element name="routeConfigurations" type="tns:routeConfigurationsDefinition">
+    <xs:annotation>
+      <xs:documentation xml:lang="en"><![CDATA[
+A series of route configurations
+      ]]></xs:documentation>
+    </xs:annotation>
+  </xs:element>
+
   <xs:element name="routeContext" type="tns:camelRouteContextFactoryBean">
     <xs:annotation>
       <xs:documentation xml:lang="en"><![CDATA[
@@ -1329,22 +1345,6 @@ A series of Camel routes
     </xs:annotation>
   </xs:element>
 
-  <xs:element name="routesConfiguration" type="tns:routesConfigurationDefinition">
-    <xs:annotation>
-      <xs:documentation xml:lang="en"><![CDATA[
-Global configuration for Camel routes
-      ]]></xs:documentation>
-    </xs:annotation>
-  </xs:element>
-
-  <xs:element name="routesConfigurations" type="tns:routesConfigurationsDefinition">
-    <xs:annotation>
-      <xs:documentation xml:lang="en"><![CDATA[
-A series of global configuration for Camel routes
-      ]]></xs:documentation>
-    </xs:annotation>
-  </xs:element>
-
   <xs:element name="routingSlip" type="tns:routingSlipDefinition">
     <xs:annotation>
       <xs:documentation xml:lang="en"><![CDATA[
@@ -10627,6 +10627,29 @@ Reference to the route builder instance.
     </xs:complexContent>
   </xs:complexType>
 
+  <xs:complexType name="routeConfigurationDefinition">
+    <xs:complexContent>
+      <xs:extension base="tns:optionalIdentifiedDefinition">
+        <xs:sequence>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onException"/>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onCompletion"/>
+          <xs:choice maxOccurs="unbounded" minOccurs="0">
+            <xs:element ref="tns:intercept"/>
+            <xs:element ref="tns:interceptFrom"/>
+          </xs:choice>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:interceptFrom"/>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:interceptSendToEndpoint"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name="routeConfigurationsDefinition">
+    <xs:sequence>
+      <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:routeConfiguration"/>
+    </xs:sequence>
+  </xs:complexType>
+
   <xs:complexType name="routeContextRefDefinition">
     <xs:sequence/>
     <xs:attribute name="ref" type="xs:string" use="required">
@@ -10922,33 +10945,6 @@ Description of the parameter.
     </xs:complexContent>
   </xs:complexType>
 
-  <xs:complexType name="routesConfigurationDefinition">
-    <xs:complexContent>
-      <xs:extension base="tns:optionalIdentifiedDefinition">
-        <xs:sequence>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onException"/>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onCompletion"/>
-          <xs:choice maxOccurs="unbounded" minOccurs="0">
-            <xs:element ref="tns:intercept"/>
-            <xs:element ref="tns:interceptFrom"/>
-          </xs:choice>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:interceptFrom"/>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:interceptSendToEndpoint"/>
-        </xs:sequence>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-
-  <xs:complexType name="routesConfigurationsDefinition">
-    <xs:complexContent>
-      <xs:extension base="tns:optionalIdentifiedDefinition">
-        <xs:sequence>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:routesConfiguration"/>
-        </xs:sequence>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-
   <xs:complexType name="routesDefinition">
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
index e4b4090..3ffb1f1 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
@@ -135,4 +135,64 @@ public class RouteConfigurationDefinition extends OptionalIdentifiedDefinition<R
         return answer;
     }
 
+    /**
+     * <a href="http://camel.apache.org/oncompletion.html">On completion</a> callback for doing custom routing when the
+     * {@link org.apache.camel.Exchange} is complete.
+     *
+     * @return the on completion builder to configure
+     */
+    public OnCompletionDefinition onCompletion() {
+        OnCompletionDefinition answer = new OnCompletionDefinition();
+        // is global scoped by default
+        answer.setRouteScoped(false);
+        onCompletions.add(answer);
+        return answer;
+    }
+
+    /**
+     * Adds a route for an interceptor that intercepts every processing step.
+     *
+     * @return the builder
+     */
+    public InterceptDefinition intercept() {
+        InterceptDefinition answer = new InterceptDefinition();
+        intercepts.add(answer);
+        return answer;
+    }
+
+    /**
+     * Adds a route for an interceptor that intercepts incoming messages on any inputs in this route
+     *
+     * @return the builder
+     */
+    public InterceptFromDefinition interceptFrom() {
+        InterceptFromDefinition answer = new InterceptFromDefinition();
+        interceptFroms.add(answer);
+        return answer;
+    }
+
+    /**
+     * Adds a route for an interceptor that intercepts incoming messages on the given endpoint.
+     *
+     * @param  uri endpoint uri
+     * @return     the builder
+     */
+    public InterceptFromDefinition interceptFrom(String uri) {
+        InterceptFromDefinition answer = new InterceptFromDefinition(uri);
+        interceptFroms.add(answer);
+        return answer;
+    }
+
+    /**
+     * Applies a route for an interceptor if an exchange is send to the given endpoint
+     *
+     * @param  uri endpoint uri
+     * @return     the builder
+     */
+    public InterceptSendToEndpointDefinition interceptSendToEndpoint(String uri) {
+        InterceptSendToEndpointDefinition answer = new InterceptSendToEndpointDefinition(uri);
+        interceptSendTos.add(answer);
+        return answer;
+    }
+
 }
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderTest.java
index 38e31b0..5e70d18 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderTest.java
@@ -35,7 +35,7 @@ public class RoutesConfigurationBuilderTest extends ContextTestSupport {
     }
 
     @Test
-    public void testRoutesConfiguration() throws Exception {
+    public void testRoutesConfigurationOnException() throws Exception {
         List<RoutesBuilder> routes = new ArrayList<>();
 
         routes.add(new RouteBuilder() {
@@ -84,4 +84,227 @@ public class RoutesConfigurationBuilderTest extends ContextTestSupport {
         assertMockEndpointsSatisfied();
     }
 
+    @Test
+    public void testRoutesConfigurationOnCompletion() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        // route scoped that overrides the global scoped
+                        .onCompletion().to("mock:done2").end()
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // global routes configuration
+                routeConfiguration().onCompletion().to("mock:done");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:done").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:done2").expectedBodiesReceived("Bye World");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testRoutesConfigurationIntercept() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .setBody(constant("A"))
+                        .setBody(constant("B"))
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .setBody(constant("C"))
+                        .setBody(constant("D"))
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // global routes configuration
+                routeConfiguration().intercept().to("mock:step");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:step").expectedBodiesReceived("Hello World", "A", "B", "Bye World", "C", "D");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testRoutesConfigurationInterceptFrom() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("seda:start")
+                        .setBody(constant("A"))
+                        .setBody(constant("B"))
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .setBody(constant("C"))
+                        .setBody(constant("D"))
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // global routes configuration
+                routeConfiguration().interceptFrom("direct*").to("mock:step");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:step").expectedBodiesReceived("Bye World");
+
+        template.sendBody("seda:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testRoutesConfigurationInterceptSendTo() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .setBody(constant("A"))
+                        .to("mock:foo")
+                        .setBody(constant("B"))
+                        .to("mock:bar")
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .setBody(constant("C"))
+                        .to("mock:foo")
+                        .setBody(constant("D"))
+                        .to("mock:bar")
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // global routes configuration
+                routeConfiguration().interceptSendToEndpoint("mock:foo").to("mock:step");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:step").expectedBodiesReceived("A", "C");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
 }