Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make your GWT application plug-able?

Tags:

plugins

gwt

I am writing (with my team) an GWT application, which parses and represent some domain specific language - for example, plays media presentation with text, video and UI controls. So the application has a set of components: ones - for holding model, ones - for control routines (controllers), and of course we have classes for View.

Now we have a problem - make it all plug-able, in the sense of:

  • should be one core plugin, which make all common stuff. This coer block must be an JavaScript file (one for every permutation)

  • should be ability to extend core classes, write custom ones - and compile it to separate JS file (one for every permutation)

Every plugin must registers (export it's classes etc) itself to the core platform, so it could be used.

Problems:

  1. How to compile the custom stuff separately ?
  2. How to load plugins ?

For the second one problem i've found http://code.google.com/p/gwt-exporter/, that exports GWT classes to outer world, so they could be invoked from pure JS.

Also I have an idea to create new module for new plugin, so it will be compiled to separate file (first problem).

Have you an experience of building such architecture, have you some best practices in this case ?

like image 486
ajukraine Avatar asked Oct 24 '22 21:10

ajukraine


1 Answers

I have experimented with this same question since GWT 1.5 and every time I come up with a more elegant solution they change the linker and break it. The only way that I have come up with that would work independent of linker design is to do exactly what you are talking about and create a new module for ever plug-in. Then use GWT exporter to create an abstract class that plugins must extend that would have an abstract method that would take the root element of the plugin passed to it by the core and populate it. The issue with this method is all plug-in modules must be added to the DOM on the initial load of the page because since 2.0 the iFrame linker relies on a page load event so dynamically added modules wont fully load. So because of this you will want to have the exported population method wrapped in runAsync so that you aren't downloading modules till you use them.

Edit:

Here is a rough example of what I am talking about. Please be aware that I haven't done any GWT in a couple years and there may be a better way of doing this by now.

public final class PluginManager
{
    public static final PluginManager INSTANCE = new PluginManager();

    private PluginManager()
    {
    }

    private static native void loadPlugin( AbstractPlugin plugin )
    /*-{
        if (!$wnd.Plugins) {
            $wnd.Plugins = {};
        }
        var name = [email protected]::getName()();
        $wnd.Plugins[name] = $entry([email protected]::load(Ljava/lang/String;));
    }-*/;

    private static native void unloadPlugin( AbstractPlugin plugin )
    /*-{
        if ($wnd.Plugins) {
            var name = [email protected]::getName()();
            delete $wnd.Plugins[name];
        }
    }-*/;

    private static native JsArrayString getPlugins()
    /*-{
        if ($wnd.Plugins) {
            return Object.keys($wnd.Plugins);
        }
        return undefined;
    }-*/;

    public static abstract class AbstractPlugin implements EntryPoint
    {
        @Override
        public final void onModuleLoad()
        {
            PluginManager.INSTANCE.loadPlugin( this );
        }

        protected final void unload()
        {
            PluginManager.INSTANCE.unloadPlugin( this );
        }

        protected abstract String getName();

        protected abstract void load( String rootPanelId );
    }
}
like image 117
LINEMAN78 Avatar answered Nov 01 '22 11:11

LINEMAN78