United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-5043245 : Attribute type check is too restrictive in RequiredModelMBean.getAttribute()

Details
Type:
Enhancement
Submit Date:
2004-05-06
Status:
Resolved
Updated Date:
2005-04-01
Project Name:
JDK
Resolved Date:
2005-04-01
Component:
core-svc
OS:
windows_2000
Sub-Component:
javax.management
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:

Related Reports
Backport:
Relates:

Sub Tasks

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
                                     
2005-03-02
PUBLIC COMMENTS

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

BugTraq+ Release Management Values

COMMIT TO FIX:
mustang


                                     
2004-09-01
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
                                     
2004-05-06



Hardware and Software, Engineered to Work Together