JDK-5043245 : Attribute type check is too restrictive in RequiredModelMBean.getAttribute()
  • Type: Enhancement
  • Component: core-svc
  • Sub-Component: javax.management
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2004-05-06
  • Updated: 2017-05-16
  • Resolved: 2005-04-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
5.0u6Fixed 6 b31Fixed
Related Reports
Relates :  
Description
Name: gm110360			Date: 05/06/2004


FULL PRODUCT VERSION :
jdk 1.5.0 beta 1
jmx RI 1.2.1

A DESCRIPTION OF THE PROBLEM :
The method getAttribute(String attribute) from RequiredModelMBean checks at runtime that the actual class of the attribute is the same as the one declared in ModelMBeanAttributeInfo.
However, this check is too restrictive : it only succeeds if the class is exactly the same or if it is a primitive type.
But what about interfaces or sub-classes ? For example, I want to return a map. My accessor declares a return type "java.util.Map", but within the method I return a "java.util.Hashtable", which implements "java.util.Map". Then an exception is thrown, although this should work.
The problem is the same when declaring a return type "MyClass" and actually returning an object of type "MySubclass", which extends "MyClass".

The specification is not very clear on this point. But it doesn't say anywhere that the declared return type should be EXACTLY the same as the actual return object type. I think it rather means that both types should be consistent or compatible.

A simple way to correct that would be to replace the "equals()" with "instanceof" for the type check in the code of getAttribute(String attribute)


ps: Looking at the source code from RequiredModelMBean, the method invoke(...) used to include the same kind of check, but it has been commented out in the source code.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Declare a class with the following method :

public java.util.Map getMap() { return new java.util.Hashtable(); }

2) Create a ModelMBeanInfo with the following ModelMBeanAttributeInfo :

ModelMBeanAttributeInfo("map", "a map attribute", /* the method above goes here */, null)

3) Register the class in the MBeanServer through a ModelMBean, with the following ObjectName :

"MyDomain:myattribute=myclass"

4) get the MBeanServer and do :

mBeanServer.getAttribute("MyDomain:myattribute=myclass", "map")

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
an object java.util.Hashtable should be returned
ACTUAL -
an InvalidAttributeValueException with the message  "Wrong value type received for get attribute", wrapped in an MBeanException

ERROR MESSAGES/STACK TRACES THAT OCCUR :
see Actual Result

REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER SUBMITTED WORKAROUND :
It is still possible to get the value of the attribute by calling the operation with "invoke", but this is not a real workaround.
(Incident Review ID: 261196) 
======================================================================

Comments
EVALUATION The implementation is within its rights to behave as it does. The spec says: "If the operation fails or the returned value is not of the same type as the attribute, an exception will be thrown." A java.util.Hashtable is not of the same type as java.util.Map, even if it is assignable to it. However, it is clear that this restriction is too strong. It should indeed be possible to return a java.util.Hashtable when the declared type is java.util.Map. Because the declared type is a string, this means that the spec has to explicitly say what it means: the getAttribute succeeds if the returned value has a type with the exact declared name; or if the returned value is null and the declared name is not a primitive type; or if the declared name can be loaded by the returned value's class loader and produces a class to which the returned value can be assigned. This is a nontrivial spec change, so it cannot reasonably be made in the Tiger timeframe. ###@###.### 2004-05-06 The RMMB.getAttribute javadoc will be changed as follows: In the last paragraph of RMMB.getAttribute, change this text: "If the operation fails or the returned value is not of the same type as the attribute, an exception will be thrown." to "If the operation fails or the returned value is not compatible with the declared type of the attribute, an exception will be thrown." Add a new paragraph: "The declared type of the attribute is the String returned by {@link ModelMBeanAttributeInfo#getType()}. A value is compatible with this type if one of the following is true: * the value is null; * the declared name is a primitive type name (such as "int") and the value is an instance of the corresponding wrapper type (such as java.lang.Integer); * the name of the value's class is identical to the declared name; * the declared name can be loaded by the value's class loader and produces a class to which the value can be assigned." ###@###.### 2005-03-02 16:30:19 GMT
02-03-2005

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
01-09-2004

PUBLIC COMMENTS RequiredModelMBean.getAttribute requires you to return an instance of exactly the type declared in the ModelMBeanAttributeInfo, not a subclass of that type.
01-09-2004

WORK AROUND Always declare the attribute type as a concrete type and always return a value of exactly that type. This is restrictive. ###@###.### 2004-05-06
06-05-2004