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/12/30 12:04:28 UTC
[camel] 12/30: CAMEL-17384: Developer Console SPI
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch console
in repository https://gitbox.apache.org/repos/asf/camel.git
commit b27f2c403779f97924699b5a9779e08c1f8450f5
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Dec 27 16:41:08 2021 +0100
CAMEL-17384: Developer Console SPI
---
.../main/java/org/apache/camel/CamelContext.java | 10 +++
.../apache/camel/console/DevConsoleRegistry.java | 2 +-
.../camel/impl/engine/AbstractCamelContext.java | 19 +++++
.../impl/console/DefaultDevConsoleRegistry.java | 5 +-
.../impl/console/DefaultDevConsolesLoader.java | 5 ++
.../camel/impl/ExtendedCamelContextConfigurer.java | 6 ++
.../camel/impl/lw/LightweightCamelContext.java | 10 +++
.../impl/lw/LightweightRuntimeCamelContext.java | 10 +++
.../apache/camel/dsl/jbang/core/commands/Run.java | 7 +-
dsl/camel-kamelet-main/pom.xml | 8 ++
.../java/org/apache/camel/main/KameletMain.java | 10 +++
.../org/apache/camel/main/VertxHttpServer.java | 86 +++++++++++++++-------
12 files changed, 149 insertions(+), 29 deletions(-)
diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index 74138f6..3193799 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -1187,6 +1187,16 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio
void setLoadHealthChecks(Boolean loadHealthChecks);
/**
+ * Whether to load custom dev consoles by scanning classpath.
+ */
+ Boolean isLoadDevConsoles();
+
+ /**
+ * Whether to load custom dev consoles by scanning classpath.
+ */
+ void setLoadDevConsoles(Boolean loadDevConsoles);
+
+ /**
* Whether or not type converter statistics is enabled.
* <p/>
* By default the type converter utilization statistics is disabled. <b>Notice:</b> If enabled then there is a
diff --git a/core/camel-api/src/main/java/org/apache/camel/console/DevConsoleRegistry.java b/core/camel-api/src/main/java/org/apache/camel/console/DevConsoleRegistry.java
index 03ecf79..4a160b9 100644
--- a/core/camel-api/src/main/java/org/apache/camel/console/DevConsoleRegistry.java
+++ b/core/camel-api/src/main/java/org/apache/camel/console/DevConsoleRegistry.java
@@ -40,7 +40,7 @@ public interface DevConsoleRegistry extends CamelContextAware, StaticService, Id
/**
* Service factory key.
*/
- String FACTORY = "console/" + NAME;
+ String FACTORY = "dev-console/" + NAME;
/**
* Whether dev console is enabled globally
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 31306c3..99e7ae1 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -263,6 +263,7 @@ public abstract class AbstractCamelContext extends BaseService
private Boolean disableJMX = Boolean.FALSE;
private Boolean loadTypeConverters = Boolean.FALSE;
private Boolean loadHealthChecks = Boolean.FALSE;
+ private Boolean loadDevConsoles = Boolean.FALSE;
private Boolean typeConverterStatisticsEnabled = Boolean.FALSE;
private Boolean dumpRoutes = Boolean.FALSE;
private Boolean useMDCLogging = Boolean.FALSE;
@@ -2768,6 +2769,15 @@ public abstract class AbstractCamelContext extends BaseService
}
startupStepRecorder.endStep(step3);
}
+ // ensure additional dev consoles is loaded
+ if (loadDevConsoles) {
+ StartupStep step4 = startupStepRecorder.beginStep(CamelContext.class, null, "Scan DevConsoles");
+ DevConsoleRegistry dcr = getExtension(DevConsoleRegistry.class);
+ if (dcr != null) {
+ dcr.loadDevConsoles();
+ }
+ startupStepRecorder.endStep(step4);
+ }
// custom properties may use property placeholders so resolve those
// early on
@@ -4218,6 +4228,15 @@ public abstract class AbstractCamelContext extends BaseService
this.loadHealthChecks = loadHealthChecks;
}
+ public Boolean isLoadDevConsoles() {
+ return loadDevConsoles != null && loadDevConsoles;
+ }
+
+ @Override
+ public void setLoadDevConsoles(Boolean loadDevConsoles) {
+ this.loadDevConsoles = loadDevConsoles;
+ }
+
@Override
public Boolean isTypeConverterStatisticsEnabled() {
return typeConverterStatisticsEnabled != null && typeConverterStatisticsEnabled;
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
index eeb2301..14eb111 100644
--- a/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
@@ -153,8 +153,11 @@ public class DefaultDevConsoleRegistry extends ServiceSupport implements DevCons
DefaultDevConsolesLoader loader = new DefaultDevConsolesLoader(camelContext);
Collection<DevConsole> col = loader.loadDevConsoles();
- // report how many health checks we have loaded
if (col.size() > 0) {
+ // register the loaded consoles
+ for (DevConsole console : col) {
+ register(console);
+ }
String time = TimeUtils.printDuration(watch.taken());
LOG.info("Dev consoles (scanned: {}) loaded in {}", col.size(), time);
}
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsolesLoader.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsolesLoader.java
index 0226551..da2c848 100644
--- a/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsolesLoader.java
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsolesLoader.java
@@ -82,6 +82,11 @@ public class DefaultDevConsolesLoader {
if (loc == null) {
return false;
}
+ if (loc.endsWith("default-registry")) {
+ // this is the registry so should be skipped
+ return false;
+ }
+
return true;
}
diff --git a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
index 0df43cb..31ab8e8 100644
--- a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
+++ b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
@@ -95,6 +95,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
case "LanguageResolver": target.setLanguageResolver(property(camelContext, org.apache.camel.spi.LanguageResolver.class, value)); return true;
case "lightweight":
case "Lightweight": target.setLightweight(property(camelContext, boolean.class, value)); return true;
+ case "loaddevconsoles":
+ case "LoadDevConsoles": target.setLoadDevConsoles(property(camelContext, java.lang.Boolean.class, value)); return true;
case "loadhealthchecks":
case "LoadHealthChecks": target.setLoadHealthChecks(property(camelContext, java.lang.Boolean.class, value)); return true;
case "loadtypeconverters":
@@ -280,6 +282,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
case "LanguageResolver": return org.apache.camel.spi.LanguageResolver.class;
case "lightweight":
case "Lightweight": return boolean.class;
+ case "loaddevconsoles":
+ case "LoadDevConsoles": return java.lang.Boolean.class;
case "loadhealthchecks":
case "LoadHealthChecks": return java.lang.Boolean.class;
case "loadtypeconverters":
@@ -466,6 +470,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
case "LanguageResolver": return target.getLanguageResolver();
case "lightweight":
case "Lightweight": return target.isLightweight();
+ case "loaddevconsoles":
+ case "LoadDevConsoles": return target.isLoadDevConsoles();
case "loadhealthchecks":
case "LoadHealthChecks": return target.isLoadHealthChecks();
case "loadtypeconverters":
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
index ecc68de..41e15c4 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
@@ -901,6 +901,16 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
}
@Override
+ public Boolean isLoadDevConsoles() {
+ return delegate.isLoadDevConsoles();
+ }
+
+ @Override
+ public void setLoadDevConsoles(Boolean loadDevConsoles) {
+ delegate.setLoadDevConsoles(loadDevConsoles);
+ }
+
+ @Override
public Boolean isDumpRoutes() {
return delegate.isDumpRoutes();
}
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
index 0601169..49cf2d8 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
@@ -1201,6 +1201,16 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat
}
@Override
+ public Boolean isLoadDevConsoles() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setLoadDevConsoles(Boolean loadDevConsoles) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public void setLoadHealthChecks(Boolean loadHealthChecks) {
throw new UnsupportedOperationException();
}
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index 655f73d..6fbfb1b 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -85,6 +85,9 @@ class Run implements Callable<Integer> {
@Option(names = { "--port" }, description = "Embeds a local HTTP server on this port")
private int port;
+ @Option(names = { "--console" }, description = "Developer console at /dev on local HTTP server (port 8080 by default)")
+ private boolean console;
+
@Override
public Integer call() throws Exception {
if (stopRequested) {
@@ -128,7 +131,6 @@ class Run implements Callable<Integer> {
// turn off lightweight if we have routes reload enabled
main.addInitialProperty("camel.main.routesReloadEnabled", reload ? "true" : "false");
- // durations
if (maxMessages > 0) {
main.addInitialProperty("camel.main.durationMaxMessages", String.valueOf(maxMessages));
}
@@ -141,6 +143,9 @@ class Run implements Callable<Integer> {
if (port > 0) {
main.addInitialProperty("camel.jbang.platform-http.port", String.valueOf(port));
}
+ if (console) {
+ main.addInitialProperty("camel.jbang.console", "true");
+ }
if (fileLock) {
lockFile = createLockFile();
diff --git a/dsl/camel-kamelet-main/pom.xml b/dsl/camel-kamelet-main/pom.xml
index f70c5cd..daf5105 100644
--- a/dsl/camel-kamelet-main/pom.xml
+++ b/dsl/camel-kamelet-main/pom.xml
@@ -74,6 +74,14 @@
<groupId>org.apache.camel</groupId>
<artifactId>camel-catalog</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-platform-http-vertx</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-console</artifactId>
+ </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index 9ade32a..924ba23 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -166,6 +166,16 @@ public class KameletMain extends MainCommandLineSupport {
if (port != null) {
VertxHttpServer.registerServer(answer, Integer.parseInt(port.toString()));
}
+ boolean console = "true".equals(getInitialProperties().get("camel.jbang.console"));
+ if (console && port == null) {
+ // use default port 8080 if console is enabled
+ VertxHttpServer.registerServer(answer, 8080);
+ }
+ if (console) {
+ // turn on developer console
+ answer.setLoadDevConsoles(true);
+ VertxHttpServer.registerConsole(answer);
+ }
if (download) {
try {
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/VertxHttpServer.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/VertxHttpServer.java
index 6aaf136..e2c9257 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/VertxHttpServer.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/VertxHttpServer.java
@@ -16,20 +16,25 @@
*/
package org.apache.camel.main;
-import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import io.vertx.core.Handler;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.ext.web.Route;
+import io.vertx.ext.web.RoutingContext;
import org.apache.camel.CamelContext;
-import org.apache.camel.Component;
-import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.StartupListener;
+import org.apache.camel.component.platform.http.PlatformHttpComponent;
+import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpRouter;
+import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpServer;
+import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpServerConfiguration;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.console.DevConsoleRegistry;
import org.apache.camel.spi.CamelEvent;
-import org.apache.camel.support.ObjectHelper;
import org.apache.camel.support.SimpleEventNotifierSupport;
-import org.apache.camel.util.ReflectionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,6 +46,11 @@ public final class VertxHttpServer {
private static final Logger LOG = LoggerFactory.getLogger(VertxHttpServer.class);
private static final AtomicBoolean REGISTERED = new AtomicBoolean();
+ private static final AtomicBoolean CONSOLE = new AtomicBoolean();
+
+ private static VertxPlatformHttpRouter router;
+ private static VertxPlatformHttpServer server;
+ private static PlatformHttpComponent phc;
private VertxHttpServer() {
}
@@ -59,20 +69,13 @@ public final class VertxHttpServer {
private static void doRegisterServer(CamelContext camelContext, int port) {
try {
- // must load via the classloader set on camel context that will have the classes on its classpath
- Class<?> clazz = camelContext.getClassResolver()
- .resolveMandatoryClass(
- "org.apache.camel.component.platform.http.vertx.VertxPlatformHttpServerConfiguration");
- Object config = clazz.getConstructors()[0].newInstance();
- camelContext.adapt(ExtendedCamelContext.class).getBeanIntrospection()
- .setProperty(camelContext, config, "port", port);
-
- clazz = camelContext.getClassResolver()
- .resolveMandatoryClass(
- "org.apache.camel.component.platform.http.vertx.VertxPlatformHttpServer");
- Object server = clazz.getConstructors()[0].newInstance(config);
-
+ VertxPlatformHttpServerConfiguration config = new VertxPlatformHttpServerConfiguration();
+ config.setPort(port);
+ server = new VertxPlatformHttpServer(config);
camelContext.addService(server);
+ server.start();
+ router = VertxPlatformHttpRouter.lookup(camelContext);
+ phc = camelContext.getComponent("platform-http", PlatformHttpComponent.class);
// after camel is started then add event notifier
camelContext.addStartupListener(new StartupListener() {
@@ -80,8 +83,6 @@ public final class VertxHttpServer {
public void onCamelContextStarted(CamelContext context, boolean alreadyStarted) throws Exception {
camelContext.getManagementStrategy().addEventNotifier(new SimpleEventNotifierSupport() {
- private volatile Component phc;
- private volatile Method method;
private Set<String> last;
@Override
@@ -92,11 +93,6 @@ public final class VertxHttpServer {
@Override
public void notify(CamelEvent event) throws Exception {
- if (method == null) {
- phc = camelContext.getComponent("platform-http", Component.class);
- method = ReflectionHelper.findMethod(phc.getClass(), "getHttpEndpoints");
- }
-
// when reloading then there may be more routes in the same batch, so we only want
// to log the summary at the end
if (event instanceof CamelEvent.RouteReloadedEvent) {
@@ -106,7 +102,7 @@ public final class VertxHttpServer {
}
}
- Set<String> endpoints = (Set<String>) ObjectHelper.invokeMethodSafe(method, phc);
+ Set<String> endpoints = phc.getHttpEndpoints();
if (endpoints.isEmpty()) {
return;
}
@@ -131,4 +127,42 @@ public final class VertxHttpServer {
}
}
+ public static void registerConsole(CamelContext camelContext) {
+ if (CONSOLE.compareAndSet(false, true)) {
+ doRegisterConsole(camelContext);
+ }
+ }
+
+ private static void doRegisterConsole(CamelContext context) {
+ Route dev = router.route("/dev");
+ dev.method(HttpMethod.GET);
+ dev.handler(router.bodyHandler());
+ dev.handler(new Handler<RoutingContext>() {
+ @Override
+ public void handle(RoutingContext ctx) {
+ DevConsoleRegistry dcr = context.getExtension(DevConsoleRegistry.class);
+ if (dcr != null && dcr.isEnabled()) {
+ StringBuilder sb = new StringBuilder();
+ dcr.stream().forEach(c -> {
+ if (c.supportMediaType(DevConsole.MediaType.TEXT)) {
+ String text = (String) c.call(DevConsole.MediaType.TEXT);
+ if (text != null) {
+ sb.append(text);
+ sb.append("\n\n");
+ }
+ }
+ });
+ if (sb.length() > 0) {
+ ctx.end(sb.toString());
+ } else {
+ ctx.end("Developer Console is not enabled");
+ }
+ } else {
+ ctx.end("Developer Console is not enabled");
+ }
+ }
+ });
+ phc.addHttpEndpoint("/dev");
+ }
+
}