This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push: new bb5c5a455f Add native support for camel-quarkus-management bb5c5a455f is described below commit bb5c5a455f0a9f79d0bf9abe1568194a5e49a15c Author: James Netherton <jamesnether...@gmail.com> AuthorDate: Fri Jun 30 10:20:44 2023 +0100 Add native support for camel-quarkus-management Fixes #5029 --- .../pages/reference/extensions/management.adoc | 28 ++-- .../management/deployment/ManagementProcessor.java | 47 ------- .../runtime/src/main/doc/limitations.adoc | 2 - .../management/runtime/src/main/doc/usage.adoc | 9 -- extensions-jvm/pom.xml | 1 - .../management/deployment/pom.xml | 0 .../management/deployment/ManagementProcessor.java | 144 +++++++++++++++++++++ {extensions-jvm => extensions}/management/pom.xml | 2 +- .../management/runtime/pom.xml | 1 + .../management/runtime/src/main/doc/usage.adoc | 21 +++ .../management/CamelManagementRecorder.java | 0 .../main/resources/META-INF/quarkus-extension.yaml | 0 extensions/pom.xml | 1 + .../component/management/it/ManagementTest.java | 103 --------------- integration-tests-jvm/pom.xml | 1 - .../management/pom.xml | 36 ++++++ .../component/management/it/ManagedCounter.java | 0 .../management/it/ManagementResource.java | 97 ++++++++++++++ .../quarkus/component/management/it/Routes.java | 0 .../src/main/resources/application.properties | 17 +++ .../component/management/it/ManagementIT.java | 18 +-- .../component/management/it/ManagementTest.java | 110 ++++++++++++++++ integration-tests/pom.xml | 1 + tooling/scripts/test-categories.yaml | 1 + 24 files changed, 452 insertions(+), 188 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/management.adoc b/docs/modules/ROOT/pages/reference/extensions/management.adoc index db055589d3..2bc436d588 100644 --- a/docs/modules/ROOT/pages/reference/extensions/management.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/management.adoc @@ -4,17 +4,17 @@ = Management :linkattrs: :cq-artifact-id: camel-quarkus-management -:cq-native-supported: false -:cq-status: Preview -:cq-status-deprecation: Preview +:cq-native-supported: true +:cq-status: Stable +:cq-status-deprecation: Stable :cq-description: JMX management strategy and associated managed resources. :cq-deprecated: false :cq-jvm-since: 1.1.0 -:cq-native-since: n/a +:cq-native-since: 3.0.0 ifeval::[{doc-show-badges} == true] [.badges] -[.badge-key]##JVM since##[.badge-supported]##1.1.0## [.badge-key]##Native##[.badge-unsupported]##unsupported## +[.badge-key]##JVM since##[.badge-supported]##1.1.0## [.badge-key]##Native since##[.badge-supported]##3.0.0## endif::[] JMX management strategy and associated managed resources. @@ -22,6 +22,10 @@ JMX management strategy and associated managed resources. [id="extensions-management-maven-coordinates"] == Maven coordinates +https://{link-quarkus-code-generator}/?extension-search=camel-quarkus-management[Create a new project with this extension on {link-quarkus-code-generator}, window="_blank"] + +Or add the coordinates to your existing project: + [source,xml] ---- <dependency> @@ -46,10 +50,16 @@ JMX can be enabled or disabled in Camel-Quarkus by any of the following methods: . Setting the `camel.main.jmxEnabled` configuration property to a boolean value. . Setting the system property `-Dorg.apache.camel.jmx.disabled` to a boolean value. +[id="extensions-management-usage-native-mode"] +=== Native mode + +**Experimental** JMX support was added for native executables in GraalVM for JDK 17/20 / Mandrel 23.0. You can enable this feature by +adding the following configuration property to `application.properties`. -[id="extensions-management-camel-quarkus-limitations"] -== Camel Quarkus limitations +[source,properties] +---- +quarkus.native.monitoring=jmxserver +---- -The JMX management beans exposed by this extension will not work in native mode, as GraalVM has no support for JMX. Therefore, attempting to build a native -image with this extension on the classpath will result in a build failure. +For more information, refer to the https://quarkus.io/guides/building-native-image#using-monitoring-options[Quarkus native guide]. diff --git a/extensions-jvm/management/deployment/src/main/java/org/apache/camel/quarkus/component/management/deployment/ManagementProcessor.java b/extensions-jvm/management/deployment/src/main/java/org/apache/camel/quarkus/component/management/deployment/ManagementProcessor.java deleted file mode 100644 index 859f09ceb6..0000000000 --- a/extensions-jvm/management/deployment/src/main/java/org/apache/camel/quarkus/component/management/deployment/ManagementProcessor.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.component.management.deployment; - -import io.quarkus.deployment.annotations.BuildStep; -import io.quarkus.deployment.annotations.ExecutionTime; -import io.quarkus.deployment.annotations.Record; -import io.quarkus.deployment.builditem.FeatureBuildItem; -import io.quarkus.deployment.pkg.steps.NativeBuild; -import org.apache.camel.quarkus.component.management.CamelManagementRecorder; -import org.apache.camel.quarkus.core.deployment.spi.RuntimeCamelContextCustomizerBuildItem; - -class ManagementProcessor { - - private static final String FEATURE = "camel-management"; - - @BuildStep - FeatureBuildItem feature() { - return new FeatureBuildItem(FEATURE); - } - - @Record(ExecutionTime.RUNTIME_INIT) - @BuildStep - RuntimeCamelContextCustomizerBuildItem configureCamelContext(CamelManagementRecorder recorder) { - return new RuntimeCamelContextCustomizerBuildItem(recorder.createContextCustomizer()); - } - - @BuildStep(onlyIf = NativeBuild.class) - void nativeUnsupported() { - throw new RuntimeException("The " + FEATURE + " extension is not supported in native mode " - + "as JMX is not supported on GraalVM"); - } -} diff --git a/extensions-jvm/management/runtime/src/main/doc/limitations.adoc b/extensions-jvm/management/runtime/src/main/doc/limitations.adoc deleted file mode 100644 index 9bb2269773..0000000000 --- a/extensions-jvm/management/runtime/src/main/doc/limitations.adoc +++ /dev/null @@ -1,2 +0,0 @@ -The JMX management beans exposed by this extension will not work in native mode, as GraalVM has no support for JMX. Therefore, attempting to build a native -image with this extension on the classpath will result in a build failure. diff --git a/extensions-jvm/management/runtime/src/main/doc/usage.adoc b/extensions-jvm/management/runtime/src/main/doc/usage.adoc deleted file mode 100644 index 1f962b1fef..0000000000 --- a/extensions-jvm/management/runtime/src/main/doc/usage.adoc +++ /dev/null @@ -1,9 +0,0 @@ -For information on using Managed Beans in Camel, consult the xref:manual::jmx.adoc[JMX section of the Camel Manual]. - -=== Enabling and Disabling JMX - -JMX can be enabled or disabled in Camel-Quarkus by any of the following methods: - -. Adding or removing the `camel-quarkus-management` extension. -. Setting the `camel.main.jmxEnabled` configuration property to a boolean value. -. Setting the system property `-Dorg.apache.camel.jmx.disabled` to a boolean value. \ No newline at end of file diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml index 7e9ad015a0..b7002e51cd 100644 --- a/extensions-jvm/pom.xml +++ b/extensions-jvm/pom.xml @@ -84,7 +84,6 @@ <module>jt400</module> <module>ldif</module> <module>lucene</module> - <module>management</module> <module>mapstruct</module> <module>mvel</module> <module>printer</module> diff --git a/extensions-jvm/management/deployment/pom.xml b/extensions/management/deployment/pom.xml similarity index 100% rename from extensions-jvm/management/deployment/pom.xml rename to extensions/management/deployment/pom.xml diff --git a/extensions/management/deployment/src/main/java/org/apache/camel/quarkus/component/management/deployment/ManagementProcessor.java b/extensions/management/deployment/src/main/java/org/apache/camel/quarkus/component/management/deployment/ManagementProcessor.java new file mode 100644 index 0000000000..7a07f21de2 --- /dev/null +++ b/extensions/management/deployment/src/main/java/org/apache/camel/quarkus/component/management/deployment/ManagementProcessor.java @@ -0,0 +1,144 @@ +/* + * 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.component.management.deployment; + +import java.lang.reflect.Modifier; +import java.util.Objects; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.management.MBeanException; +import javax.management.MBeanServerNotification; +import javax.management.modelmbean.DescriptorSupport; +import javax.management.modelmbean.ModelMBeanAttributeInfo; +import javax.management.modelmbean.ModelMBeanInfoSupport; +import javax.management.modelmbean.ModelMBeanOperationInfo; +import javax.management.modelmbean.RequiredModelMBean; + +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.annotations.ExecutionTime; +import io.quarkus.deployment.annotations.Record; +import io.quarkus.deployment.builditem.CombinedIndexBuildItem; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.nativeimage.NativeImageProxyDefinitionBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import org.apache.camel.api.management.ManagedAttribute; +import org.apache.camel.api.management.ManagedNotification; +import org.apache.camel.api.management.ManagedNotifications; +import org.apache.camel.api.management.ManagedOperation; +import org.apache.camel.api.management.ManagedResource; +import org.apache.camel.quarkus.component.management.CamelManagementRecorder; +import org.apache.camel.quarkus.core.deployment.spi.CamelSerializationBuildItem; +import org.apache.camel.quarkus.core.deployment.spi.RuntimeCamelContextCustomizerBuildItem; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget.Kind; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; + +class ManagementProcessor { + private static final String FEATURE = "camel-management"; + private static final Class<?>[] CAMEL_MANAGEMENT_ANNOTATIONS = { + ManagedAttribute.class, + ManagedNotification.class, + ManagedNotifications.class, + ManagedOperation.class, + ManagedResource.class + }; + private static final String[] SERIALIZATION_CLASSES = { + DescriptorSupport.class.getName(), + ModelMBeanAttributeInfo.class.getName(), + ModelMBeanInfoSupport.class.getName(), + ModelMBeanOperationInfo.class.getName(), + MBeanException.class.getName(), + MBeanServerNotification.class.getName(), + Object.class.getName() + }; + + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(FEATURE); + } + + @BuildStep + void camelManagementMBeanSupport( + CombinedIndexBuildItem combinedIndex, + BuildProducer<ReflectiveClassBuildItem> reflectiveClass, + BuildProducer<NativeImageProxyDefinitionBuildItem> nativeImageProxy, + BuildProducer<CamelSerializationBuildItem> camelSerialization) { + + IndexView index = combinedIndex.getIndex(); + + // Find Camel management interfaces and configure native proxy definitions for them + Set<String> managedBeanInterfaces = getManagedTypes(index, classInfo -> Modifier.isInterface(classInfo.flags())); + managedBeanInterfaces.stream() + .map(NativeImageProxyDefinitionBuildItem::new) + .forEach(nativeImageProxy::produce); + + // Find the implementations of the managed bean interfaces and register them for reflection + Set<String> managedBeanClasses = managedBeanInterfaces.stream() + .map(DotName::createSimple) + .flatMap((dotName) -> index.getAllKnownImplementors(dotName).stream()) + .map(classInfo -> classInfo.name().toString()) + .collect(Collectors.toSet()); + + // Get any managed classes (ones that do not implement Camel managed interfaces) and register them for reflection + managedBeanClasses.addAll(getManagedTypes(index, classInfo -> !Modifier.isInterface(classInfo.flags()))); + // DefaultManagementMBeanAssembler dynamically instantiates this via the MBeanServer + managedBeanClasses.add(RequiredModelMBean.class.getName()); + + reflectiveClass.produce( + ReflectiveClassBuildItem.builder(managedBeanClasses.toArray(String[]::new)) + .fields().methods().build()); + + // Various javax.management classes require serialization + reflectiveClass.produce(ReflectiveClassBuildItem.builder(SERIALIZATION_CLASSES).serialization().build()); + + // Add serialization support for some core JDK & Camel classes + camelSerialization.produce(new CamelSerializationBuildItem()); + } + + @Record(ExecutionTime.RUNTIME_INIT) + @BuildStep + RuntimeCamelContextCustomizerBuildItem configureCamelContext(CamelManagementRecorder recorder) { + return new RuntimeCamelContextCustomizerBuildItem(recorder.createContextCustomizer()); + } + + private Set<String> getManagedTypes(IndexView index, Predicate<ClassInfo> typeFilter) { + return Stream.of(CAMEL_MANAGEMENT_ANNOTATIONS) + .flatMap(annotation -> index.getAnnotations(annotation).stream()) + .map(AnnotationInstance::target) + .map(annotationTarget -> { + Kind kind = annotationTarget.kind(); + if (kind.equals(Kind.CLASS)) { + return annotationTarget.asClass(); + } else if (kind.equals(Kind.FIELD)) { + return annotationTarget.asField().declaringClass(); + } else if (kind.equals(Kind.METHOD)) { + return annotationTarget.asMethod().declaringClass(); + } + return null; + }) + .filter(Objects::nonNull) + .filter(typeFilter) + .map(classInfo -> classInfo.name().toString()) + .collect(Collectors.toSet()); + } +} diff --git a/extensions-jvm/management/pom.xml b/extensions/management/pom.xml similarity index 96% rename from extensions-jvm/management/pom.xml rename to extensions/management/pom.xml index 23b1f3e43c..f562839459 100644 --- a/extensions-jvm/management/pom.xml +++ b/extensions/management/pom.xml @@ -21,7 +21,7 @@ <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-extensions-jvm</artifactId> + <artifactId>camel-quarkus-extensions</artifactId> <version>3.0.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/extensions-jvm/management/runtime/pom.xml b/extensions/management/runtime/pom.xml similarity index 98% rename from extensions-jvm/management/runtime/pom.xml rename to extensions/management/runtime/pom.xml index 2f51c52938..d8ec3ade46 100644 --- a/extensions-jvm/management/runtime/pom.xml +++ b/extensions/management/runtime/pom.xml @@ -32,6 +32,7 @@ <properties> <camel.quarkus.jvmSince>1.1.0</camel.quarkus.jvmSince> + <camel.quarkus.nativeSince>3.0.0</camel.quarkus.nativeSince> </properties> <dependencies> diff --git a/extensions/management/runtime/src/main/doc/usage.adoc b/extensions/management/runtime/src/main/doc/usage.adoc new file mode 100644 index 0000000000..0cfcd5b138 --- /dev/null +++ b/extensions/management/runtime/src/main/doc/usage.adoc @@ -0,0 +1,21 @@ +For information on using Managed Beans in Camel, consult the xref:manual::jmx.adoc[JMX section of the Camel Manual]. + +=== Enabling and Disabling JMX + +JMX can be enabled or disabled in Camel-Quarkus by any of the following methods: + +. Adding or removing the `camel-quarkus-management` extension. +. Setting the `camel.main.jmxEnabled` configuration property to a boolean value. +. Setting the system property `-Dorg.apache.camel.jmx.disabled` to a boolean value. + +=== Native mode + +**Experimental** JMX support was added for native executables in GraalVM for JDK 17/20 / Mandrel 23.0. You can enable this feature by +adding the following configuration property to `application.properties`. + +[source,properties] +---- +quarkus.native.monitoring=jmxserver +---- + +For more information, refer to the https://quarkus.io/guides/building-native-image#using-monitoring-options[Quarkus native guide]. \ No newline at end of file diff --git a/extensions-jvm/management/runtime/src/main/java/org/apache/camel/quarkus/component/management/CamelManagementRecorder.java b/extensions/management/runtime/src/main/java/org/apache/camel/quarkus/component/management/CamelManagementRecorder.java similarity index 100% rename from extensions-jvm/management/runtime/src/main/java/org/apache/camel/quarkus/component/management/CamelManagementRecorder.java rename to extensions/management/runtime/src/main/java/org/apache/camel/quarkus/component/management/CamelManagementRecorder.java diff --git a/extensions-jvm/management/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/management/runtime/src/main/resources/META-INF/quarkus-extension.yaml similarity index 100% rename from extensions-jvm/management/runtime/src/main/resources/META-INF/quarkus-extension.yaml rename to extensions/management/runtime/src/main/resources/META-INF/quarkus-extension.yaml diff --git a/extensions/pom.xml b/extensions/pom.xml index 0c9bb9cf1e..6c93986a3b 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -166,6 +166,7 @@ <module>lumberjack</module> <module>lzf</module> <module>mail</module> + <module>management</module> <module>master</module> <module>micrometer</module> <module>microprofile-fault-tolerance</module> diff --git a/integration-tests-jvm/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementTest.java b/integration-tests-jvm/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementTest.java deleted file mode 100644 index b99cdb83bf..0000000000 --- a/integration-tests-jvm/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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.component.management.it; - -import java.lang.management.ManagementFactory; -import java.util.Set; - -import javax.management.MBeanServer; -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -import io.quarkus.test.junit.QuarkusTest; -import jakarta.inject.Inject; -import org.apache.camel.CamelContext; -import org.apache.camel.ProducerTemplate; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -@QuarkusTest -class ManagementTest { - - private MBeanServer server; - - @Inject - ProducerTemplate template; - - @Inject - CamelContext camelContext; - - @BeforeEach - public void setUp() { - server = ManagementFactory.getPlatformMBeanServer(); - } - - @ParameterizedTest - @ValueSource(strings = { "components", "consumers", "context", "dataformats", "endpoints", "processors", "routes", - "services" }) - public void testManagementObjects(String type) throws Exception { - // Look up an object instance by type - ObjectName objectName = new ObjectName("org.apache.camel:type=" + type + ",*"); - Set<ObjectInstance> mbeans = server.queryMBeans(objectName, null); - assertTrue(mbeans.size() > 0); - - // The CamelId attribute is common to all managed Camel objects, - // and should match the name of the CamelContext. - ObjectInstance mbean = mbeans.iterator().next(); - String camelId = (String) server.getAttribute(mbean.getObjectName(), "CamelId"); - assertEquals(camelContext.getName(), camelId); - } - - @Test - public void testDumpRoutesAsXml() throws Exception { - ObjectName objectName = new ObjectName("org.apache.camel:type=context,*"); - Set<ObjectInstance> mbeans = server.queryMBeans(objectName, null); - assertEquals(1, mbeans.size()); - - ObjectInstance instance = mbeans.iterator().next(); - String routeXML = (String) server.invoke(instance.getObjectName(), "dumpRoutesAsXml", new Object[] {}, new String[] {}); - assertTrue(routeXML.contains("<from uri=\"direct:start\"/>")); - } - - @Test - public void testManagedBean() throws Exception { - ObjectName objectName = new ObjectName("org.apache.camel:type=processors,name=\"counter\",*"); - Set<ObjectInstance> mbeans = server.queryMBeans(objectName, null); - assertEquals(1, mbeans.size()); - ObjectInstance instance = mbeans.iterator().next(); - - // Counter should be initialized to 0 - Integer count = (Integer) server.getAttribute(instance.getObjectName(), "Count"); - assertEquals(0, count); - - // Calling the increment() method should set counter to 1 - server.invoke(instance.getObjectName(), "increment", new Object[] {}, new String[] {}); - count = (Integer) server.getAttribute(instance.getObjectName(), "Count"); - assertEquals(1, count); - - // Call the "direct:count" endpoint to increment the counter - template.requestBody("direct:count", ""); - - count = (Integer) server.getAttribute(instance.getObjectName(), "Count"); - assertEquals(2, count); - } -} diff --git a/integration-tests-jvm/pom.xml b/integration-tests-jvm/pom.xml index 4195d56634..be5b009ec7 100644 --- a/integration-tests-jvm/pom.xml +++ b/integration-tests-jvm/pom.xml @@ -83,7 +83,6 @@ <module>jt400</module> <module>ldif</module> <module>lucene</module> - <module>management</module> <module>mapstruct</module> <module>mvel</module> <module>printer</module> diff --git a/integration-tests-jvm/management/pom.xml b/integration-tests/management/pom.xml similarity index 78% rename from integration-tests-jvm/management/pom.xml rename to integration-tests/management/pom.xml index 15b7dd6fe0..74514dae3e 100644 --- a/integration-tests-jvm/management/pom.xml +++ b/integration-tests/management/pom.xml @@ -43,8 +43,17 @@ <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-jackson</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy</artifactId> + </dependency> <!-- test dependencies --> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit5</artifactId> @@ -104,6 +113,33 @@ </dependency> </dependencies> </profile> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> </profiles> </project> diff --git a/integration-tests-jvm/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagedCounter.java b/integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagedCounter.java similarity index 100% copy from integration-tests-jvm/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagedCounter.java copy to integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagedCounter.java diff --git a/integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagementResource.java b/integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagementResource.java new file mode 100644 index 0000000000..e6326924b3 --- /dev/null +++ b/integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagementResource.java @@ -0,0 +1,97 @@ +/* + * 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.component.management.it; + +import java.lang.management.ManagementFactory; +import java.util.Iterator; +import java.util.Set; + +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectInstance; +import javax.management.ObjectName; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; + +@Path("/management") +public class ManagementResource { + + @Inject + ProducerTemplate template; + + @Inject + CamelContext camelContext; + + @GET + @Path("/context/name") + @Produces(MediaType.TEXT_PLAIN) + public String getContextName() { + return camelContext.getName(); + } + + @GET + @Path("/attribute") + @Produces(MediaType.TEXT_PLAIN) + public String getMBeanAttribute(@QueryParam("name") String name, @QueryParam("attribute") String attribute) + throws Exception { + ObjectInstance mbean = getMBean(name); + if (mbean != null) { + return String.valueOf(getMBeanServer().getAttribute(mbean.getObjectName(), attribute)); + } + return null; + } + + @POST + @Path("/invoke") + @Produces(MediaType.TEXT_PLAIN) + public String invokeMBeanOperation(@QueryParam("name") String name, @QueryParam("operation") String operation) + throws Exception { + ObjectInstance mbean = getMBean(name); + if (mbean != null) { + return String.valueOf(getMBeanServer().invoke(mbean.getObjectName(), operation, new Object[] {}, new String[] {})); + } + return null; + } + + @POST + @Path("/invoke/route") + public String invokeRoute(@QueryParam("endpointUri") String endpointUri) { + return template.requestBody(endpointUri, null, String.class); + } + + private ObjectInstance getMBean(String name) throws MalformedObjectNameException { + ObjectName objectName = new ObjectName(name); + Set<ObjectInstance> mbeans = getMBeanServer().queryMBeans(objectName, null); + Iterator<ObjectInstance> iterator = mbeans.iterator(); + if (iterator.hasNext()) { + return iterator.next(); + } + return null; + } + + private MBeanServer getMBeanServer() { + return ManagementFactory.getPlatformMBeanServer(); + } +} diff --git a/integration-tests-jvm/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 similarity index 100% rename from integration-tests-jvm/management/src/main/java/org/apache/camel/quarkus/component/management/it/Routes.java rename to integration-tests/management/src/main/java/org/apache/camel/quarkus/component/management/it/Routes.java diff --git a/integration-tests/management/src/main/resources/application.properties b/integration-tests/management/src/main/resources/application.properties new file mode 100644 index 0000000000..819bc64146 --- /dev/null +++ b/integration-tests/management/src/main/resources/application.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +quarkus.native.monitoring=jmxserver diff --git a/integration-tests-jvm/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagedCounter.java b/integration-tests/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementIT.java similarity index 64% rename from integration-tests-jvm/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagedCounter.java rename to integration-tests/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementIT.java index cbf84327d1..d030bc546d 100644 --- a/integration-tests-jvm/management/src/main/java/org/apache/camel/quarkus/component/management/it/ManagedCounter.java +++ b/integration-tests/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementIT.java @@ -16,21 +16,9 @@ */ package org.apache.camel.quarkus.component.management.it; -import org.apache.camel.api.management.ManagedAttribute; -import org.apache.camel.api.management.ManagedOperation; -import org.apache.camel.api.management.ManagedResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; -@ManagedResource -public class ManagedCounter { - private int count = 0; +@QuarkusIntegrationTest +class ManagementIT extends ManagementTest { - @ManagedAttribute(description = "The count value") - public int getCount() { - return count; - } - - @ManagedOperation(description = "Increment the counter") - public void increment() { - this.count++; - } } 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 new file mode 100644 index 0000000000..90d7d12de7 --- /dev/null +++ b/integration-tests/management/src/test/java/org/apache/camel/quarkus/component/management/it/ManagementTest.java @@ -0,0 +1,110 @@ +/* + * 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.component.management.it; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +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; + +@QuarkusTest +class ManagementTest { + + @ParameterizedTest + @ValueSource(strings = { "components", "consumers", "context", "dataformats", "endpoints", "processors", "routes", + "services" }) + public void testManagementObjects(String type) { + String contextName = RestAssured.get("/management/context/name") + .then() + .statusCode(200) + .extract() + .body() + .asString(); + + // Look up an object instance by type + // The CamelId attribute is common to all managed Camel objects, + // and should match the name of the CamelContext. + String name = "org.apache.camel:type=" + type + ",*"; + RestAssured.given() + .queryParam("name", name) + .queryParam("attribute", "CamelId") + .get("/management/attribute") + .then() + .statusCode(200) + .body(is(contextName)); + } + + @Test + public void testDumpRoutesAsXml() { + RestAssured.given() + .queryParam("name", "org.apache.camel:type=context,*") + .queryParam("operation", "dumpRoutesAsXml") + .post("/management/invoke") + .then() + .statusCode(200) + .body(containsString("<from uri=\"direct:start\"/>")); + } + + @Test + public void testManagedBean() { + String name = "org.apache.camel:type=processors,name=\"counter\",*"; + + // Counter should be initialized to 0 + RestAssured.given() + .queryParam("name", name) + .queryParam("attribute", "Count") + .get("/management/attribute") + .then() + .statusCode(200) + .body(is("0")); + + // Calling the increment() method should set counter to 1 + RestAssured.given() + .queryParam("name", name) + .queryParam("operation", "increment") + .post("/management/invoke") + .then() + .statusCode(200); + + RestAssured.given() + .queryParam("name", name) + .queryParam("attribute", "Count") + .get("/management/attribute") + .then() + .statusCode(200) + .body(is("1")); + + // Call the "direct:count" endpoint to increment the counter + RestAssured.given() + .queryParam("endpointUri", "direct:count") + .post("/management/invoke/route") + .then() + .statusCode(204); + + RestAssured.given() + .queryParam("name", name) + .queryParam("attribute", "Count") + .get("/management/attribute") + .then() + .statusCode(200) + .body(is("2")); + } +} diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 3b04494949..bb197206fa 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -156,6 +156,7 @@ <module>lra</module> <module>lumberjack</module> <module>mail</module> + <module>management</module> <module>master</module> <module>master-file</module> <module>master-openshift</module> diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml index e10ac6e13d..ebf510879f 100644 --- a/tooling/scripts/test-categories.yaml +++ b/tooling/scripts/test-categories.yaml @@ -142,6 +142,7 @@ group-09: - kafka-sasl-ssl - kafka-ssl - paho + - management - nats - splunk - spring-rabbitmq