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/17 10:04:43 UTC
tomee git commit: Apply Jonathan Gallimore's JMX Patch to 7.0.5
Repository: tomee
Updated Branches:
refs/heads/tomee-7.0.x e4ba57043 -> 03f34aa6c
Apply Jonathan Gallimore's JMX Patch to 7.0.5
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/03f34aa6
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/03f34aa6
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/03f34aa6
Branch: refs/heads/tomee-7.0.x
Commit: 03f34aa6c97272e747a4408a001cd5bc44652ee1
Parents: e4ba570
Author: Jonathan S. Fisher <ex...@gmail.com>
Authored: Sat Sep 15 10:26:42 2018 -0500
Committer: Jonathan S. Fisher <ex...@gmail.com>
Committed: Sat Sep 15 10:26:42 2018 -0500
----------------------------------------------------------------------
.../openejb/assembler/classic/Assembler.java | 87 ++++++++-
.../monitoring/ConnectionFactoryMonitor.java | 167 +++++++++++++++++
.../openejb/monitoring/MBeanPojoWrapper.java | 162 ++++++++++++++++
.../GeronimoConnectionManagerFactory.java | 30 +++
.../classic/ConnectionFactoryJMXTest.java | 133 ++++++++++++++
.../assembler/classic/ResourcesJMXTest.java | 184 +++++++++++++++++++
6 files changed, 756 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/03f34aa6/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 ac2d080..803744d 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
@@ -109,6 +109,7 @@ import org.apache.openejb.loader.ProvisioningUtil;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.monitoring.DynamicMBeanWrapper;
import org.apache.openejb.monitoring.LocalMBeanServer;
+import org.apache.openejb.monitoring.MBeanPojoWrapper;
import org.apache.openejb.monitoring.ObjectNameBuilder;
import org.apache.openejb.monitoring.remote.RemoteResourceMonitor;
import org.apache.openejb.observer.Observes;
@@ -178,11 +179,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;
@@ -2128,9 +2125,14 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
ExecutorService.class.cast(resourceAdapter.pool).shutdownNow();
}
resourceAdapter.ra.stop();
+
+ // remove associated JMX object
} catch (final Throwable t) {
logger.fatal("ResourceAdapter Shutdown Failed: " + name, t);
}
+
+ removeResourceMBean(name, "ResourceAdapter");
+
} else if (object instanceof ResourceAdapter) {
final ResourceAdapter resourceAdapter = (ResourceAdapter) object;
try {
@@ -2144,6 +2146,9 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
} catch (final Throwable t) {
logger.fatal("ResourceAdapter Shutdown Failed: " + name, t);
}
+
+ removeResourceMBean(name, "ResourceAdapter");
+
} else if (DataSourceFactory.knows(object)) {
logger.info("Closing DataSource: " + name);
@@ -2162,14 +2167,41 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
} catch (final Exception e) {
logger.debug("Not processing resource on destroy: " + className, e);
}
+
+ removeResourceMBean(name, "ConnectionFactory");
+
} else if (DestroyableResource.class.isInstance(object)) {
try {
DestroyableResource.class.cast(object).destroyResource();
} catch (final RuntimeException e) {
logger.error(e.getMessage(), e);
}
- } else if (logger.isDebugEnabled() && !DataSource.class.isInstance(object)) {
- logger.debug("Not processing resource on destroy: " + className);
+
+ removeResourceMBean(name, "Resource");
+ } else if (!DataSource.class.isInstance(object)) {
+ removeResourceMBean(name, "Resource");
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Not processing resource on destroy: " + className);
+ }
+ }
+ }
+
+ private void removeResourceMBean(String name, String type) {
+ final ObjectNameBuilder jmxName = new ObjectNameBuilder("openejb.management");
+ jmxName.set("J2EEServer", "openejb");
+ jmxName.set("J2EEApplication", null);
+ jmxName.set("j2eeType", "");
+ jmxName.set("name",name);
+
+ final MBeanServer server = LocalMBeanServer.get();
+ try {
+ final ObjectName objectName = jmxName.set("j2eeType", type).build();
+ if (server.isRegistered(objectName)) {
+ server.unregisterMBean(objectName);
+ }
+ } catch (final Exception e) {
+ logger.error("Unable to unregister MBean ", e);
}
}
@@ -3218,6 +3250,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;
@@ -3245,6 +3278,19 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
// create the connection manager
final ConnectionManager connectionManager = (ConnectionManager) connectionManagerRecipe.create();
+
+
+ String txSupport = "xa";
+ try {
+ txSupport = (String) connectionManagerRecipe.getProperty("transactionSupport");
+ } catch (Exception e) {
+ // ignore
+ }
+
+ if (txSupport == null || txSupport.trim().length() == 0) {
+ txSupport = "xa";
+ }
+
if (connectionManager == null) {
throw new OpenEJBRuntimeException(messages.format("assembler.invalidConnectionManager", serviceInfo.id));
}
@@ -3317,6 +3363,8 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
if (serviceInfo.unsetProperties == null || isTemplatizedResource(serviceInfo)) {
logUnusedProperties(serviceRecipe, serviceInfo);
} // else wait post construct
+
+ registerAsMBean(serviceInfo.id, "Resource", service);
}
final ResourceCreated event = new ResourceCreated(service, serviceInfo.id);
@@ -3324,6 +3372,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/03f34aa6/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
new file mode 100644
index 0000000..3dad61f
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ConnectionFactoryMonitor.java
@@ -0,0 +1,167 @@
+/*
+ * 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.monitoring;
+
+import org.apache.geronimo.connector.outbound.GenericConnectionManager;
+import org.apache.geronimo.connector.outbound.connectionmanagerconfig.NoPool;
+import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PartitionedPool;
+import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PoolingSupport;
+import org.apache.geronimo.connector.outbound.connectionmanagerconfig.SinglePool;
+
+public class ConnectionFactoryMonitor {
+
+ private final String name;
+ private final GenericConnectionManager connectionManager;
+ private final String txSupport;
+
+ public ConnectionFactoryMonitor(final String name, final GenericConnectionManager connectionManager, final String txSupport) {
+ this.name = name;
+ this.connectionManager = connectionManager;
+ this.txSupport = txSupport;
+ }
+
+ private PoolingSupport getPooling() {
+ return connectionManager.getPooling();
+ }
+
+ @Managed
+ public int getMaxSize() {
+ final PoolingSupport pooling = getPooling();
+
+ if (PartitionedPool.class.isInstance(pooling)) {
+ return PartitionedPool.class.cast(pooling).getMaxSize();
+ } else if (SinglePool.class.isInstance(pooling)) {
+ return SinglePool.class.cast(pooling).getMaxSize();
+ } else if (NoPool.class.isInstance(pooling)) {
+ return 0;
+ } else {
+ return 0;
+ }
+ }
+
+ @Managed
+ public int getMinSize() {
+ final PoolingSupport pooling = getPooling();
+
+ if (PartitionedPool.class.isInstance(pooling)) {
+ return 0;
+ } else if (SinglePool.class.isInstance(pooling)) {
+ return SinglePool.class.cast(pooling).getMinSize();
+ } else if (NoPool.class.isInstance(pooling)) {
+ return 0;
+ } else {
+ return 0;
+ }
+ }
+
+ @Managed
+ public int getBlockingTimeoutMilliseconds() {
+ return connectionManager.getBlockingTimeoutMilliseconds();
+ }
+
+ @Managed
+ public int getIdleTimeoutMinutes() {
+ return connectionManager.getIdleTimeoutMinutes();
+ }
+
+ @Managed
+ public boolean isMatchAll() {
+ final PoolingSupport pooling = getPooling();
+
+ if (PartitionedPool.class.isInstance(pooling)) {
+ return PartitionedPool.class.cast(pooling).isMatchAll();
+ } else if (SinglePool.class.isInstance(pooling)) {
+ return SinglePool.class.cast(pooling).isMatchAll();
+ } else {
+ return false;
+ }
+ }
+
+ @Managed
+ public String getPartitionStrategy() {
+ final PoolingSupport pooling = getPooling();
+
+ if (PartitionedPool.class.isInstance(pooling)) {
+ if (PartitionedPool.class.cast(pooling).isPartitionByConnectionRequestInfo()) {
+ return PartitionStrategy.BY_CONNECTOR_PROPERTIES.toString();
+ }
+
+ if (PartitionedPool.class.cast(pooling).isPartitionBySubject()) {
+ return PartitionStrategy.BY_SUBJECT.toString();
+ }
+
+ return PartitionStrategy.UNKNOWN.toString();
+ } else if (SinglePool.class.isInstance(pooling)) {
+ return PartitionStrategy.NONE.toString();
+ } else if (NoPool.class.isInstance(pooling)) {
+ return PartitionStrategy.NONE.toString();
+ } else {
+ return PartitionStrategy.NONE.toString();
+ }
+ }
+
+ @Managed
+ public String getTxSupport() {
+ return txSupport;
+ }
+
+ @Managed
+ public int getPartitionCount() {
+ return connectionManager.getPartitionCount();
+ }
+
+ @Managed
+ public int getPartitionMaxSize() {
+ return connectionManager.getPartitionMaxSize();
+ }
+
+ @Managed
+ public int getPartitionMinSize() {
+ return connectionManager.getPartitionMinSize();
+ }
+
+ @Managed
+ public int getIdleConnectionCount() {
+ return connectionManager.getIdleConnectionCount();
+ }
+
+ @Managed
+ public int getConnectionCount() {
+ return connectionManager.getConnectionCount();
+ }
+
+ @Managed
+ public String getName() {
+ return name;
+ }
+
+ public enum PartitionStrategy {
+ NONE("none"), BY_SUBJECT("by-subject"), BY_CONNECTOR_PROPERTIES("by-connector-properties"), UNKNOWN("unknown");
+
+ private final String name;
+
+ PartitionStrategy(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/03f34aa6/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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/03f34aa6/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
index cebe9cc..852dc32 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
@@ -38,9 +38,17 @@ import org.apache.geronimo.connector.outbound.connectionmanagerconfig.XATransact
import org.apache.geronimo.transaction.manager.NamedXAResourceFactory;
import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
import org.apache.openejb.OpenEJBRuntimeException;
+import org.apache.openejb.monitoring.ConnectionFactoryMonitor;
+import org.apache.openejb.monitoring.LocalMBeanServer;
+import org.apache.openejb.monitoring.ManagedMBean;
+import org.apache.openejb.monitoring.ObjectNameBuilder;
import org.apache.openejb.util.Duration;
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
import org.apache.openejb.util.reflection.Reflections;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
import javax.resource.ResourceException;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionFactory;
@@ -64,6 +72,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
public class GeronimoConnectionManagerFactory {
+ private final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, GeronimoConnectionManagerFactory.class);
private String name;
private ClassLoader classLoader;
@@ -260,6 +269,27 @@ public class GeronimoConnectionManagerFactory {
mcf, name, classLoader);
}
+
+ final ConnectionFactoryMonitor cfm = new ConnectionFactoryMonitor(name, mgr, transactionSupport);
+ 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", "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);
+ }
+
return mgr;
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/03f34aa6/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ConnectionFactoryJMXTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ConnectionFactoryJMXTest.java b/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ConnectionFactoryJMXTest.java
new file mode 100644
index 0000000..5490fa7
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ConnectionFactoryJMXTest.java
@@ -0,0 +1,133 @@
+/**
+ *
+ * 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 junit.framework.TestCase;
+import org.apache.openejb.OpenEJB;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.config.EjbModule;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.StatelessBean;
+import org.apache.openejb.client.LocalInitialContextFactory;
+import org.apache.openejb.monitoring.LocalMBeanServer;
+
+import javax.annotation.Resource;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import java.util.Properties;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConnectionFactoryJMXTest extends TestCase {
+
+ public void test() throws Exception {
+ final ConfigurationFactory config = new ConfigurationFactory();
+ final Assembler assembler = new Assembler();
+
+ // System services
+ assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+ assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+ assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+ // Fake connection factory
+ assembler.createResource(config.configureService("Default JMS Resource Adapter", ResourceInfo.class));
+ final ResourceInfo resourceInfo = config.configureService("Default JMS Connection Factory", ResourceInfo.class);
+ resourceInfo.id = "CF";
+ resourceInfo.properties.setProperty("TransactionSupport", "xa");
+ resourceInfo.properties.setProperty("MaxConnections", "5");
+ assembler.createResource(resourceInfo);
+
+ // generate ejb jar application
+ final EjbJar ejbJar = new EjbJar();
+ ejbJar.addEnterpriseBean(new StatelessBean("fakeBean", FakeStatelessBean.class));
+ final EjbModule ejbModule = new EjbModule(getClass().getClassLoader(), "FakeEjbJar", "fake.jar", ejbJar, null);
+
+ // configure and deploy it
+ final EjbJarInfo info = config.configureApplication(ejbModule);
+ assembler.createEjbJar(info);
+
+ check(new ObjectName("openejb.management:J2EEServer=openejb,J2EEApplication=<empty>,j2eeType=ConnectionFactory,name=CF"), 0, 0);
+
+ final Properties p = new Properties();
+ p.setProperty(Context.INITIAL_CONTEXT_FACTORY, LocalInitialContextFactory.class.getName());
+ final FakeStateless fakeBeanLocal = (FakeStateless) new InitialContext(p).lookup("fakeBeanLocal");
+ fakeBeanLocal.doIt();
+
+ OpenEJB.destroy();
+
+ // ensure the bean is removed when the resource is undeployed
+ assertFalse(LocalMBeanServer.get().isRegistered(new ObjectName("openejb.management:J2EEServer=openejb,J2EEApplication=<empty>,j2eeType=ConnectionFactory,name=CF")));
+ }
+
+ private static void check(ObjectName on, final int connectionCount, final int idleCount) throws InstanceNotFoundException, IntrospectionException, ReflectionException, MBeanException, AttributeNotFoundException {
+ assertNotNull(LocalMBeanServer.get().getMBeanInfo(on));
+
+ assertEquals(5000, LocalMBeanServer.get().getAttribute(on, "BlockingTimeoutMilliseconds"));
+ assertEquals(connectionCount, LocalMBeanServer.get().getAttribute(on, "ConnectionCount"));
+ assertEquals(idleCount, LocalMBeanServer.get().getAttribute(on, "IdleConnectionCount"));
+ assertEquals(15, LocalMBeanServer.get().getAttribute(on, "IdleTimeoutMinutes"));
+ assertEquals(false, LocalMBeanServer.get().getAttribute(on, "MatchAll"));
+ assertEquals(10, LocalMBeanServer.get().getAttribute(on, "MaxSize"));
+ assertEquals(0, LocalMBeanServer.get().getAttribute(on, "MinSize"));
+ assertEquals("CF", LocalMBeanServer.get().getAttribute(on, "Name"));
+ assertEquals(1, LocalMBeanServer.get().getAttribute(on, "PartitionCount"));
+ assertEquals(10, LocalMBeanServer.get().getAttribute(on, "PartitionMaxSize"));
+ assertEquals(0, LocalMBeanServer.get().getAttribute(on, "PartitionMinSize"));
+ assertEquals("none", LocalMBeanServer.get().getAttribute(on, "PartitionStrategy"));
+ assertEquals("xa", LocalMBeanServer.get().getAttribute(on, "TxSupport"));
+ }
+
+ public interface FakeStateless {
+ public void doIt();
+ }
+
+ public static class FakeStatelessBean implements FakeStateless {
+
+ @Resource
+ private ConnectionFactory cf;
+
+ @Override
+ public void doIt() {
+ try {
+ final Connection connection = cf.createConnection();
+
+ // check we see the connection and it is not idle
+ check(
+ new ObjectName("openejb.management:J2EEServer=openejb,J2EEApplication=<empty>,j2eeType=ConnectionFactory,name=CF"),
+ 1,
+ 0
+ );
+
+ connection.close();
+ } catch (Exception e) {
+ fail("Unexpected exception thrown " + e);
+ }
+
+
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/03f34aa6/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ResourcesJMXTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ResourcesJMXTest.java b/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ResourcesJMXTest.java
new file mode 100644
index 0000000..6b81600
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ResourcesJMXTest.java
@@ -0,0 +1,184 @@
+/**
+ *
+ * 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 junit.framework.TestCase;
+import org.apache.openejb.OpenEJB;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.monitoring.LocalMBeanServer;
+
+import javax.management.*;
+import javax.resource.ResourceException;
+import javax.resource.spi.*;
+import javax.resource.spi.endpoint.MessageEndpoint;
+import javax.resource.spi.endpoint.MessageEndpointFactory;
+import javax.transaction.xa.XAResource;
+import java.util.Properties;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ResourcesJMXTest extends TestCase {
+ public void test() throws Exception {
+ final ConfigurationFactory config = new ConfigurationFactory();
+ final Assembler assembler = new Assembler();
+
+ // System services
+ assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+ assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+ assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+ // FakeRA
+ final ResourceInfo resourceInfo = new ResourceInfo();
+ resourceInfo.service = "Resource";
+ resourceInfo.className = FakeRA.class.getName();
+ resourceInfo.id = "FakeRA";
+ resourceInfo.properties = new Properties();
+ assembler.createResource(resourceInfo);
+
+ // FakeRA container
+ final ContainerInfo containerInfo = config.configureService(MdbContainerInfo.class);
+ containerInfo.id = "FakeContainer";
+ containerInfo.displayName = "Fake Container";
+ containerInfo.properties.setProperty("ResourceAdapter", "FakeRA");
+ containerInfo.properties.setProperty("MessageListenerInterface", FakeMessageListener.class.getName());
+ containerInfo.properties.setProperty("ActivationSpecClass", FakeActivationSpec.class.getName());
+ assembler.createContainer(containerInfo);
+
+ final ResourceInfo testResource = new ResourceInfo();
+ testResource.id = "testResource";
+ testResource.className = FakeResource.class.getName();
+
+ final Properties p = new Properties();
+ p.put("host", "localhost");
+ p.put("port", "12345");
+ p.put("parameter", "test param");
+ testResource.properties = p;
+
+ assembler.createResource(testResource);
+
+ {
+ ObjectName on = new ObjectName("openejb.management:J2EEServer=openejb,J2EEApplication=<empty>,j2eeType=ResourceAdapter,name=FakeRA");
+ assertNotNull(LocalMBeanServer.get().getMBeanInfo(on));
+ assertEquals("faketest", LocalMBeanServer.get().getAttribute(on, "name"));
+ assertEquals(10, LocalMBeanServer.get().getAttribute(on, "priority"));
+ }
+ {
+ ObjectName on = new ObjectName("openejb.management:J2EEServer=openejb,J2EEApplication=<empty>,j2eeType=Resource,name=testResource");
+ assertNotNull(LocalMBeanServer.get().getMBeanInfo(on));
+ assertEquals("localhost", LocalMBeanServer.get().getAttribute(on, "host"));
+ assertEquals(12345, LocalMBeanServer.get().getAttribute(on, "port"));
+ assertEquals("test param", LocalMBeanServer.get().getAttribute(on, "parameter"));
+ }
+
+ OpenEJB.destroy();
+
+ assertFalse(LocalMBeanServer.get().isRegistered(new ObjectName("openejb.management:J2EEServer=openejb,J2EEApplication=<empty>,j2eeType=ResourceAdapter,name=FakeRA")));
+ assertFalse(LocalMBeanServer.get().isRegistered(new ObjectName("openejb.management:J2EEServer=openejb,J2EEApplication=<empty>,j2eeType=Resource,name=testResource")));
+ }
+
+ public interface FakeMessageListener {
+ void doIt(Properties properties);
+ }
+
+ public static class FakeRA implements ResourceAdapter {
+
+ private String name = "faketest";
+ private int priority = 10;
+
+
+ public void start(final BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {
+ }
+
+ public void stop() {
+ }
+
+ public void endpointActivation(final MessageEndpointFactory messageEndpointFactory, final ActivationSpec activationSpec) throws ResourceException {
+ final MessageEndpoint endpoint = messageEndpointFactory.createEndpoint(null);
+ }
+
+ public void endpointDeactivation(final MessageEndpointFactory messageEndpointFactory, final ActivationSpec activationSpec) {
+ }
+
+ public XAResource[] getXAResources(final ActivationSpec[] activationSpecs) throws ResourceException {
+ return new XAResource[0];
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+ }
+
+ public static class FakeActivationSpec implements ActivationSpec {
+ private FakeRA fakeRA;
+
+ public void validate() throws InvalidPropertyException {
+ }
+
+ public FakeRA getResourceAdapter() {
+ return fakeRA;
+ }
+
+ public void setResourceAdapter(final ResourceAdapter resourceAdapter) {
+ this.fakeRA = (FakeRA) resourceAdapter;
+ }
+ }
+
+ public static class FakeResource {
+ private String host;
+ private int port;
+ private String parameter;
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getParameter() {
+ return parameter;
+ }
+
+ public void setParameter(String parameter) {
+ this.parameter = parameter;
+ }
+ }
+
+}