Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 663
Umesh Awasthi Avatar asked Apr 03 '12 10:04

Umesh Awasthi


People also ask

Can multiple classes implement the same interface?

Your class can implement more than one interface, so the implements keyword is followed by a comma-separated list of the interfaces implemented by the class. By convention, the implements clause follows the extends clause, if there is one.

How do I find all implemented classes for an interface in eclipse?

Put the cursor on the name of the interface and press F4 (Open Type Hierarchy). That will open a window that shows a tree with all classes that Eclipse can find that implement the interface.

Where is the implementation class of interface in Intellij?

Press Ctrl+F12 or choose Navigate | Implementation(s) from the main menu . Alternatively, you can press Ctrl+Shift+A , start typing the command name in the popup, and then choose it there.


2 Answers

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); 
like image 96
Alex Stybaev Avatar answered Sep 22 '22 03:09

Alex Stybaev


I had a similar need where I wanted to make sure that any classes created that implemented a certain interface were always truly serializable. I created a JavaClassFinder which walks through all directories in the classpath, and finds all classes assignable to the interface I cared about. Here is a code snippet:

public <T> List<Class<? extends T>> findAllMatchingTypes(Class<T> toFind) {     foundClasses = new ArrayList<Class<?>>();     List<Class<? extends T>> returnedClasses = new ArrayList<Class<? extends T>>();     this.toFind = toFind;     walkClassPath();     for (Class<?> clazz : foundClasses) {         returnedClasses.add((Class<? extends T>) clazz);     }     return returnedClasses; } 

I'm happy to share the code with you if it helps. The only draw back is that this will only handle .class files -- I didn't add the feature to unzip .jars and read class files from there. (But it wouldn't be a huge project to add that.)

UPDATE: I checked my source code for the above, and found it depends on a lot of helper classes in our standard utility library. To make it easier, I zipped up all the code needed, which you can download from JavaClassFinder.zip. This will set up directly in Eclipse, and you can take whatever portions of the code you need.

You will find a JUnit3 test in the project, called JavaClassFinderTest.java, which shows you the features and usage of the JavaClassFinder class. The only external dependency needed to run the Junit test is Junit.

Basic usage of this utility:

    JavaClassFinder classFinder = new JavaClassFinder();     List<Class<? extends MyTagInterface>> classes = classFinder.findAllMatchingTypes(MyTagInterface.class); 

This will give you a List which contains any classes in the classpath which are assignable from the "MyTagInterface.class" (for example). Hope this helps.

like image 23
Sam Goldberg Avatar answered Sep 26 '22 03:09

Sam Goldberg