You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ji...@apache.org on 2024/06/24 07:34:03 UTC
(camel-quarkus) 07/41: Handle DebuggerJmxConnectorService being present in the camel core
This is an automated email from the ASF dual-hosted git repository.
jiriondrusek pushed a commit to branch camel-main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 0b95f0e910b99f4fb1d37fa85942efede3feb2c1
Author: James Netherton <ja...@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);
+ }
+ }
}