Finding all classes in a package, and all packages on the classpath

2,227 views
Skip to first unread message

Tim Armstrong

unread,
Oct 24, 2012, 11:51:01 AM10/24/12
to google-code...@googlegroups.com
Hello,

Reflections is a great library, and I've made extensive use of it.  I'm trying to do something new with it now that I can't get to work.  I would greatly appreciate any help.  I'm using 0.9.8 from Maven.  I'm just trying to find all classes, interfaces, and annotations within a package.  Here is what I'm trying, for the "my.package" package:


Reflections reflections = new Reflections("my.package", new SubTypesScanner(false));

Collection<Class<?>> classes = reflections.getSubTypesOf(Object.class);


It's not detecting all the classes.  What seems to be happening is that it detects a class if it directly extends java.lang.Object, but if it extends a class in another package (which of course extends Object), it doesn't detect it.  E.g., I have this class in a package it doesn't detect, where ThingNoAttributes is in another package:


public class Person extends ThingNoAttributes
{
  ...
}


But it detects it when it is just:


public class Person
{
  ...
}


Is there a way just to find all the classes in a package?

Also, is there a way to find all packages on the classpath using Reflections?  java.lang.Package.getPackages() only finds some of them when I use it, not all of them.  A "getPackagesAnnotatedWith()" method might be useful, but for the moment I'm just looking to find all packages.

Thank you very much if you can help,
Tim

mamo

unread,
Oct 25, 2012, 3:44:34 AM10/25/12
to google-code...@googlegroups.com, notar...@gmail.com
1. looking at http://code.google.com/p/reflections/source/browse/trunk/reflections/src/main/java/org/reflections/scanners/SubTypesScanner.java
you can see that Object.class is excluded by default, so you need to construct it accordingly.
2. how would you annotate a package?

finding all packages can be done by either
1. writing a new scanner
2. or just iterating the relevant url entries - you can use ClasspathHelper to find the urls and Vfs to iterate. check out the sources http://code.google.com/p/reflections/source/browse/trunk/reflections/src/main/java/org/reflections/vfs/Vfs.java
but than, why would you "ask" about the found packages?

mamo

unread,
Oct 25, 2012, 3:46:28 AM10/25/12
to google-code...@googlegroups.com, notar...@gmail.com
but than, *WHAT would you "ask" about the found packages?

Tim Armstrong

unread,
Oct 26, 2012, 8:34:45 AM10/26/12
to google-code...@googlegroups.com, notar...@gmail.com
Hi mamo,

Thanks so much for the response.  I'm not sure I follow about SubTypesScanner.  If I specify "false" in the constructor, it looks like the line to exclude Object shouldn't trigger.  Am I writing the code wrong to find all classes, interfaces, and annotations in a package?

I mean the annotations in package-info.java, which are accessible from the java.lang.Package object.  I'm writing a Java library.  I'm just looking to scan all the packages at the beginning of the program and create a directory of them based on their annotations.  When I call ClasspathHelper.forJavaClassPath(), I get a list of JAR's and directories with .class files.  Are all the directories contained in them all the packages on the classpath?

Thank you,
Tim

Tim Armstrong

unread,
Nov 3, 2012, 4:46:59 PM11/3/12
to google-code...@googlegroups.com, notar...@gmail.com
Hi,

Oh, I thought maybe I encountered a bug...  I thought I would show you how to reproduce it, if you're interested.

Let us have two classes, A.java and B.java, in the package "ab", and the class C.java in the package "c":


---------

  package ab;

  public class A {}

---------

  package ab;

  public class B extends A {}

---------

  package c;

  import ab.B;

  public class C extends B {}

---------



We want to find all the classes in pacakge "c".  Here is how I'm constructing the Reflections object:


  Reflections reflections = new Reflections("c", new SubTypesScanner(false));


Then this code:



  Collection<Class<?>> classes = reflections.getSubTypesOf(Object.class);

  for (Class<?> cls : classes)
  {   
      System.out.println("class present: " + cls);
  }


does not detect C, nor does:


  Collection<Class<? extends A>> classes = reflections.getSubTypesOf(A.class);
 
 
but:


  Collection<Class<? extends B>> classes = reflections.getSubTypesOf(B.class);

 
does detect C.  If I change C to:


  package c;

  public class C {}


then



  Collection<Class<?>> classes = reflections.getSubTypesOf(Object.class);

 
does detect C.  Is what I describe a bug, or is there a different way to get all classes, interfaces, and annotations in a package?

Thank you for the software.  People say it's impossible to do some tasks in Java without it.

Tim

Ron m

unread,
Nov 3, 2012, 6:01:22 PM11/3/12
to google-code...@googlegroups.com
I think that's not a bug but a default behavior, maybe needed to be changed.
new Reflections("c") actually scans urls containing package "c", as ClasspathHelper.forPackage("c") would return, and input filter accepting only prefix "c". 
in that case a.jar and b.jar won't be scanned. even if all these packages are located in the same jar, B and A won't be scanned because of the input filter. than reflections.getSubTypesOf(A.class) returns nothing.
you could, instead use new Reflections("a", "b", "c", scanners) or new Reflections(urls, scanners).

Tim Armstrong

unread,
Nov 6, 2012, 9:35:25 AM11/6/12
to google-code...@googlegroups.com
Hi,

OK, thank you, I think we're getting somewhere.  These lines:


  Reflections reflections = new Reflections("ab", "c", new SubTypesScanner(false));

  Collection<Class<?>> classes = reflections.getSubTypesOf(Object.class);
 

work, i.e. correctly detect A, B, and C.  However, when I just want to scan "c", do I have any way of knowing that I have to scan "ab" as well?

Is this line what you meant to try?:


  Reflections reflections = new Reflections(ClasspathHelper.forPackage("c"), new SubTypesScanner(false));
 

It picks up A, B, C, and a lot of other classes and annotations not in "c".  However, when I use a real package as on my first post instead of forPackage("c"), it still just detects the annotations and not the packages.  This time it picks up a lot of other classes too not in the package. 

I've tried a lot with constructing the Reflections object with the ConfigurationBuilder too without success.

Thanks for your help!

Tim
Reply all
Reply to author
Forward
0 new messages