0

The org.reflections library does not function correctly when it's used inside an Eclipse Plugin project.

For instance, the following code should return all classes of a given subtype in a given package:

Reflections reflections = new Reflections("my.package");
Set<Class<? extends Subtype>> classes = reflections.getSubTypesOf(Subtype.class);

When running the project as a Plugin, classes will be empty. Inserting a main() and running it as a normal Java application will correctly return the expected classes.

I've tried to:

Include the Reflections library as a normal third-party jar dependency

Include the Reflections library as an OSGi bundle (http://stackoverflow.com/questions/8339845/reflections-library-not-working-when-used-in-an-eclipse-plug-in)

Edit: current process (based on stackoverflow answer above):

1) New Plugin-Project (OSGIReflections called) based on external JARs (Reflections and Javassist)

2) In my actual Plugin-project (X) I add a dependency on OSGIReflections in Dependencies -> Required Plug-ins

2.a) If I run the project as normal java app: Reflections is working

2.b) If I run the project as plugin project: Reflections is not working

3) Create the BundleUrlType class

4) How do I activate this BundleUrlType? In my plugin Activator I call the createReflections(context.getBundle()) function but I do not have a .data file. How do I generate that?

  • The second link to [Include the Reflections library as an OSGi bundle](http://stackoverflow.com/questions/8339845/reflections-library-not-working-when-used-in-an-eclipse-plug-in) looks pretty good. Try following those instructions. If they don't work, give details of what went wrong. – Neil Bartlett Jul 21 '16 at 00:08
  • @NeilBartlett This is my process: 1) New Plugin-Project (OSGIReflections called) based on external JARs (Reflections and Javassist) 2) In my actual Plugin-project (X) I add a dependency on OSGIReflections in Dependencies -> Required Plug-ins 2.a) If I run the project as normal java app: Reflections is working 2.b) If I run the project as plugin project: Reflections is not working 3) Create the BundleUrlType class 4) How do I activate this BundleUrlType? In my plugin Activator I call the createReflections(context.getBundle()) function but I do not have a .data file. How do I generate that? – memoryStream Jul 21 '16 at 12:09
  • I don't know what a `.data` file is. It's not needed for OSGi, is it something required by the Reflections library? If so, check the docs for Reflections. – Neil Bartlett Jul 21 '16 at 16:02
  • Oh I see, `reflectiveplugin.data` is not a file, it's a package name. I think it's where the author of that SO answer put his sample classes. – Neil Bartlett Jul 21 '16 at 16:06
  • have you tried using "Eclipse-RegisterBuddy: bundle-symbolic-name" header? – Hisham Khalil Jul 22 '16 at 11:02

1 Answers1

0

I know that's pretty old question, but for all struggling with OSGi with probably all suggestions on SO not working I have small tip:

My case: Reflections 0.9.8 (later versions should work similar) on a Fabric8 container.

TL;DR: The key was make org.osgi.framework.Bundle to work as java.lang.ClassLoader and passed to Reflections instance.

During debugging sessions I've found that org.reflections.util.ClasspathHelper finds two ClassLoaders by default as a result of:

  • Thread.currentThread().getContextClassLoader();

    containing only org.osgi.* and org.apache.karaf.* packages

  • Reflections.class.getClassLoader();

    containing org.reflections.* package

so there is no place with user created code. I've found that both ClassLoader and Bundle have two common methods:

    Class<?> loadClass(String var1) throws ClassNotFoundException;

    Enumeration<URL> getResources(String var1) throws IOException;

so I've created ClassLoader with delegation to Bundle:

public class BundleClassLoader extends ClassLoader {

    private final Bundle bundle;

    public BundleClassLoader(Bundle bundle) {
        this.bundle = bundle;
    }

    @Override
    public Enumeration<URL> getResources(String name) throws IOException {
        return bundle.getResources(name);
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return bundle.loadClass(name);
    }

}

and passed it to Reflections instance:

new Reflections(packageName, new BundleClassLoader(bundleContext.getBundle()), new SubTypesScanner(false));

edit: As I found out later, I still needed own implementation of UrlType that matches OSGi implementation. In my case, despite of using fixed version of Reflections (mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.reflections/0.9.8_1 which has its own bundle protocol implementation) I needed to add implementation based on example in answer from similar thread changing BUNDLE_PROTOCOL from bundleresource to bundle.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Trishun
  • 1
  • 3