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 2018/09/14 15:22:36 UTC

[06/12] tomee git commit: Expose resource adapter and other resources, read-only, via JMX

Expose resource adapter and other resources, read-only, via JMX


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/c15931f2
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/c15931f2
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/c15931f2

Branch: refs/heads/master
Commit: c15931f2ad841709dbe98a994e99a6a1c05593a2
Parents: d18fbc0
Author: Jonathan Gallimore <jo...@jrg.me.uk>
Authored: Wed Sep 5 16:36:58 2018 +0100
Committer: Jonathan Gallimore <jo...@jrg.me.uk>
Committed: Wed Sep 5 16:36:58 2018 +0100

----------------------------------------------------------------------
 .../openejb/assembler/classic/Assembler.java    |  54 ++++---
 .../monitoring/ConnectionFactoryMonitor.java    |   2 -
 .../openejb/monitoring/MBeanPojoWrapper.java    | 162 +++++++++++++++++++
 3 files changed, 191 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/c15931f2/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
index 3b3d60f..1d45c08 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
@@ -178,11 +178,7 @@ import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.DefinitionException;
 import javax.enterprise.inject.spi.DeploymentException;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
+import javax.management.*;
 import javax.naming.Binding;
 import javax.naming.Context;
 import javax.naming.InitialContext;
@@ -3238,6 +3234,7 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
             unset.remove("threadPoolSize");
             logUnusedProperties(unset, serviceInfo);
 
+            registerAsMBean(serviceInfo.id, "ResourceAdapter", resourceAdapter);
             service = new ResourceAdapterReference(resourceAdapter, threadPool, OPENEJB_RESOURCE_JNDI_PREFIX + serviceInfo.id);
         } else if (service instanceof ManagedConnectionFactory) {
             final ManagedConnectionFactory managedConnectionFactory = (ManagedConnectionFactory) service;
@@ -3279,25 +3276,7 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
             }
 
             final ConnectionFactoryMonitor cfm = new ConnectionFactoryMonitor(serviceInfo.id, connectionManager, txSupport);
-
-            final MBeanServer server = LocalMBeanServer.get();
-
-            final ObjectNameBuilder jmxName = new ObjectNameBuilder("openejb.management");
-            jmxName.set("J2EEServer", "openejb");
-            jmxName.set("J2EEApplication", null);
-            jmxName.set("j2eeType", "");
-            jmxName.set("name",serviceInfo.id);
-
-            // register the invocation stats interceptor
-            try {
-                final ObjectName objectName = jmxName.set("j2eeType", "ConnectionFactory").build();
-                if (server.isRegistered(objectName)) {
-                    server.unregisterMBean(objectName);
-                }
-                server.registerMBean(new ManagedMBean(cfm), objectName);
-            } catch (final Exception e) {
-                logger.error("Unable to register MBean ", e);
-            }
+            registerAsMBean(serviceInfo.id, "ConnectionFactory", new ManagedMBean(cfm));
 
             if (connectionManager == null) {
                 throw new OpenEJBRuntimeException(messages.format("assembler.invalidConnectionManager", serviceInfo.id));
@@ -3372,7 +3351,7 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
                 logUnusedProperties(serviceRecipe, serviceInfo);
             } // else wait post construct
 
-            // TODO: create something to expose the properties of the object readonly through JMX
+            registerAsMBean(serviceInfo.id, "Resource", service);
         }
 
         final ResourceCreated event = new ResourceCreated(service, serviceInfo.id);
@@ -3380,6 +3359,31 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
         return event.getReplacement() == null ? service : event.getReplacement();
     }
 
+    private void registerAsMBean(final String name, final String type, Object resource) {
+        final MBeanServer server = LocalMBeanServer.get();
+
+        final ObjectNameBuilder jmxName = new ObjectNameBuilder("openejb.management");
+        jmxName.set("J2EEServer", "openejb");
+        jmxName.set("J2EEApplication", null);
+        jmxName.set("j2eeType", "");
+        jmxName.set("name", name);
+
+        try {
+            final ObjectName objectName = jmxName.set("j2eeType", type).build();
+            if (server.isRegistered(objectName)) {
+                server.unregisterMBean(objectName);
+            }
+
+            if (DynamicMBean.class.isInstance(resource)) {
+                server.registerMBean(resource, objectName);
+            } else {
+                server.registerMBean(new MBeanPojoWrapper(name, resource), objectName);
+            }
+        } catch (final Exception e) {
+            logger.error("Unable to register MBean ", e);
+        }
+    }
+
     private void bindResource(final String id, final Object service, final boolean canReplace) throws OpenEJBException {
         final String name = OPENEJB_RESOURCE_JNDI_PREFIX + id;
         final Context jndiContext = containerSystem.getJNDIContext();

http://git-wip-us.apache.org/repos/asf/tomee/blob/c15931f2/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ConnectionFactoryMonitor.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ConnectionFactoryMonitor.java b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ConnectionFactoryMonitor.java
index 2f57f89..3dad61f 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ConnectionFactoryMonitor.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ConnectionFactoryMonitor.java
@@ -86,8 +86,6 @@ public class ConnectionFactoryMonitor {
             return PartitionedPool.class.cast(pooling).isMatchAll();
         } else if (SinglePool.class.isInstance(pooling)) {
             return SinglePool.class.cast(pooling).isMatchAll();
-        } else if (NoPool.class.isInstance(pooling)) {
-            return false;
         } else {
             return false;
         }

http://git-wip-us.apache.org/repos/asf/tomee/blob/c15931f2/container/openejb-core/src/main/java/org/apache/openejb/monitoring/MBeanPojoWrapper.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/monitoring/MBeanPojoWrapper.java b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/MBeanPojoWrapper.java
new file mode 100644
index 0000000..70367f86
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/MBeanPojoWrapper.java
@@ -0,0 +1,162 @@
+package org.apache.openejb.monitoring;
+
+import org.apache.openejb.util.Duration;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.IntrospectionException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ReflectionException;
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/*
+ * This class attempts to wrap a given class by using Bean introspection to get a list of attributes.
+ * The intention of the MBean generated is to provide a read-only view of resources available in the server.
+ * At the present time, this wrapper does not provide write support for attributes, and does not support
+ * method invocation.
+ */
+public class MBeanPojoWrapper implements DynamicMBean {
+
+    private final Object delegate;
+    private final String name;
+    private MBeanInfo info;
+    private final Map<String, PropertyDescriptor> attributeMap = new HashMap<>();
+
+    private static final Set<Class<?>> SUPPORTED_PROPERTY_TYPES = new HashSet<Class<?>>() {
+        {
+            add(Integer.class);
+            add(Boolean.class);
+            add(Byte.class);
+            add(Short.class);
+            add(Float.class);
+            add(Long.class);
+            add(Double.class);
+            add(Integer.TYPE);
+            add(Boolean.TYPE);
+            add(Byte.TYPE);
+            add(Short.TYPE);
+            add(Float.TYPE);
+            add(Long.TYPE);
+            add(Double.TYPE);
+            add(String.class);
+            add(Duration.class);
+        }
+    };
+
+    public MBeanPojoWrapper(final String name, final Object delegate) {
+        this.name = name;
+        if (delegate == null) {
+            throw new NullPointerException("Delegate cannot be null");
+        }
+
+        this.delegate = delegate;
+        scan(delegate.getClass());
+    }
+
+    private void scan(Class clazz) {
+        final List<MBeanAttributeInfo> mBeanAttributeInfoList = new ArrayList<>();
+
+        try {
+            final BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
+
+            final PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
+
+            for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+                final String propertyName = propertyDescriptor.getName();
+                Class<?> propertyType = propertyDescriptor.getPropertyType();
+
+                if (! isSupported(propertyType)) {
+                    continue;
+                }
+
+                attributeMap.put(propertyName, propertyDescriptor);
+                try {
+                    mBeanAttributeInfoList.add(new MBeanAttributeInfo(propertyName, "", propertyDescriptor.getReadMethod(), null));
+                } catch (IntrospectionException e) {
+                    // no-op
+                }
+            }
+        } catch (java.beans.IntrospectionException e) {
+            // no-op
+        }
+
+        // default constructor is mandatory
+        info = new MBeanInfo(name,
+                "Auto-created by OpenEJB",
+                mBeanAttributeInfoList.toArray(new MBeanAttributeInfo[attributeMap.size()]),
+                null, // default constructor is mandatory
+                new MBeanOperationInfo[0],
+                new MBeanNotificationInfo[0]);
+    }
+
+    private static boolean isSupported(Class<?> type) {
+        return SUPPORTED_PROPERTY_TYPES.contains(type);
+    }
+
+
+    @Override
+    public Object getAttribute(final String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
+        if (! attributeMap.containsKey(attribute)) {
+            throw new AttributeNotFoundException();
+        }
+
+        try {
+            return attributeMap.get(attribute).getReadMethod().invoke(delegate);
+        } catch (IllegalAccessException e) {
+            throw new MBeanException(e);
+        } catch (InvocationTargetException e) {
+            throw new MBeanException(e);
+        }
+    }
+
+    @Override
+    public void setAttribute(final Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
+        // no-op
+    }
+
+    @Override
+    public AttributeList getAttributes(final String[] attributes) {
+        final AttributeList list = new AttributeList();
+        for (final String attribute : attributes) {
+            try {
+                list.add(new Attribute(attribute, getAttribute(attribute)));
+            } catch (final Exception ignore) {
+                // no-op
+            }
+        }
+        return list;
+    }
+
+    @Override
+    public AttributeList setAttributes(final AttributeList attributes) {
+        // no-op - not supported
+        return null;
+    }
+
+    @Override
+    public Object invoke(final String actionName, final Object[] params, final String[] signature) throws MBeanException, ReflectionException {
+        // no-op - not supported
+        return null;
+    }
+
+    @Override
+    public MBeanInfo getMBeanInfo() {
+        return info;
+    }
+}