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 2010/08/04 17:31:37 UTC

svn commit: r982303 - in /camel/trunk: camel-core/src/main/java/org/apache/camel/builder/ camel-core/src/main/java/org/apache/camel/impl/ camel-core/src/main/java/org/apache/camel/model/ camel-core/src/test/java/org/apache/camel/impl/ camel-core/src/te...

Author: davsclaus
Date: Wed Aug  4 15:31:37 2010
New Revision: 982303

URL: http://svn.apache.org/viewvc?rev=982303&view=rev
Log:
CAMEL-3024: Routes added from JAXB need to be prepared before being add to CamelContext. camel-spring etc. does custom preparation.

Added:
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
    camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route3.xml
      - copied, changed from r982232, camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route1.xml
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/RouteBuilder.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/CamelContextAddRouteDefinitionsFromXmlTest.java
    camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/RouteBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/RouteBuilder.java?rev=982303&r1=982302&r2=982303&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/RouteBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/RouteBuilder.java Wed Aug  4 15:31:37 2010
@@ -293,6 +293,11 @@ public abstract class RouteBuilder exten
                 setErrorHandlerBuilder(camelContext.getErrorHandlerBuilder());
             }
             configure();
+            // mark all route definitions as custom prepared because
+            // a route builder prepares the route definitions correctly already
+            for (RouteDefinition route : getRouteCollection().getRoutes()) {
+                route.customPrepared();
+            }
         }
     }
 

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java?rev=982303&r1=982302&r2=982303&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java Wed Aug  4 15:31:37 2010
@@ -595,6 +595,8 @@ public class DefaultCamelContext extends
         List<Route> routes = new ArrayList<Route>();
         List<RouteContext> routeContexts = route.addRoutes(this, routes);
         RouteService routeService = new RouteService(this, route, routeContexts, routes);
+        // must ensure route is prepared, before we can start it 
+        route.prepare();
         startRouteService(routeService, true);
     }
 

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java?rev=982303&r1=982302&r2=982303&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java Wed Aug  4 15:31:37 2010
@@ -19,6 +19,7 @@ package org.apache.camel.model;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
@@ -57,6 +58,7 @@ import org.apache.camel.util.ObjectHelpe
 @XmlType(propOrder = {"inputs", "outputs" })
 @XmlAccessorType(XmlAccessType.PROPERTY)
 public class RouteDefinition extends ProcessorDefinition<RouteDefinition> {
+    private final AtomicBoolean prepared = new AtomicBoolean(false);
     private List<FromDefinition> inputs = new ArrayList<FromDefinition>();
     private List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>();
     private String group;
@@ -82,6 +84,40 @@ public class RouteDefinition extends Pro
         from(endpoint);
     }
 
+    /**
+     * Prepares the route definition to be ready to be added to {@link CamelContext}
+     */
+    public void prepare() {
+        if (prepared.compareAndSet(false, true)) {
+            // at first init the parent
+            RouteDefinitionHelper.initParent(this);
+
+            // abstracts is the cross cutting concerns
+            List<ProcessorDefinition> abstracts = new ArrayList<ProcessorDefinition>();
+
+            // upper is the cross cutting concerns such as interceptors, error handlers etc
+            List<ProcessorDefinition> upper = new ArrayList<ProcessorDefinition>();
+
+            // lower is the regular route
+            List<ProcessorDefinition> lower = new ArrayList<ProcessorDefinition>();
+
+            RouteDefinitionHelper.prepareRouteForInit(this, abstracts, lower);
+
+            // rebuild route as upper + lower
+            this.clearOutput();
+            this.getOutputs().addAll(lower);
+            this.getOutputs().addAll(0, upper);
+        }
+    }
+
+    /**
+     * Marks the route definition as already prepared, for example using custom logic
+     * such as a {@link RouteBuilder} or from <tt>camel-core-xml</tt> component.
+     */
+    public void customPrepared() {
+        prepared.set(true);
+    }
+
     @Override
     public String toString() {
         return "Route[" + inputs + " -> " + outputs + "]";

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java?rev=982303&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java Wed Aug  4 15:31:37 2010
@@ -0,0 +1,68 @@
+/**
+ * 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.List;
+
+/**
+ * Helper for {@link org.apache.camel.model.RouteDefinition}
+ * <p/>
+ * Utility methods to help preparing {@link org.apache.camel.model.RouteDefinition} before they are added to
+ * {@link org.apache.camel.CamelContext}.
+ *
+ * @version $Revision$
+ */
+public final class RouteDefinitionHelper {
+
+    private RouteDefinitionHelper() {
+    }
+
+    public static void initParent(RouteDefinition route) {
+        for (ProcessorDefinition output : route.getOutputs()) {
+            output.setParent(route);
+            if (output.getOutputs() != null) {
+                // recursive the outputs
+                initParent(output);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void initParent(ProcessorDefinition parent) {
+        List<ProcessorDefinition> children = parent.getOutputs();
+        for (ProcessorDefinition child : children) {
+            child.setParent(parent);
+            if (child.getOutputs() != null) {
+                // recursive the children
+                initParent(child);
+            }
+        }
+    }
+
+    public static void prepareRouteForInit(RouteDefinition route, List<ProcessorDefinition> abstracts,
+                                     List<ProcessorDefinition> lower) {
+        // filter the route into abstracts and lower
+        for (ProcessorDefinition output : route.getOutputs()) {
+            if (output.isAbstract()) {
+                abstracts.add(output);
+            } else {
+                lower.add(output);
+            }
+        }
+    }
+
+}

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/CamelContextAddRouteDefinitionsFromXmlTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/CamelContextAddRouteDefinitionsFromXmlTest.java?rev=982303&r1=982302&r2=982303&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/CamelContextAddRouteDefinitionsFromXmlTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/CamelContextAddRouteDefinitionsFromXmlTest.java Wed Aug  4 15:31:37 2010
@@ -22,7 +22,10 @@ import javax.xml.bind.JAXBException;
 import javax.xml.bind.Unmarshaller;
 
 import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
 import org.apache.camel.model.Constants;
+import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.RouteDefinition;
 
 /**
@@ -106,4 +109,50 @@ public class CamelContextAddRouteDefinit
         assertMockEndpointsSatisfied();
     }
 
+    public void testAddRouteDefinitionsFromXmlIsPrepared() throws Exception {
+        RouteDefinition route = loadRoute("route1.xml");
+        assertNotNull(route);
+
+        assertEquals("foo", route.getId());
+        assertEquals(0, context.getRoutes().size());
+
+        context.addRouteDefinition(route);
+        assertEquals(1, context.getRoutes().size());
+        assertTrue("Route should be started", context.getRouteStatus("foo").isStarted());
+
+        // should be prepared, check parents has been set
+        assertNotNull("Parent should be set on outputs");
+        route = context.getRouteDefinition("foo");
+        for (ProcessorDefinition output : route.getOutputs()) {
+            assertNotNull("Parent should be set on output", output.getParent());
+            assertEquals(route, output.getParent());
+        }
+    }
+
+    public void testAddRouteDefinitionsFromXml3() throws Exception {
+        RouteDefinition route = loadRoute("route3.xml");
+        assertNotNull(route);
+
+        assertEquals("foo", route.getId());
+        assertEquals(0, context.getRoutes().size());
+
+        context.addRouteDefinition(route);
+        assertEquals(1, context.getRoutes().size());
+        assertTrue("Route should be started", context.getRouteStatus("foo").isStarted());
+
+        getMockEndpoint("mock:foo").whenExchangeReceived(2, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.setException(new IllegalArgumentException("Damn"));
+            }
+        });
+
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:handled").expectedBodiesReceived("Bye World");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
 }

Copied: camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route3.xml (from r982232, camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route1.xml)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route3.xml?p2=camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route3.xml&p1=camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route1.xml&r1=982232&r2=982303&rev=982303&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route1.xml (original)
+++ camel/trunk/camel-core/src/test/resources/org/apache/camel/impl/route3.xml Wed Aug  4 15:31:37 2010
@@ -17,5 +17,11 @@
 -->
 <route id="foo" xmlns="http://camel.apache.org/schema/spring">
     <from uri="direct:start"/>
+    <onException>
+        <exception>java.lang.IllegalArgumentException</exception>
+        <handled><constant>true</constant></handled>
+        <to uri="mock:handled"/>
+    </onException>
+    <to uri="mock:foo"/>
     <to uri="mock:result"/>
 </route>

Modified: camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java?rev=982303&r1=982302&r2=982303&view=diff
==============================================================================
--- camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java (original)
+++ camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java Wed Aug  4 15:31:37 2010
@@ -53,6 +53,7 @@ import org.apache.camel.model.RouteBuild
 import org.apache.camel.model.RouteContainer;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.RouteDefinitionHelper;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
 import org.apache.camel.model.TransactedDefinition;
 import org.apache.camel.model.config.PropertiesDefinition;
@@ -274,7 +275,7 @@ public abstract class AbstractCamelConte
         for (RouteDefinition route : getRoutes()) {
 
             // at first init the parent
-            initParent(route);
+            RouteDefinitionHelper.initParent(route);
 
             // abstracts is the cross cutting concerns
             List<ProcessorDefinition> abstracts = new ArrayList<ProcessorDefinition>();
@@ -285,7 +286,7 @@ public abstract class AbstractCamelConte
             // lower is the regular route
             List<ProcessorDefinition> lower = new ArrayList<ProcessorDefinition>();
 
-            prepareRouteForInit(route, abstracts, lower);
+            RouteDefinitionHelper.prepareRouteForInit(route, abstracts, lower);
 
             // interceptors should be first for the cross cutting concerns
             initInterceptors(route, upper);
@@ -300,6 +301,9 @@ public abstract class AbstractCamelConte
             route.clearOutput();
             route.getOutputs().addAll(lower);
             route.getOutputs().addAll(0, upper);
+
+            // mark as custom prepared
+            route.customPrepared();
         }
 
         if (getDataFormats() != null) {
@@ -318,47 +322,13 @@ public abstract class AbstractCamelConte
 
     protected abstract void initCustomRegistry(T context);
 
-    private void prepareRouteForInit(RouteDefinition route, List<ProcessorDefinition> abstracts,
-                                     List<ProcessorDefinition> lower) {
-        // filter the route into abstracts and lower
-        for (ProcessorDefinition output : route.getOutputs()) {
-            if (output.isAbstract()) {
-                abstracts.add(output);
-            } else {
-                lower.add(output);
-            }
-        }
-    }
-
-    private void initParent(RouteDefinition route) {
-        for (ProcessorDefinition output : route.getOutputs()) {
-            output.setParent(route);
-            if (output.getOutputs() != null) {
-                // recursive the outputs
-                initParent(output);
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private void initParent(ProcessorDefinition parent) {
-        List<ProcessorDefinition> children = parent.getOutputs();
-        for (ProcessorDefinition child : children) {
-            child.setParent(parent);
-            if (child.getOutputs() != null) {
-                // recursive the children
-                initParent(child);
-            }
-        }
-    }
-
     private void initOnExceptions(List<ProcessorDefinition> abstracts, List<ProcessorDefinition> upper) {
         // add global on exceptions if any
         List<OnExceptionDefinition> onExceptions = getOnExceptions();
         if (onExceptions != null && !onExceptions.isEmpty()) {
             // init the parent
             for (OnExceptionDefinition global : onExceptions) {
-                initParent(global);
+                RouteDefinitionHelper.initParent(global);
             }
             abstracts.addAll(onExceptions);
         }
@@ -378,7 +348,7 @@ public abstract class AbstractCamelConte
         for (InterceptDefinition intercept : getIntercepts()) {
             intercept.afterPropertiesSet();
             // init the parent
-            initParent(intercept);
+            RouteDefinitionHelper.initParent(intercept);
             // add as first output so intercept is handled before the actual route and that gives
             // us the needed head start to init and be able to intercept all the remaining processing steps
             upper.add(0, intercept);
@@ -402,7 +372,7 @@ public abstract class AbstractCamelConte
             if (match) {
                 intercept.afterPropertiesSet();
                 // init the parent
-                initParent(intercept);
+                RouteDefinitionHelper.initParent(intercept);
                 // add as first output so intercept is handled before the actual route and that gives
                 // us the needed head start to init and be able to intercept all the remaining processing steps
                 upper.add(0, intercept);
@@ -413,7 +383,7 @@ public abstract class AbstractCamelConte
         for (InterceptSendToEndpointDefinition intercept : getInterceptSendToEndpoints()) {
             intercept.afterPropertiesSet();
             // init the parent
-            initParent(intercept);
+            RouteDefinitionHelper.initParent(intercept);
             // add as first output so intercept is handled before the actual route and that gives
             // us the needed head start to init and be able to intercept all the remaining processing steps
             upper.add(0, intercept);
@@ -435,7 +405,7 @@ public abstract class AbstractCamelConte
             completions = getOnCompletions();
             // init the parent
             for (OnCompletionDefinition global : completions) {
-                initParent(global);
+                RouteDefinitionHelper.initParent(global);
             }
         }