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:35 UTC

[camel] 05/22: CAMEL-16757: Java DSL should prepare route after configure method just like the other DSLs do. Make it possible for route configurations to be specificied per route which ones to use via id or pattern matching.

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 2e44237f5bd29119161a91e8a6a97f3394606fa3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 13:00:47 2021 +0200

    CAMEL-16757: Java DSL should prepare route after configure method just like the other DSLs do. Make it possible for route configurations to be specificied per route which ones to use via id or pattern matching.
---
 .../java/org/apache/camel/builder/AdviceWith.java  |  4 +
 .../org/apache/camel/builder/RouteBuilder.java     | 11 ++-
 .../org/apache/camel/model/RouteDefinition.java    | 30 +++++++
 .../org/apache/camel/model/RoutesDefinition.java   | 30 ++++---
 .../RoutesConfigurationBuilderIdOrPatternTest.java | 93 ++++++++++++++++++++++
 .../java/org/apache/camel/xml/in/ModelParser.java  |  1 +
 6 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java
index 81ddafd..b7c23b5 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java
@@ -229,6 +229,10 @@ public final class AdviceWith {
         // mixed in correctly as well
         RouteDefinition merged = routes.route(definition);
 
+        // must re-prepare the merged route before it can be used
+        merged.markUnprepared();
+        routes.prepareRoute(merged);
+
         // add the new merged route
         model.getRouteDefinitions().add(0, merged);
 
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
index c9ebeea..d5185c8d 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
@@ -478,6 +478,11 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
         populateTransformers();
         populateValidators();
         populateRouteTemplates();
+
+        // ensure routes are prepared before being populated
+        for (RouteDefinition route : routeCollection.getRoutes()) {
+            routeCollection.prepareRoute(route);
+        }
         populateRoutes();
 
         if (this instanceof OnCamelContextEvent) {
@@ -549,10 +554,10 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
             }
 
             configure();
-            // mark all route definitions as custom prepared because
-            // a route builder prepares the route definitions correctly already
+
             for (RouteDefinition route : getRouteCollection().getRoutes()) {
-                route.markPrepared();
+                // ensure the route is prepared after configure method is complete
+                getRouteCollection().prepareRoute(route);
             }
 
             for (RouteBuilderLifecycleStrategy interceptor : lifecycleInterceptors) {
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
index e6a3d0d..d3ef4dd 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
@@ -57,6 +57,7 @@ import org.apache.camel.spi.RoutePolicy;
 public class RouteDefinition extends OutputDefinition<RouteDefinition> implements NamedRoute {
     private final AtomicBoolean prepared = new AtomicBoolean();
     private FromDefinition input;
+    private String routeConfiguration;
     private String group;
     private String streamCache;
     private String trace;
@@ -203,6 +204,18 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
     }
 
     /**
+     * The route configuration id or pattern this route should use for configuration. Multiple id/pattern can be
+     * separated by comma.
+     *
+     * @param  routeConfiguration id or pattern
+     * @return                    the builder
+     */
+    public RouteDefinition routeConfiguration(String routeConfiguration) {
+        setRouteConfiguration(routeConfiguration);
+        return this;
+    }
+
+    /**
      * Set the group name for this route
      *
      * @param  name the group name
@@ -718,6 +731,23 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
     }
 
     /**
+     * The route configuration id or pattern this route should use for configuration. Multiple id/pattern can be
+     * separated by comma.
+     */
+    public String getRouteConfiguration() {
+        return routeConfiguration;
+    }
+
+    /**
+     * The route configuration id or pattern this route should use for configuration. Multiple id/pattern can be
+     * separated by comma.
+     */
+    @XmlAttribute
+    public void setRouteConfiguration(String routeConfiguration) {
+        this.routeConfiguration = routeConfiguration;
+    }
+
+    /**
      * The group that this route belongs to; could be the name of the RouteBuilder class or be explicitly configured in
      * the XML.
      * <p/>
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
index 2df9432..f4df5fa 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
@@ -32,6 +32,7 @@ import org.apache.camel.ErrorHandlerFactory;
 import org.apache.camel.builder.EndpointConsumerBuilder;
 import org.apache.camel.spi.AsEndpointUri;
 import org.apache.camel.spi.Metadata;
+import org.apache.camel.support.PatternHelper;
 
 /**
  * A series of Camel routes
@@ -203,6 +204,14 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit
         if (handler != null) {
             route.setErrorHandlerFactoryIfNull(handler);
         }
+        getRoutes().add(route);
+        return route;
+    }
+
+    public void prepareRoute(RouteDefinition route) {
+        if (route.isPrepared()) {
+            return;
+        }
 
         // merge global and route scoped together
         List<OnExceptionDefinition> oe = new ArrayList<>(onExceptions);
@@ -214,23 +223,26 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit
             List<RouteConfigurationDefinition> globalConfigurations
                     = getCamelContext().adapt(ModelCamelContext.class).getRouteConfigurationDefinitions();
             if (globalConfigurations != null) {
-                globalConfigurations.forEach(g -> {
-                    oe.addAll(g.getOnExceptions());
-                    icp.addAll(g.getIntercepts());
-                    ifrom.addAll(g.getInterceptFroms());
-                    ito.addAll(g.getInterceptSendTos());
-                    oc.addAll(g.getOnCompletions());
-                });
+                globalConfigurations.stream()
+                        // global configurations have no id assigned or is a wildcard
+                        // if the route has a route configuration assigned then use pattern matching
+                        .filter(g -> (g.getId() == null || g.getId().equals("*"))
+                                || (PatternHelper.matchPattern(g.getId(), route.getRouteConfiguration())))
+                        .forEach(g -> {
+                            oe.addAll(g.getOnExceptions());
+                            icp.addAll(g.getIntercepts());
+                            ifrom.addAll(g.getInterceptFroms());
+                            ito.addAll(g.getInterceptSendTos());
+                            oc.addAll(g.getOnCompletions());
+                        });
             }
         }
 
         // must prepare the route before we can add it to the routes list
         RouteDefinitionHelper.prepareRoute(getCamelContext(), route, oe, icp, ifrom, ito, oc);
 
-        getRoutes().add(route);
         // mark this route as prepared
         route.markPrepared();
-        return route;
     }
 
     /**
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
new file mode 100644
index 0000000..2a45ad7
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.RouteConfigurationsBuilder;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.builder.RouteConfigurationBuilder;
+import org.apache.camel.support.OrderedComparator;
+import org.junit.jupiter.api.Test;
+
+public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testRoutesConfigurationOnException() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        //        routes.add(new RouteBuilder() {
+        //            @Override
+        //            public void configure() throws Exception {
+        //                from("direct:start")
+        //                        .throwException(new IllegalArgumentException("Foo"));
+        //            }
+        //        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .routeConfiguration("handle*")
+                        .throwException(new IllegalArgumentException("Foo2"));
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // named routes configuration
+                routeConfiguration("handleError").onException(Exception.class).handled(true).to("mock:error");
+            }
+        });
+        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:error").expectedBodiesReceived("Bye World");
+
+        //        try {
+        //            template.sendBody("direct:start", "Hello World");
+        //            fail("Should throw exception");
+        //        } catch (Exception e) {
+        // expected
+        //        }
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index b5be6f8..53df0c2 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -1001,6 +1001,7 @@ public class ModelParser extends BaseParser {
                 case "group": def.setGroup(val); break;
                 case "logMask": def.setLogMask(val); break;
                 case "messageHistory": def.setMessageHistory(val); break;
+                case "routeConfiguration": def.setRouteConfiguration(val); break;
                 case "routePolicyRef": def.setRoutePolicyRef(val); break;
                 case "shutdownRoute": def.setShutdownRoute(val); break;
                 case "shutdownRunningTask": def.setShutdownRunningTask(val); break;