18

I am using a third party library called Reflections (not to be mistaken with Java reflection) to search another jar for Classes that extend Foo using the following code:

Reflections reflections = new Reflections("com.example");
for(Class<? extends Foo> e : reflections.getSubTypesOf(Foo.class)) {
    doSomething()
}

When I do this Reflections throws the following error:

org.reflections.ReflectionsException: could not get type for name com.example.ExtendsFoo

Does anyone know how to fix this cause I'm stumped?

Thanks in advance!

Lonzak
  • 9,334
  • 5
  • 57
  • 88
Kezz
  • 1,680
  • 3
  • 19
  • 37
  • you need to provide some more code (like the ExtendsFoo class), maybe some info about the package structure, and maybe a bit more of the stack trace of the exception. – Nikola Yovchev May 29 '13 at 22:54
  • Is Reflections a class from Java API? give us more info.. – Satya May 30 '13 at 03:18
  • I'm using this as indicated by my tag: https://code.google.com/p/reflections/ – Kezz May 30 '13 at 07:53

3 Answers3

15

The problem may be due to not having a class loader that can resolve the name (even though it can resolve the subtype). This sounds contradictory, but I had the error message when I was building a Configuration and using ClasspathHelper.forClassLoader on an application- instantiated URLClassloader to figure out what to scan on the classpath, but not passing in said URLClassLoader into the Reflections configuration so that it could instantiate things correctly.

So you may want to try something along the lines of the following:

URLClassLoader urlcl = new URLClassLoader(urls);
Reflections reflections = new Reflections(
  new ConfigurationBuilder().setUrls(
    ClasspathHelper.forClassLoader(urlcl)
  ).addClassLoader(urlcl)
);

where urls is an array of URLS to the jars containing the classes you want to load. I was getting the same error as you if I did not have the final addClassLoader(...) call to the ConfigurationBuilder.

If this doesn't work, or is not applicable, it may be worth just setting a breakpoint in ReflectionsUtil.forName(String typeName, ClassLoader... classLoaders)) to see what is going on.

Mzzzzzz
  • 4,770
  • 7
  • 30
  • 47
chooks
  • 694
  • 7
  • 20
  • Yes this was the issue I was having. In the end I just wrote my own implementation of `getSubtypesOf`. This is also better because the Reflections API can be too cumbersome for some projects. If anyone wants the class just let me know. – Kezz Aug 25 '13 at 15:17
  • In case you don't have the urls of the jars containing your classes, you can construct the Reflection class by the following line: `Reflections reflections = new Reflections(ClasspathHelper.forPackage("com.example"));` – uris Jan 13 '19 at 13:38
3

Take a look: https://code.google.com/p/reflections/issues/detail?id=163

Reflections (in its current version 0.9.9-RC1) doesn't re-throw exception correctly. That's why you may miss the true cause of the problem. In my case it was a broken .class file, which my default class loader failed to load and threw an exception. So, first of all, try to make sure that your class is truly loadable.

yegor256
  • 102,010
  • 123
  • 446
  • 597
  • This was my problem. I have two versions of the JDK installed (7 and 8). I was compiling a Java8 project with JDK8 but running it with Java7. Whoops! – Joel May 14 '15 at 21:47
-4

Scanning for classes is not easy with pure Java.

The spring framework offers a class called ClassPathScanningCandidateComponentProvider that can do what you need. The following example would find all subclasses of MyClass in the package org.example.package

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
 provider.addIncludeFilter(new AssignableTypeFilter(MyClass.class));

// scan in org.example.package
 Set<BeanDefinition> components = provider.findCandidateComponents("org/example/package");
for (BeanDefinition component : components)
{

This method has the additional benefit of using a bytecode analyzer to find the candidates which means it will not load all classes it scans. Class cls = Class.forName(component.getBeanClassName()); // use class cls found }

Fore more info read the link

Community
  • 1
  • 1
Satya
  • 8,146
  • 9
  • 38
  • 43