5

I have an application that allows, using an abstract class, people to write their own implementations. I load these implementations as .class-files from a directory. Currently, I have this solution:

File classDir = new File("/users/myproject/classes/");

URL[] url = { classDir.toURI().toURL() };
URLClassLoader urlLoader = new URLClassLoader(url);

String filename;
for (File file : classDir.listFiles()) {
    filename = string.getFilenameWithoutExtension(file);
    if (filename.equals(".") || filename.equals("..") || filename.startsWith("."))
        continue;

AbstractClass instance = (AbstractClass)urlLoader
    .loadClass("org.mypackage." + filename)
    .getConstructor(ConfigUtil.class, DatabaseUtil.class, StringUtil.class)
    .newInstance(config, database, string));

    instance.doSomething();
}

As you see - I need to specify the package the classes are located in in order to correctly load them. Omitting the package, I get an

 java.lang.NoClassDefFoundError:
     MyClass (wrong name: org/mypackage/MyClass)

error.

Now, from a architectural POV, I think it is very ill-designed that classes other people designed have to be compiled to MY package when loading them.

So I ask you: Is there a way I can load classes form the file system without having to specify the package they reside in?

F.P
  • 17,421
  • 34
  • 123
  • 189
  • 1
    You could keep the package structure as a folder structure under your path? And create the package name from the path before loading the class? – Peter Svensson Feb 08 '12 at 14:54
  • That would be a possibility... At least then I wouldn't have to trouble myself when two classes have the same name... nice thinking from another angle! :) – F.P Feb 09 '12 at 08:02
  • Try it and see if it works, if you want some code examples let me know! – Peter Svensson Feb 09 '12 at 08:14

2 Answers2

3

Yes; implement an interface (or use an annotation).

Then use any class-scanning library (there are lots of SO questions about this, like this one) to load the particular class in question. Searching for "Java class scanning" or "Java plugin mechanism" will help.

You might also just want to use the Java Plugin Framework and avoid some effort. Although it's not clear to me that it's maintained any more, I know people are still using it.

Community
  • 1
  • 1
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • I don't think an interface would work correctly (semantically speaking) in my case. The `AbstractClass` has many predefined functions that only use the overridden (passive of override, wtf?) methods of the implementation. An interface doesn't allow that. – F.P Feb 08 '12 at 14:57
  • @FlorianPeschka ... same difference. – Dave Newton Feb 08 '12 at 15:01
  • I don't understand your comment. What difference of what? – F.P Feb 09 '12 at 08:01
1

You can use the ServiceProvider to load implementations which you don't know.

ollins
  • 1,851
  • 12
  • 16