3 Replies Latest reply: Jan 20, 2011 6:49 AM by jtahlborn RSS

    Edit tabluardatasupport in jconsole

    832442
      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
          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
            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
              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.