'Finding all classes implementing a specific interface [duplicate]

I am in the process of developing an application (Quartz scheduler) where we have a job class which is responsible for actually executing the work and we need to tell/pass the name of the job class while creating a trigger in the Quartz scheduler.

I want to provide an extension point to all who want to use the API (beside the some generic jobs which I will provide as part of the API). The idea is to create an (marker) interface and if any one wants to declare their class as scheduler job class, all they have to do is, to (declare to) implement the interface.

I am not sure how I can find which classes are following the contract (by implementing the interface) so that I can show them to the user who want to schedule a trigger in the scheduler.

My requirement is not to load the classes at run time but to show user list of classes which implement the required interface so that user can select the class and class name can be passed to the scheduler. It's the Quartz scheduler which at the end will be responsible to create an instance of class.

Can any one suggest how I can achieve the above goal or is there any other better way to achieve what I am trying to do?

Edit

I went through the doc of ServiceLoader and it seems that for implementing a service one has to create a file in the META-INF folder with the name of the implementation class, which leads me to think that if the user of my API wants 20 different implementations, he has to put 20 entries in the file which for me seems a lot of extra work for the end user since each job class will be created for executing a specific job and there can be 100s of job classes.

Please correct me if my assumption is wrong.



Solution 1:[1]

You can find an answer here.

I can suggest using org.reflections

You can take a look at it here

Reflections reflections = new Reflections("com.mycompany");    
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);

Solution 2:[2]

Probably the best (standard) way to do this by using the Java SPI mechanism, see Javadoc. The inconvenient (which is also a nice feature) is that it expects Jars that define extensions to list them in META-INF/services/your.fully.qualified.Interface.

The only other way I can think of would be to wall through all ClassLoaders in hope you'll be able to list the files in there, load the class files, and see if they implement your interface or not - which is not a nice thing to do.

Solution 3:[3]

I think that org.reflections is a proper solution as mentioned by Alex Stybaev, you don't need to reference the classes in a property file.

Another approach (which I would take) is Spring, since I am using Spring anyway for my applications and therefore wouldn't need any additionally dependencies.

You can find hints for solving your problem with Spring (and alternatives in the other comments or answers) here:

In the comments of your question heikkim and polypiel also link to questions with have answers for solving it with Spring:

Solution 4:[4]

From the answers of Find Java classes implementing an interface, I used http://software.clapper.org/javautil/: Very fast, very useful.

Solution 5:[5]

To do so in pure java, the most correct answer is already voted (from sam goldberg apr 10,2012)

However full code of his is unnecessarily complex. I used his idea and pushed ClassFinder there: http://icedtea.classpath.org/hg/icedtea-web/file/0527ad4eb2dd/netx/net/sourceforge/jnlp/controlpanel/ClassFinder.java

Note - this will work in stand alone application (or any application using regular classpath with jars and dirs) not in ServerContainer.

if your app is running in webserver, you need to know location of your war/ear and search there. Or you have to ask your parent classlaoder where it is he getting yours (and other) sources.

Second note - I'm filtering final locations classes to match only netx and icedtea-web as I do not wont dependencies searched. So if you need to include rt.jar please, rmeove thsoe filters. Or remove bootclasspath at all if you on contrary do not need it at all.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bloeckchen
Solution 2 Romain
Solution 3 Spring
Solution 4 Community
Solution 5 judovana