This content has been marked as final.
Show 24 replies
-
1. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
starksm64 Nov 19, 2008 3:38 PM (in response to starksm64)It looks like whatever the issue is, its random as often the test passes, but when it fails its failing over confusing an enum as another type. In this case it was treated as an Integer:
Caused by: java.lang.NumberFormatException: For input string: "ONE" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:447) at java.lang.Integer.valueOf(Integer.java:526) at java.lang.Integer.decode(Integer.java:919) at org.jboss.util.propertyeditor.IntegerEditor.setAsText(IntegerEditor.java:42) at org.jboss.reflect.plugins.ValueConvertor.convertValue(ValueConvertor.java:139) at org.jboss.reflect.plugins.ValueConvertor.convertValue(ValueConvertor.java:90) at org.jboss.reflect.plugins.ValueConvertor.convertValue(ValueConvertor.java:75) at org.jboss.reflect.spi.PrimitiveInfo.convertValue(PrimitiveInfo.java:228) at org.jboss.metatype.plugins.values.DefaultMetaValueFactory.convertValue(DefaultMetaValueFactory.java:1030) ... 33 more
-
2. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
alesj Nov 19, 2008 4:52 PM (in response to starksm64)You can leave it, and I'll have a look as it's my test.
But I won't object if you fix it. :-) -
3. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
starksm64 Nov 19, 2008 5:03 PM (in response to starksm64)The problem is in determining the component type when a java.util.Set generic is passed in. In this case its a Set[TestEnum], but the component type is determined to be java.lang.Integer.
441 DEBUG [DefaultMetaValueFactory] unwrapCollection, type: ReflectClassInfoImpl@30cb4b{name=java.util.Set} 441 DEBUG [DefaultMetaValueFactory] unwrapCollection, componentType: java.lang.Integer 443 DEBUG [DefaultMetaValueFactory] convertValue failure(For input string: "TWO"), value=TWO, value.class: java.lang.String, typeInfo: java.lang.Integer
Just adding a logging statement can change the failure or even fix the problem. Its some issue with reflection on the generic element type that is suspect. -
5. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
alesj Nov 20, 2008 7:08 AM (in response to starksm64)"scott.stark@jboss.org" wrote:
The problem is in determining the component type when a java.util.Set generic is passed in. In this case its a Set[TestEnum], but the component type is determined to be java.lang.Integer.441 DEBUG [DefaultMetaValueFactory] unwrapCollection, type: ReflectClassInfoImpl@30cb4b{name=java.util.Set} 441 DEBUG [DefaultMetaValueFactory] unwrapCollection, componentType: java.lang.Integer 443 DEBUG [DefaultMetaValueFactory] convertValue failure(For input string: "TWO"), value=TWO, value.class: java.lang.String, typeInfo: java.lang.Integer
Just adding a logging statement can change the failure or even fix the problem. Its some issue with reflection on the generic element type that is suspect.
This looks like caching issue.
See UnwrapValueUnitTestCase::testCollectionUnwrap.
Before Enums we test Integers.
Looks like Set.class is mapped to ClassInfo who's component type is
a leftover from previous Integers testing.
I'll dig into more. -
6. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
alesj Nov 20, 2008 7:31 AM (in response to starksm64)"alesj" wrote:
This looks like caching issue.
Yup, caching:
- https://jira.jboss.org/jira/browse/JBREFLECT-7
This is what's actually going on:
(code is from WeakTypeCache)
1) checkCollection(new HashSet(), getType("Integer", Set.class), i1, i2);protected void put(ParameterizedType type, T result) { Class<?> rawType = (Class<?>) type.getRawType(); ClassLoader cl = SecurityActions.getClassLoader(rawType); Map<String, T> classLoaderCache = getClassLoaderCache(cl); synchronized (classLoaderCache) { // TODO JBMICROCONT-131 something better than toString()? classLoaderCache.put(type.toString(), result); } }
interface java.util.Set + result are now part of cache
2) checkCollection(new HashSet(), getType("Enum", Set.class), one, two, three, one);protected T peek(ParameterizedType type) { Class<?> rawType = (Class<?>) type.getRawType(); ClassLoader cl = SecurityActions.getClassLoader(rawType); Map<String, T> classLoaderCache = getClassLoaderCache(cl); synchronized (classLoaderCache) { return classLoaderCache.get(type.toString()); } }
And you're 'unlucky' that weak value is still cached under "interface java.util.Set".
Hence you get integer Set --> Integer component type.
So, JBMAN-38 is purely JBREFLECT-7's result.
Who's gonna bite into JBREFLECT-7, Adrian? :-) -
7. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
adrian.brock Nov 20, 2008 8:10 AM (in response to starksm64)"alesj" wrote:
So, JBMAN-38 is purely JBREFLECT-7's result.
Who's gonna bite into JBREFLECT-7, Adrian? :-)
What makes you think JBREFLECT-7 is causing this?
The toString() of the parameterized types are clearly different so they
shouldn't conflict in the cache.
I added some System.out.printlns to DefaultMetaTypeFactoryIndex: src/main/java/org/jboss/metatype/plugins/types/DefaultMetaTypeFactory.java =================================================================== --- src/main/java/org/jboss/metatype/plugins/types/DefaultMetaTypeFactory.java (revision 81358) +++ src/main/java/org/jboss/metatype/plugins/types/DefaultMetaTypeFactory.java (working copy) @@ -133,10 +133,14 @@ { // Generate it result = generate(typeInfo); + +System.out.println(typeInfo + " ==> " + result); // Cache it typeInfo.setAttachment(MetaType.class.getName(), result); } + +System.out.println(typeInfo + " <== " + result); // Return the result return result;
And modified the test to just the Set retrieval you point to.
The output I get is:0 DEBUG [UnwrapValueUnitTestCase] ==== Starting testCollectionUnwrap ==== ReflectClassInfoImpl@3570b0{name=java.lang.Object} ==> MutableCompositeMetaType{java.lang.Object} ReflectClassInfoImpl@3570b0{name=java.lang.Object} <== MutableCompositeMetaType{java.lang.Object} ReflectClassInfoImpl@982589{name=java.util.HashSet} ==> CollectionMetaType{type=java.util.HashSet elementType=MutableCompositeMetaType{java. lang.Object} ReflectClassInfoImpl@982589{name=java.util.HashSet} <== CollectionMetaType{type=java.util.HashSet elementType=MutableCompositeMetaType{java. lang.Object} java.lang.Integer ==> SimpleMetaType:java.lang.Integer java.lang.Integer <== SimpleMetaType:java.lang.Integer ReflectClassInfoImpl@982589{name=java.util.HashSet} <== CollectionMetaType{type=java.util.HashSet elementType=MutableCompositeMetaType{java. lang.Object} java.lang.Integer <== SimpleMetaType:java.lang.Integer ReflectClassInfoImpl@3570b0{name=java.lang.Object} <== MutableCompositeMetaType{java.lang.Object} ReflectClassInfoImpl@a9c09e{name=java.util.Set} ==> CollectionMetaType{type=java.util.Set elementType=MutableCompositeMetaType{java.lang.Obj ect} ReflectClassInfoImpl@a9c09e{name=java.util.Set} <== CollectionMetaType{type=java.util.Set elementType=MutableCompositeMetaType{java.lang.Obj ect} java.lang.Integer <== SimpleMetaType:java.lang.Integer java.lang.Integer <== SimpleMetaType:java.lang.Integer HERE you can see the parameterized type for Set<Integer> ParameterizedClassInfo@a4e743{java.util.Set<java.lang.Integer>} ==> CollectionMetaType{type=java.util.Set elementType=SimpleMetaType:java.la ng.Integer ParameterizedClassInfo@a4e743{java.util.Set<java.lang.Integer>} <== CollectionMetaType{type=java.util.Set elementType=SimpleMetaType:java.la ng.Integer java.lang.Integer <== SimpleMetaType:java.lang.Integer ReflectClassInfoImpl@982589{name=java.util.HashSet} <== CollectionMetaType{type=java.util.HashSet elementType=MutableCompositeMetaType{java. lang.Object} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} ==> org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} ReflectClassInfoImpl@982589{name=java.util.HashSet} <== CollectionMetaType{type=java.util.HashSet elementType=MutableCompositeMetaType{java. lang.Object} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} ReflectClassInfoImpl@a9c09e{name=java.util.Set} <== CollectionMetaType{type=java.util.Set elementType=MutableCompositeMetaType{java.lang.Obj ect} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} HERE you can see the parameterized type for Set<TestEnum> ParameterizedClassInfo@1cbfe9d{java.util.Set<org.jboss.test.metatype.values.factory.support.TestEnum>} ==> CollectionMetaType{type=java.util .Set elementType=org.jboss.test.metatype.values.factory.support.TestEnum{[ONE, TWO, THREE]} ParameterizedClassInfo@1cbfe9d{java.util.Set<org.jboss.test.metatype.values.factory.support.TestEnum>} <== CollectionMetaType{type=java.util .Set elementType=org.jboss.test.metatype.values.factory.support.TestEnum{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} EnumInfoImpl@14c194d{name=org.jboss.test.metatype.values.factory.support.TestEnum} <== org.jboss.test.metatype.values.factory.support.TestEn um{[ONE, TWO, THREE]} 88 DEBUG [UnwrapValueUnitTestCase] testCollectionUnwrap took 87ms 88 DEBUG [UnwrapValueUnitTestCase] ==== Stopping testCollectionUnwrap ====
-
8. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
adrian.brock Nov 20, 2008 8:13 AM (in response to starksm64)"adrian@jboss.org" wrote:
"alesj" wrote:
So, JBMAN-38 is purely JBREFLECT-7's result.
Who's gonna bite into JBREFLECT-7, Adrian? :-)
What makes you think JBREFLECT-7 is causing this?
The toString() of the parameterized types are clearly different so they
shouldn't conflict in the cache.
I agree toString() is not reliable (since it is not documented what format it will have)
which is why I raised the FIXME, but it doesn't look to me like it is causing this problem? -
9. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
adrian.brock Nov 20, 2008 8:23 AM (in response to starksm64)"alesj" wrote:
And you're 'unlucky' that weak value is still cached under "interface java.util.Set".
Hence you get integer Set --> Integer component type.
I don't know that luck comes into it, since AFAIK java requires the
ParameterizedType to be held as a strong reference until the testCollectionUnWrap
method finishes (that is its scope of definition).
Just in case that is not true, I changed the method to ensure that a strong ref is heldpublic void testCollectionUnwrap() throws Exception { Integer i1 = 123; Integer i2 = 123; Type hold = getType("Integer", Set.class); checkCollection(new HashSet<Integer>(), i1, i2); checkCollection(new HashSet<Integer>(), Set.class, i1, i2); checkCollection(new HashSet<Integer>(), hold, i1, i2); TestEnum one = TestEnum.ONE; TestEnum two = TestEnum.TWO; TestEnum three = TestEnum.THREE; checkCollection(new HashSet<TestEnum>(), one, two, three, one); checkCollection(new HashSet<TestEnum>(), Set.class, one, two, three, one); checkCollection(new HashSet<TestEnum>(), getType("Enum", Set.class), one, two, three, one); System.out.println(hold); // We still hold a reference }
And I still can't reproduce the problem. -
10. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
alesj Nov 20, 2008 8:31 AM (in response to starksm64)"adrian@jboss.org" wrote:
What makes you think JBREFLECT-7 is causing this?
Since it has all the symptoms that JBREFLECT-7 might cause. :-)"adrian@jboss.org" wrote:
The toString() of the parameterized types are clearly different so they
shouldn't conflict in the cache.
Yes, I missed this.
As I've thought we do toString on raw.
But like you say in your fixme,
this only shows how it's done in Sun JDK."adrian@jboss.org" wrote:
but it doesn't look to me like it is causing this problem?
Dunno what else could.
If I was able to reproduce it, things would be a lot easier. -
11. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
alesj Nov 20, 2008 8:34 AM (in response to starksm64)"adrian@jboss.org" wrote:
Just in case that is not true, I changed the method to ensure that a strong ref is held
...
And I still can't reproduce the problem.
Perhaps if Scott does this, he should get exception every time - if PT::toString is really the cause. -
12. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
alesj Nov 20, 2008 8:48 AM (in response to starksm64)What about if we built our own String key?
Type type = getType("Integer", Set.class); ParameterizedType pt = ParameterizedType.class.cast(type); System.out.println(pt.getRawType()); System.out.println(pt.getOwnerType()); System.out.println(Arrays.toString(pt.getActualTypeArguments())); interface java.util.Set null [class java.lang.Integer]
-
13. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
adrian.brock Nov 20, 2008 9:22 AM (in response to starksm64)I think I've found A problem? But I'm still not sure
if this is the cause of the problem seen.
The issue is that DefaultMetaValueFactory::unwrapCollection() has thisBeanInfo collectionInfo; // null is not instance of if (type instanceof ClassInfo) { collectionInfo = configuration.getBeanInfo(type); }
Which if you look in AbstractBeanInfoFactory has this cachingpublic BeanInfo getBeanInfo(ClassAdapter classAdapter, BeanAccessMode accessMode) { if (classAdapter == null) throw new IllegalArgumentException("Null class adapter."); if (accessMode == null) accessMode = BeanAccessMode.STANDARD; synchronized (cache) { ClassLoader cl = classAdapter.getClassLoader(); ClassInfo classInfo = classAdapter.getClassInfo(); String className = classInfo.getName(); Map<String, Map<BeanAccessMode, BeanInfo>> map = cache.get(cl);
The issue being that for ParameterizedClassInfo, classInfo.getName()
effectively maps to getRawType().getName() (actually this is done
through the super construction of the DelegateClassInfo).
Then the next step in unwrapCollection is to use the ClassInfo of the
BeanInfo to get the componentTypeClassInfo classInfo = collectionInfo.getClassInfo(); Collection collection = (Collection)createNewInstance(collectionInfo); TypeInfo componentType = classInfo.getComponentType();
which should be the raw type?
Clearly, the caching in AbstractBeanInfoFactory shouldn't be using
classInfo.getName() in its caching.
Or if it is going to use that, then ParameterizedClassInfo needs to override getName()
to return the generic name (but I'm not sure what that would break?).
Parameterized types should get their own BeanInfo, e.g.// This is a parameterized type with one Object property "something" public class GenericBean<T> { private T t; public T getSomething() { return t; } public void setSomething(T t) { this.t = t; } } // This is a parameterized type with one **String** property "something" public class StringBean extends GenericBean<String> {}
-
14. Re: UnwrapValueUnitTestCase.testCollectionUnwrap failure on
adrian.brock Nov 20, 2008 9:28 AM (in response to starksm64)"alesj" wrote:
What about if we built our own String key?
The toString() in openjdk looks like this:public String toString() { StringBuilder sb = new StringBuilder(); if (ownerType != null) { if (ownerType instanceof Class) sb.append(((Class)ownerType).getName()); else sb.append(ownerType.toString()); // HERE! sb.append("."); if (ownerType instanceof ParameterizedTypeImpl) { // Find simple name of nested type by removing the // shared prefix with owner. sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$", "")); } else sb.append(rawType.getName()); } else sb.append(rawType.getName()); if (actualTypeArguments != null && actualTypeArguments.length > 0) { sb.append("<"); boolean first = true; for(Type t: actualTypeArguments) { if (!first) sb.append(", "); if (t instanceof Class) sb.append(((Class)t).getName()); else sb.append(t.toString()); // HERE! first = false; } sb.append(">"); } return sb.toString();
But note the the code I've marked HERE! which in turn would also need fixing
if we assume these reflective objects don't have valid toString()s