This discussion is archived
3 Replies Latest reply: Jan 20, 2011 4:49 AM by jtahlborn RSS

Edit tabluardatasupport in jconsole

832442 Newbie
Currently Being Moderated
Hey All,

I am trying for some time now to be able to edit complex types I manage with JMX, meaning I have a class A which holds int string and an instance of B (another class)
class B holds int and int ... all I want to do is to be able to edit class B. I managed to dig deep inside openMBeans and I know how to manually create them and expose them to the jconsole as tabluardatasupport (if collection) or Compositetype (if only one instance) but my issue now is that I can't edit them. I am using Jconsole and as far as I understand if the OpenMBeanAttributeInfoSupport of the attribute (when constructing the MBeanInfo) is on writable=true the JConsole should let me edit this attribute but it doesn't (for the other int and string it does)
maybe I am missing something, ANY HELP WOULD BE GREATLY APPRECIATED!!!

Thanks!
  • 1. Re: Edit tabluardatasupport in jconsole
    jtahlborn Expert
    Currently Being Moderated
    do you have setters for the collection and setters on any pojos? can you provide some example code for your mbeaninterface?
  • 2. Re: Edit tabluardatasupport in jconsole
    832442 Newbie
    Currently Being Moderated
    Hey jtahlborn,
    Thanks for the quick replay, I am attaching the whole class, would love to hear where did I go wrong.
    I decided to start with only 1 instance of a composite type instead of an Tabular type or collections. All I want to do is to be able to modify the composite type members through any JMX console (currently I am using Jconsole)

    package openMBean.jmx;

    import java.io.PrintWriter;
    import java.io.ByteArrayOutputStream;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Iterator;
    import java.util.List;
    import java.util.ListIterator;

    import javax.management.openmbean.OpenMBeanInfoSupport;
    import javax.management.openmbean.OpenMBeanOperationInfoSupport;
    import javax.management.openmbean.OpenMBeanParameterInfoSupport;
    import javax.management.openmbean.OpenMBeanParameterInfo;
    import javax.management.openmbean.SimpleType;
    import javax.management.openmbean.OpenMBeanConstructorInfoSupport;
    import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
    import javax.management.openmbean.OpenDataException;
    import javax.management.openmbean.CompositeData;
    import javax.management.openmbean.CompositeDataSupport;
    import javax.management.openmbean.KeyAlreadyExistsException;
    import javax.management.openmbean.TabularData;
    import javax.management.openmbean.TabularDataSupport;
    import javax.management.openmbean.TabularType;
    import javax.management.openmbean.CompositeType;
    import javax.management.openmbean.OpenType;
    import javax.management.MBeanOperationInfo;
    import javax.management.MBeanNotificationInfo;
    import javax.management.MBeanInfo;
    import javax.management.ReflectionException;
    import javax.management.MBeanException;
    import javax.management.RuntimeOperationsException;
    import javax.management.AttributeList;
    import javax.management.Attribute;
    import javax.management.AttributeNotFoundException;
    import javax.management.InvalidAttributeValueException;
    import javax.management.DynamicMBean;

    public class SimpleOpenMBean implements DynamicMBean {

         // Open MBean Info
         private OpenMBeanInfoSupport OMBInfo;

         // Attributes exposed for management
         private int nbChanges = 0;
         private CompositeData tShirt;     

         // Custom open types (and related info) used by this Open MBean class
         private static String[] itemNames = { "model", "color", "size",
                   "price" };
         private static String[] itemDescriptions = { "TShirt's model name",
                   "TShirt's color", "TShirt's size", "TShirt's price" };
         private static OpenType[] itemTypes = { SimpleType.STRING,
                   SimpleType.STRING, SimpleType.STRING, SimpleType.FLOAT };
         private static CompositeType tShirtType = null;

         // Legal values for TShirt features
         private static String[] legalModels = { "JDMK", "JMX", "JAVA" };
         private static OpenMBeanParameterInfoSupport modelParamInfo;

         private static String[] legalColors = { "black", "white", "red", "green", "blue" };
         private static OpenMBeanParameterInfoSupport colorParamInfo;

         private static String[] legalSizes = { "S", "M", "L", "XL", "XXL" };
         private static OpenMBeanParameterInfoSupport sizeParamInfo;

         private static float minPrice = 9.00f;
         private static float maxPrice = 19.99f;
         private static OpenMBeanParameterInfoSupport priceParamInfo;

         /* *** Static initialization *** */
         static {

              // initializes OpenType instances and ParameterInfo instances
              try {
                   // CompositeType instance for a TShirt
                   tShirtType = new CompositeType("tShirt", "a TShirt",
                             itemNames, itemDescriptions, itemTypes);
                   
                   // Parameter info for the model, color, size and price parameters
                   modelParamInfo = new OpenMBeanParameterInfoSupport("model",
                             "Valid TShirt model name. Legal models: "
                                       + Arrays.asList(legalModels).toString(),
                             SimpleType.STRING, "JMX", // default model is JMX
                             legalModels); // array of legal models
                   
                   colorParamInfo = new OpenMBeanParameterInfoSupport("color",
                             "Valid product color. Legal colors: "
                                       + Arrays.asList(legalColors).toString(),
                             SimpleType.STRING, "white", // default color is white
                             legalColors); // array of legal colors
                   
                   sizeParamInfo = new OpenMBeanParameterInfoSupport("size",
                             "Valid product size. Legal sizes: "
                                       + Arrays.asList(legalSizes).toString(),
                             SimpleType.STRING, "XL", // default size is XL
                             legalSizes); // array of legal sizes
                   
                   priceParamInfo = new OpenMBeanParameterInfoSupport("price",
                             "Valid product price (ranging from $" + minPrice
                                       + " to $" + maxPrice + ")",
                             SimpleType.FLOAT, null, // no default price
                             new Float(minPrice), // Min legal value for price
                             new Float(maxPrice)); // Max legal value for price
              } catch (OpenDataException e) {
                   // should not happen
                   ByteArrayOutputStream bout = new ByteArrayOutputStream();
                   PrintWriter pout = new PrintWriter(bout);
                   e.printStackTrace(pout);
                   pout.flush();
                   throw new RuntimeException(bout.toString());
              }

         }

         /* *** Contructor *** */

         /**
         * Constructs a SimpleOpenMBean instance containing an empty TShirts list
         */
         public SimpleOpenMBean() throws OpenDataException {

              buildTShirt("JMX","red","S",9.00f);
              
              buildMBeanInfo();
         }

         //Getters & Setters

         public CompositeData gettShirt() {
              return (CompositeData) tShirt;
         }
         
         public void settShirt(CompositeData newTShirt) {
              tShirt = newTShirt;
         }

         public void setNbChanges(int nbChanges) {
              this.nbChanges = nbChanges;
         }

         public int getNbChanges() {
              return nbChanges;
         }

         /* *** Operations *** */
         protected Object checkParam(OpenMBeanParameterInfo paramInfo,
                   Object param) throws OpenDataException {

              Object result;

              if (!paramInfo.isValue(param)) {
                   throw new OpenDataException("parameter "
                             + paramInfo.getName() + "'s value [" + param
                             + "] is not valid");
              } else if (param == null && paramInfo.hasDefaultValue()) {
                   result = paramInfo.getDefaultValue();
              } else {
                   result = param;
              }

              return result;
         }

         public CompositeData buildTShirt(String model, String color,
                   String size, Float price) throws OpenDataException {

              // Check parameter values are legal, assign default if necessary, or throws OpenDataException
              //
              model = (String) checkParam(modelParamInfo, model);
              color = (String) checkParam(colorParamInfo, color);
              size = (String) checkParam(sizeParamInfo, size);
              price = (Float) checkParam(priceParamInfo, price);

              Object[] itemValues = { model, color, size, price };
              tShirt = new CompositeDataSupport(tShirtType,
                        itemNames, itemValues);

              //addTShirt(result);
              return tShirt;
         }

         /* *** DynamicMBean interface implementation *** */
         public Object getAttribute(String attribute_name)
                   throws AttributeNotFoundException, MBeanException,
                   ReflectionException {

              if (attribute_name == null) {
                   throw new RuntimeOperationsException(
                             new IllegalArgumentException(
                                       "Attribute name cannot be null"),
                             "Cannot call getAttributeInfo with null attribute name");
              }
              if (attribute_name.equals("tShirt")) {
                   return gettShirt();
              }
              if (attribute_name.equals("NbChanges")) {
                   return getNbChanges();
              }
              throw new AttributeNotFoundException("Cannot find "
                        + attribute_name + " attribute ");
         }

         public void setAttribute(Attribute attribute)
                   throws AttributeNotFoundException,
                   InvalidAttributeValueException, MBeanException,
                   ReflectionException {

              if (attribute == null) {
                   throw new RuntimeOperationsException(
                             new IllegalArgumentException(
                                       "Attribute name cannot be null"),
                             "Cannot call getAttributeInfo with null attribute name");
              }
              
              if (attribute.getName().equals("tShirt")) {
                   settShirt((CompositeData) attribute.getValue());
              }
              
              if (attribute.getName().equals("NbChanges")) {
                   setNbChanges((Integer)attribute.getValue());
              }
              else{
                   throw new AttributeNotFoundException("Cannot find " + attribute.getName() + " attribute ");
              }
         }

         public AttributeList getAttributes(String[] attributeNames) {

              if (attributeNames == null) {
                   throw new RuntimeOperationsException(
                             new IllegalArgumentException(
                                       "attributeNames[] cannot be null"),
                             "Cannot call getAttributes with null attribute names");
              }
              AttributeList resultList = new AttributeList();

              if (attributeNames.length == 0)
                   return resultList;

              for (int i = 0; i < attributeNames.length; i++) {
                   try {
                        Object value = getAttribute(attributeNames);
                        resultList.add(new Attribute(attributeNames[i], value));
                   } catch (Exception e) {
                        e.printStackTrace();
                   }
              }
              return (resultList);
         }

         public AttributeList setAttributes(AttributeList attributes) {
              return new AttributeList(); // always empty
         }

         public Object invoke(String operationName, Object[] params,
                   String[] signature) throws MBeanException,
                   ReflectionException {

              if (operationName == null) {
                   throw new RuntimeOperationsException(
                             new IllegalArgumentException(
                                       "Operation name cannot be null"),
                             "Cannot call reflectInvoke with null operation name");
              }

              if (operationName.equals("buildTShirt")) {
                   // check params
                   if ((params.length != 4) || !(params[0] instanceof String)
                             || !(params[1] instanceof String)
                             || !(params[2] instanceof String)
                             || !(params[3] instanceof Float)) {
                        throw new RuntimeOperationsException(
                                  new IllegalArgumentException(
                                            "cannot reflectInvoke buildTShirt: "
                                                      + "expecting params[i] instanceof SimpleData for i = 0 to 3"),
                                  "Wrong content for array Object[] params to reflectInvoke buildTShirt method");
                   }
                   // reflectInvoke buildTShirt
                   try {
                        return buildTShirt((String) params[0],
                                  (String) params[1], (String) params[2],
                                  (Float) params[3]);
                   } catch (Exception e) {
                        throw new MBeanException(e, "invoking buildTShirt: "
                                  + e.getClass().getName() + "caught ["
                                  + e.getMessage() + "]");
                   }
              } else {
                   throw new ReflectionException(new NoSuchMethodException(
                             operationName), "Cannot find the operation "
                             + operationName);
              }
         } // reflectInvoke


         public MBeanInfo getMBeanInfo() {
              return OMBInfo;
         }

         /* *** Open MBean Info *** */
         private void buildMBeanInfo() {

              OpenMBeanAttributeInfoSupport[] attributes = new OpenMBeanAttributeInfoSupport[2];
              OpenMBeanConstructorInfoSupport[] constructors = new OpenMBeanConstructorInfoSupport[1];
              OpenMBeanOperationInfoSupport[] operations = new OpenMBeanOperationInfoSupport[1];
              MBeanNotificationInfo[] notifications = new MBeanNotificationInfo[0];

              // attribute TShirts (no default or legal values: not supported for tabular types anyway)
              attributes[0] = new OpenMBeanAttributeInfoSupport("tShirt",
                        "Test", tShirtType, true, true,
                        false);

              // attribute NbChanges (no default or legal values)
              attributes[1] = new OpenMBeanAttributeInfoSupport("NbChanges",
                        "Number of times the TShirts list has been updated.",
                        SimpleType.INTEGER, true, true, false);          

              // constructor
              constructors[0] = new OpenMBeanConstructorInfoSupport(
                        "SimpleOpenMBean",
                        "Constructs a SimpleOpenMBean instance containing an empty TShirts list.",
                        new OpenMBeanParameterInfoSupport[0]);

              // operation buildTShirt
              OpenMBeanParameterInfo[] params_build = new OpenMBeanParameterInfoSupport[4];
              params_build[0] = modelParamInfo;
              params_build[1] = colorParamInfo;
              params_build[2] = sizeParamInfo;
              params_build[3] = priceParamInfo;
              operations[0] = new OpenMBeanOperationInfoSupport(
                        "buildTShirt",
                        "Builds and returns a CompositeData TShirt instance from the specified parameters. "
                                  + "If parameter values are not legal according to the OpenMBeanParameterInfo instances for this method, "
                                  + "it throws an OpenDataException. "
                                  + "If model, color or size are null, it uses the default value provided in the OpenMBeanParameterInfo instances for this method.",
                        params_build, tShirtType, MBeanOperationInfo.INFO);

              // The OpenMBeanInfo
              OMBInfo = new OpenMBeanInfoSupport(this .getClass().getName(),
                        "Sample Open MBean", attributes, constructors,
                        operations, notifications);
         }
    }
  • 3. Re: Edit tabluardatasupport in jconsole
    jtahlborn Expert
    Currently Being Moderated
    that looks pretty much correct couple of comments. did a quick search and saw some comments that the limitation may just be jconsole (e.g. http://www.thatsjava.com/java-core-apis/56675/ ). did you try using jvisualvm? it's much nicer than jconsole. (you'll need to install a plugin in order to see mbeans).

    also, did you try using MXBeans? they are 100 times easier to use than openmbeans.

    p.s. please put code in code tags next time so that it is readable.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points