Hi, all. I was talking about this on the users list, but I found out about the dev list, so I wanted to share this question with fellow camel devs/contributors.
I am adding JMX reporting and control to my dynamic router eip component (not the original dynamic router that you can use with the DSL in core). I have two services that I annotated with camel-management annotations: For JMX control (things removed for brevity): @Converter(generateBulkLoader = true) @ManagedResource(description = "Dynamic Router control operations service") public class DynamicRouterControlService extends ServiceSupport { private final CamelContext camelContext; private final DynamicRouterFilterService filterService; public DynamicRouterControlService(CamelContext camelContext, DynamicRouterFilterService filterService) { this.camelContext = camelContext; this.filterService = filterService; } @ManagedOperation(description = "Subscribe for dynamic routing with a predicate expression") public String subscribeWithPredicateExpression( String subscribeChannel, String subscriptionId, String destinationUri, int priority, String predicate, String expressionLanguage, boolean update) { return filterService.addFilterForChannel(subscriptionId, priority, obtainPredicateFromExpression(camelContext, predicate, expressionLanguage), destinationUri, subscribeChannel, update); } @ManagedOperation(description = "Subscribe for dynamic routing with the name of a predicate bean in the registry") public String subscribeWithPredicateBean( String subscribeChannel, String subscriptionId, String destinationUri, int priority, String predicateBean, boolean update) { return filterService.addFilterForChannel(subscriptionId, priority, obtainPredicateFromBeanName(predicateBean, camelContext), destinationUri, subscribeChannel, update); } @ManagedOperation(description = "Subscribe for dynamic routing with a predicate instance") public String subscribeWithPredicateInstance( String subscribeChannel, String subscriptionId, String destinationUri, int priority, Object predicate, boolean update) { return filterService.addFilterForChannel(subscriptionId, priority, obtainPredicateFromInstance(predicate), destinationUri, subscribeChannel, update); } @ManagedOperation(description = "Unsubscribe for dynamic routing on a channel by subscription ID") public boolean removeSubscription( String subscribeChannel, String subscriptionId) { return filterService.removeFilterById(subscriptionId, subscribeChannel); } @Override public void start() { // no-op } @Override public void stop() { // no-op } } For reporting/monitoring (things removed for brevity): @ManagedResource(description = "Dynamic Router filter service") public class DynamicRouterFilterService extends ServiceSupport { private final Map<String, ConcurrentSkipListSet<PrioritizedFilter>> filterMap = new ConcurrentHashMap<>(); private final Map<String, List<PrioritizedFilterStatistics>> filterStatisticsMap = new ConcurrentHashMap<>(); private final Supplier<PrioritizedFilterFactory> filterFactorySupplier; public DynamicRouterFilterService(final Supplier<PrioritizedFilterFactory> filterFactorySupplier) { this.filterFactorySupplier = filterFactorySupplier; LOG.debug("Created Dynamic Router component"); } @ManagedAttribute(description = "Get the list of filters for the specified dynamic router channel") public Collection<PrioritizedFilter> getFiltersForChannel(final String channel) { return List.copyOf(filterMap.get(channel)); } @ManagedAttribute(description = "Get the map of filters for all dynamic router channels") public Map<String, ConcurrentSkipListSet<PrioritizedFilter>> getFilterMap() { return Map.copyOf(filterMap); } @ManagedAttribute(description = "Get the set of filter statistics for the specified dynamic router channel") public List<PrioritizedFilterStatistics> getStatisticsForChannel(final String channel) { return List.copyOf(filterStatisticsMap.get(channel)); } @ManagedAttribute(description = "Get the map of statistics for all dynamic router channels") public Map<String, List<PrioritizedFilterStatistics>> getFilterStatisticsMap() { return Map.copyOf(filterStatisticsMap); } @Override public void start() { // no-op } @Override public void stop() { // no-op } } I want to write a test that verifies that camel is registering these. I have added camel-management to my pom in the "test" scope. I originally tried to use a test annotated with @CamelSpringTest, but I could not it to work, and when I tried to get the ManagementAgent, it was always null. So I switched to a normal test that extends CamelTestSupport, and now I can at least get the agent and the MBeanServer. Here is my test class: class DynamicRouterManagementIT extends CamelTestSupport { @Override protected boolean useJmx() { return true; } @Test void testExpectedMbeansExist() throws MalformedObjectNameException { MBeanServer mBeanServer = context.getManagementStrategy().getManagementAgent().getMBeanServer(); String names = mBeanServer.queryNames(null, null).stream() .map(ObjectName::getCanonicalName) .filter(name -> name.contains("ynamic")) .collect(Collectors.joining("\n")); System.err.println("MBean names:\n" + names); } @Override protected RoutesBuilder createRouteBuilder() { return new RouteBuilder() { @Override public void configure() { from("direct:subscribe").to("dynamic-router-control:subscribe"); from("direct:command").to("dynamic-router:test"); } }; } } The output does not show either of the two @ManagedResource classes. Here is the output: MBean names: > > org.apache.camel:context=camel-1,name="dynamic-router-control",type=components > org.apache.camel:context=camel-1,name="dynamic-router",type=components > > org.apache.camel:context=camel-1,name="dynamic-router-control://subscribe",type=endpoints > > org.apache.camel:context=camel-1,name=DynamicRouterProducer(0x511505e7),type=producers > > org.apache.camel:context=camel-1,name=DynamicRouterControlProducer(0x70abf9b0),type=producers > > org.apache.camel:context=camel-1,name="dynamic-router://test",type=endpoints Why don't I see the MBeans that I expect for the classes that I included above? Thanks, Steve