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 2017/11/02 18:43:05 UTC

[camel] branch master updated: CAMEL-11985: Add ExtendedStartupListener

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

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new c7c18b4  CAMEL-11985: Add ExtendedStartupListener
c7c18b4 is described below

commit c7c18b485d21dba439ed41b7bf5b24f0cbeaade2
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Nov 2 19:42:49 2017 +0100

    CAMEL-11985: Add ExtendedStartupListener
---
 .../org/apache/camel/ExtendedStartupListener.java  |  39 ++++++++
 .../java/org/apache/camel/StartupListener.java     |   2 +
 .../org/apache/camel/impl/DefaultCamelContext.java |  10 ++
 .../impl/ExtendedStartupListenerComponentTest.java | 101 +++++++++++++++++++++
 4 files changed, 152 insertions(+)

diff --git a/camel-core/src/main/java/org/apache/camel/ExtendedStartupListener.java b/camel-core/src/main/java/org/apache/camel/ExtendedStartupListener.java
new file mode 100644
index 0000000..7ae639b
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/ExtendedStartupListener.java
@@ -0,0 +1,39 @@
+/**
+ * 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;
+
+/**
+ * Extended {@link StartupListener} that is invoked when the {@link CamelContext} is fully started.
+ * <p/>
+ * <b>Important:</b> You can use this listener to add and start new routes to the {@link CamelContext} which is now supported.
+ *
+ * @see StartupListener
+ */
+public interface ExtendedStartupListener extends StartupListener {
+
+    /**
+     * Callback invoked when the {@link CamelContext} has been fully started.
+     *
+     * @param context        the Camel context
+     * @param alreadyStarted whether or not the {@link CamelContext} already has been started. For example the context
+     *                       could already have been started, and then a service is added/started later which still
+     *                       triggers this callback to be invoked.
+     * @throws Exception     can be thrown in case of errors to fail the startup process and have the application
+     *                       fail on startup.
+     */
+    void onCamelContextFullyStarted(CamelContext context, boolean alreadyStarted) throws Exception;
+}
diff --git a/camel-core/src/main/java/org/apache/camel/StartupListener.java b/camel-core/src/main/java/org/apache/camel/StartupListener.java
index 2485aee..d6da3a8 100644
--- a/camel-core/src/main/java/org/apache/camel/StartupListener.java
+++ b/camel-core/src/main/java/org/apache/camel/StartupListener.java
@@ -32,7 +32,9 @@ package org.apache.camel;
  * <b>Important:</b> You cannot use this listener to add and start new routes to the {@link CamelContext} as this is not
  * supported by design, as this listener plays a role during starting up routes. Instead you can use an {@link org.apache.camel.spi.EventNotifier}
  * and listen on the {@link org.apache.camel.management.event.CamelContextStartedEvent} event and then add and start new routes from there.
+ * Instead use the {@link ExtendedStartupListener} if you wish to add new routes.
  *
+ * @see ExtendedStartupListener
  * @version
  */
 public interface StartupListener {
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index b2bf974..bbbaf69 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -56,6 +56,7 @@ import org.apache.camel.Consumer;
 import org.apache.camel.ConsumerTemplate;
 import org.apache.camel.Endpoint;
 import org.apache.camel.ErrorHandlerFactory;
+import org.apache.camel.ExtendedStartupListener;
 import org.apache.camel.FailedToStartRouteException;
 import org.apache.camel.FluentProducerTemplate;
 import org.apache.camel.IsSingleton;
@@ -3194,6 +3195,15 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") started in " + TimeUtils.printDuration(stopWatch.taken()));
             }
             EventHelper.notifyCamelContextStarted(this);
+
+            // now call the startup listeners where the routes has been warmed up
+            // (only the actual route consumer has not yet been started)
+            for (StartupListener startup : startupListeners) {
+                if (startup instanceof ExtendedStartupListener) {
+                    ((ExtendedStartupListener) startup).onCamelContextFullyStarted(this, isStarted());
+                }
+            }
+
         }
     }
 
diff --git a/camel-core/src/test/java/org/apache/camel/impl/ExtendedStartupListenerComponentTest.java b/camel-core/src/test/java/org/apache/camel/impl/ExtendedStartupListenerComponentTest.java
new file mode 100644
index 0000000..efc98a6
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/impl/ExtendedStartupListenerComponentTest.java
@@ -0,0 +1,101 @@
+/**
+ * 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.impl;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.ExtendedStartupListener;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.direct.DirectComponent;
+
+/**
+ * @version 
+ */
+public class ExtendedStartupListenerComponentTest extends ContextTestSupport {
+
+    private MyComponent my;
+
+    public void testExtendedStartupListenerComponent() throws Exception {
+        // and now the routes are started
+        assertTrue(context.getRouteStatus("foo").isStarted());
+        assertTrue(context.getRouteStatus("bar").isStarted());
+        assertTrue(context.getRouteStatus("late").isStarted());
+
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+        getMockEndpoint("mock:late").expectedMessageCount(1);
+
+        template.sendBody("direct:foo", "Hello World");
+        template.sendBody("direct:late", "Bye World");
+
+        assertMockEndpointsSatisfied();
+
+        // we are invoked 2 times and then 1 extra when we add new routes because the component
+        // will trigger again when the new routes are being started
+        assertEquals(2 + 1, my.getInvoked());
+    }
+
+    private static class MyComponent extends DirectComponent implements ExtendedStartupListener {
+
+        private int invoked;
+
+        public void onCamelContextStarted(CamelContext context, boolean alreadyStarted) throws Exception {
+            invoked++;
+
+            // the routes should not have been started as they start afterwards
+            if (!alreadyStarted) {
+                assertTrue(context.getRouteStatus("foo").isStopped());
+                assertTrue(context.getRouteStatus("bar").isStopped());
+            }
+        }
+
+        public int getInvoked() {
+            return invoked;
+        }
+
+        @Override
+        public void onCamelContextFullyStarted(CamelContext context, boolean alreadyStarted) throws Exception {
+            invoked++;
+
+            // the original routes are now started
+            assertTrue(context.getRouteStatus("foo").isStarted());
+            assertTrue(context.getRouteStatus("bar").isStarted());
+
+            // we can add new routes
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:late").routeId("late").to("mock:late");
+                }
+            });
+
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                my = new MyComponent();
+                context.addComponent("my", my);
+
+                from("direct:foo").routeId("foo").to("my:bar");
+                from("my:bar").routeId("bar").to("mock:result");
+            }
+        };
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
['"commits@camel.apache.org" <co...@camel.apache.org>'].