5 Replies Latest reply on Apr 4, 2003 2:38 AM by Juha Lindfors

    What is wrong with ModelMBean and what is the difference wit

    Alexander Rabinowitz Newbie

      I am using JBoss 3.0.6.

      I am trying to implement the same MBean as DynamicMBean and as ModelMBean.

      I call it both times the same way from my code:
      String pulsarName = "com.peerdirect.rmapplications.master.jmx.PulsarStandard" ;
      Object pulsar = Class.forName (pulsarName).newInstance();
      String name = myMBeanServer.getDefaultDomain() + ":type=" + pulsarName;
      myMBeanServer.registerMBean (pulsar, new ObjectName(name)); // line 67

      When I implement it as a DynamicMBean, it works OK.
      Here is the implementation:
      ------------- start of implementation -------------------
      package com.peerdirect.rmapplications.master.jmx;

      import com.peerdirect.rmapplications.master.jms.StatusNotificationClient;

      import javax.management.*;
      import javax.management.modelmbean.*;
      import java.util.Iterator;
      import java.lang.Runnable;
      import java.io.*;
      import org.jboss.mx.modelmbean.*;
      import org.jboss.mx.modelmbean.ModelMBeanConstants.*;

      public class PulsarStandard extends NotificationBroadcasterSupport
      implements DynamicMBean, Runnable

      {
      // support for generic notification listeners
      private NotificationBroadcasterSupport notifier = new NotificationBroadcasterSupport();

      // sequence numbers for notifications
      protected long notifierSequence = 0;
      protected long attrNotifierSequence = 0;

      // mgmt attribute name constants
      final static String PULSE_PERIOD = "PulsePeriodInMills";
      final static String IF_STARTED = "Started";

      // mgmt operation name constants
      final static String START_PULSE = "startPulse";
      final static String STOP_PULSE = "stopPulse";

      // fields for attribute values
      private static final int DEFAULT_PULSE_PERIOD = 1000;
      private static final boolean DEFAULT_STARTED= false;

      private int mPulsePeriod = 0;
      private boolean mStarted = false;
      private StatusNotificationClient mSNC = null;
      private Thread mThread = null;

      // getAttribute implementation

      public PulsarStandard () throws MBeanException
      {
      System.out.println ("PulsarStandard");
      mPulsePeriod = DEFAULT_PULSE_PERIOD;
      mStarted = DEFAULT_STARTED;
      mSNC = new StatusNotificationClient ();
      mThread = new Thread (this);
      startPulse () ;
      }

      public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException
      {
      System.out.println ("getAttribute");
      if (attribute == null || attribute.equals(""))
      throw new IllegalArgumentException("null or empty attribute name");

      // map the named attributes to fields

      if (attribute.equals(PULSE_PERIOD))
      return new Integer (mPulsePeriod);
      else if (attribute.equals(IF_STARTED))
      return new Boolean (mStarted);

      throw new AttributeNotFoundException("Attribute " + attribute + " not found.");
      }


      // getAttributes implementation

      public AttributeList getAttributes (String[] attributes)
      {
      System.out.println ("getAttributes");
      if (attributes == null)
      throw new IllegalArgumentException("null array");

      AttributeList list = new AttributeList();

      for (int i = 0; i < attributes.length; ++i)
      {
      try
      {
      list.add (new Attribute (attributes, getAttribute(attributes)));
      }
      catch (JMException ignored)
      {
      // if the attribute could not be retrieved, skip it
      }
      }
      return list;
      }


      // setAttribute implementation

      public void setAttribute (Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException,
      MBeanException, ReflectionException
      {
      System.out.println ("setAttribute");
      if (attribute == null) throw new
      AttributeNotFoundException("null attribute");

      // map attributes to fields
      try
      {
      if (attribute.getName().equals(PULSE_PERIOD))
      this.mPulsePeriod = ((Integer)attribute.getValue()).intValue();
      else if (attribute.getName().equals(IF_STARTED))
      this.mStarted = ((Boolean)attribute.getValue()).booleanValue();
      else
      throw new AttributeNotFoundException("attribute " + attribute.getName() + " not found.");
      }
      catch (ClassCastException e)
      {
      throw new InvalidAttributeValueException("Invalid attribute type " + attribute.getValue().getClass().getName());
      }
      }


      // setAttributes implementation

      public AttributeList setAttributes (AttributeList list)
      {
      System.out.println ("setAttributes");
      if (list == null)
      throw new IllegalArgumentException("null list");

      AttributeList results = new AttributeList();
      Iterator it = list.iterator();

      while (it.hasNext())
      {
      try
      {
      Attribute attr = (Attribute)it.next();
      setAttribute(attr);
      results.add(attr);
      }
      catch (JMException ignored)
      {
      // if unable to set the attribute, skip it
      }
      }
      return results;
      }


      // invoke implementation

      public Object invoke(String actionName,
      Object[] params,
      String[] signature) throws MBeanException, ReflectionException {
      System.out.println ("invoke");
      if (actionName == null || actionName.equals(""))
      throw new IllegalArgumentException("no operation");

      // map operation names to methods
      if (actionName.equals(START_PULSE))
      {
      startPulse();
      return null;
      }
      else if (actionName.equals(STOP_PULSE))
      {
      stopPulse ();
      return null;
      }
      else
      throw new UnsupportedOperationException("unknown operation " + actionName);
      }


      // getMBeanInfo implementation
      /*public static MBeanInfo getMBeanInfo()
      {
      return getMBeanInfo1();
      }*/

      public MBeanInfo getMBeanInfo()
      {
      System.out.println ("getMBeanInfo");
      final boolean IS_READABLE = true;
      final boolean IS_WRITABLE = true;
      final boolean IS_IS = true;

      // MBean class and description
      //String className = getClass().getName();
      String className = PulsarStandard.class.getName();
      String description =
      "User resource with dynamic management interface";

      // meta data for 'PULSE_PERIOD' attribute.
      MBeanAttributeInfo mPulsePeriod = new MBeanAttributeInfo(
      PULSE_PERIOD, // name
      int.class.getName(), // type
      "Pulse Period", // description
      IS_READABLE, IS_WRITABLE, !IS_IS // access
      );

      // meta data for 'IF_STARTED' attribute.
      MBeanAttributeInfo mStarted = new MBeanAttributeInfo(
      IF_STARTED, // name
      boolean.class.getName(), // type
      "If the Pulser has Started", // description
      IS_READABLE, !IS_WRITABLE, !IS_IS // access
      );

      // meta data for 'startPulse' operation
      MBeanOperationInfo startPulse = new MBeanOperationInfo(
      START_PULSE, // name
      "Start the pulsar", // description
      null, // signature
      void.class.getName(), // return type
      MBeanOperationInfo.ACTION // impact
      );

      // meta data for 'stopPulse' operation
      MBeanOperationInfo stopPulse = new MBeanOperationInfo(
      STOP_PULSE, // name
      "Stop the pulsar", // description
      null, // signature
      void.class.getName(), // return type
      MBeanOperationInfo.ACTION // impact
      );

      // mbean constructors
      MBeanConstructorInfo defaultConstructor =
      new MBeanConstructorInfo(
      "Default Constructor",
      "Creates a new Pulsar", null
      );

      // attribute, constructor and operation lists
      MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[] {mPulsePeriod, mStarted};

      MBeanConstructorInfo[] constructors = new MBeanConstructorInfo[] {defaultConstructor};

      MBeanOperationInfo[] operations = new MBeanOperationInfo[] {startPulse, stopPulse};

      // return the MBeanInfo
      return new MBeanInfo (className, description, attributes, constructors, operations, null);
      }

      public void startPulse ()
      {
      System.out.println ("startPulse");
      mThread.start ();
      try
      {
      mSNC.connect();
      mStarted = true ;
      }
      catch (Exception e)
      {
      mStarted = false ;
      }
      }

      public void stopPulse ()
      {
      System.out.println ("stopPulse");
      mThread.stop ();
      mSNC.disconnect();
      mStarted = false ;
      }

      public void run ()
      {
      System.out.println ("run");
      try
      {
      while (true)
      {
      mThread.sleep (mPulsePeriod);
      if (mStarted)
      {
      System.out.println("Pulsing");
      mSNC.sendPulse();
      }
      }
      }
      catch (Exception ex)
      {
      ex.printStackTrace();
      }
      }
      }

      //////////////////////////////////////////////////////////////////////////////////////
      //////////////////////////////////////////////////////////////////////////////////////
      //////////////////////////////////////////////////////////////////////////////////////
      ----------------- end of implementation ---------------

      However, whan I implement it as a ModelMBean (not directly ModelMBean, because I need to use PersistPolicy; I tried to implement it as ModelBase or as XMBean - both times) it does not wortk - it bring out an exception (which is not brough out when I use DynamicMBean implementation of the same Mbean):

      MBeanException: preRegister() failed
      [ObjectName='DefaultDomain:type=com.peerdirect.rmapplications.master.jmx.PulsarStandard',Class=com.peerdirect.rmapplications.master.jmx.PulsarStandard
      (com.peerdirect.rmapplications.master.jmx.PulsarStandard@5bdc50)]
      Cause: java.lang.NullPointerException
      at
      org.jboss.mx.server.registry.BasicMBeanRegistry.registerMBean(BasicMBeanRegistry.java:187)
      at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:975)
      at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:302)
      at com.peerdirect.rmapplications.agent.BaseAgent.(BaseAgent.java:67)
      at com.peerdirect.rmapplications.agent.MasterAgent.(MasterAgent.java:5)
      at com.peerdirect.rmapplications.agent.MasterAgent.main(MasterAgent.java:15)

      Here is my implementation as ModelBase (absolutely the same thing happens when I use XMBean instead of ModelBase):
      --------------------- start of implementation --------
      package com.peerdirect.rmapplications.master.jmx;

      import com.peerdirect.rmapplications.master.jms.StatusNotificationClient;

      import javax.management.*;
      import javax.management.modelmbean.*;
      import java.util.Iterator;
      import java.lang.Runnable;
      import java.io.*;
      import org.jboss.mx.modelmbean.*;
      import org.jboss.mx.modelmbean.ModelMBeanConstants.*;

      public class PulsarStandard extends ModelBase
      implements Runnable
      {
      // support for generic notification listeners
      private NotificationBroadcasterSupport notifier = new NotificationBroadcasterSupport();

      // sequence numbers for notifications
      protected long notifierSequence = 0;
      protected long attrNotifierSequence = 0;

      // mgmt attribute name constants
      final static String PULSE_PERIOD = "PulsePeriodInMills";
      final static String IF_STARTED = "Started";

      // mgmt operation name constants
      final static String START_PULSE = "startPulse";
      final static String STOP_PULSE = "stopPulse";

      // fields for attribute values
      private static final int DEFAULT_PULSE_PERIOD = 1000;
      private static final boolean DEFAULT_STARTED= false;

      private int mPulsePeriod = 0;
      private boolean mStarted = false;
      private StatusNotificationClient mSNC = null;
      private Thread mThread = null;

      protected ModelMBeanInfo metadata = null;
      protected Object resource = null;
      protected String resourceType = null;

      public boolean isSupportedResourceType(String resourceType)
      {
      System.out.println("isSupportedResourceType");
      return true;
      }

      // getAttribute implementation

      public PulsarStandard () throws MBeanException
      {
      super ();
      System.out.println ("PulsarStandard");
      mPulsePeriod = DEFAULT_PULSE_PERIOD;
      mStarted = DEFAULT_STARTED;
      mSNC = new StatusNotificationClient ();
      mThread = new Thread (this);
      startPulse () ;
      }

      public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException
      {
      System.out.println ("getAttribute");
      if (attribute == null || attribute.equals(""))
      throw new IllegalArgumentException("null or empty attribute name");

      // map the named attributes to fields

      if (attribute.equals(PULSE_PERIOD))
      return new Integer (mPulsePeriod);
      else if (attribute.equals(IF_STARTED))
      return new Boolean (mStarted);

      throw new AttributeNotFoundException("Attribute " + attribute + " not found.");
      }


      // getAttributes implementation

      public AttributeList getAttributes (String[] attributes)
      {
      System.out.println ("getAttributes");
      if (attributes == null)
      throw new IllegalArgumentException("null array");

      AttributeList list = new AttributeList();

      for (int i = 0; i < attributes.length; ++i)
      {
      try
      {
      list.add (new Attribute (attributes, getAttribute(attributes)));
      }
      catch (JMException ignored)
      {
      // if the attribute could not be retrieved, skip it
      }
      }
      return list;
      }


      // setAttribute implementation

      public void setAttribute (Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException,
      MBeanException, ReflectionException
      {
      System.out.println ("setAttribute");
      if (attribute == null) throw new
      AttributeNotFoundException("null attribute");

      // map attributes to fields
      try
      {
      if (attribute.getName().equals(PULSE_PERIOD))
      this.mPulsePeriod = ((Integer)attribute.getValue()).intValue();
      else if (attribute.getName().equals(IF_STARTED))
      this.mStarted = ((Boolean)attribute.getValue()).booleanValue();
      else
      throw new AttributeNotFoundException("attribute " + attribute.getName() + " not found.");
      }
      catch (ClassCastException e)
      {
      throw new InvalidAttributeValueException("Invalid attribute type " + attribute.getValue().getClass().getName());
      }
      }


      // setAttributes implementation

      public AttributeList setAttributes (AttributeList list)
      {
      System.out.println ("setAttributes");
      if (list == null)
      throw new IllegalArgumentException("null list");

      AttributeList results = new AttributeList();
      Iterator it = list.iterator();

      while (it.hasNext())
      {
      try
      {
      Attribute attr = (Attribute)it.next();
      setAttribute(attr);
      results.add(attr);
      }
      catch (JMException ignored)
      {
      // if unable to set the attribute, skip it
      }
      }
      return results;
      }


      // invoke implementation

      public Object invoke(String actionName,
      Object[] params,
      String[] signature) throws MBeanException, ReflectionException {
      System.out.println ("invoke");
      if (actionName == null || actionName.equals(""))
      throw new IllegalArgumentException("no operation");

      // map operation names to methods
      if (actionName.equals(START_PULSE))
      {
      startPulse();
      return null;
      }
      else if (actionName.equals(STOP_PULSE))
      {
      stopPulse ();
      return null;
      }
      else
      throw new UnsupportedOperationException("unknown operation " + actionName);
      }


      // getMBeanInfo implementation
      /*public static MBeanInfo getMBeanInfo()
      {
      return getMBeanInfo1();
      }*/

      public MBeanInfo getMBeanInfo()
      {
      System.out.println ("getMBeanInfo");
      //final boolean IS_READABLE = true;
      //final boolean IS_WRITABLE = true;
      //final boolean IS_IS = true;

      // MBean class and description
      //String className = getClass().getName();
      String className = PulsarStandard.class.getName();
      String description =
      "User resource with model management interface";

      // build 'RoomName' read-write attribute
      /*Descriptor descr_my = new DescriptorSupport();
      descr_my.setField(PERSIST_POLICY, "OnUpdate");
      descr_my.setField(PERSIST_LOCATION, "c:\\aa");
      descr_my.setField(PERSIST_NAME, "storage.txt");
      System.out.println ("Valid " + descr_my.isValid());*/

      // meta data for 'PULSE_PERIOD' attribute.
      ModelMBeanAttributeInfo mPulsePeriod = new ModelMBeanAttributeInfo(
      PULSE_PERIOD, // name
      int.class.getName(), // type
      "Pulse Period", // description
      IS_READABLE, IS_WRITABLE, !IS_IS//, // access
      //descr_my
      );

      // meta data for 'IF_STARTED' attribute.
      ModelMBeanAttributeInfo mStarted = new ModelMBeanAttributeInfo(
      IF_STARTED, // name
      boolean.class.getName(), // type
      "If the Pulser has Started", // description
      IS_READABLE, !IS_WRITABLE, !IS_IS // access
      );

      // meta data for 'startPulse' operation
      ModelMBeanOperationInfo startPulse = new ModelMBeanOperationInfo(
      START_PULSE, // name
      "Start the pulsar", // description
      null, // signature
      void.class.getName(), // return type
      MBeanOperationInfo.ACTION // impact
      );

      // meta data for 'stopPulse' operation
      ModelMBeanOperationInfo stopPulse = new ModelMBeanOperationInfo(
      STOP_PULSE, // name
      "Stop the pulsar", // description
      null, // signature
      void.class.getName(), // return type
      MBeanOperationInfo.ACTION // impact
      );

      // mbean constructors
      ModelMBeanConstructorInfo defaultConstructor =
      new ModelMBeanConstructorInfo(
      "Default Constructor",
      "Creates a new Pulsar", null
      );

      // attribute, constructor and operation lists
      ModelMBeanAttributeInfo[] attributes = new ModelMBeanAttributeInfo[] {mPulsePeriod, mStarted};

      ModelMBeanConstructorInfo[] constructors = new ModelMBeanConstructorInfo[] {defaultConstructor};

      ModelMBeanOperationInfo[] operations = new ModelMBeanOperationInfo[] {startPulse, stopPulse};

      // return the MBeanInfo
      return new ModelMBeanInfoSupport (className, description, attributes, constructors, operations, null);
      }

      // RW attributes
      /*
      public int getPulsePeriodInMills ()
      {
      return mPulsePeriod;
      }

      public void setPulsePeriodInMills (int pPulsePeriod)
      {
      mPulsePeriod = pPulsePeriod ;
      }

      public boolean getStarted ()
      {
      return mStarted;
      }
      */

      public void startPulse ()
      {
      System.out.println ("startPulse");
      mThread.start ();
      try
      {
      mSNC.connect();
      mStarted = true ;
      }
      catch (Exception e)
      {
      mStarted = false ;
      }
      }

      public void stopPulse ()
      {
      System.out.println ("stopPulse");
      mThread.stop ();
      mSNC.disconnect();
      mStarted = false ;
      }

      public void run ()
      {
      System.out.println ("run");
      try
      {
      while (true)
      {
      mThread.sleep (mPulsePeriod);
      if (mStarted)
      {
      System.out.println("Pulsing");
      mSNC.sendPulse();
      }
      }
      }
      catch (Exception ex)
      {
      ex.printStackTrace();
      }
      }
      }

      //////////////////////////////////////////////////////////////////////////////////////
      //////////////////////////////////////////////////////////////////////////////////////
      //////////////////////////////////////////////////////////////////////////////////////
      --------------------- end of implementation --------

        • 1. Re: What is wrong with ModelMBean and what is the difference
          Juha Lindfors Master

          If you're extending directly from ModelBase you need to either call setModelMBeanInfo(ModelMBeanInfo info) on your MBean instance before you register, or call super(ModelMBeanInfo info) from your MBean implementation's constructor. Right now you you're using the default constructor that does not set the metadata ('info' field in the ModelBase.java) and that causes the null pointer exception.

          So either provide a constructor in your impl. or call setModelMBeanInfo before you register.

          • 2. Re: What is wrong with ModelMBean and what is the difference
            Alexander Rabinowitz Newbie

            I modified the cinstructor to call super (createMBeanInfo()):

            public PulsarStandard () throws MBeanException
            {
            super (createMBeanInfo());
            System.out.println ("PulsarStandard");
            try
            {
            setManagedResource (new Object (), OBJECT_REF);
            }
            catch (Exception e)
            {
            e.printStackTrace();
            }
            mPulsePeriod = DEFAULT_PULSE_PERIOD;
            mStarted = DEFAULT_STARTED;
            mSNC = new StatusNotificationClient ();
            mThread = new Thread (this);
            startPulse () ;
            }

            while I have now:

            public MBeanInfo getMBeanInfo()
            {
            return info;
            }

            public static /*MBeanInfo*/ ModelMBeanInfo createMBeanInfo()
            {
            System.out.println ("getMBeanInfo");
            //final boolean IS_READABLE = true;
            //final boolean IS_WRITABLE = true;
            //final boolean IS_IS = true;

            // MBean class and description
            //String className = getClass().getName();
            String className = PulsarStandard.class.getName();
            String description =
            "User resource with model management interface";

            // build 'RoomName' read-write attribute
            /*Descriptor descr_my = new DescriptorSupport();
            descr_my.setField(PERSIST_POLICY, "OnUpdate");
            descr_my.setField(PERSIST_LOCATION, "c:\\aa");
            descr_my.setField(PERSIST_NAME, "storage.txt");
            System.out.println ("Valid " + descr_my.isValid());*/

            // meta data for 'PULSE_PERIOD' attribute.
            ModelMBeanAttributeInfo mPulsePeriod = new ModelMBeanAttributeInfo(
            PULSE_PERIOD, // name
            int.class.getName(), // type
            "Pulse Period", // description
            IS_READABLE, IS_WRITABLE, !IS_IS//, // access
            //descr_my
            );

            // meta data for 'IF_STARTED' attribute.
            ModelMBeanAttributeInfo mStarted = new ModelMBeanAttributeInfo(
            IF_STARTED, // name
            boolean.class.getName(), // type
            "If the Pulser has Started", // description
            IS_READABLE, !IS_WRITABLE, !IS_IS // access
            );

            // meta data for 'startPulse' operation
            ModelMBeanOperationInfo startPulse = new ModelMBeanOperationInfo(
            START_PULSE, // name
            "Start the pulsar", // description
            null, // signature
            void.class.getName(), // return type
            MBeanOperationInfo.ACTION // impact
            );

            // meta data for 'stopPulse' operation
            ModelMBeanOperationInfo stopPulse = new ModelMBeanOperationInfo(
            STOP_PULSE, // name
            "Stop the pulsar", // description
            null, // signature
            void.class.getName(), // return type
            MBeanOperationInfo.ACTION // impact
            );

            // mbean constructors
            ModelMBeanConstructorInfo defaultConstructor =
            new ModelMBeanConstructorInfo(
            "Default Constructor",
            "Creates a new Pulsar", null
            );

            // attribute, constructor and operation lists
            ModelMBeanAttributeInfo[] attributes = new ModelMBeanAttributeInfo[] {mPulsePeriod, mStarted};

            ModelMBeanConstructorInfo[] constructors = new ModelMBeanConstructorInfo[] {defaultConstructor};

            ModelMBeanOperationInfo[] operations = new ModelMBeanOperationInfo[] {startPulse, stopPulse};

            // return the MBeanInfo
            return new ModelMBeanInfoSupport (className, description, attributes, constructors, operations, null);
            }

            However, I have the following exception now:

            MBeanException: preRegister() failed [ObjectName='DefaultDomain:type=com.peerdir
            ect.rmapplications.master.jmx.PulsarStandard', Class=com.peerdirect.rmapplicatio
            ns.master.jmx.PulsarStandard (com.peerdirect.rmapplications.master.jmx.PulsarSta
            ndard@3020ad)]
            Cause: ReflectionException: null
            Cause: javax.management.IntrospectionException: no method found for operation: startPulse
            at org.jboss.mx.server.registry.BasicMBeanRegistry.registerMBean(BasicMBeanRegistry.java:187)
            at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:975)
            at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:302)
            at com.peerdirect.rmapplications.agent.BaseAgent.(BaseAgent.java:67)
            at com.peerdirect.rmapplications.agent.MasterAgent.(MasterAgent.java:5)
            at com.peerdirect.rmapplications.agent.MasterAgent.main(MasterAgent.java
            :15)
            Instantiating an HTML protocol adaptor with default port...
            Pulsing

            The full class code is the following:
            package com.peerdirect.rmapplications.master.jmx;

            import com.peerdirect.rmapplications.master.jms.StatusNotificationClient;

            import javax.management.*;
            import javax.management.modelmbean.*;
            import java.util.Iterator;
            import java.lang.Runnable;
            import java.io.*;
            import org.jboss.mx.modelmbean.*;
            import org.jboss.mx.modelmbean.ModelMBeanConstants.*;

            public class PulsarStandard extends ModelBase
            implements Runnable
            {
            // support for generic notification listeners
            private NotificationBroadcasterSupport notifier = new NotificationBroadcasterSupport();

            // sequence numbers for notifications
            protected long notifierSequence = 0;
            protected long attrNotifierSequence = 0;

            // mgmt attribute name constants
            final static String PULSE_PERIOD = "PulsePeriodInMills";
            final static String IF_STARTED = "Started";

            // mgmt operation name constants
            final static String START_PULSE = "startPulse";
            final static String STOP_PULSE = "stopPulse";

            // fields for attribute values
            private static final int DEFAULT_PULSE_PERIOD = 1000;
            private static final boolean DEFAULT_STARTED= false;

            private int mPulsePeriod = 0;
            private boolean mStarted = false;
            private StatusNotificationClient mSNC = null;
            private Thread mThread = null;

            protected ModelMBeanInfo metadata = null;
            protected Object resource = null;
            protected String resourceType = null;

            public boolean isSupportedResourceType(String resourceType)
            {
            System.out.println("isSupportedResourceType");
            return true;
            }

            // getAttribute implementation

            public PulsarStandard () throws MBeanException
            {
            super (createMBeanInfo());
            System.out.println ("PulsarStandard");
            try
            {
            setManagedResource (new Object (), OBJECT_REF);
            }
            catch (Exception e)
            {
            e.printStackTrace();
            }
            mPulsePeriod = DEFAULT_PULSE_PERIOD;
            mStarted = DEFAULT_STARTED;
            mSNC = new StatusNotificationClient ();
            mThread = new Thread (this);
            startPulse () ;
            }

            public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException
            {
            System.out.println ("getAttribute");
            if (attribute == null || attribute.equals(""))
            throw new IllegalArgumentException("null or empty attribute name");

            // map the named attributes to fields

            if (attribute.equals(PULSE_PERIOD))
            return new Integer (mPulsePeriod);
            else if (attribute.equals(IF_STARTED))
            return new Boolean (mStarted);

            throw new AttributeNotFoundException("Attribute " + attribute + " not found.");
            }


            // getAttributes implementation

            public AttributeList getAttributes (String[] attributes)
            {
            System.out.println ("getAttributes");
            if (attributes == null)
            throw new IllegalArgumentException("null array");

            AttributeList list = new AttributeList();

            for (int i = 0; i < attributes.length; ++i)
            {
            try
            {
            list.add (new Attribute (attributes, getAttribute(attributes)));
            }
            catch (JMException ignored)
            {
            // if the attribute could not be retrieved, skip it
            }
            }
            return list;
            }


            // setAttribute implementation

            public void setAttribute (Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException,
            MBeanException, ReflectionException
            {
            System.out.println ("setAttribute");
            if (attribute == null) throw new
            AttributeNotFoundException("null attribute");

            // map attributes to fields
            try
            {
            if (attribute.getName().equals(PULSE_PERIOD))
            this.mPulsePeriod = ((Integer)attribute.getValue()).intValue();
            else if (attribute.getName().equals(IF_STARTED))
            this.mStarted = ((Boolean)attribute.getValue()).booleanValue();
            else
            throw new AttributeNotFoundException("attribute " + attribute.getName() + " not found.");
            }
            catch (ClassCastException e)
            {
            throw new InvalidAttributeValueException("Invalid attribute type " + attribute.getValue().getClass().getName());
            }
            }


            // setAttributes implementation

            public AttributeList setAttributes (AttributeList list)
            {
            System.out.println ("setAttributes");
            if (list == null)
            throw new IllegalArgumentException("null list");

            AttributeList results = new AttributeList();
            Iterator it = list.iterator();

            while (it.hasNext())
            {
            try
            {
            Attribute attr = (Attribute)it.next();
            setAttribute(attr);
            results.add(attr);
            }
            catch (JMException ignored)
            {
            // if unable to set the attribute, skip it
            }
            }
            return results;
            }


            // invoke implementation

            public Object invoke(String actionName,
            Object[] params,
            String[] signature) throws MBeanException, ReflectionException {
            System.out.println ("invoke");
            if (actionName == null || actionName.equals(""))
            throw new IllegalArgumentException("no operation");

            // map operation names to methods
            if (actionName.equals(START_PULSE))
            {
            startPulse();
            return null;
            }
            else if (actionName.equals(STOP_PULSE))
            {
            stopPulse ();
            return null;
            }
            else
            throw new UnsupportedOperationException("unknown operation " + actionName);
            }


            // getMBeanInfo implementation
            public MBeanInfo getMBeanInfo()
            {
            return info;
            }

            public static /*MBeanInfo*/ ModelMBeanInfo createMBeanInfo()
            {
            System.out.println ("getMBeanInfo");
            //final boolean IS_READABLE = true;
            //final boolean IS_WRITABLE = true;
            //final boolean IS_IS = true;

            // MBean class and description
            //String className = getClass().getName();
            String className = PulsarStandard.class.getName();
            String description =
            "User resource with model management interface";

            // build 'RoomName' read-write attribute
            /*Descriptor descr_my = new DescriptorSupport();
            descr_my.setField(PERSIST_POLICY, "OnUpdate");
            descr_my.setField(PERSIST_LOCATION, "c:\\aa");
            descr_my.setField(PERSIST_NAME, "storage.txt");
            System.out.println ("Valid " + descr_my.isValid());*/

            // meta data for 'PULSE_PERIOD' attribute.
            ModelMBeanAttributeInfo mPulsePeriod = new ModelMBeanAttributeInfo(
            PULSE_PERIOD, // name
            int.class.getName(), // type
            "Pulse Period", // description
            IS_READABLE, IS_WRITABLE, !IS_IS//, // access
            //descr_my
            );

            // meta data for 'IF_STARTED' attribute.
            ModelMBeanAttributeInfo mStarted = new ModelMBeanAttributeInfo(
            IF_STARTED, // name
            boolean.class.getName(), // type
            "If the Pulser has Started", // description
            IS_READABLE, !IS_WRITABLE, !IS_IS // access
            );

            // meta data for 'startPulse' operation
            ModelMBeanOperationInfo startPulse = new ModelMBeanOperationInfo(
            START_PULSE, // name
            "Start the pulsar", // description
            null, // signature
            void.class.getName(), // return type
            MBeanOperationInfo.ACTION // impact
            );

            // meta data for 'stopPulse' operation
            ModelMBeanOperationInfo stopPulse = new ModelMBeanOperationInfo(
            STOP_PULSE, // name
            "Stop the pulsar", // description
            null, // signature
            void.class.getName(), // return type
            MBeanOperationInfo.ACTION // impact
            );

            // mbean constructors
            ModelMBeanConstructorInfo defaultConstructor =
            new ModelMBeanConstructorInfo(
            "Default Constructor",
            "Creates a new Pulsar", null
            );

            // attribute, constructor and operation lists
            ModelMBeanAttributeInfo[] attributes = new ModelMBeanAttributeInfo[] {mPulsePeriod, mStarted};

            ModelMBeanConstructorInfo[] constructors = new ModelMBeanConstructorInfo[] {defaultConstructor};

            ModelMBeanOperationInfo[] operations = new ModelMBeanOperationInfo[] {startPulse, stopPulse};

            // return the MBeanInfo
            return new ModelMBeanInfoSupport (className, description, attributes, constructors, operations, null);
            }

            // RW attributes
            /*
            public int getPulsePeriodInMills ()
            {
            return mPulsePeriod;
            }

            public void setPulsePeriodInMills (int pPulsePeriod)
            {
            mPulsePeriod = pPulsePeriod ;
            }

            public boolean getStarted ()
            {
            return mStarted;
            }
            */

            public void startPulse ()
            {
            System.out.println ("startPulse");
            mThread.start ();
            try
            {
            mSNC.connect();
            mStarted = true ;
            }
            catch (Exception e)
            {
            mStarted = false ;
            }
            }

            public void stopPulse ()
            {
            System.out.println ("stopPulse");
            mThread.stop ();
            mSNC.disconnect();
            mStarted = false ;
            }

            public void run ()
            {
            System.out.println ("run");
            try
            {
            while (true)
            {
            mThread.sleep (mPulsePeriod);
            if (mStarted)
            {
            System.out.println("Pulsing");
            mSNC.sendPulse();
            }
            }
            }
            catch (Exception ex)
            {
            ex.printStackTrace();
            }
            }
            }

            //////////////////////////////////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////////////////////////////////////

            • 3. Re: What is wrong with ModelMBean and what is the difference
              Alexander Rabinowitz Newbie

              Actually, the type of Exception depends on what I use:

              If I use the following (the constructors do not use the descriptor):
              /*Descriptor descr_my = new DescriptorSupport();
              descr_my.setField(PERSIST_POLICY, "OnUpdate");
              descr_my.setField(PERSIST_LOCATION, "c:\\aa");
              descr_my.setField(PERSIST_NAME, "storage.txt");
              System.out.println ("Valid " + descr_my.isValid());
              System.out.println ("Name: " + void.class.getName());*/

              // meta data for 'PULSE_PERIOD' attribute.
              ModelMBeanAttributeInfo mPulsePeriod = new ModelMBeanAttributeInfo(
              PULSE_PERIOD, // name
              int.class.getName(), // type
              "Pulse Period", // description
              ModelBase.IS_READABLE, ModelBase.IS_WRITABLE, !ModelBase.IS_IS//, // access
              //descr_my
              );

              // meta data for 'IF_STARTED' attribute.
              ModelMBeanAttributeInfo mStarted = new ModelMBeanAttributeInfo(
              IF_STARTED, // name
              boolean.class.getName(), // type
              "If the Pulser has Started", // description
              ModelBase.IS_READABLE, !ModelBase.IS_WRITABLE, !ModelBase.IS_IS // access
              );

              // meta data for 'startPulse' operation
              ModelMBeanOperationInfo startPulse = new ModelMBeanOperationInfo(
              START_PULSE, // name
              "Start the pulsar", // description
              null, // signature
              void.class.getName(), // return type
              MBeanOperationInfo.ACTION//, // impact
              //descr_my
              );

              // meta data for 'stopPulse' operation
              ModelMBeanOperationInfo stopPulse = new ModelMBeanOperationInfo(
              STOP_PULSE, // name
              "Stop the pulsar", // description
              null, // signature
              void.class.getName(), // return type
              MBeanOperationInfo.ACTION // impact
              );

              Then I have
              MBeanException: preRegister() failed
              [ObjectName='DefaultDomain:type=com.peerdirect.rmapplications.master.jmx.PulsarStandard',Class=com.peerdirect.rmapplications.master.jmx.PulsarStandard
              (com.peerdirect.rmapplications.master.jmx.PulsarStandard@5bdc50)]
              Cause: java.lang.NullPointerException
              at
              org.jboss.mx.server.registry.BasicMBeanRegistry.registerMBean(BasicMBeanRegistry.java:187)
              at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:975)
              at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:302)
              at com.peerdirect.rmapplications.agent.BaseAgent.(BaseAgent.java:67)
              at com.peerdirect.rmapplications.agent.MasterAgent.(MasterAgent.java:5)
              at com.peerdirect.rmapplications.agent.MasterAgent.main(MasterAgent.java:15)

              But if I use another constructor, which uses descriptor:

              // meta data for 'startPulse' operation
              ModelMBeanOperationInfo startPulse = new ModelMBeanOperationInfo(
              START_PULSE, // name
              "Start the pulsar", // description
              null, // signature
              void.class.getName(), // return type
              MBeanOperationInfo.ACTION//, // impact
              descr_my
              );

              Then I have the following:

              MBeanException: preRegister() failed [ObjectName='DefaultDomain:type=com.peerdir
              ect.rmapplications.master.jmx.PulsarStandard',
              Class=com.peerdirect.rmapplications.master.jmx.PulsarStandard (com.peerdirect.rmapplications.master.jmx.PulsarStandard@3020ad)]
              Cause: ReflectionException: null
              Cause: javax.management.IntrospectionException: no method found for operation: startPulse
              at org.jboss.mx.server.registry.BasicMBeanRegistry.registerMBean(BasicMBeanRegistry.java:187)
              at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:975)
              at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:302)
              at com.peerdirect.rmapplications.agent.BaseAgent.(BaseAgent.java:67)
              at com.peerdirect.rmapplications.agent.MasterAgent.(MasterAgent.java:5)
              at com.peerdirect.rmapplications.agent.MasterAgent.main(MasterAgent.java:15)

              And that is all after the changes I made for the constructor.

              • 4. Re: What is wrong with ModelMBean and what is the difference
                Juha Lindfors Master

                descriptor needs to at minimum have a name field that matches the operation name, descriptorType field that contains "operation" field and possible role field with "operation" as its value as well.

                All in all, when using model mbeans you usually should not extend the model mbean implementation, rather than configure it to match your requirements.

                So you just create your own object and say:

                MyObject myobject = new MyObject();
                ModelMBean mmb = new RequiredModelMBean();
                mmb.setModelMBeanInfo(getMBeanInfoFromSomewhere());
                mmb.setManagedResource(myobject, "ObjectReference");
                mbeanServer.register(mmb, ObjectName);

                • 5. Re: What is wrong with ModelMBean and what is the difference
                  Juha Lindfors Master

                  although I realize if you're looking to plugin your own persistence manager then you do need to use the extends method.