From f92ebea9f0512a03c26bb94f5bbe2715bc909ee6 Mon Sep 17 00:00:00 2001 From: Jesse McConnell Date: Fri, 10 Aug 2012 10:29:09 -0500 Subject: [PATCH] updates to managed attribute, tests, objectmbean impl and a note to improve id as viewed in jconsole --- .../org/eclipse/jetty/jmx/MBeanContainer.java | 2 + .../org/eclipse/jetty/jmx/ObjectMBean.java | 206 +++++++----------- .../eclipse/jetty/util/log/jmx/LogMBean.java | 14 +- jetty-jmx/src/test/java/com/acme/Derived.java | 4 +- jetty-jmx/src/test/java/com/acme/Managed.java | 8 +- .../test/java/com/acme/jmx/ManagedMBean.java | 3 +- .../eclipse/jetty/jmx/ObjectMBeanTest.java | 111 ++++++++-- .../util/annotation/ManagedAttribute.java | 13 +- .../util/component/AbstractLifeCycle.java | 7 +- .../jetty/util/thread/QueuedThreadPool.java | 23 +- .../eclipse/jetty/util/thread/ThreadPool.java | 6 + 11 files changed, 236 insertions(+), 161 deletions(-) diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java index 8961a3e6452..4d681e0d2f5 100644 --- a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java +++ b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java @@ -228,6 +228,8 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste * Implementation of Container.Listener interface * * @see org.eclipse.jetty.util.component.Container.Listener#addBean(java.lang.Object) + * + * TODO improve the id property to include better information */ public synchronized void addBean(Object obj) { diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java index f4601775a57..ffaeb33bacb 100644 --- a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java +++ b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java @@ -75,10 +75,10 @@ public class ObjectMBean implements DynamicMBean protected Object _managed; private MBeanInfo _info; - private Map _getters=new HashMap(); - private Map _setters=new HashMap(); - private Map _methods=new HashMap(); - private Set _convert=new HashSet(); + private Map _getters=new HashMap(); + private Map _setters=new HashMap(); + private Map _methods=new HashMap(); + private Set _convert=new HashSet(); private ClassLoader _loader; private MBeanContainer _mbeanContainer; @@ -261,19 +261,6 @@ public class ObjectMBean implements DynamicMBean continue; } - // Process Field Annotations - for (Field field : oClass.getDeclaredFields()) - { - LOG.debug("Checking: " + field.getName()); - ManagedAttribute fieldAnnotation = field.getAnnotation(ManagedAttribute.class); - - if (fieldAnnotation != null) - { - LOG.debug("Field Annotation found for: " + field.getName()); - attributes.add(defineAttribute(field.getName(),fieldAnnotation)); - } - } - // Process Method Annotations for (Method method : oClass.getDeclaredMethods()) @@ -284,7 +271,7 @@ public class ObjectMBean implements DynamicMBean { // TODO sort out how a proper name could get here, its a method name as an attribute at this point. LOG.debug("Attribute Annotation found for: " + method.getName()); - attributes.add(defineAttribute(method.getName(),methodAttributeAnnotation)); + attributes.add(defineAttribute(method,methodAttributeAnnotation)); } ManagedOperation methodOperationAnnotation = method.getAnnotation(ManagedOperation.class); @@ -572,119 +559,80 @@ public class ObjectMBean implements DynamicMBean * * the access is either "RW" or "RO". */ - public MBeanAttributeInfo defineAttribute(String name, ManagedAttribute attributeAnnotation) + public MBeanAttributeInfo defineAttribute(Method method, ManagedAttribute attributeAnnotation) { - //String name = field.getName(); + // determine the name of the managed attribute + String name = attributeAnnotation.name(); + + if ("".equals(name)) + { + name = toVariableName(method.getName()); + } + String description = attributeAnnotation.value(); - boolean writable = !attributeAnnotation.readonly(); + boolean readonly = attributeAnnotation.readonly(); boolean onMBean = attributeAnnotation.proxied(); boolean convert = attributeAnnotation.managed(); String uName = name.substring(0, 1).toUpperCase() + name.substring(1); - Class oClass = onMBean ? this.getClass() : _managed.getClass(); + Class oClass = onMBean ? this.getClass() : _managed.getClass(); - LOG.debug("defineAttribute {} {}:{}:{}:{}",name,onMBean,writable,oClass,description); + LOG.debug("defineAttribute {} {}:{}:{}:{}",name,onMBean,readonly,oClass,description); - Class type = null; - Method getter = null; + Class type = null; Method setter = null; + + type = method.getReturnType(); - String declaredGetter = attributeAnnotation.getter(); - String declaredSetter = attributeAnnotation.setter(); - - - Method[] methods = oClass.getMethods(); - for (int m = 0; m < methods.length; m++) + + // dig out a setter if one exists + if (!readonly) { - if ((methods[m].getModifiers() & Modifier.PUBLIC) == 0) - continue; + String declaredSetter = attributeAnnotation.setter(); - // Check if it is a declared getter - if (methods[m].getName().equals(declaredGetter) && methods[m].getParameterTypes().length == 0) + LOG.debug("DeclaredSetter:" + declaredSetter); + Method[] methods = oClass.getMethods(); + for (int m = 0; m < methods.length; m++) { - if (getter != null) - { - LOG.warn("Multiple mbean getters for attr " + name+ " in "+oClass); + if ((methods[m].getModifiers() & Modifier.PUBLIC) == 0) continue; - } - getter = methods[m]; - if (type != null && !type.equals(methods[m].getReturnType())) + + if (!"".equals(declaredSetter)) { - LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass); - continue; + + // look for a declared setter + if (methods[m].getName().equals(declaredSetter) && methods[m].getParameterTypes().length == 1) + { + if (setter != null) + { + LOG.warn("Multiple setters for mbean attr " + name + " in " + oClass); + continue; + } + setter = methods[m]; + if ( !type.equals(methods[m].getParameterTypes()[0])) + { + LOG.warn("Type conflict for mbean attr " + name + " in " + oClass); + continue; + } + LOG.debug("Declared Setter: " + declaredSetter); + } } - type = methods[m].getReturnType(); - LOG.debug("Declared Getter: " + declaredGetter); - } - - // Look for a getter - if (methods[m].getName().equals("get" + uName) && methods[m].getParameterTypes().length == 0) - { - if (getter != null) + // look for a setter + if ( methods[m].getName().equals("set" + uName) && methods[m].getParameterTypes().length == 1) { - LOG.warn("Multiple mbean getters for attr " + name+ " in "+oClass); - continue; - } - getter = methods[m]; - if (type != null && !type.equals(methods[m].getReturnType())) - { - LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass); - continue; - } - type = methods[m].getReturnType(); - } - - // Look for an is getter - if (methods[m].getName().equals("is" + uName) && methods[m].getParameterTypes().length == 0) - { - if (getter != null) - { - LOG.warn("Multiple mbean getters for attr " + name+ " in "+oClass); - continue; - } - getter = methods[m]; - if (type != null && !type.equals(methods[m].getReturnType())) - { - LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass); - continue; - } - type = methods[m].getReturnType(); - } - - // look for a declared setter - if (writable && methods[m].getName().equals(declaredSetter) && methods[m].getParameterTypes().length == 1) - { - if (setter != null) - { - LOG.warn("Multiple setters for mbean attr " + name+ " in "+oClass); - continue; - } - setter = methods[m]; - if (type != null && !type.equals(methods[m].getParameterTypes()[0])) - { - LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass); - continue; - } - LOG.debug("Declared Setter: " + declaredSetter); - type = methods[m].getParameterTypes()[0]; - } - - // look for a setter - if (writable && methods[m].getName().equals("set" + uName) && methods[m].getParameterTypes().length == 1) - { - if (setter != null) - { - LOG.warn("Multiple setters for mbean attr " + name+ " in "+oClass); - continue; + if (setter != null) + { + LOG.warn("Multiple setters for mbean attr " + name + " in " + oClass); + continue; + } + setter = methods[m]; + if ( !type.equals(methods[m].getParameterTypes()[0])) + { + LOG.warn("Type conflict for mbean attr " + name + " in " + oClass); + continue; + } } - setter = methods[m]; - if (type != null && !type.equals(methods[m].getParameterTypes()[0])) - { - LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass); - continue; - } - type = methods[m].getParameterTypes()[0]; } } @@ -704,16 +652,10 @@ public class ObjectMBean implements DynamicMBean LOG.debug("passed convert checks {} for type {}", name, type); } - if (getter == null && setter == null) - { - LOG.warn("No mbean getter or setters found for {} in {}", name, oClass); - return null; - } - try { // Remember the methods - _getters.put(name, getter); + _getters.put(name, method); _setters.put(name, setter); MBeanAttributeInfo info=null; @@ -723,16 +665,16 @@ public class ObjectMBean implements DynamicMBean if (type.isArray()) { - info= new MBeanAttributeInfo(name,OBJECT_NAME_ARRAY_CLASS,description,getter!=null,setter!=null,getter!=null&&getter.getName().startsWith("is")); + info= new MBeanAttributeInfo(name,OBJECT_NAME_ARRAY_CLASS,description,true,setter!=null,method.getName().startsWith("is")); } else { - info= new MBeanAttributeInfo(name,OBJECT_NAME_CLASS,description,getter!=null,setter!=null,getter!=null&&getter.getName().startsWith("is")); + info= new MBeanAttributeInfo(name,OBJECT_NAME_CLASS,description,true,setter!=null,method.getName().startsWith("is")); } } else { - info= new MBeanAttributeInfo(name,description,getter,setter); + info= new MBeanAttributeInfo(name,description,method,setter); } return info; @@ -834,5 +776,25 @@ public class ObjectMBean implements DynamicMBean } } + + + protected String toVariableName( String methodName ) + { + String variableName = methodName; + + if ( methodName.startsWith("get") || methodName.startsWith("set") ) + { + variableName = variableName.substring(3); + } + else if ( methodName.startsWith("is") ) + { + variableName = variableName.substring(2); + } + + variableName = variableName.substring(0,1).toLowerCase() + variableName.substring(1); + + return variableName; + } + } diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/util/log/jmx/LogMBean.java b/jetty-jmx/src/main/java/org/eclipse/jetty/util/log/jmx/LogMBean.java index b5fa44b9c8e..415f7c90865 100644 --- a/jetty-jmx/src/main/java/org/eclipse/jetty/util/log/jmx/LogMBean.java +++ b/jetty-jmx/src/main/java/org/eclipse/jetty/util/log/jmx/LogMBean.java @@ -17,11 +17,16 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.jmx.ObjectMBean; +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedObject; +import org.eclipse.jetty.util.annotation.ManagedOperation; +import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.log.Log; /* ------------------------------------------------------------ */ /** */ +@ManagedObject("Jetty Logging") public class LogMBean extends ObjectMBean { @@ -30,18 +35,21 @@ public class LogMBean extends ObjectMBean super(managedObject); } + @ManagedAttribute(value="list of instantiated loggers") public List getLoggers() { List keySet = new ArrayList(Log.getLoggers().keySet()); return keySet; } - public boolean isDebugEnabled(String logger) + @ManagedOperation(value="true if debug enabled for the given logger") + public boolean isDebugEnabled(@Name("logger") String logger) { return Log.getLogger(logger).isDebugEnabled(); } - - public void setDebugEnabled(String logger, Boolean enabled) + + @ManagedOperation(value="Set debug enabled for given logger") + public void setDebugEnabled(@Name("logger")String logger, @Name("enabled") Boolean enabled) { Log.getLogger(logger).setDebugEnabled(enabled); } diff --git a/jetty-jmx/src/test/java/com/acme/Derived.java b/jetty-jmx/src/test/java/com/acme/Derived.java index 4fc9f73627a..49fdf0a66d0 100644 --- a/jetty-jmx/src/test/java/com/acme/Derived.java +++ b/jetty-jmx/src/test/java/com/acme/Derived.java @@ -21,12 +21,11 @@ import org.eclipse.jetty.util.annotation.Name; @ManagedObject(value="Test the mbean stuff", wrapper="com.acme.jmx.DerivedMBean") public class Derived extends Base implements Signature { - @ManagedAttribute(value="The full name of something", getter="getFullName", setter="setFullName") String fname="Full Name"; - @ManagedAttribute( value="sample managed object") Managed managedInstance = new Managed(); + @ManagedAttribute(value="The full name of something", name="fname", setter="setFullName") public String getFullName() { return fname; @@ -54,6 +53,7 @@ public class Derived extends Base implements Signature return "bad"; } + @ManagedAttribute( value="sample managed object") public Managed getManagedInstance() { return managedInstance; diff --git a/jetty-jmx/src/test/java/com/acme/Managed.java b/jetty-jmx/src/test/java/com/acme/Managed.java index 8cc83370142..e79ad5a3462 100644 --- a/jetty-jmx/src/test/java/com/acme/Managed.java +++ b/jetty-jmx/src/test/java/com/acme/Managed.java @@ -6,9 +6,9 @@ import org.eclipse.jetty.util.annotation.ManagedObject; @ManagedObject(value="Managed Object", wrapper="com.acme.jmx.ManagedMBean") public class Managed { - @ManagedAttribute("Managed Attribute") String managed = "foo"; + @ManagedAttribute("Managed Attribute") public String getManaged() { return managed; @@ -19,4 +19,10 @@ public class Managed this.managed = managed; } + + public String bad() + { + return "bad"; + } + } diff --git a/jetty-jmx/src/test/java/com/acme/jmx/ManagedMBean.java b/jetty-jmx/src/test/java/com/acme/jmx/ManagedMBean.java index c78145e0b44..f71bf0c5b8e 100644 --- a/jetty-jmx/src/test/java/com/acme/jmx/ManagedMBean.java +++ b/jetty-jmx/src/test/java/com/acme/jmx/ManagedMBean.java @@ -6,6 +6,7 @@ import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedOperation; import com.acme.Derived; +import com.acme.Managed; @ManagedObject("Managed MBean Wrapper") public class ManagedMBean extends ObjectMBean @@ -18,7 +19,7 @@ public class ManagedMBean extends ObjectMBean @ManagedOperation(value="test of proxy operations", managed=true) public String good() { - return "not " + ((Derived)_managed).bad(); + return "not managed " + ((Managed)_managed).bad(); } @ManagedAttribute(value="test of proxy attributes", getter="goop", proxied=true) diff --git a/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java b/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java index a97562b8b83..8ce6d736eca 100644 --- a/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java +++ b/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java @@ -1,4 +1,4 @@ -// ======================================================================== +// =====7=================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials @@ -25,7 +25,10 @@ import junit.framework.Assert; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -39,15 +42,15 @@ public class ObjectMBeanTest private static MBeanContainer container; - @BeforeClass - public static void beforeClass() throws Exception + @Before + public void beforeClass() throws Exception { container = new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); container.start(); } - @AfterClass - public static void afterClass() throws Exception + @After + public void afterClass() throws Exception { container.stop(); container = null; @@ -57,7 +60,7 @@ public class ObjectMBeanTest * this test uses the com.acme.Derived test classes */ @Test - public void testMbeanInfo() throws Exception + public void testDerivedAttributes() throws Exception { Derived derived = new Derived(); @@ -67,8 +70,8 @@ public class ObjectMBeanTest mbean.setMBeanContainer(container); managed.setMBeanContainer(container); - container.addBean(mbean); - container.addBean(managed); + container.addBean(derived); + container.addBean(derived.getManagedInstance()); MBeanInfo toss = managed.getMBeanInfo(); @@ -79,15 +82,15 @@ public class ObjectMBeanTest Assert.assertEquals("name does not match", "com.acme.Derived", info.getClassName()); Assert.assertEquals("description does not match", "Test the mbean stuff", info.getDescription()); - for ( MBeanAttributeInfo i : info.getAttributes()) - { - LOG.debug(i.toString()); - } + //for ( MBeanAttributeInfo i : info.getAttributes()) + //{ + // LOG.debug(i.toString()); + //} /* - * 6 attributes from lifecycle and 2 from Derived and 1 from MBean + * 1 attribute from lifecycle and 2 from Derived and 1 from MBean */ - Assert.assertEquals("attribute count does not match", 9, info.getAttributes().length); + Assert.assertEquals("attribute count does not match", 4, info.getAttributes().length); Assert.assertEquals("attribute values does not match", "Full Name", mbean.getAttribute("fname") ); @@ -95,10 +98,25 @@ public class ObjectMBeanTest Assert.assertEquals("set attribute value does not match", "Fuller Name", mbean.getAttribute("fname") ); - Assert.assertEquals("proxy attribute values do not match", "goop", mbean.getAttribute("goop") ); + Assert.assertEquals("proxy attribute values do not match", "goop", mbean.getAttribute("goop") ); + + //Thread.sleep(100000); + } + + @Test + public void testDerivedOperations() throws Exception + { + Derived derived = new Derived(); + ObjectMBean mbean = (ObjectMBean)ObjectMBean.mbeanFor(derived); + mbean.setMBeanContainer(container); + + container.addBean(derived); + + MBeanInfo info = mbean.getMBeanInfo(); + Assert.assertEquals("operation count does not match", 5, info.getOperations().length); - + MBeanOperationInfo[] opinfos = info.getOperations(); boolean publish = false; boolean doodle = false; @@ -106,9 +124,7 @@ public class ObjectMBeanTest for ( int i = 0 ; i < opinfos.length; ++i ) { MBeanOperationInfo opinfo = opinfos[i]; - - LOG.debug(opinfo.getName()); - + if ("publish".equals(opinfo.getName())) { publish = true; @@ -126,6 +142,7 @@ public class ObjectMBeanTest Assert.assertEquals("parameter name doesn't match", "doodle", pinfos[0].getName()); } + // This is a proxied operation on the JMX wrapper if ("good".equals(opinfo.getName())) { good = true; @@ -138,11 +155,63 @@ public class ObjectMBeanTest Assert.assertTrue("publish operation was not not found", publish); Assert.assertTrue("doodle operation was not not found", doodle); Assert.assertTrue("good operation was not not found", good); - - // TODO sort out why this is not working...something off in Bean vs MBean ism's + + } + + @Test + public void testDerivedObjectAttributes() throws Exception + { + Derived derived = new Derived(); + ObjectMBean mbean = (ObjectMBean)ObjectMBean.mbeanFor(derived); + + ObjectMBean managed = (ObjectMBean)ObjectMBean.mbeanFor(derived.getManagedInstance()); + mbean.setMBeanContainer(container); + managed.setMBeanContainer(container); + + Assert.assertNotNull(mbean.getMBeanInfo()); + + container.addBean(derived); + container.addBean(derived.getManagedInstance()); Managed managedInstance = (Managed)mbean.getAttribute("managedInstance"); Assert.assertNotNull(managedInstance); Assert.assertEquals("managed instance returning nonsense", "foo", managedInstance.getManaged()); + } + + @Test + public void testThreadPool() throws Exception + { + QueuedThreadPool qtp = new QueuedThreadPool(); + + ObjectMBean bqtp = (ObjectMBean)ObjectMBean.mbeanFor(qtp); + + bqtp.getMBeanInfo(); + + + + container.addBean(qtp); + + + Thread.sleep(10000000); + + } + + @Test + public void testMethodNameMining() throws Exception + { + ObjectMBean mbean = new ObjectMBean(new Derived()); + + Assert.assertEquals("fullName",mbean.toVariableName("getFullName")); + Assert.assertEquals("fullName",mbean.toVariableName("getfullName")); + Assert.assertEquals("fullName",mbean.toVariableName("isFullName")); + Assert.assertEquals("fullName",mbean.toVariableName("isfullName")); + Assert.assertEquals("fullName",mbean.toVariableName("setFullName")); + Assert.assertEquals("fullName",mbean.toVariableName("setfullName")); + Assert.assertEquals("fullName",mbean.toVariableName("FullName")); + Assert.assertEquals("fullName",mbean.toVariableName("fullName")); + } + + } + diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/annotation/ManagedAttribute.java b/jetty-util/src/main/java/org/eclipse/jetty/util/annotation/ManagedAttribute.java index 3e0279cbf6b..c5cf94f6eae 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/annotation/ManagedAttribute.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/annotation/ManagedAttribute.java @@ -20,16 +20,23 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Documented -@Target( { ElementType.METHOD, ElementType.FIELD } ) +@Target( { ElementType.METHOD } ) public @interface ManagedAttribute { /** - * Description of the Managed Object + * Description of the Managed Attribute * - * @return + * @returngit checkout */ String value() default "Not Specified"; + /** + * name to use for the attribute + * + * @return the name of the attribute + */ + String name() default ""; + /** * Is the managed field read-only? * diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AbstractLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AbstractLifeCycle.java index ab00ce5b044..24685f8c805 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AbstractLifeCycle.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AbstractLifeCycle.java @@ -30,17 +30,11 @@ public abstract class AbstractLifeCycle implements LifeCycle { private static final Logger LOG = Log.getLogger(AbstractLifeCycle.class); - @ManagedAttribute(value="instance is stopped", readonly=true, getter="isStopped") public static final String STOPPED="STOPPED"; - @ManagedAttribute(value="instance is failed", readonly=true, getter="isFailed") public static final String FAILED="FAILED"; - @ManagedAttribute(value="instance is starting", readonly=true, getter="isStarting") public static final String STARTING="STARTING"; - @ManagedAttribute(value="instance is started", readonly=true, getter="isStarted") public static final String STARTED="STARTED"; - @ManagedAttribute(value="instance is stopping", readonly=true, getter="isStopping") public static final String STOPPING="STOPPING"; - @ManagedAttribute(value="instance is running", readonly=true, getter="isRunning") public static final String RUNNING="RUNNING"; private final CopyOnWriteArrayList _listeners=new CopyOnWriteArrayList(); @@ -139,6 +133,7 @@ public abstract class AbstractLifeCycle implements LifeCycle _listeners.remove(listener); } + @ManagedAttribute(value="Lifecycle State for this instance", readonly=true) public String getState() { switch(_state) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java index e7743e1c7ff..8928b0192c0 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java @@ -28,6 +28,10 @@ import java.util.concurrent.atomic.AtomicLong; import org.eclipse.jetty.util.BlockingArrayQueue; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedObject; +import org.eclipse.jetty.util.annotation.ManagedOperation; +import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Dumpable; @@ -36,6 +40,7 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.ThreadPool.SizedThreadPool; +@ManagedObject("A thread pool with no max bound by default") public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPool, Dumpable { private static final Logger LOG = Log.getLogger(QueuedThreadPool.class); @@ -46,14 +51,20 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo private final ConcurrentLinkedQueue _threads=new ConcurrentLinkedQueue(); private final Object _joinLock = new Object(); private BlockingQueue _jobs; + private String _name; private int _maxIdleTimeMs=60000; + private int _maxThreads; + private int _minThreads; private int _maxQueued=-1; + private int _priority=Thread.NORM_PRIORITY; + private boolean _daemon=false; private int _maxStopTime=100; + private boolean _detailedDump=false; /* ------------------------------------------------------------------- */ @@ -312,6 +323,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo * @return minimum number of threads. */ @Override + @ManagedAttribute("minimum number of threads in the pool") public int getMinThreads() { return _minThreads; @@ -321,6 +333,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo /** * @return The name of the BoundedThreadPool. */ + @ManagedAttribute("name of the thread pool") public String getName() { return _name; @@ -330,6 +343,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo /** Get the priority of the pool threads. * @return the priority of the pool threads. */ + @ManagedAttribute("priority of threads in the pool") public int getThreadsPriority() { return _priority; @@ -339,12 +353,14 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo /** * Delegated to the named or anonymous Pool. */ + @ManagedAttribute("thead pool using a daemon thread") public boolean isDaemon() { return _daemon; } /* ------------------------------------------------------------ */ + @ManagedAttribute("full stack detail on dump output") public boolean isDetailedDump() { return _detailedDump; @@ -471,6 +487,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo /* ------------------------------------------------------------ */ @Override + @ManagedOperation("dump thread state") public String dump() { return AggregateLifeCycle.dump(this); @@ -658,7 +675,8 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo * @param id The thread ID to interrupt. * @return true if the thread was found and interrupted. */ - public boolean interruptThread(long id) + @ManagedOperation("interrupt a pool thread") + public boolean interruptThread(@Name("id") long id) { for (Thread thread: _threads) { @@ -676,7 +694,8 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo * @param id The thread ID to interrupt. * @return true if the thread was found and interrupted. */ - public String dumpThread(long id) + @ManagedOperation("dump a pool thread stack") + public String dumpThread(@Name("id") long id) { for (Thread thread: _threads) { diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPool.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPool.java index 6e3b8ea493e..28ac01ff8d1 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPool.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPool.java @@ -15,6 +15,8 @@ package org.eclipse.jetty.util.thread; import java.util.concurrent.Executor; +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.component.LifeCycle; /* ------------------------------------------------------------ */ @@ -22,6 +24,7 @@ import org.eclipse.jetty.util.component.LifeCycle; * * */ +@ManagedObject("Pool of Threads") public interface ThreadPool extends Executor { /* ------------------------------------------------------------ */ @@ -41,18 +44,21 @@ public interface ThreadPool extends Executor /** * @return The total number of threads currently in the pool */ + @ManagedAttribute("number of threads in pool") public int getThreads(); /* ------------------------------------------------------------ */ /** * @return The number of idle threads in the pool */ + @ManagedAttribute("number of idle threads in pool") public int getIdleThreads(); /* ------------------------------------------------------------ */ /** * @return True if the pool is low on threads */ + @ManagedAttribute("indicates the pool is low on available threads") public boolean isLowOnThreads();