From 5315efe13cdec24c7b3b9b4410a1a34f24981c4a Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Tue, 30 Dec 2025 16:46:49 +0100 Subject: [PATCH 1/4] Remove unused unreachable MBeanExporter constructor --- src/main/java/org/weakref/jmx/MBeanExporter.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/org/weakref/jmx/MBeanExporter.java b/src/main/java/org/weakref/jmx/MBeanExporter.java index 7ef0aad..b213ee6 100644 --- a/src/main/java/org/weakref/jmx/MBeanExporter.java +++ b/src/main/java/org/weakref/jmx/MBeanExporter.java @@ -47,11 +47,6 @@ public class MBeanExporter private final ObjectNameGenerator objectNameGenerator; private final Map exportedManagedClasses = new ConcurrentHashMap<>(); - MBeanExporter() - { - this(ManagementFactory.getPlatformMBeanServer()); - } - public MBeanExporter(MBeanServer server) { this(server, Optional.empty()); From 8c6ec21e0d9aa696180f0c3f60553f6082bd415b Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Tue, 30 Dec 2025 16:44:50 +0100 Subject: [PATCH 2/4] Disallow MBeanModule subclassing It was deprecated since bd231bf9e4f33a94d329e9a500430097432015bf commit, i.e. for over decade. --- .../jmx/guice/AnnotatedExportBuilder.java | 41 --------- .../org/weakref/jmx/guice/ExportBuilder.java | 25 ----- .../org/weakref/jmx/guice/MBeanModule.java | 61 +------------ .../jmx/guice/NamedBindingBuilder.java | 67 -------------- .../jmx/guice/TestModuleSubclassing.java | 91 ------------------- 5 files changed, 2 insertions(+), 283 deletions(-) delete mode 100644 src/main/java/org/weakref/jmx/guice/AnnotatedExportBuilder.java delete mode 100644 src/main/java/org/weakref/jmx/guice/ExportBuilder.java delete mode 100644 src/main/java/org/weakref/jmx/guice/NamedBindingBuilder.java delete mode 100644 src/test/java/org/weakref/jmx/guice/TestModuleSubclassing.java diff --git a/src/main/java/org/weakref/jmx/guice/AnnotatedExportBuilder.java b/src/main/java/org/weakref/jmx/guice/AnnotatedExportBuilder.java deleted file mode 100644 index cd3a507..0000000 --- a/src/main/java/org/weakref/jmx/guice/AnnotatedExportBuilder.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright 2009 Martin Traverso - * - * Licensed 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.weakref.jmx.guice; - -import com.google.inject.Key; -import com.google.inject.multibindings.Multibinder; - -import java.lang.annotation.Annotation; - -@Deprecated -public class AnnotatedExportBuilder - extends NamedBindingBuilder -{ - AnnotatedExportBuilder(Multibinder binder, Key key) - { - super(binder, key); - } - - public NamedBindingBuilder annotatedWith(Annotation annotation) - { - return new NamedBindingBuilder(binder, Key.get(key.getTypeLiteral(), annotation)); - } - - public NamedBindingBuilder annotatedWith(Class annotationClass) - { - return new NamedBindingBuilder(binder, Key.get(key.getTypeLiteral(), annotationClass)); - } -} diff --git a/src/main/java/org/weakref/jmx/guice/ExportBuilder.java b/src/main/java/org/weakref/jmx/guice/ExportBuilder.java deleted file mode 100644 index 0efbed7..0000000 --- a/src/main/java/org/weakref/jmx/guice/ExportBuilder.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.weakref.jmx.guice; - -import com.google.inject.Key; -import com.google.inject.multibindings.Multibinder; - -@Deprecated -public class ExportBuilder -{ - private final Multibinder binder; - - ExportBuilder(Multibinder binder) - { - this.binder = binder; - } - - public AnnotatedExportBuilder export(Class clazz) - { - return new AnnotatedExportBuilder(binder, Key.get(clazz)); - } - - public NamedBindingBuilder export(Key key) - { - return new NamedBindingBuilder(binder, key); - } -} diff --git a/src/main/java/org/weakref/jmx/guice/MBeanModule.java b/src/main/java/org/weakref/jmx/guice/MBeanModule.java index ddb0c48..8e6f1df 100644 --- a/src/main/java/org/weakref/jmx/guice/MBeanModule.java +++ b/src/main/java/org/weakref/jmx/guice/MBeanModule.java @@ -16,8 +16,6 @@ package org.weakref.jmx.guice; import com.google.inject.AbstractModule; -import com.google.inject.Binder; -import com.google.inject.Key; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; import org.weakref.jmx.MBeanExporter; @@ -26,72 +24,17 @@ import static com.google.inject.multibindings.Multibinder.newSetBinder; import static com.google.inject.multibindings.OptionalBinder.newOptionalBinder; -public class MBeanModule +public final class MBeanModule extends AbstractModule { - private ExportBuilder builder; - @Override - protected final void configure() + protected void configure() { - builder = newExporter(binder()); - bind(GuiceMBeanExporter.class).asEagerSingleton(); bind(MBeanExporter.class).in(Scopes.SINGLETON); newOptionalBinder(binder(), ObjectNameGenerator.class); newSetBinder(binder(), new TypeLiteral>() {}); newSetBinder(binder(), new TypeLiteral>() {}); - - configureMBeans(); - } - - /** - * To be overridden by subclasses. E.g., - * - * protected void configureMBeans() { - * export(ManagedObject.class).as("test:name=X"); - * export(ManagedObject.class).annotatedWith(SomeAnnotation.class).as("test:name=Y"); - * } - * - * When ExportBuilder is used, a raw MBeanModule can be imported to trigger the - * registration of exported mbeans: - * - *
-     * {@code
-     * Injector injector = Guice.createInjector(new MBeanModule(),
-     *      new AbstractModule() {
-     *          @Override
-     *          protected void configure() {
-     *              ExportBuilder builder = MBeanModule.newExporter();
-     *              builder.export(AnotherManagedObject.class).as("test:name="Z");
-     *          }
-     *      });
-     * }
-     * 
- * - * @deprecated subclassing no longer supported. Use ExportBinder instead - */ - @Deprecated - protected void configureMBeans() { - } - - @Deprecated - protected NamedBindingBuilder export(Key key) - { - return builder.export(key); } - - @Deprecated - protected AnnotatedExportBuilder export(Class clazz) - { - return builder.export(clazz); - } - - @Deprecated - public static ExportBuilder newExporter(Binder binder) - { - return new ExportBuilder(newSetBinder(binder, Mapping.class)); - } - } diff --git a/src/main/java/org/weakref/jmx/guice/NamedBindingBuilder.java b/src/main/java/org/weakref/jmx/guice/NamedBindingBuilder.java deleted file mode 100644 index 1eed531..0000000 --- a/src/main/java/org/weakref/jmx/guice/NamedBindingBuilder.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright 2009 Martin Traverso - * - * Licensed 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.weakref.jmx.guice; - -import com.google.inject.Key; -import com.google.inject.multibindings.Multibinder; -import com.google.inject.name.Named; -import org.weakref.jmx.ObjectNameGenerator; - -import java.util.function.Function; - -@Deprecated -public class NamedBindingBuilder -{ - protected final Multibinder binder; - protected final Key key; - - NamedBindingBuilder(Multibinder binder, Key key) - { - this.binder = binder; - this.key = key; - } - - /** - * Names the MBean according to {@link org.weakref.jmx.ObjectNames} name generator methods. - */ - public void withGeneratedName() - { - if (key.getAnnotation() != null) { - if (key.getAnnotation() instanceof Named annotation) { - as(factory -> factory.generatedNameOf(key.getTypeLiteral().getRawType(), annotation.value())); - } - else { - as(factory -> factory.generatedNameOf(key.getTypeLiteral().getRawType(), key.getAnnotation().annotationType().getSimpleName())); - } - } - else if (key.getAnnotationType() != null) { - as(factory -> factory.generatedNameOf(key.getTypeLiteral().getRawType(), key.getAnnotationType().getSimpleName())); - } - else { - as(factory -> factory.generatedNameOf(key.getTypeLiteral().getRawType())); - } - } - - public void as(String name) - { - as(factory -> name); - } - - private void as(Function mappingNameFactory) - { - binder.addBinding().toInstance(new Mapping(mappingNameFactory, key)); - } -} diff --git a/src/test/java/org/weakref/jmx/guice/TestModuleSubclassing.java b/src/test/java/org/weakref/jmx/guice/TestModuleSubclassing.java deleted file mode 100644 index ec2e168..0000000 --- a/src/test/java/org/weakref/jmx/guice/TestModuleSubclassing.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright 2009 Martin Traverso - * - * Licensed 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.weakref.jmx.guice; - -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Stage; -import com.google.inject.name.Named; -import com.google.inject.name.Names; -import org.testng.Assert; -import org.testng.annotations.Test; -import org.weakref.jmx.Managed; -import org.weakref.jmx.testing.TestingMBeanServer; - -import javax.management.MBeanServer; -import javax.management.ObjectName; - -public class TestModuleSubclassing -{ - @Test - public void testSubclassing() - throws Exception - { - final Named name1 = Names.named("bean1"); - final Named name2 = Names.named("bean2"); - - final TestingMBeanServer tms = new TestingMBeanServer(); - - final Module m1 = new MBeanModule() { - @Override - protected void configureMBeans() { - export(Key.get(Bean.class, name1)).as("bean1:name=bean1"); - } - }; - - final Module m2 = new MBeanModule() { - @Override - protected void configureMBeans() { - export(Key.get(Bean.class, name2)).as("bean2:name=bean2"); - } - }; - - Guice.createInjector(Stage.PRODUCTION, - m1, - m2, - new AbstractModule() { - @Override - public void configure() { - bind(MBeanServer.class).toInstance(tms); - bind(Bean.class).annotatedWith(name1).toInstance(new Bean("name1")); - bind(Bean.class).annotatedWith(name2).toInstance(new Bean("name2")); - } - }); - - Assert.assertEquals(2, tms.getMBeanCount().intValue()); - Assert.assertNotNull(tms.getMBeanInfo(new ObjectName("bean1:name=bean1"))); - Assert.assertNotNull(tms.getMBeanInfo(new ObjectName("bean2:name=bean2"))); - } - - public static final class Bean - { - private final String name; - - Bean(final String name) - { - this.name = name; - } - - @Managed - public String getName() - { - return name; - } - } -} - From e31987dd725933e3829689720bb8e58bf750e72a Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Tue, 30 Dec 2025 17:25:30 +0100 Subject: [PATCH 3/4] Fix MBeanModule init when nothing exported --- .../java/org/weakref/jmx/guice/MBeanModule.java | 1 + .../org/weakref/jmx/guice/TestMBeanModule.java | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/org/weakref/jmx/guice/MBeanModule.java b/src/main/java/org/weakref/jmx/guice/MBeanModule.java index 8e6f1df..d60fc04 100644 --- a/src/main/java/org/weakref/jmx/guice/MBeanModule.java +++ b/src/main/java/org/weakref/jmx/guice/MBeanModule.java @@ -34,6 +34,7 @@ protected void configure() bind(MBeanExporter.class).in(Scopes.SINGLETON); newOptionalBinder(binder(), ObjectNameGenerator.class); + newSetBinder(binder(), new TypeLiteral() {}); newSetBinder(binder(), new TypeLiteral>() {}); newSetBinder(binder(), new TypeLiteral>() {}); } diff --git a/src/test/java/org/weakref/jmx/guice/TestMBeanModule.java b/src/test/java/org/weakref/jmx/guice/TestMBeanModule.java index 2d6b9cf..0ee8bfe 100644 --- a/src/test/java/org/weakref/jmx/guice/TestMBeanModule.java +++ b/src/test/java/org/weakref/jmx/guice/TestMBeanModule.java @@ -23,6 +23,7 @@ import com.google.inject.multibindings.Multibinder; import org.testng.Assert; import org.testng.annotations.Test; +import org.weakref.jmx.MBeanExporter; import org.weakref.jmx.ObjectNameBuilder; import org.weakref.jmx.ObjectNameGenerator; import org.weakref.jmx.SimpleObject; @@ -268,6 +269,19 @@ protected void configure() server.unregisterMBean(objectName2); } + @Test + public void testNothingExported() + { + Injector injector = Guice.createInjector( + new MBeanModule(), + binder -> { + binder.requireExplicitBindings(); + binder.disableCircularProxies(); + binder.bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer()); + }); + injector.getInstance(MBeanExporter.class); + } + @Test public void testSet() throws Exception From efaf0704b425f2a8cb6db87fad9797e4498caa33 Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Tue, 30 Dec 2025 16:52:05 +0100 Subject: [PATCH 4/4] Require opt-in for using unnamespaced mbean exports Some applications exports mbeans in one place, from one class loader, and so they do not need namespacing as class name-generated mbean names do not collide. Some applications use multiple class loaders and therefore require additional configuration for exporting mbeans safely. The `MBeanModule` provides sufficient configuration options, allowing users to bind `ObjectNameGenerator`, but its default behavior turned out to be error-prone at least in projects such as Trino. It seems safer to require explicit opt-in into unnamespaced exports. This commit deprecates `MBeanModule` constructor in favor of named factory methods for explicit declaration whether default `ObjectNameGenerator` should be used, or custom one will be provided. The "for custom" factory creates a module that will fail to load unless a custom `ObjectNameGenerator` is bound. The "for unnamespaced" creates a module with default `ObjectNameGenerator`. The factory name is meant to be thought-provoking and therefore the name generator bound this way is not rebindable. The `new MBeanModule()` constructor is kept, but deprecated. It supports the original behavior allowing users to rebind name generator. --- pom.xml | 7 + .../java/org/weakref/jmx/MBeanExporter.java | 20 ++- .../weakref/jmx/guice/GuiceMBeanExporter.java | 10 +- .../org/weakref/jmx/guice/MBeanModule.java | 146 +++++++++++++++++- .../weakref/jmx/guice/TestMBeanModule.java | 28 ++++ 5 files changed, 196 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index ba176ac..7adbf54 100644 --- a/pom.xml +++ b/pom.xml @@ -73,6 +73,13 @@ 3.0.0 true + + + org.assertj + assertj-core + 3.27.6 + test + diff --git a/src/main/java/org/weakref/jmx/MBeanExporter.java b/src/main/java/org/weakref/jmx/MBeanExporter.java index b213ee6..cddbeb4 100644 --- a/src/main/java/org/weakref/jmx/MBeanExporter.java +++ b/src/main/java/org/weakref/jmx/MBeanExporter.java @@ -18,9 +18,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.MapMaker; import com.google.inject.Inject; +import jakarta.annotation.PreDestroy; import org.weakref.jmx.JmxException.Reason; -import jakarta.annotation.PreDestroy; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.MBeanRegistrationException; @@ -47,16 +47,22 @@ public class MBeanExporter private final ObjectNameGenerator objectNameGenerator; private final Map exportedManagedClasses = new ConcurrentHashMap<>(); + /** + * @deprecated Use {@link #MBeanExporter(MBeanServer, ObjectNameGenerator)} instead. + * You can obtain an instance of {@link ObjectNameGenerator} via {@link ObjectNameGenerator#defaultObjectNameGenerator()} + * if usage of the mbean exporter requires no namespacing. + */ + @Deprecated public MBeanExporter(MBeanServer server) { - this(server, Optional.empty()); + this(server, ObjectNameGenerator.defaultObjectNameGenerator()); } @Inject - public MBeanExporter(MBeanServer server, Optional objectNameGenerator) + public MBeanExporter(MBeanServer server, ObjectNameGenerator objectNameGenerator) { - this.server = server; - this.objectNameGenerator = objectNameGenerator.orElseGet(ObjectNameGenerator::defaultObjectNameGenerator); + this.server = requireNonNull(server, "server is null"); + this.objectNameGenerator = requireNonNull(objectNameGenerator, "objectNameGenerator is null"); exportedObjects = new MapMaker().weakValues().makeMap(); } @@ -260,7 +266,9 @@ public Optional getExportedObject(ObjectName objectName) */ public static MBeanExporter withPlatformMBeanServer() { - return new MBeanExporter(ManagementFactory.getPlatformMBeanServer()); + return new MBeanExporter( + ManagementFactory.getPlatformMBeanServer(), + ObjectNameGenerator.defaultObjectNameGenerator()); } private static ObjectName createObjectName(String name) diff --git a/src/main/java/org/weakref/jmx/guice/GuiceMBeanExporter.java b/src/main/java/org/weakref/jmx/guice/GuiceMBeanExporter.java index 72ab9bb..8b54d49 100644 --- a/src/main/java/org/weakref/jmx/guice/GuiceMBeanExporter.java +++ b/src/main/java/org/weakref/jmx/guice/GuiceMBeanExporter.java @@ -24,7 +24,6 @@ import java.util.Map; import java.util.Map.Entry; -import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; @@ -35,15 +34,14 @@ public GuiceMBeanExporter(Set mappings, Set> setMappings, Set> mapMappings, MBeanExporter exporter, - Optional objectNameGenerator, + ObjectNameGenerator objectNameGenerator, Injector injector) { - ObjectNameGenerator generator = objectNameGenerator.orElseGet(ObjectNameGenerator::defaultObjectNameGenerator); - export(mappings, exporter, injector, generator); + export(mappings, exporter, injector, objectNameGenerator); // cast to Object to get around Java's broken generics - exportSets(castSetMapping(setMappings), exporter, injector, generator); - exportMaps(castMapMappings(mapMappings), exporter, injector, generator); + exportSets(castSetMapping(setMappings), exporter, injector, objectNameGenerator); + exportMaps(castMapMappings(mapMappings), exporter, injector, objectNameGenerator); } @SuppressWarnings("unchecked") diff --git a/src/main/java/org/weakref/jmx/guice/MBeanModule.java b/src/main/java/org/weakref/jmx/guice/MBeanModule.java index d60fc04..4bc0c9a 100644 --- a/src/main/java/org/weakref/jmx/guice/MBeanModule.java +++ b/src/main/java/org/weakref/jmx/guice/MBeanModule.java @@ -16,26 +16,166 @@ package org.weakref.jmx.guice; import com.google.inject.AbstractModule; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Provider; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; import org.weakref.jmx.MBeanExporter; import org.weakref.jmx.ObjectNameGenerator; +import javax.management.MBeanServer; + +import java.util.Optional; +import java.util.Set; + import static com.google.inject.multibindings.Multibinder.newSetBinder; import static com.google.inject.multibindings.OptionalBinder.newOptionalBinder; +import static java.util.Objects.requireNonNull; public final class MBeanModule extends AbstractModule { + + public static MBeanModule withUnnamespacedObjectNames() + { + return new MBeanModule(ObjectNameGeneratorStrategy.NO_NAMESPACE); + } + + public static MBeanModule forCustomObjectNameGenerator() + { + return new MBeanModule(ObjectNameGeneratorStrategy.EXPLICIT_NAMING); + } + + private final ObjectNameGeneratorStrategy objectNameGeneratorStrategy; + + /** + * @deprecated It should be explicit choice to export MBeans without namespacing, as this can easily lead to name collisions. + * Use {@link #withUnnamespacedObjectNames()} if you want this behavior and use {@link #forCustomObjectNameGenerator()} if you + * want to provide your own naming strategy perhaps for namespacing. + */ + @Deprecated + public MBeanModule() + { + this(ObjectNameGeneratorStrategy.LEGACY); + } + + private MBeanModule(ObjectNameGeneratorStrategy objectNameGeneratorStrategy) + { + this.objectNameGeneratorStrategy = requireNonNull(objectNameGeneratorStrategy, "objectNameGeneratorStrategy is null"); + } + @Override protected void configure() { - bind(GuiceMBeanExporter.class).asEagerSingleton(); - bind(MBeanExporter.class).in(Scopes.SINGLETON); + switch (objectNameGeneratorStrategy) { + case LEGACY -> { + bind(GuiceMBeanExporter.class) + .toProvider(LegacyBindingGuiceMBeanExporterProvider.class) + .asEagerSingleton(); + bind(MBeanExporter.class) + .toProvider(LegacyBindingMBeanExporterProvider.class) + .in(Scopes.SINGLETON); + newOptionalBinder(binder(), ObjectNameGenerator.class); + } + + case NO_NAMESPACE -> { + bind(GuiceMBeanExporter.class).asEagerSingleton(); + bind(MBeanExporter.class).in(Scopes.SINGLETON); + bind(ObjectNameGenerator.class).toInstance(ObjectNameGenerator.defaultObjectNameGenerator()); + } + + case EXPLICIT_NAMING -> { + bind(GuiceMBeanExporter.class).asEagerSingleton(); + bind(MBeanExporter.class).in(Scopes.SINGLETON); + // require explicit binding + bind(ObjectNameGenerator.class); + } + } - newOptionalBinder(binder(), ObjectNameGenerator.class); newSetBinder(binder(), new TypeLiteral() {}); newSetBinder(binder(), new TypeLiteral>() {}); newSetBinder(binder(), new TypeLiteral>() {}); } + + enum ObjectNameGeneratorStrategy + { + /** + * As it used to be - user can export mbeans with the {@link ObjectNameGenerator#defaultObjectNameGenerator() default strategy}, + * or bind their own generator to {@code ObjectNameGenerator.class} key (or via optional binder) + * + * @deprecated exists only to support deprecated legacy mode + */ + @Deprecated + LEGACY, + + /** + * This strategy forces user can export mbeans with the {@link ObjectNameGenerator#defaultObjectNameGenerator() default strategy}. + * If custom strategy is needed, {@link #EXPLICIT_NAMING} should be used. + * This strategy is suitable when MBeanModule is used in top level Guice context of an application. + */ + NO_NAMESPACE, + + /** + * This strategy requires that {@link ObjectNameGenerator} is separately bound. + * This strategy is suitable when MBeanModule is used in a library/module Guice context, + * where lack of namespacing may lead to name collisions. + */ + EXPLICIT_NAMING, + } + + private static class LegacyBindingGuiceMBeanExporterProvider + implements Provider + { + private final Set mappings; + private final Set> setMappings; + private final Set> mapMappings; + private final MBeanExporter exporter; + private final ObjectNameGenerator objectNameGenerator; + private final Injector injector; + + @Inject + public LegacyBindingGuiceMBeanExporterProvider( + Set mappings, + Set> setMappings, + Set> mapMappings, + MBeanExporter exporter, + Optional objectNameGenerator, + Injector injector) + { + this.mappings = requireNonNull(mappings, "mappings is null"); + this.setMappings = requireNonNull(setMappings, "setMappings is null"); + this.mapMappings = requireNonNull(mapMappings, "mapMappings is null"); + this.exporter = requireNonNull(exporter, "exporter is null"); + this.objectNameGenerator = objectNameGenerator.orElseGet(ObjectNameGenerator::defaultObjectNameGenerator); + this.injector = requireNonNull(injector, "injector is null"); + } + + @Override + public GuiceMBeanExporter get() + { + return new GuiceMBeanExporter(mappings, setMappings, mapMappings, exporter, objectNameGenerator, injector); + } + } + + private static class LegacyBindingMBeanExporterProvider + implements Provider + { + + private final MBeanServer server; + private final ObjectNameGenerator objectNameGenerator; + + @Inject + public LegacyBindingMBeanExporterProvider(MBeanServer server, Optional objectNameGenerator) + { + this.server = requireNonNull(server, "server is null"); + this.objectNameGenerator = objectNameGenerator.orElseGet(ObjectNameGenerator::defaultObjectNameGenerator); + } + + @Override + public MBeanExporter get() + { + return new MBeanExporter(server, objectNameGenerator); + } + } } diff --git a/src/test/java/org/weakref/jmx/guice/TestMBeanModule.java b/src/test/java/org/weakref/jmx/guice/TestMBeanModule.java index 0ee8bfe..6bdbd17 100644 --- a/src/test/java/org/weakref/jmx/guice/TestMBeanModule.java +++ b/src/test/java/org/weakref/jmx/guice/TestMBeanModule.java @@ -41,10 +41,38 @@ import static com.google.inject.Stage.PRODUCTION; import static com.google.inject.name.Names.named; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.weakref.jmx.ObjectNames.generatedNameOf; public class TestMBeanModule { + @Test + public void testLegacy() + { + Injector injector = Guice.createInjector( + new MBeanModule(), + binder -> binder.bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer())); + injector.getInstance(MBeanExporter.class); + } + + @Test + public void testWithUnnamespacedObjectNames() + { + Injector injector = Guice.createInjector( + MBeanModule.withUnnamespacedObjectNames(), + binder -> binder.bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer())); + injector.getInstance(MBeanExporter.class); + } + + @Test + public void testForCustomObjectNameGenerator() + { + assertThatThrownBy(() -> Guice.createInjector( + MBeanModule.forCustomObjectNameGenerator(), + binder -> binder.bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer()))) + .hasMessageContaining("No implementation for ObjectNameGenerator was bound"); + } + @Test public void testExportedInDevelopmentStageToo() throws Exception