views:

3278

answers:

10

What is the best way of searching the whole classpath for an annotated class?

I'm doing a library and I want to allow the users to annotate their classes, so when the Web application starts I need to scann the whole classpath for certain annotation.

Do you know a library or a Java facility to do this?

Edit: I'm thinking about something like the new functionality for Java EE 5 Web Services or EJB's. You annotate your class with @WebService or @EJB and the system find these classes while loading so they are accessible remotely.

+1  A: 

Java does not have "Discovery". The only way I know of is to scan the directory that the .class files should be in, parse the names and use that. Horribly ugly, maybe there is a better package these days--I haven't looked in a few years.

Usually this problem used to be addressed by including a properties file or a .xml file with the classnames in it.

I'd be interested in hearing a better answer as well.

Bill K
A: 

I don't have an answer, but I do have a pointer to where the anser may be. The SEAM code does just that when it looks for all the annotations it uses. I imagine the Hibernate code does the same thing looking for hibernate annotations.

They're open source. You might be able to figure out if they're using a library or something home grown for their annotation scanning.

Chris Kessel
+2  A: 

Slightly offtopic, but Spring also does something similar, using <context:component-scan>, which you could perhaps study the source code of?

Spring provides the capability of automatically detecting 'stereotyped' classes [...]. To autodetect these classes and register the corresponding beans requires the inclusion of the [context:component-scan element].

toolkit
A: 

The Classloader API doesn't have an "enumerate" method, because class loading is an "on-demand" activity -- you usually have thousands of classes in your classpath, only a fraction of which will ever be needed (the rt.jar alone is 48MB nowadays!).

So, even if you could enumerate all classes, this would be very time- and memory-consuming.

The simple approach is to list the concerned classes in a setup file (xml or whatever suits your fancy); if you want to do this automatically, restrict yourself to one JAR or one class directory.

mfx
+2  A: 

I'm not sure if it will help you or not, but you could look into the apache commons-discovery project.

discovery project

Ian McLaird
+2  A: 

Use the ServiceLoader, or implement your own if you are not in Java 6.

Perhaps an annotation processor could produce the necessary files under META-INF/services at compile-time.

erickson
+2  A: 

Try Scannotation.

It can be used to search the classpath or your web application lib directory for specific annotations.

Wolf
+5  A: 

Hi,

Use org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider

API

A component provider that scans the classpath from a base package. It then applies exclude and include filters to the resulting classes to find candidates.

ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(<DO_YOU_WANT_TO_USE_DEFALT_FILTER>);

scanner.addIncludeFilter(new AnnotationTypeFilter(<TYPE_YOUR_ANNOTATION_HERE>.class));

for (BeanDefinition bd : scanner.findCandidateComponents(<TYPE_YOUR_BASE_PACKAGE_HERE>))
    System.out.println(bd.getBeanClassName());

regards,

Arthur Ronald F D Garcia
A: 

You might want to use http://code.google.com/p/annovention/

Animesh
+1  A: 

And another solution is Google reflections:

http://code.google.com/p/reflections/

Quick review:

  • Spring solution is the way to go if you're using Spring. Otherwise it's a big dependency.
  • Using ASM directly is a bit cumbersome.
  • Using Java Assist directly is clunky too.
  • Annovention is super lightweight and convenient. No maven integration yet.
  • Google reflections pulls in Google collections. Indexes everything and then is super fast.
Jonathan