Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Custom validator in launched Eclipse cannot find classes from project workspace sources(Custom validator in launched Eclipse cannot find classes from project workspace sources. Class.forName() gives ClassNotFoundException. Integration tests work.)
Custom validator in launched Eclipse cannot find classes from project workspace sources [message #987533] Tue, 27 November 2012 00:55 Go to next message
Espinosa CZ is currently offline Espinosa CZFriend
Messages: 27
Registered: July 2009
Junior Member
My custom Validator in Launched Eclipse cannot find classes from project workspace sources. The Class.forName(qualifiedName) in my custom validator works in integration tests but not when run as Eclipse Application.

My language DeepCloneJavaValidator works well in tests but gives ClassNotFoundException for any class in workspace/src directory when the DSL is launched as Run as Eclipse Application.

I need to get real Class object from JvmTypeReference assignment value. I need the class to compare fields via introspection with declared fields in the DSL, they must match. And also I can infer types of fields and sub-classes. Only root type needs to be specified this way.

The JvmTypeReference assignment works flawlessly. The contextual help sees correctly project classes, like a.b.m.Book, dummy classes from my dummy project. Just Validator Class Loader does not see them.

Here is the problematic check.

@Check
public void checkFieldClass(ClassCloner rootCloner) {
	String qualifiedName = rootCloner.getClassToClone().getQualifiedName();
	try {
		Class<?> clazz = Class.forName(qualifiedName); 
		rootCloner.setJavaType(clazz.getName());
	} catch (ClassNotFoundException e) {
		error("Class '" + qualifiedName + "' does not exist (DCValidator)",
			DeepClonePackage.Literals.CLASS_CLONER__CLASS_TO_CLONE);
	}
}
// Method name is somewhat misleading, it should be like checkRootClonerClass()


I have tried different class loaders, but nothing works:
Class<?> clazz = Class.forName(qualifiedName); 
Class<?> clazz = Class.forName(qualifiedName, false, ClassLoader.getSystemClassLoader()); 
Class<?> clazz = Class.forName(qualifiedName);  // internally calls ClassLoader.getCallerClassLoader(); 
Class<?> clazz = Class.forName(qualifiedName, false, this.getClass().getClassLoader());
Class<?> clazz = getClass().getClassLoader().loadClass(qualifiedName);


Each approach gives different ClassLoader but none recognizes my project workspace classes (a.b.m.Book).

Sources for Validator:
https://bitbucket.org/espinosa/deepclonedsl/src/86cee21b23cf884bffce2d8140338e98123db7c7/src/my/home/dsl/validation/DeepCloneJavaValidator.java?at=master

Sources for language definition:
https://bitbucket.org/espinosa/deepclonedsl/src/3f6ca054212223ccad2f43f7ec1c934e358f05f7/src/my/home/dsl/DeepClone.xtext?at=master

Sources of my validator tests (all passing tests!):
https://bitbucket.org/espinosa/deepclonedsl.tests/src/e89ce276a060641aac65ba0701d37a865edb69e6/src/my/home/dsl/deepclone/DeepCloneValidationTest.xtend?at=master

Stacktrace (clipped):
java.lang.ClassNotFoundException: a.b.m.Book
org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
 org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
 org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412) org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
java.lang.ClassLoader.loadClass(ClassLoader.java:247) my.home.dsl.validation.DeepCloneJavaValidator.checkFieldClass(DeepCloneJavaValidator.java:73) . . .


Stacktrace when SystemClassLoader is used (clipped):
java.lang.ClassNotFoundException: a.b.m.Book
java.net.URLClassLoader$1.run(URLClassLoader.java:202)
java.security.AccessController.doPrivileged(Native Method)
java.net.URLClassLoader.findClass(URLClassLoader.java:190)
java.lang.ClassLoader.loadClass(ClassLoader.java:306)
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
java.lang.ClassLoader.loadClass(ClassLoader.java:247)
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:247) my.home.dsl.validation.DeepCloneJavaValidator.checkFieldClass(DeepCloneJavaValidator.java:70) . . .


Any hints?
Espinosa
Re: Custom validator in launched Eclipse cannot find classes from project workspace sources [message #987648 is a reply to message #987533] Tue, 27 November 2012 12:30 Go to previous messageGo to next message
Espinosa CZ is currently offline Espinosa CZFriend
Messages: 27
Registered: July 2009
Junior Member
I have a partial solution. This worked:

Class<?> clazz = DeepCloneJavaValidator.class.getClassLoader().getParent().getParent().loadClass(qualifiedName);


or

Class<?> clazz = this.getClass().getClassLoader().getParent().getParent().loadClass(qualifiedName);


To make it general, does this mean that I need to reach for the top most parent ClassLoader?
Re: Custom validator in launched Eclipse cannot find classes from project workspace sources [message #987661 is a reply to message #987648] Tue, 27 November 2012 13:37 Go to previous messageGo to next message
Espinosa CZ is currently offline Espinosa CZFriend
Messages: 27
Registered: July 2009
Junior Member
False positive.
It just fails with NullPointerException, silently, in a different thread, it is not propagated back to original thread so it looked like it passed, no stack traces, just execution of that particular validation check is interrupted and silently skipped.
So I am still on search for solution.

This problem should be so common!? Every second JVM based DSL must touch introspection at some point. And getting the Class it the starting point. Strange.
Eclipse: Version: 4.2.0, Build id: I20120608-1400
Xtext Runtime 2.3.1.v201208210947
Re: Custom validator in launched Eclipse cannot find classes from project workspace sources [message #987662 is a reply to message #987648] Tue, 27 November 2012 13:39 Go to previous messageGo to next message
Espinosa CZ is currently offline Espinosa CZFriend
Messages: 27
Registered: July 2009
Junior Member
False positive.
It just fails with NullPointerException, silently, in a different thread, it is not propagated back to original thread so it looked like it passed, no stack traces, just execution of that particular validation check is interrupted and silently skipped.
So I am still on search for solution.

This problem should be so common!? Every second JVM based DSL must touch introspection at some point. And getting the Class it the starting point. Strange.
Eclipse: Version: 4.2.0, Build id: I20120608-1400
Xtext Runtime 2.3.1.v201208210947
Re: Custom validator in launched Eclipse cannot find classes from project workspace sources [message #987664 is a reply to message #987662] Tue, 27 November 2012 13:47 Go to previous messageGo to next message
Espinosa CZ is currently offline Espinosa CZFriend
Messages: 27
Registered: July 2009
Junior Member
And for record this does not work either:

Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(qualifiedName); 

gives same ClassNotFoundException

((BundleHost) Activator.getBundleContext().getBundle()).getLoaderProxy().getBundleLoader();

This I found in another forum. There is no Activator.getBundleContext(),
There is one Activator class in Xtext libs, probably not the right one.

String[] classPathEntries = JavaRuntime.computeDefaultRuntimeClassPath(project);

This I found in another forum. No idea what JavaRuntime is. Eclispse/JDT stuff?
Re: Custom validator in launched Eclipse cannot find classes from project workspace sources [message #987865 is a reply to message #987533] Wed, 28 November 2012 12:45 Go to previous message
Espinosa CZ is currently offline Espinosa CZFriend
Messages: 27
Registered: July 2009
Junior Member
I have found a solution. I have not solved the ClassLoader issue, but found at least a way out. Key is to redefine question, do I really need introspection?

Instead I can use Xtext Common Types package to get the same information.
Instead of java.bean.Introspector and PropertyDescriptors I can use org.eclipse.xtext.common.types.JvmTypeReference, JvmDeclaredType and JvmField.

Benefits - no dealings with any ClassLoader and I guess better handling of things like generics, build time versus run-time information.

Here is example how to get list of all member fields names for a given JVM Type (Java Class):

public List<String> getFieldNamesForClass(JvmTypeReference jvmTypeRef) {
   List<String> result = new ArrayList<String>();
   if (jvmTypeRef.getType() instanceof JvmDeclaredType) {
       JvmDeclaredType declaredType = (JvmDeclaredType)jvmTypeRef.getType();
       for (JvmField field : declaredType.getDeclaredFields()) {
          result.add(field.getSimpleName());
        }
   }
   return result;
}

The input parameter is provided by the model.

For full code see https://bitbucket.org/espinosa/deepclonedsl/src/f9e146b33aadaa70f26a900bc8cffe1b928ffc60/src/my/home/dsl/utils/ReflectionUtils.java?at=master

Espinosa, 28/11/2012, 12:45 GMT

[Updated on: Wed, 05 December 2012 20:42]

Report message to a moderator

Previous Topic:Beginner: how to reference attribute of entity (scope, context, ??)
Next Topic:Test my grammar
Goto Forum:
  


Current Time: Tue Apr 16 08:41:15 GMT 2024

Powered by FUDForum. Page generated in 2.11156 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top