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

jamesnetherton pushed a commit to branch camel-main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit d31ba7659d5b39db47ae239d74edb6d62b61110a
Author: James Netherton <jamesnether...@gmail.com>
AuthorDate: Tue May 21 14:45:47 2024 +0100

    Handle DebuggerJmxConnectorService being present in the camel core
---
 .../core/deployment/CamelDebugProcessor.java       | 46 +++++++++++++++
 .../DebuggerJmxConnectorServiceSubstitutions.java  | 67 ++++++++++++++++++++++
 .../camel/quarkus/main/CoreMainResource.java       | 31 ++++++++++
 .../main/src/main/resources/application.properties |  2 +
 .../apache/camel/quarkus/main/CoreMainTest.java    | 18 ++++++
 .../quarkus/component/management/it/Routes.java    |  2 +
 .../src/main/resources/application.properties      |  3 +
 .../component/management/it/ManagementTest.java    | 14 +++++
 8 files changed, 183 insertions(+)

diff --git 
a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelDebugProcessor.java
 
b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelDebugProcessor.java
new file mode 100644
index 0000000000..5ee593c439
--- /dev/null
+++ 
b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelDebugProcessor.java
@@ -0,0 +1,46 @@
+/*
+ * 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.quarkus.core.deployment;
+
+import java.util.function.BooleanSupplier;
+import java.util.stream.StreamSupport;
+
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.BuildSteps;
+import io.quarkus.deployment.builditem.AllowJNDIBuildItem;
+import org.eclipse.microprofile.config.ConfigProvider;
+
+/**
+ * Build steps relating to camel debugging support. This is primarily required 
due to camel-main
+ * having the capability to enable debugging features that live in the Camel 
core such as the
+ * DebuggerJmxConnectorService
+ */
+@BuildSteps(onlyIf = CamelDebugProcessor.CamelDebugConfigurationPresent.class)
+public class CamelDebugProcessor {
+    @BuildStep
+    AllowJNDIBuildItem allowJNDI() {
+        return new AllowJNDIBuildItem();
+    }
+
+    static final class CamelDebugConfigurationPresent implements 
BooleanSupplier {
+        @Override
+        public boolean getAsBoolean() {
+            return 
StreamSupport.stream(ConfigProvider.getConfig().getPropertyNames().spliterator(),
 false)
+                    .anyMatch(key -> key.startsWith("camel.debug"));
+        }
+    }
+}
diff --git 
a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/graal/DebuggerJmxConnectorServiceSubstitutions.java
 
b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/graal/DebuggerJmxConnectorServiceSubstitutions.java
new file mode 100644
index 0000000000..866bcb7f89
--- /dev/null
+++ 
b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/graal/DebuggerJmxConnectorServiceSubstitutions.java
@@ -0,0 +1,67 @@
+/*
+ * 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.quarkus.core.graal;
+
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+
+import com.oracle.svm.core.annotate.Alias;
+import com.oracle.svm.core.annotate.RecomputeFieldValue;
+import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import org.apache.camel.impl.debugger.DebuggerJmxConnectorService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Disable MBean server interactions in DebuggerJmxConnectorService if 
camel-management is not present.
+ */
+@TargetClass(value = DebuggerJmxConnectorService.class, onlyWith = 
CamelManagementAbsent.class)
+final class DebuggerJmxConnectorServiceSubstitutions {
+    @Alias
+    @RecomputeFieldValue(kind = Kind.FromAlias)
+    private static Logger LOG = 
LoggerFactory.getLogger(DebuggerJmxConnectorService.class);
+
+    @Substitute
+    protected void doStart() throws Exception {
+        LOG.warn(
+                "The JmxConnectorService is enabled but 
camel-quarkus-management is not detected. DebuggerJmxConnectorService will not 
be started.");
+    }
+
+    @Substitute
+    protected void doStop() throws Exception {
+        // Noop
+    }
+
+    @Substitute
+    protected void createJmxConnector(String host) throws IOException {
+        // Noop
+    }
+}
+
+final class CamelManagementAbsent implements BooleanSupplier {
+    @Override
+    public boolean getAsBoolean() {
+        try {
+            
Thread.currentThread().getContextClassLoader().loadClass("org.apache.camel.management.ManagedCamelContextImpl");
+            return false;
+        } catch (ClassNotFoundException e) {
+            return true;
+        }
+    }
+}
diff --git 
a/integration-tests/main/src/main/java/org/apache/camel/quarkus/main/CoreMainResource.java
 
b/integration-tests/main/src/main/java/org/apache/camel/quarkus/main/CoreMainResource.java
index 1652f2d49a..5b369df9ce 100644
--- 
a/integration-tests/main/src/main/java/org/apache/camel/quarkus/main/CoreMainResource.java
+++ 
b/integration-tests/main/src/main/java/org/apache/camel/quarkus/main/CoreMainResource.java
@@ -16,6 +16,9 @@
  */
 package org.apache.camel.quarkus.main;
 
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.Socket;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
@@ -34,7 +37,9 @@ import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.core.MediaType;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
+import org.apache.camel.ServiceStatus;
 import org.apache.camel.component.log.LogComponent;
+import org.apache.camel.impl.debugger.DebuggerJmxConnectorService;
 import org.apache.camel.model.ModelCamelContext;
 import org.apache.camel.quarkus.core.FastFactoryFinderResolver;
 import org.apache.camel.quarkus.it.support.typeconverter.MyPair;
@@ -251,4 +256,30 @@ public class CoreMainResource {
         final DefaultRegistry registry = 
main.getCamelContext().getRegistry(DefaultRegistry.class);
         return registry.getFallbackRegistry().lookupByNameAndType(name, 
String.class);
     }
+
+    @Path("/service/jmx-connector/status")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String getJmxConnectorServiceStatus() {
+        DebuggerJmxConnectorService service = 
main.getCamelContext().hasService(DebuggerJmxConnectorService.class);
+        if (service == null) {
+            return ServiceStatus.Stopped.name().toUpperCase();
+        }
+        return service.getStatus().name().toUpperCase();
+    }
+
+    @Path("/service/jmx-connector/expected/connect/state")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public boolean jmxConnectorServiceAvailabilityIsExpectedState() {
+        boolean isNativeMode = 
"executable".equals(System.getProperty("org.graalvm.nativeimage.kind"));
+        try (Socket socket = new Socket("localhost", 
DebuggerJmxConnectorService.DEFAULT_REGISTRY_PORT)) {
+            return true;
+        } catch (IOException e) {
+            // Since camel-quarkus-management is not on the classpath
+            // native mode will replace DebuggerJmxConnectorService methods 
with noop implementations
+            // hence the expected state is that we should not be able to 
connect
+            return isNativeMode && e instanceof ConnectException;
+        }
+    }
 }
diff --git a/integration-tests/main/src/main/resources/application.properties 
b/integration-tests/main/src/main/resources/application.properties
index c5c221fa62..ad3438bc34 100644
--- a/integration-tests/main/src/main/resources/application.properties
+++ b/integration-tests/main/src/main/resources/application.properties
@@ -32,6 +32,8 @@ camel.resilience4j.sliding-window-size = 1234
 #
 camel.main.auto-configuration-log-summary = false
 
+# To verify DebuggerJmxConnectorService substitutions take effect due to lack 
of camel-quarkus-management on the classpath
+camel.debug.enabled = true
 
 #
 # Other
diff --git 
a/integration-tests/main/src/test/java/org/apache/camel/quarkus/main/CoreMainTest.java
 
b/integration-tests/main/src/test/java/org/apache/camel/quarkus/main/CoreMainTest.java
index 5eb958bd2f..125726ed7e 100644
--- 
a/integration-tests/main/src/test/java/org/apache/camel/quarkus/main/CoreMainTest.java
+++ 
b/integration-tests/main/src/test/java/org/apache/camel/quarkus/main/CoreMainTest.java
@@ -25,6 +25,7 @@ import io.restassured.http.ContentType;
 import io.restassured.path.json.JsonPath;
 import io.restassured.response.Response;
 import jakarta.ws.rs.core.MediaType;
+import org.apache.camel.ServiceStatus;
 import org.apache.camel.quarkus.core.DisabledModelToXMLDumper;
 import org.apache.camel.quarkus.core.RegistryRoutesLoaders;
 import org.apache.camel.quarkus.it.support.mainlistener.CustomMainListener;
@@ -207,4 +208,21 @@ public class CoreMainTest {
                 .statusCode(200)
                 .body(is("String From Registry"));
     }
+
+    @Test
+    public void testJmxConnectorService() {
+        RestAssured.given()
+                .accept(MediaType.TEXT_PLAIN)
+                .get("/test/service/jmx-connector/status")
+                .then()
+                .statusCode(200)
+                .body(is(ServiceStatus.Started.name().toUpperCase()));
+
+        RestAssured.given()
+                .accept(MediaType.TEXT_PLAIN)
+                .get("/test/service/jmx-connector/expected/connect/state")
+                .then()
+                .statusCode(200)
+                .body(is("true"));
+    }
 }
diff --git 
a/integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/Routes.java
 
b/integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/Routes.java
index 7f2aa5ece9..9b57e78a6b 100644
--- 
a/integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/Routes.java
+++ 
b/integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/Routes.java
@@ -21,6 +21,8 @@ import org.apache.camel.builder.RouteBuilder;
 public class Routes extends RouteBuilder {
     @Override
     public void configure() throws Exception {
+        getContext().setDebugging(false);
+
         from("direct:start").routeId("hello").setBody().constant("Hello 
World");
 
         from("direct:count").routeId("count")
diff --git 
a/integration-tests/management/src/main/resources/application.properties 
b/integration-tests/management/src/main/resources/application.properties
index 8df9285f2f..f136dbd57b 100644
--- a/integration-tests/management/src/main/resources/application.properties
+++ b/integration-tests/management/src/main/resources/application.properties
@@ -18,3 +18,6 @@ quarkus.native.monitoring=jmxserver
 
 # Required to update routes via JMX
 camel.main.jmxUpdateRouteEnabled = true
+
+# To test DebuggerJmxConnectorService provided by Camel core
+camel.debug.enabled = true
\ No newline at end of file
diff --git 
a/integration-tests/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementTest.java
 
b/integration-tests/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementTest.java
index f5f9145e0d..1c5c944132 100644
--- 
a/integration-tests/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementTest.java
+++ 
b/integration-tests/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementTest.java
@@ -16,14 +16,19 @@
  */
 package org.apache.camel.quarkus.component.management.it;
 
+import java.io.IOException;
+import java.net.Socket;
+
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
+import org.apache.camel.impl.debugger.DebuggerJmxConnectorService;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @QuarkusTest
 class ManagementTest {
@@ -158,4 +163,13 @@ class ManagementTest {
                 .statusCode(200)
                 .body(is("2"));
     }
+
+    @Test
+    public void jmxConnectorService() {
+        try (Socket socket = new Socket("localhost", 
DebuggerJmxConnectorService.DEFAULT_REGISTRY_PORT)) {
+            assertTrue(socket.isConnected());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }

Reply via email to