Menu

#28 BeanAnalyzer sometimes returning wrong PropertyType

3.2.0
open-accepted
5
2013-08-28
2011-04-13
Joerg M.
No

In a certain constellation of interfaces and their implementations BeanAnalyzer returns the wrong type. Following situation:

There are two classes A and B where B extends A.
Then there is an Interface X:

public interface X {
A getField()
}

and there is an implementation of the Interface XImpl

public class XImpl implements X {
public B getField() {
//some implementation
}
}

Please note the different return type.

Now the problem is, what class.getDeclaredMethods() returns in this situation.
BeanAnalyzer uses this Method on line 37 to search for all properties of a class:
...
for( Method method : clazz.getDeclaredMethods() ) {
...
In that situation getDeclaredMethods() will return two entries even though there is only one method in the class.
One of the entries will have A (the parent) as return type and one will have B as return type.

BeanAnalyzer will only store the first of the types. As in Line 48 it checks whether the property already exists and ignores any other entries.

...
if( !properties.containsKey( property ) ) {
properties.put( property, new BeanProperty(property, this) );
}
...

Now comes the nasty part. The order of the methods in getDeclaredMethods() is undefined. (see Javadoc) This lead to funny effects like the type was wrong in debug mode, but correct in normal mode.

If the type is wrong, this leads to certain consequences. One of them is that the writeMethod can not be correctly identified by BeanProperty. See line 53

...
writeMethod = writeMethods.get(propertyType);
...

I hope you could follow my description of this pretty complex bug :) If there are any questions please do not hesitate to ask.

(Version was 2.1, the line-numbers refer to the source in tags/flexjson-2.1)

Discussion

  • Charlie Hubbard

    Charlie Hubbard - 2011-06-25

    This is basically problems with covariant return types and how the BeanAnalyzer matches up the setter/getter for those. Yes this is a tricky bug so good catch in finding it.

     
  • Charlie Hubbard

    Charlie Hubbard - 2012-03-12
    • status: open --> open-accepted
     
  • Brandon Goodin

    Brandon Goodin - 2013-08-28

    I have noticed that our BeanAnalyzerTest will fail intermittently when running:

    compare(Introspector.getBeanInfo( Book.class ), BeanAnalyzer.analyze( Book.class ) );
    

    with the following error:

    junit.framework.AssertionFailedError: 
    Expected :public java.lang.String flexjson.mock.Book.getID()
    Actual   :public abstract java.lang.String flexjson.mock.Periodical.getID()
    

    So, it does appear that our tests catch the issue intermittently.

     
  • Brandon Goodin

    Brandon Goodin - 2013-08-28
    • Group: --> 3.2.0
     

Log in to post a comment.

MongoDB Logo MongoDB