This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new b2869327ce88 CAMEL-22935: Add JMX for simple function repository
(#21169)
b2869327ce88 is described below
commit b2869327ce88d0fbf55202f591542190e87bf9f1
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Feb 1 21:21:45 2026 +0100
CAMEL-22935: Add JMX for simple function repository (#21169)
---
.../apache/camel/catalog/dev-consoles.properties | 1 +
.../catalog/dev-consoles/simple-language.json | 15 +++++
.../apache/camel/spi/SimpleFunctionRegistry.java | 3 +-
.../apache/camel/dev-console/simple-language.json | 15 +++++
.../org/apache/camel/dev-console/simple-language | 2 +
.../org/apache/camel/dev-consoles.properties | 2 +-
.../camel/impl/console/SimpleLanguageConsole.java | 62 +++++++++++++++++
.../impl/console/SimpleLanguageDevConsoleTest.java | 52 +++++++++++++++
.../simple/ast/SimpleFunctionExpression.java | 2 +-
.../mbean/ManagedSimpleFunctionRegistryMBean.java} | 44 +++----------
.../management/JmxManagementLifecycleStrategy.java | 4 ++
.../mbean/ManagedSimpleFunctionRepository.java | 50 ++++++++++++++
.../ManagedSimpleFunctionRegistryTest.java | 77 ++++++++++++++++++++++
13 files changed, 291 insertions(+), 38 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles.properties
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles.properties
index 482964cf14ff..eccfcfb03b00 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles.properties
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles.properties
@@ -47,6 +47,7 @@ route-structure
send
service
sftp
+simple-language
source
startup-recorder
stub
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/simple-language.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/simple-language.json
new file mode 100644
index 000000000000..574bed5374d6
--- /dev/null
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/simple-language.json
@@ -0,0 +1,15 @@
+{
+ "console": {
+ "kind": "console",
+ "group": "camel",
+ "name": "simple-language",
+ "title": "Simple Language",
+ "description": "Display simple language details",
+ "deprecated": false,
+ "javaType": "org.apache.camel.impl.console.SimpleLanguageConsole",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-console",
+ "version": "4.18.0-SNAPSHOT"
+ }
+}
+
diff --git
a/core/camel-api/src/main/java/org/apache/camel/spi/SimpleFunctionRegistry.java
b/core/camel-api/src/main/java/org/apache/camel/spi/SimpleFunctionRegistry.java
index 1eb3f9fa66af..ea594014d5f5 100644
---
a/core/camel-api/src/main/java/org/apache/camel/spi/SimpleFunctionRegistry.java
+++
b/core/camel-api/src/main/java/org/apache/camel/spi/SimpleFunctionRegistry.java
@@ -19,11 +19,12 @@ package org.apache.camel.spi;
import java.util.Set;
import org.apache.camel.Expression;
+import org.apache.camel.StaticService;
/**
* Registry for custom simple functions.
*/
-public interface SimpleFunctionRegistry {
+public interface SimpleFunctionRegistry extends StaticService {
/**
* Add a function
diff --git
a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/simple-language.json
b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/simple-language.json
new file mode 100644
index 000000000000..574bed5374d6
--- /dev/null
+++
b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/simple-language.json
@@ -0,0 +1,15 @@
+{
+ "console": {
+ "kind": "console",
+ "group": "camel",
+ "name": "simple-language",
+ "title": "Simple Language",
+ "description": "Display simple language details",
+ "deprecated": false,
+ "javaType": "org.apache.camel.impl.console.SimpleLanguageConsole",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-console",
+ "version": "4.18.0-SNAPSHOT"
+ }
+}
+
diff --git
a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/simple-language
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/simple-language
new file mode 100644
index 000000000000..347f59529c4f
--- /dev/null
+++
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/simple-language
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.console.SimpleLanguageConsole
diff --git
a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties
index 65578a3c3840..d1f4d2b43665 100644
---
a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties
+++
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties
@@ -1,5 +1,5 @@
# Generated by camel build tools - do NOT edit this file!
-dev-consoles=bean blocked browse circuit-breaker consumer context debug
endpoint event gc health inflight internal-tasks java-security jvm log memory
message-history processor producer properties receive reload rest route
route-controller route-dump route-group route-structure send service source
startup-recorder system-properties thread top trace transformers
type-converters variables
+dev-consoles=bean blocked browse circuit-breaker consumer context debug
endpoint event gc health inflight internal-tasks java-security jvm log memory
message-history processor producer properties receive reload rest route
route-controller route-dump route-group route-structure send service
simple-language source startup-recorder system-properties thread top trace
transformers type-converters variables
groupId=org.apache.camel
artifactId=camel-console
version=4.18.0-SNAPSHOT
diff --git
a/core/camel-console/src/main/java/org/apache/camel/impl/console/SimpleLanguageConsole.java
b/core/camel-console/src/main/java/org/apache/camel/impl/console/SimpleLanguageConsole.java
new file mode 100644
index 000000000000..d32421c14ce2
--- /dev/null
+++
b/core/camel-console/src/main/java/org/apache/camel/impl/console/SimpleLanguageConsole.java
@@ -0,0 +1,62 @@
+/*
+ * 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.impl.console;
+
+import java.util.Map;
+
+import org.apache.camel.spi.SimpleFunctionRegistry;
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.console.AbstractDevConsole;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+
+@DevConsole(name = "simple-language", displayName = "Simple Language",
description = "Display simple language details")
+public class SimpleLanguageConsole extends AbstractDevConsole {
+
+ public SimpleLanguageConsole() {
+ super("camel", "simple-language", "Simple Language", "Display simple
language details");
+ }
+
+ @Override
+ protected String doCallText(Map<String, Object> options) {
+ StringBuilder sb = new StringBuilder();
+
+ SimpleFunctionRegistry reg =
PluginHelper.getSimpleFunctionRegistry(getCamelContext());
+ sb.append(String.format("%n Custom Functions: %d", reg.size()));
+ for (String name : reg.getFunctionNames()) {
+ sb.append(String.format("%n %s", name));
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ protected JsonObject doCallJson(Map<String, Object> options) {
+ SimpleFunctionRegistry reg =
PluginHelper.getSimpleFunctionRegistry(getCamelContext());
+
+ JsonObject root = new JsonObject();
+ root.put("size", reg.size());
+ JsonArray arr = new JsonArray();
+ arr.addAll(reg.getFunctionNames());
+ if (!arr.isEmpty()) {
+ root.put("functions", arr);
+ }
+
+ return root;
+ }
+}
diff --git
a/core/camel-console/src/test/java/org/apache/camel/impl/console/SimpleLanguageDevConsoleTest.java
b/core/camel-console/src/test/java/org/apache/camel/impl/console/SimpleLanguageDevConsoleTest.java
new file mode 100644
index 000000000000..ae79db9056ce
--- /dev/null
+++
b/core/camel-console/src/test/java/org/apache/camel/impl/console/SimpleLanguageDevConsoleTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.impl.console;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class SimpleLanguageDevConsoleTest extends ContextTestSupport {
+
+ @Test
+ public void testSimpleLanguageTest() {
+ DevConsole con =
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("simple-language");
+ Assertions.assertNotNull(con);
+ Assertions.assertEquals("camel", con.getGroup());
+ Assertions.assertEquals("simple-language", con.getId());
+
+ String out = (String) con.call(DevConsole.MediaType.TEXT);
+ Assertions.assertNotNull(out);
+ Assertions.assertTrue(out.contains("Custom Functions: 0"));
+ }
+
+ @Test
+ public void testSimpleLanguageJson() {
+ DevConsole con =
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("simple-language");
+ Assertions.assertNotNull(con);
+ Assertions.assertEquals("camel", con.getGroup());
+ Assertions.assertEquals("simple-language", con.getId());
+
+ JsonObject out = (JsonObject) con.call(DevConsole.MediaType.JSON);
+ Assertions.assertEquals(0, out.getInteger("size"));
+ Assertions.assertNotNull(out);
+ }
+
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index b53b4a9f6899..c5b624b4ba88 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -375,7 +375,7 @@ public class SimpleFunctionExpression extends
LiteralExpression {
String name = StringHelper.before(function, "(", function);
if
(PluginHelper.getSimpleFunctionRegistry(camelContext).getFunctionNames().contains(name))
{
String after = StringHelper.after(function, "(");
- if (after.equals(")")) {
+ if (after == null || after.equals(")")) {
function = "function(" + name + ")";
} else {
function = "function(" + name + "," + after;
diff --git
a/core/camel-api/src/main/java/org/apache/camel/spi/SimpleFunctionRegistry.java
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedSimpleFunctionRegistryMBean.java
similarity index 51%
copy from
core/camel-api/src/main/java/org/apache/camel/spi/SimpleFunctionRegistry.java
copy to
core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedSimpleFunctionRegistryMBean.java
index 1eb3f9fa66af..f1c687932fcd 100644
---
a/core/camel-api/src/main/java/org/apache/camel/spi/SimpleFunctionRegistry.java
+++
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedSimpleFunctionRegistryMBean.java
@@ -14,48 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.spi;
+package org.apache.camel.api.management.mbean;
import java.util.Set;
-import org.apache.camel.Expression;
+import org.apache.camel.api.management.ManagedAttribute;
+import org.apache.camel.api.management.ManagedOperation;
-/**
- * Registry for custom simple functions.
- */
-public interface SimpleFunctionRegistry {
-
- /**
- * Add a function
- *
- * @param name name of function
- * @param expression the expression to use as the function
- */
- void addFunction(String name, Expression expression);
-
- /**
- * Remove a function
- *
- * @param name name of function
- */
- void removeFunction(String name);
+public interface ManagedSimpleFunctionRegistryMBean extends
ManagedServiceMBean {
- /**
- * Gets the function
- *
- * @param name name of function
- * @return the function, or <tt>null</tt> if no function exists
- */
- Expression getFunction(String name);
+ @ManagedAttribute(description = "Number of custom functions")
+ int getSize();
- /**
- * Returns a set with all the function names
- */
+ @ManagedAttribute(description = "The names of the custom functions")
Set<String> getFunctionNames();
- /**
- * Number of custom functions
- */
- int size();
+ @ManagedOperation(description = "Is there a custom function with the given
name")
+ boolean hasFunction(String name);
}
diff --git
a/core/camel-management/src/main/java/org/apache/camel/management/JmxManagementLifecycleStrategy.java
b/core/camel-management/src/main/java/org/apache/camel/management/JmxManagementLifecycleStrategy.java
index 9770c932c4de..f654deaa3eaf 100644
---
a/core/camel-management/src/main/java/org/apache/camel/management/JmxManagementLifecycleStrategy.java
+++
b/core/camel-management/src/main/java/org/apache/camel/management/JmxManagementLifecycleStrategy.java
@@ -71,6 +71,7 @@ import org.apache.camel.management.mbean.ManagedRouteGroup;
import org.apache.camel.management.mbean.ManagedRuntimeEndpointRegistry;
import org.apache.camel.management.mbean.ManagedService;
import org.apache.camel.management.mbean.ManagedShutdownStrategy;
+import org.apache.camel.management.mbean.ManagedSimpleFunctionRepository;
import org.apache.camel.management.mbean.ManagedStreamCachingStrategy;
import org.apache.camel.management.mbean.ManagedTaskManagerRegistry;
import org.apache.camel.management.mbean.ManagedThrottlingExceptionRoutePolicy;
@@ -109,6 +110,7 @@ import org.apache.camel.spi.ProducerCache;
import org.apache.camel.spi.RestRegistry;
import org.apache.camel.spi.RuntimeEndpointRegistry;
import org.apache.camel.spi.ShutdownStrategy;
+import org.apache.camel.spi.SimpleFunctionRegistry;
import org.apache.camel.spi.StreamCachingStrategy;
import org.apache.camel.spi.Tracer;
import org.apache.camel.spi.TransformerRegistry;
@@ -600,6 +602,8 @@ public class JmxManagementLifecycleStrategy extends
ServiceSupport implements Li
answer = new ManagedTaskManagerRegistry(camelContext, registry);
} else if (service instanceof CamelClusterService camelClusterService)
{
answer =
getManagementObjectStrategy().getManagedObjectForClusterService(context,
camelClusterService);
+ } else if (service instanceof SimpleFunctionRegistry registry) {
+ answer = new ManagedSimpleFunctionRepository(context, registry);
} else if (service != null) {
// fallback as generic service
answer =
getManagementObjectStrategy().getManagedObjectForService(context, service);
diff --git
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedSimpleFunctionRepository.java
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedSimpleFunctionRepository.java
new file mode 100644
index 000000000000..d3137d506e02
--- /dev/null
+++
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedSimpleFunctionRepository.java
@@ -0,0 +1,50 @@
+/*
+ * 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.management.mbean;
+
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.api.management.ManagedResource;
+import
org.apache.camel.api.management.mbean.ManagedSimpleFunctionRegistryMBean;
+import org.apache.camel.spi.SimpleFunctionRegistry;
+
+@ManagedResource(description = "Managed SimpleFunctionRegistry")
+public class ManagedSimpleFunctionRepository extends ManagedService implements
ManagedSimpleFunctionRegistryMBean {
+
+ private final SimpleFunctionRegistry registry;
+
+ public ManagedSimpleFunctionRepository(CamelContext context,
SimpleFunctionRegistry simpleFunctionRegistry) {
+ super(context, simpleFunctionRegistry);
+ this.registry = simpleFunctionRegistry;
+ }
+
+ @Override
+ public int getSize() {
+ return registry.size();
+ }
+
+ @Override
+ public Set<String> getFunctionNames() {
+ return registry.getFunctionNames();
+ }
+
+ @Override
+ public boolean hasFunction(String name) {
+ return registry.getFunction(name) != null;
+ }
+}
diff --git
a/core/camel-management/src/test/java/org/apache/camel/management/ManagedSimpleFunctionRegistryTest.java
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedSimpleFunctionRegistryTest.java
new file mode 100644
index 000000000000..93ac38180fe4
--- /dev/null
+++
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedSimpleFunctionRegistryTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.management;
+
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.SimpleFunctionRegistry;
+import org.apache.camel.support.PluginHelper;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static
org.apache.camel.management.DefaultManagementObjectNameStrategy.TYPE_SERVICE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@DisabledOnOs(OS.AIX)
+public class ManagedSimpleFunctionRegistryTest extends ManagementTestSupport {
+
+ @Test
+ public void testSimpleFunction() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("Bonjour World");
+
+ template.sendBody("direct:start", "World");
+
+ assertMockEndpointsSatisfied();
+
+ MBeanServer mbeanServer = getMBeanServer();
+ ObjectName name = getCamelObjectName(TYPE_SERVICE,
"DefaultSimpleFunctionRegistry");
+
+ Integer size = (Integer) mbeanServer.getAttribute(name, "Size");
+ assertEquals(1, size);
+
+ Set<String> names = (Set) mbeanServer.getAttribute(name,
"FunctionNames");
+ assertEquals(1, names.size());
+ assertEquals("hi", names.iterator().next());
+
+ Boolean bool
+ = (Boolean) mbeanServer.invoke(name, "hasFunction", new
Object[] { "hi" }, new String[] { "java.lang.String" });
+ assertEquals(Boolean.TRUE, bool);
+
+ bool = (Boolean) mbeanServer.invoke(name, "hasFunction", new Object[]
{ "goodbye" },
+ new String[] { "java.lang.String" });
+ assertEquals(Boolean.FALSE, bool);
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ SimpleFunctionRegistry r =
PluginHelper.getSimpleFunctionRegistry(context);
+ r.addFunction("hi", simple("Bonjour ${body}"));
+
+
from("direct:start").setBody(simple("${hi}")).to("mock:result");
+ }
+ };
+ }
+
+}