You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jg...@apache.org on 2015/04/17 14:23:17 UTC
[1/2] tomee git commit: TOMEE-1547 adding test to ensure additional
properties are not leaked when creating resources using class-name
Repository: tomee
Updated Branches:
refs/heads/tomee-1.7.x 59437efcb -> 4c0e766d9
TOMEE-1547 adding test to ensure additional properties are not leaked when creating resources using class-name
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/c3d247a6
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/c3d247a6
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/c3d247a6
Branch: refs/heads/tomee-1.7.x
Commit: c3d247a671539e2cec081e840f09526a99ba6840
Parents: 59437ef
Author: Jonathan Gallimore <jo...@jrg.me.uk>
Authored: Fri Apr 17 11:05:17 2015 +0100
Committer: Jonathan Gallimore <jo...@jrg.me.uk>
Committed: Fri Apr 17 11:05:17 2015 +0100
----------------------------------------------------------------------
.../classic/ResourcePropertyLeakTest.java | 112 +++++++++++++++++++
1 file changed, 112 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/c3d247a6/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ResourcePropertyLeakTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ResourcePropertyLeakTest.java b/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ResourcePropertyLeakTest.java
new file mode 100644
index 0000000..e576e6c
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ResourcePropertyLeakTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.openejb.assembler.classic;
+
+import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;
+import org.apache.openejb.config.AppModule;
+import org.apache.openejb.config.EjbModule;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+import org.apache.openejb.testing.Configuration;
+import org.apache.openejb.testing.Module;
+import org.apache.openejb.testng.PropertiesBuilder;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.naming.NamingException;
+import java.util.Properties;
+
+
+/**
+ * This test ensures that additional properties are not leaked into the properties map when creating a resource
+ * using class-name, without a provider or type. When using "SkipImpliedAttributes" only the properties the
+ * user specified in their configuration should be available in the map.
+ *
+ * With "SkipImpliedAttributes" set to false (the default), ServiceId (the id of the resource itself) and transactionManager
+ * (the Geronimo Transaction Manager) are the only additional properties that should be available for resources to consume.
+ */
+@RunWith(ApplicationComposer.class)
+public class ResourcePropertyLeakTest {
+ @Test
+ public void testResourceProperties() throws NamingException {
+
+ final MyResource r1 = (MyResource) SystemInstance.get()
+ .getComponent(ContainerSystem.class).getJNDIContext().lookup("openejb/Resource/r1");
+
+ Assert.assertEquals(4, r1.properties.size());
+ Assert.assertTrue(r1.properties.containsKey("prop1"));
+ Assert.assertTrue(r1.properties.containsKey("prop2"));
+ Assert.assertTrue(r1.properties.containsKey("ServiceId"));
+ Assert.assertTrue(r1.properties.containsKey("transactionManager"));
+
+ Assert.assertEquals("value1", r1.properties.get("prop1"));
+ Assert.assertEquals("value2", r1.properties.get("prop2"));
+ Assert.assertEquals("r1", r1.properties.get("ServiceId"));
+ Assert.assertTrue(GeronimoTransactionManager.class.isInstance(r1.properties.get("transactionManager")));
+
+ // Resource 2 should not contain implied attributes
+ final MyResource r2 = (MyResource) SystemInstance.get()
+ .getComponent(ContainerSystem.class).getJNDIContext().lookup("openejb/Resource/r2");
+
+ Assert.assertEquals(2, r2.properties.size());
+ Assert.assertTrue(r2.properties.containsKey("prop1"));
+ Assert.assertTrue(r2.properties.containsKey("prop2"));
+ Assert.assertEquals("value1", r1.properties.get("prop1"));
+ Assert.assertEquals("value2", r1.properties.get("prop2"));
+
+ }
+
+ @Module
+ public AppModule application() {
+ final EjbModule ejbModule = new EjbModule(new EjbJar());
+
+ final AppModule appModule = new AppModule(Thread.currentThread().getContextClassLoader(), null);
+ appModule.getEjbModules().add(ejbModule);
+
+ return appModule;
+ }
+
+ @Configuration
+ public Properties config() {
+ return new PropertiesBuilder()
+ .p("r1", "new://Resource?class-name=org.apache.openejb.assembler.classic.ResourcePropertyLeakTest$MyResource")
+ .p("r1.prop1", "value1")
+ .p("r1.prop2", "value2")
+ .p("r2", "new://Resource?class-name=org.apache.openejb.assembler.classic.ResourcePropertyLeakTest$MyResource")
+ .p("r2.SkipImplicitAttributes", "true")
+ .p("r2.prop1", "value1")
+ .p("r2.prop2", "value2")
+ .build();
+ }
+
+ public static class MyResource {
+ private Properties properties;
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public void setProperties(final Properties properties) {
+ this.properties = properties;
+ }
+ }
+}
[2/2] tomee git commit: Iterate over properties and set values on
MBean as opposed to looping through fields using reflection. Demonstrate
SkipImplicitAttributes and using a prefix.
Posted by jg...@apache.org.
Iterate over properties and set values on MBean as opposed to looping through fields using reflection. Demonstrate SkipImplicitAttributes and using a prefix.
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/4c0e766d
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/4c0e766d
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/4c0e766d
Branch: refs/heads/tomee-1.7.x
Commit: 4c0e766d9c0114e3d9b85d86ca273e03637d3536
Parents: c3d247a
Author: Jonathan Gallimore <jo...@jrg.me.uk>
Authored: Fri Apr 17 13:20:31 2015 +0100
Committer: Jonathan Gallimore <jo...@jrg.me.uk>
Committed: Fri Apr 17 13:20:31 2015 +0100
----------------------------------------------------------------------
.../resource/jmx/factory/JMXBeanCreator.java | 114 ++++++++++++-------
.../resource/jmx/resources/Alternative.java | 110 +++++++++++++-----
.../src/main/resources/META-INF/resources.xml | 19 +++-
.../java/org/superbiz/resource/jmx/JMXTest.java | 19 +++-
4 files changed, 186 insertions(+), 76 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/4c0e766d/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/factory/JMXBeanCreator.java
----------------------------------------------------------------------
diff --git a/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/factory/JMXBeanCreator.java b/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/factory/JMXBeanCreator.java
index 311879c..14a21a6 100644
--- a/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/factory/JMXBeanCreator.java
+++ b/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/factory/JMXBeanCreator.java
@@ -19,48 +19,69 @@
package org.superbiz.resource.jmx.factory;
-import javax.management.InstanceAlreadyExistsException;
+import javax.management.Attribute;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
+import javax.management.StandardMBean;
import java.lang.management.ManagementFactory;
-import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
public class JMXBeanCreator {
+ private final Map<String, Class<?>> primitives = new HashMap<String, Class<?>>() {
+ {
+ put("boolean", Boolean.TYPE);
+ put("byte", Byte.TYPE);
+ put("char", Character.TYPE);
+ put("long", Long.TYPE);
+ put("float", Float.TYPE);
+ put("int", Integer.TYPE);
+ put("double", Double.TYPE);
+ put("short", Short.TYPE);
+ }
+ };
+
private static Logger LOGGER = Logger.getLogger(JMXBeanCreator.class.getName());
private Properties properties;
- public Object create() throws MBeanRegistrationException {
- // instantiate the bean
-
- final String code = properties.getProperty("code");
- final String name = properties.getProperty("name");
+ public <T> Object create() throws MBeanRegistrationException {
+ final String code = (String) properties.remove("code");
+ final String name = (String) properties.remove("name");
+ final String iface = (String) properties.remove("interface");
+ final String prefix = (String) properties.remove("prefix");
requireNotNull(code);
requireNotNull(name);
+ requireNotNull(iface);
try {
- final Class<?> cls = Class.forName(code, true, Thread.currentThread().getContextClassLoader());
- final Object instance = cls.newInstance();
-
- final Field[] fields = cls.getDeclaredFields();
- for (final Field field : fields) {
-
- final String property = properties.getProperty(field.getName());
- if (property == null) {
- continue;
+ final Class<? extends T> cls = (Class<? extends T>) Class.forName(code, true, Thread.currentThread().getContextClassLoader());
+ final Class<T> ifaceCls = (Class<T>) Class.forName(iface, true, Thread.currentThread().getContextClassLoader());
+ final T instance = (T) cls.newInstance();
+ final StandardMBean mBean = new StandardMBean(instance, ifaceCls);
+
+ for (Object property : properties.keySet()) {
+ String attributeName = (String) property;
+ final Object value = properties.getProperty(attributeName);
+
+ if (prefix != null) {
+ if (! attributeName.startsWith(prefix + ".")) {
+ continue;
+ } else {
+ attributeName = attributeName.substring(prefix.length() + 1);
+ }
}
- try {
- field.setAccessible(true);
- field.set(instance, Converter.convert(property, field.getType(), field.getName()));
- } catch (Exception e) {
- LOGGER.info(String.format("Unable to set value %s on field %s", property, field.getName()));
- }
+ final Class<?> targetType = findAttributeType(mBean.getMBeanInfo(), attributeName);
+ final Object targetValue = Converter.convert(value, targetType, null);
+
+ final Attribute attribute = new Attribute(attributeName, targetValue);
+ mBean.setAttribute(attribute);
}
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
@@ -69,30 +90,35 @@ public class JMXBeanCreator {
return instance;
- } catch (final ClassNotFoundException e) {
- LOGGER.severe("Unable to find class " + code);
- throw new MBeanRegistrationException(e);
- } catch (final InstantiationException e) {
- LOGGER.severe("Unable to create instance of class " + code);
- throw new MBeanRegistrationException(e);
- } catch (final IllegalAccessException e) {
- LOGGER.severe("Illegal access: " + code);
- throw new MBeanRegistrationException(e);
- } catch (final MalformedObjectNameException e) {
- LOGGER.severe("Malformed MBean name: " + name);
- throw new MBeanRegistrationException(e);
- } catch (final InstanceAlreadyExistsException e) {
- LOGGER.severe("Instance already exists: " + name);
- throw new MBeanRegistrationException(e);
- } catch (final NotCompliantMBeanException e) {
- LOGGER.severe("Class is not a valid MBean: " + code);
- throw new MBeanRegistrationException(e);
- } catch (final javax.management.MBeanRegistrationException e) {
- LOGGER.severe("Error registering " + name + ", " + code);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ LOGGER.severe("Unable to register mbean " + e.getMessage());
throw new MBeanRegistrationException(e);
}
}
+ private Class<?> findAttributeType(MBeanInfo mBeanInfo, String attributeName) {
+ try {
+ for (final MBeanAttributeInfo attribute : mBeanInfo.getAttributes()) {
+ if (attribute.getName().equals(attributeName)) {
+ return convertPrimitive(attribute.getType());
+ }
+ }
+
+ return null;
+ } catch (final ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ private Class<?> convertPrimitive(final String type) throws ClassNotFoundException {
+ if (primitives.containsKey(type)) {
+ return primitives.get(type);
+ }
+
+ return Class.forName(type, true, Thread.currentThread().getContextClassLoader());
+ }
+
private void requireNotNull(final String object) throws MBeanRegistrationException {
if (object == null) {
throw new MBeanRegistrationException("code property not specified, stopping");
http://git-wip-us.apache.org/repos/asf/tomee/blob/4c0e766d/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/resources/Alternative.java
----------------------------------------------------------------------
diff --git a/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/resources/Alternative.java b/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/resources/Alternative.java
index 546c53a..20799da 100644
--- a/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/resources/Alternative.java
+++ b/examples/resources-jmx-example/resources-jmx-ejb/src/main/java/org/superbiz/resource/jmx/resources/Alternative.java
@@ -19,75 +19,129 @@
package org.superbiz.resource.jmx.resources;
+import org.superbiz.resource.jmx.factory.Converter;
import org.superbiz.resource.jmx.factory.MBeanRegistrationException;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
-import javax.management.InstanceAlreadyExistsException;
+import javax.management.Attribute;
import javax.management.InstanceNotFoundException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
+import javax.management.StandardMBean;
import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
public class Alternative implements AlternativeMBean {
+ private final Map<String, Class<?>> primitives = new HashMap<String, Class<?>>() {
+ {
+ put("boolean", Boolean.TYPE);
+ put("byte", Byte.TYPE);
+ put("char", Character.TYPE);
+ put("long", Long.TYPE);
+ put("float", Float.TYPE);
+ put("int", Integer.TYPE);
+ put("double", Double.TYPE);
+ put("short", Short.TYPE);
+ }
+ };
+
private static Logger LOGGER = Logger.getLogger(Alternative.class.getName());
private Properties properties;
- @PostConstruct
- public void postConstruct() throws MBeanRegistrationException {
- // initialize the bean
-
- final String code = properties.getProperty("code");
+ @PreDestroy
+ public void preDestroy() throws MBeanRegistrationException {
final String name = properties.getProperty("name");
-
- requireNotNull(code);
requireNotNull(name);
try {
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName objectName = new ObjectName(name);
- mbs.registerMBean(this, objectName);
+ mbs.unregisterMBean(objectName);
} catch (final MalformedObjectNameException e) {
LOGGER.severe("Malformed MBean name: " + name);
throw new MBeanRegistrationException(e);
- } catch (final InstanceAlreadyExistsException e) {
- LOGGER.severe("Instance already exists: " + name);
- throw new MBeanRegistrationException(e);
- } catch (final NotCompliantMBeanException e) {
- LOGGER.severe("Class is not a valid MBean: " + code);
- throw new MBeanRegistrationException(e);
} catch (final javax.management.MBeanRegistrationException e) {
- LOGGER.severe("Error registering " + name + ", " + code);
+ LOGGER.severe("Error unregistering " + name);
+ throw new MBeanRegistrationException(e);
+ } catch (InstanceNotFoundException e) {
+ LOGGER.severe("Error unregistering " + name);
throw new MBeanRegistrationException(e);
}
}
- @PreDestroy
- public void preDestroy() throws MBeanRegistrationException {
+ @PostConstruct
+ public <T> void postConstruct() throws MBeanRegistrationException {
+
final String name = properties.getProperty("name");
+ final String iface = properties.getProperty("interface");
+ final String prefix = properties.getProperty("prefix");
+
requireNotNull(name);
+ requireNotNull(iface);
try {
+ final Class<T> ifaceCls = (Class<T>) Class.forName(iface, true, Thread.currentThread().getContextClassLoader());
+ final StandardMBean mBean = new StandardMBean((T) this, ifaceCls);
+
+ for (Object property : properties.keySet()) {
+ String attributeName = (String) property;
+ final Object value = properties.getProperty(attributeName);
+
+ if (prefix != null) {
+ if (! attributeName.startsWith(prefix + ".")) {
+ continue;
+ } else {
+ attributeName = attributeName.substring(prefix.length() + 1);
+ }
+ }
+
+ final Class<?> targetType = findAttributeType(mBean.getMBeanInfo(), attributeName);
+ final Object targetValue = Converter.convert(value, targetType, null);
+
+ final Attribute attribute = new Attribute(attributeName, targetValue);
+ mBean.setAttribute(attribute);
+ }
+
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName objectName = new ObjectName(name);
- mbs.unregisterMBean(objectName);
- } catch (final MalformedObjectNameException e) {
- LOGGER.severe("Malformed MBean name: " + name);
- throw new MBeanRegistrationException(e);
- } catch (final javax.management.MBeanRegistrationException e) {
- LOGGER.severe("Error unregistering " + name);
- throw new MBeanRegistrationException(e);
- } catch (InstanceNotFoundException e) {
- LOGGER.severe("Error unregistering " + name);
+ mbs.registerMBean(this, objectName);
+
+ } catch (final Exception e) {
+ LOGGER.severe("Unable to register mbean " + e.getMessage());
throw new MBeanRegistrationException(e);
}
}
+ private Class<?> findAttributeType(MBeanInfo mBeanInfo, String attributeName) {
+ try {
+ for (final MBeanAttributeInfo attribute : mBeanInfo.getAttributes()) {
+ if (attribute.getName().equals(attributeName)) {
+ return convertPrimitive(attribute.getType());
+ }
+ }
+
+ return null;
+ } catch (final ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ private Class<?> convertPrimitive(final String type) throws ClassNotFoundException {
+ if (primitives.containsKey(type)) {
+ return primitives.get(type);
+ }
+
+ return Class.forName(type, true, Thread.currentThread().getContextClassLoader());
+ }
+
private void requireNotNull(final String object) throws MBeanRegistrationException {
if (object == null) {
throw new MBeanRegistrationException("code property not specified, stopping");
http://git-wip-us.apache.org/repos/asf/tomee/blob/4c0e766d/examples/resources-jmx-example/resources-jmx-ejb/src/main/resources/META-INF/resources.xml
----------------------------------------------------------------------
diff --git a/examples/resources-jmx-example/resources-jmx-ejb/src/main/resources/META-INF/resources.xml b/examples/resources-jmx-example/resources-jmx-ejb/src/main/resources/META-INF/resources.xml
index 03bd9d0..54eda50 100644
--- a/examples/resources-jmx-example/resources-jmx-ejb/src/main/resources/META-INF/resources.xml
+++ b/examples/resources-jmx-example/resources-jmx-ejb/src/main/resources/META-INF/resources.xml
@@ -21,14 +21,27 @@
<Resources>
<Resource id="Hello" class-name="org.superbiz.resource.jmx.factory.JMXBeanCreator" factory-name="create">
code org.superbiz.resource.jmx.resources.Hello
+ interface org.superbiz.resource.jmx.resources.HelloMBean
name superbiz.test:name=Hello
- count 20
+ prefix mbean
+ mbean.Count 20
</Resource>
+ <!-- no prefix, but implied attributes are skipped, so additional properties should not appear in the map -->
+ <Resource id="Hello2" class-name="org.superbiz.resource.jmx.factory.JMXBeanCreator" factory-name="create">
+ code org.superbiz.resource.jmx.resources.Hello
+ interface org.superbiz.resource.jmx.resources.HelloMBean
+ name superbiz.test:name=Hello2
+ SkipImplicitAttributes true
+ Count 20
+ </Resource>
+
+
<Resource id="Alternative" class-name="org.superbiz.resource.jmx.resources.Alternative">
- code org.superbiz.resource.jmx.resources.Alternative
+ interface org.superbiz.resource.jmx.resources.AlternativeMBean
name superbiz.test:name=Alternative
- count 20
+ prefix mbean
+ mbean.Count 20
</Resource>
</Resources>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/4c0e766d/examples/resources-jmx-example/resources-jmx-ejb/src/test/java/org/superbiz/resource/jmx/JMXTest.java
----------------------------------------------------------------------
diff --git a/examples/resources-jmx-example/resources-jmx-ejb/src/test/java/org/superbiz/resource/jmx/JMXTest.java b/examples/resources-jmx-example/resources-jmx-ejb/src/test/java/org/superbiz/resource/jmx/JMXTest.java
index 42fc51f..9476cda 100644
--- a/examples/resources-jmx-example/resources-jmx-ejb/src/test/java/org/superbiz/resource/jmx/JMXTest.java
+++ b/examples/resources-jmx-example/resources-jmx-ejb/src/test/java/org/superbiz/resource/jmx/JMXTest.java
@@ -66,7 +66,7 @@ public class JMXTest {
}
@Test
- public void test() throws Exception {
+ public void testFactory() throws Exception {
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName objectName = new ObjectName("superbiz.test:name=Hello");
@@ -97,6 +97,23 @@ public class JMXTest {
}
@Test
+ public void testFactorySkipImpliedAttributes() throws Exception {
+ final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName objectName = new ObjectName("superbiz.test:name=Hello2");
+
+ Assert.assertEquals(20, mbs.getAttribute(objectName, "Count"));
+
+ mbs.invoke(objectName, "increment", new Object[0], new String[0]);
+ Assert.assertEquals(21, mbs.getAttribute(objectName, "Count"));
+
+ Attribute attribute = new Attribute("Count", 12345);
+ mbs.setAttribute(objectName, attribute);
+ Assert.assertEquals(12345, mbs.getAttribute(objectName, "Count"));
+
+ Assert.assertEquals("Hello, world", mbs.invoke(objectName, "greet", new Object[] { "world" }, new String[] { String.class.getName() }));
+ }
+
+ @Test
public void testPostConstruct() throws Exception {
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName objectName = new ObjectName("superbiz.test:name=Alternative");