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:18 UTC

[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.

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");