Generic getters and setters take a parameter that indicates the name of the attribute to read or write. There are two issues to keep in mind when implementing these methods:
Attribute names must be correctly mapped to their corresponding internal representation.
Invalid attribute names and types should raise an exception, including when writing to a read-only attribute and reading a write-only attribute.
The getAttribute method is the simplest, since only the attribute name must be verified:
public Object getAttribute(String attribute_name) throws AttributeNotFoundException, MBeanException, ReflectionException { // Check attribute_name to avoid NullPointerException later on if (attribute_name == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute name cannot be null"), "Cannot invoke a getter of " + dClassName + " with null attribute name"); } // Call the corresponding getter for a recognized attribute_name if (attribute_name.equals("State")) { return getState(); } if (attribute_name.equals("NbChanges")) { return getNbChanges(); } // If attribute_name has not been recognized throw(new AttributeNotFoundException( "Cannot find " + attribute_name + " attribute in " + dClassName)); } // internal methods for getting attributes public String getState() { return state; } public Integer getNbChanges() { return new Integer(nbChanges); } // internal variables representing attributes private String state = "initial state"; private int nbChanges = 0; |
The setAttribute method is more complicated, since you must also ensure that the given type can be assigned to the attribute and handle the special case for a null value:
public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { // Check attribute to avoid NullPointerException later on if (attribute == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute cannot be null"), "Cannot invoke a setter of " + dClassName + " with null attribute"); } // Note: Attribute class constructor ensures the name not null String name = attribute.getName(); Object value = attribute.getValue(); // Call the corresponding setter for a recognized attribute name if (name.equals("State")) { // if null value, try and see if the setter returns any exception if (value == null) { try { setState( null ); } catch (Exception e) { throw(new InvalidAttributeValueException( "Cannot set attribute "+ name +" to null")); } } // if non null value, make sure it is assignable to the attribute else { try { if ((Class.forName("java.lang.String")).isAssignableFrom( value.getClass())) { setState((String) value); } else { throw(new InvalidAttributeValueException( "Cannot set attribute "+ name + " to a " + value.getClass().getName() + " object, String expected")); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } // optional: recognize an attempt to set a read-only attribute else if (name.equals("NbChanges")) { throw(new AttributeNotFoundException( "Cannot set attribute "+ name + " because it is read-only")); } // unrecognized attribute name else { throw(new AttributeNotFoundException( "Attribute " + name + " not found in " + this.getClass().getName())); } } // internal method for setting attribute public void setState(String s) { state = s; nbChanges++; } |
Notice that if a change in your management solution requires you to change your management interface, it will be harder to do with a dynamic MBean. In a standard MBean, each attribute and operation is a separate method, so unchanged attributes are unaffected. In a dynamic MBean, you must modify the generic methods that encode all attributes.