I have a large Java desktop application and I want 3rd party developers to 
be able to create plugins for it. And I am exploring whether Guice might 
help with the API.
I expect 3rd party developers to create plugins as jars and deploy them 
into a specified dir.
At runtime I plan to pick up plugin classes using annotations (much like 
EJBs in an EE container). I am investigating whether Guice will be suitable 
for injecting important components into the plugins.

A plugin annotation that decorates a plugin class:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Plugin {}

A plugin annotation that decorates a method to be called on startup:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PluginInit {}

A plugin class:

@Plugin
public class MyPlugin {
    
    private final MyImportantClassUser myImportantClassUser;
    
    public MyPlugin() {
        myImportantClassUser = new MyImportantClassUser();
    }
    
    @PluginInit
    public void init() {
        System.out.println("MyPlugin Started");
        myImportantClassUser.doSomething();
    }
}

The important class user that needs an important class injected from the 
"franework".

public class MyImportantClassUser {

    @Inject
    ImportantClass importantClass;
    
    public MyImportantClassUser() {
    }
    
    public void doSomething() {
        System.out.println("IM DOING SOMETHING WITH THE IMPORTANT CLASS: " 
+ importantClass.getSomeMethod());
    }
}

The important class:

public class MyImportantClassUser {

    @Inject
    ImportantClass importantClass;
    
    public MyImportantClassUser() {
    }
    
    public void doSomething() {
        System.out.println("IM DOING SOMETHING WITH THE IMPORTANT CLASS: " 
+ importantClass.getSomeMethod());
    }
}

The important class Guice module:

public class ImportantClassesModule extends AbstractModule {

    private final ImportantClass importantClass;
    
    public ImportantClassesModule() {
        importantClass = new ImportantClass();
    }
    
    @Override
    protected void configure() {
        System.out.println("ImportantClassesModule configured");
    }

    @Provides
    ImportantClass provideImportantClass() {
        return importantClass;
    }
}

Current (crude) test Harness:

public class PluginProcessor {

    public void test() throws IOException, ClassNotFoundException, 
IllegalAccessException, InstantiationException, InvocationTargetException {
        final URL[] pluginJarUrls = getPluginURLs();
        
        // Using Scannotation to index annotations
        final AnnotationDB db = new AnnotationDB();
        db.scanArchives(pluginJarUrls);
        // ClassLoader for plugin jars
        final URLClassLoader classLoader = new 
URLClassLoader(pluginJarUrls);
        
        // Create injector for important classes
        Injector injector = Guice.createInjector(new 
ImportantClassesModule());
        
        // Find plugin classes and initialise them
        final Map<String, Set<String>> annotationIndex = 
db.getAnnotationIndex();
        for (final String annotation : annotationIndex.keySet()) {
            if (Plugin.class.getName().equals(annotation)) {
                for (final String pluginClassName : 
annotationIndex.get(annotation)) {
                    final Class<?> pluginClass = 
Class.forName(pluginClassName, false, classLoader);
                    for (final Method method : pluginClass.getMethods()) {
                        if (method.isAnnotationPresent(PluginInit.class)) {
                            // Get plugin class via injector to use 
injection
                            
method.invoke(injector.getInstance(pluginClass));
                            break;
                        }
                    }
                }
                break;
            }
        }
    }
    
    private URL[] getPluginURLs() throws MalformedURLException {
        // TODO - Just one jar for now
        final File pluginBin = new File("some_plugin.jar");
        return new URL[] { pluginBin.toURI().toURL() };
    }
    
    public static void main(String[] args) throws Exception {
        new PluginProcessor().test();
    }
}


I've just thrown this together to see if I can do what I envisage. But the 
injection of ImportantClass is not occuring into the instance of 
MyImportantClassUser. 
Is that because I have not instantiated MyImportantClassUser via the 
injector?
I don't want my users (3rd party developers) to have to instantiate every 
class via the injector. So is there a way to globally inject things in this 
manner? Am I misunderstanding or trying to abuse the purpose of Guice?

Thanks!

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/google-guice/-/TVPN0QQ8F7MJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to