Community
Participate
Working Groups
When common.types creates the EMF representation of a Java class, it inspects all fields of the class via clazz.getDeclaredFields(). If a class from a referenced bundle is inspected, and this type defines a field of a type that is imported in the other bundle by package import, this throws an exception. The easiest way to reproduce this is to spawn a runtime workbench from the xtext development workspace, import the Fowler example and run the workflow: StandaloneSetuop refers to Log from org.apache.commons.logging vie package import and cannot be resolved. Paradoxically, the exception is not thrown, if the bundle of the type containing the inspected type is located in the runtime workspace, so this could be another PDE issue. Further investigation is needed here. A possible workaround is to replace getDeclaredFields() by getFields() and filter the resulting set with those owned by the inspected type. The same should be applied to all other occurrences of getDeclaredFields(), as well as getDeclaredConstructors(), declared methods.
Also happens when when running eclipse directly, not only as runtime workbench.
getFields will only return the public fields while getDeclaredFields returns any field declared by the class instance so this is no solution. If getDeclaredFields throws an error, I'ld expect the same error to be thrown if any code tries to access the field and call a method on the referenced object - but that's only an assumption.
I did some investigation: I've create a test bundle with two classes, one in an exported package and one in a non-exported package: ------------ package org.test; import org.test.internal.InternalClass; public class PublicClass { private InternalClass internal; public String getFoo() { return internal.foo; } } ------------ package org.test.internal; public class InternalClass { public String foo; } ------------ When I now try tow access the exported class form a different bundle: ------------ public void testFields_02() { String typeName = org.test.PublicClass.class.getName(); JvmGenericType type = (JvmGenericType) getTypeProvider().findTypeByName(typeName); for (JvmMember m :type.getMembers()) if(m instanceof JvmField) System.out.println(((JvmField)m).getType().getType().getCanonicalName()); assertNotNull(type); } ------------ (I've put this into org.eclipse.xtext.common.types.access.impl.AbstractTypeProviderTest) then this works fine during runtime, but when executed as a plugin-test, I get the exception listed below. I expected to run into this exception at some point, but the bad thing is that it is thrown when calling getResource() and not when actually navigating the non-visible type. o.e.x.common.types.access.TypeNotFoundException: No such type available 'org.test.PublicClass' o.e.x.common.types.access.jdt.JdtTypeProvider.createMirrorForFQN(JdtTypeProvider.java:74) o.e.x.common.types.access.impl.AbstractTypeProvider.createMirror(AbstractTypeProvider.java:61) o.e.x.common.types.access.impl.AbstractTypeProvider.createResource(AbstractTypeProvider.java:40) o.e.x.common.types.access.impl.AbstractTypeProvider.createResource(AbstractTypeProvider.java:1) o.e.e.ecore.resource.impl.ResourceSetImpl.createResource(ResourceSetImpl.java:425) o.e.e.ecore.resource.impl.ResourceSetImpl.demandCreateResource(ResourceSetImpl.java:239) o.e.e.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:391) o.e.x.common.types.access.jdt.JdtTypeProvider.findTypeByName(JdtTypeProvider.java:54) o.e.x.common.types.access.impl.AbstractTypeProviderTest.testFields_02(AbstractTypeProviderTest.java:1220)
Thanks for the investigation. Looks like the wrong classloader is used in the test-setup or the code looses track of the right on internally. Would you please attach your testcase as a patch?
Created attachment 170312 [details] The new Testcase
Created attachment 170318 [details] The Bundle Accessed by the Testcase here it is. It doesn't really fit into our infrastructure, though, since it introduces a new bundle.
Looks like we have two separate issues here: 1) Package imports are not reexported, so we have to add org.apache.log4j and similar bundles to to the generator, the examples, and every Xtext project 2) Java members referring to internal classes are not handled properly. Shouldn't we separate these into two bugs?
to (1). I've already added a required-bundle dependency from the arithmetics example to commons logging. This is the only scenario where I ran into such an exception without explicitly searching for it.
I moved the testFields_02() to the ClasspathTypeProviderTest (the descendent of AbstracTypeProviderTest that actually uses reflective access based on a classLoader) and everything is green. Please note that the bundle org.test cannot be accessed by the other subclasses of AbstractTypeProvierTest as they rely on the information of an IJavaProject. This IJavaProject is created in the junit-workspace and has no reference to the bundle org.test and thereby cannot resolve the org.test.PublicClass. Futhermore it is expected that the loop in testFields_02 accesses the fields of PublicClass but due to class loader restriction it cannot resolve the actual type of the field in PublicClass as it is internal to the bundle thus field.typeRef.type returns an unresolved proxy. From my point of view, internal classes are handled gracefully and I won't like to alter the current strategy prior to the Helios release. Did I miss something?
As issue (1) is resolved and the second is hard to tackle, I'll move it to a new ticket and close this one.
See bug 315090.
Closing bug which were set to RESOLVED before Eclipse Neon.0.