You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2020/03/27 17:31:51 UTC
[camel] 01/02: Fix the lifecycle for services added with early start
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
commit aa6a4f590f5a29fa92ddadd1b7f14d7f5b22a70b
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Fri Mar 27 18:31:02 2020 +0100
Fix the lifecycle for services added with early start
---
.../org/apache/camel/ExtendedStartupListener.java | 11 ---------
.../java/org/apache/camel/StartupListener.java | 27 ++++++++++++++++++++++
.../camel/impl/engine/AbstractCamelContext.java | 25 ++++++++++++++------
.../impl/engine/DeferServiceStartupListener.java | 18 +++++++++++++--
4 files changed, 61 insertions(+), 20 deletions(-)
diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedStartupListener.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedStartupListener.java
index 941bd9e..6ec1942 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedStartupListener.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedStartupListener.java
@@ -25,15 +25,4 @@ package org.apache.camel;
*/
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/core/camel-api/src/main/java/org/apache/camel/StartupListener.java b/core/camel-api/src/main/java/org/apache/camel/StartupListener.java
index d7efbe3..6aeebd2 100644
--- a/core/camel-api/src/main/java/org/apache/camel/StartupListener.java
+++ b/core/camel-api/src/main/java/org/apache/camel/StartupListener.java
@@ -42,6 +42,19 @@ package org.apache.camel;
public interface StartupListener {
/**
+ * Callback invoked when the {@link CamelContext} is being 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.
+ */
+ default void onCamelContextStarting(CamelContext context, boolean alreadyStarted) throws Exception {
+ }
+
+ /**
* Callback invoked when the {@link CamelContext} is about to be fully started (not started yet).
* Yes we are aware of the method name, but we can all have a bad-naming day.
*
@@ -53,4 +66,18 @@ public interface StartupListener {
* fail on startup.
*/
void onCamelContextStarted(CamelContext context, boolean alreadyStarted) throws Exception;
+
+ /**
+ * 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.
+ */
+ default void onCamelContextFullyStarted(CamelContext context, boolean alreadyStarted) throws Exception {
+ }
+
}
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index e6cabb6..83b6b0a 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -1480,6 +1480,7 @@ public abstract class AbstractCamelContext extends BaseService
ServiceHelper.startService(service);
} else {
ServiceHelper.initService(service);
+ deferStartService(object, stopOnShutdown, true);
}
}
}
@@ -1543,6 +1544,10 @@ public abstract class AbstractCamelContext extends BaseService
@Override
public void deferStartService(Object object, boolean stopOnShutdown) throws Exception {
+ deferStartService(object, stopOnShutdown, false);
+ }
+
+ public void deferStartService(Object object, boolean stopOnShutdown, boolean startEarly) throws Exception {
if (object instanceof Service) {
Service service = (Service)object;
@@ -1564,7 +1569,7 @@ public abstract class AbstractCamelContext extends BaseService
if (isStarted()) {
ServiceHelper.startService(service);
} else {
- deferStartupListener.addService(service);
+ deferStartupListener.addService(service, startEarly);
}
}
}
@@ -2463,12 +2468,10 @@ public abstract class AbstractCamelContext extends BaseService
// now call the startup listeners where the routes has been started
for (StartupListener startup : startupListeners) {
- if (startup instanceof ExtendedStartupListener) {
- try {
- ((ExtendedStartupListener)startup).onCamelContextFullyStarted(this, isStarted());
- } catch (Exception e) {
- throw RuntimeCamelException.wrapRuntimeException(e);
- }
+ try {
+ startup.onCamelContextFullyStarted(this, isStarted());
+ } catch (Exception e) {
+ throw RuntimeCamelException.wrapRuntimeException(e);
}
}
}
@@ -2717,6 +2720,14 @@ public abstract class AbstractCamelContext extends BaseService
}
}
+ // sort the startup listeners so they are started in the right order
+ startupListeners.sort(OrderedComparator.get());
+ // 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) {
+ startup.onCamelContextStarting(getCamelContextReference(), isStarted());
+ }
+
// start notifiers as services
for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) {
if (notifier instanceof Service) {
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DeferServiceStartupListener.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DeferServiceStartupListener.java
index 483bb84..8e8e109 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DeferServiceStartupListener.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DeferServiceStartupListener.java
@@ -33,14 +33,28 @@ import org.apache.camel.support.service.ServiceHelper;
*/
public class DeferServiceStartupListener implements StartupListener, Ordered {
+ private final Set<Service> earlyServices = new CopyOnWriteArraySet<>();
private final Set<Service> services = new CopyOnWriteArraySet<>();
- public void addService(Service service) {
- services.add(service);
+ public void addService(Service service, boolean startEarly) {
+ if (startEarly) {
+ earlyServices.add(service);
+ } else {
+ services.add(service);
+ }
+ }
+
+ @Override
+ public void onCamelContextStarting(CamelContext context, boolean alreadyStarted) throws Exception {
+ doStart(earlyServices, context, alreadyStarted);
}
@Override
public void onCamelContextStarted(CamelContext context, boolean alreadyStarted) throws Exception {
+ doStart(services, context, alreadyStarted);
+ }
+
+ protected void doStart(Set<Service> services, CamelContext context, boolean alreadyStarted) throws Exception {
// new services may be added while starting a service
// so use a while loop to get the newly added services as well
while (!services.isEmpty()) {