]> source.dussan.org Git - vaadin-framework.git/commitdiff
code splitting + client initialization
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Fri, 11 Jun 2010 14:43:08 +0000 (14:43 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Fri, 11 Jun 2010 14:43:08 +0000 (14:43 +0000)
svn changeset:13652/svn branch:6.4

src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java [deleted file]
src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/WidgetLoader.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/WidgetMap.java
src/com/vaadin/terminal/gwt/client/WidgetSet.java
src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java

index f54032cfdbb7f599900994affdae098ee47bff28..ee89143f83b6984786900c53ad0f909c85f6fcc1 100644 (file)
@@ -9,15 +9,17 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.core.client.JsArrayString;
 import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.Timer;
 import com.vaadin.terminal.gwt.client.ui.VUnknownComponent;
 
-public class ApplicationConfiguration {
+public class ApplicationConfiguration implements EntryPoint {
 
-    // can only be inited once, to avoid multiple-entrypoint-problem
-    private static WidgetSet initedWidgetSet;
+    private static WidgetSet widgetSet = GWT.create(WidgetSet.class);
 
     private String id;
     private String themeUri;
@@ -38,10 +40,10 @@ public class ApplicationConfiguration {
 
     private String windowId;
 
-    // TODO consider to make this hashmap per application
+    static// TODO consider to make this hashmap per application
     LinkedList<Command> callbacks = new LinkedList<Command>();
 
-    private int widgetsLoading;
+    private static int widgetsLoading;
 
     private static ArrayList<ApplicationConnection> unstartedApplications = new ArrayList<ApplicationConnection>();
     private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>();
@@ -151,28 +153,20 @@ public class ApplicationConfiguration {
      * @param widgetset
      *            the widgetset that is running the apps
      */
-    public static void initConfigurations(WidgetSet widgetset) {
-
-        if (initedWidgetSet != null) {
-            // Multiple widgetsets inited; can happen with custom WS + entry
-            // point
-            String msg = "Ignoring " + widgetset.getClass().getName()
-                    + ", because " + initedWidgetSet.getClass().getName()
-                    + " was already inited (if this is wrong, your entry point"
-                    + " is probably not first your .gwt.xml).";
-            throw new IllegalStateException(msg);
-        }
-        initedWidgetSet = widgetset;
+    public static void initConfigurations() {
+
         ArrayList<String> appIds = new ArrayList<String>();
         loadAppIdListFromDOM(appIds);
 
         for (Iterator<String> it = appIds.iterator(); it.hasNext();) {
             String appId = it.next();
             ApplicationConfiguration appConf = getConfigFromDOM(appId);
-            ApplicationConnection a = new ApplicationConnection(widgetset,
+            ApplicationConnection a = new ApplicationConnection(widgetSet,
                     appConf);
             unstartedApplications.add(a);
         }
+
+        deferredWidgetLoadLoop.scheduleRepeating(100);
     }
 
     /**
@@ -242,7 +236,7 @@ public class ApplicationConfiguration {
         for (int i = 0; i < keyArray.length(); i++) {
             String key = keyArray.get(i).intern();
             int value = valueMap.getInt(key);
-            classes[value] = widgetSet.getImplementationByClassName(key, this);
+            classes[value] = widgetSet.getImplementationByClassName(key);
             if (classes[value] == VUnknownComponent.class) {
                 if (unknownComponents == null) {
                     unknownComponents = new HashMap<String, String>();
@@ -273,7 +267,7 @@ public class ApplicationConfiguration {
      * 
      * @param c
      */
-    void runWhenWidgetsLoaded(Command c) {
+    static void runWhenWidgetsLoaded(Command c) {
         if (widgetsLoading == 0) {
             c.execute();
         } else {
@@ -281,11 +275,11 @@ public class ApplicationConfiguration {
         }
     }
 
-    void widgetLoadStart() {
+    static void startWidgetLoading() {
         widgetsLoading++;
     }
 
-    void widgetLoaded() {
+    static void endWidgetLoading() {
         widgetsLoading--;
         if (widgetsLoading == 0 && !callbacks.isEmpty()) {
             for (Command cmd : callbacks) {
@@ -295,4 +289,59 @@ public class ApplicationConfiguration {
         }
 
     }
+
+    /*
+     * This loop loads widget implementation that should be loaded deferred.
+     */
+    private static final Timer deferredWidgetLoadLoop = new Timer() {
+        private static final int FREE_LIMIT = 4;
+
+        int communicationFree = 0;
+        int nextWidgetIndex = 0;
+
+        @Override
+        public void run() {
+            if (!isBusy()) {
+                Class<? extends Paintable> nextType = getNextType();
+                if (nextType == null) {
+                    // ensured that all widgets are loaded
+                    cancel();
+                } else {
+                    widgetSet.loadImplementation(nextType);
+                }
+            }
+        }
+
+        private Class<? extends Paintable> getNextType() {
+            Class<? extends Paintable>[] deferredLoadedWidgets = widgetSet
+                    .getDeferredLoadedWidgets();
+            if (deferredLoadedWidgets.length <= nextWidgetIndex) {
+                return null;
+            } else {
+                return deferredLoadedWidgets[nextWidgetIndex++];
+            }
+        }
+
+        private boolean isBusy() {
+            if (widgetsLoading > 0) {
+                communicationFree = 0;
+                return false;
+            }
+            for (ApplicationConnection app : runningApplications) {
+                if (app.hasActiveRequest()) {
+                    // if an UIDL request or widget loading is active, mark as
+                    // busy
+                    communicationFree = 0;
+                    return false;
+                }
+            }
+            communicationFree++;
+            return communicationFree < FREE_LIMIT;
+        }
+    };
+
+    public void onModuleLoad() {
+        initConfigurations();
+        startNextApplication();
+    }
 }
index d2c8f6e67c856eb72b2e2e1b82e6824b1f52fe9a..9be6e571bc28b09388d043695cdf167009733cd8 100755 (executable)
@@ -893,7 +893,7 @@ public class ApplicationConnection {
 
             }
         };
-        configuration.runWhenWidgetsLoaded(c);
+        ApplicationConfiguration.runWhenWidgetsLoaded(c);
     }
 
     /**
diff --git a/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java b/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java
deleted file mode 100644 (file)
index ae6001c..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* 
-@ITMillApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ui.VButton;
-import com.vaadin.terminal.gwt.client.ui.VCheckBox;
-import com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar;
-import com.vaadin.terminal.gwt.client.ui.VFilterSelect;
-import com.vaadin.terminal.gwt.client.ui.VListSelect;
-import com.vaadin.terminal.gwt.client.ui.VNativeSelect;
-import com.vaadin.terminal.gwt.client.ui.VOptionGroup;
-import com.vaadin.terminal.gwt.client.ui.VPasswordField;
-import com.vaadin.terminal.gwt.client.ui.VPopupCalendar;
-import com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal;
-import com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical;
-import com.vaadin.terminal.gwt.client.ui.VTextArea;
-import com.vaadin.terminal.gwt.client.ui.VTextField;
-import com.vaadin.terminal.gwt.client.ui.VTwinColSelect;
-import com.vaadin.terminal.gwt.client.ui.VUnknownComponent;
-import com.vaadin.terminal.gwt.client.ui.VView;
-import com.vaadin.terminal.gwt.client.ui.VWindow;
-
-public class DefaultWidgetSet implements WidgetSet {
-
-    /**
-     * DefaultWidgetSet (and its extensions) delegate instantiation of widgets
-     * and client-server mathing to WidgetMap. The actual implementations are
-     * generated with gwts deferred binding.
-     */
-    private WidgetMap map;
-
-    /**
-     * This is the entry point method. It will start the first
-     */
-    public void onModuleLoad() {
-        try {
-            ApplicationConfiguration.initConfigurations(this);
-        } catch (Exception e) {
-            // Log & don't continue;
-            // custom WidgetSets w/ entry points will cause this
-            ApplicationConnection.getConsole().log(e.getMessage());
-            return;
-        }
-        ApplicationConfiguration.startNextApplication(); // start first app
-        map = GWT.create(WidgetMap.class);
-    }
-
-    public Paintable createWidget(UIDL uidl, ApplicationConfiguration conf) {
-        final Class<? extends Paintable> classType = resolveWidgetType(uidl,
-                conf);
-        if (classType == null || classType == VUnknownComponent.class) {
-            String serverSideName = conf
-                    .getUnknownServerClassNameByEncodedTagName(uidl.getTag());
-            return new VUnknownComponent(serverSideName);
-        }
-
-        return map.instantiate(classType);
-    }
-
-    protected Class<? extends Paintable> resolveWidgetType(UIDL uidl,
-            ApplicationConfiguration conf) {
-        final String tag = uidl.getTag();
-
-        Class<? extends Paintable> widgetClass = conf
-                .getWidgetClassByEncodedTag(tag);
-
-        // add our historical quirks
-
-        if (widgetClass == VButton.class && uidl.hasAttribute("type")) {
-            return VCheckBox.class;
-        } else if (widgetClass == VView.class && uidl.hasAttribute("sub")) {
-            return VWindow.class;
-        } else if (widgetClass == VFilterSelect.class) {
-            if (uidl.hasAttribute("type")) {
-                // TODO check if all type checks are really neede
-                final String type = uidl.getStringAttribute("type").intern();
-                if (type == "twincol") {
-                    return VTwinColSelect.class;
-                } else if (type == "optiongroup") {
-                    return VOptionGroup.class;
-                } else if (type == "native") {
-                    return VNativeSelect.class;
-                } else if (type == "list") {
-                    return VListSelect.class;
-                } else if (uidl.hasAttribute("selectmode")
-                        && uidl.getStringAttribute("selectmode")
-                                .equals("multi")) {
-                    return VListSelect.class;
-                }
-            }
-        } else if (widgetClass == VTextField.class) {
-            if (uidl.hasAttribute("multiline")) {
-                return VTextArea.class;
-            } else if (uidl.hasAttribute("secret")) {
-                return VPasswordField.class;
-            }
-        } else if (widgetClass == VPopupCalendar.class) {
-            if (uidl.hasAttribute("type")
-                    && uidl.getStringAttribute("type").equals("inline")) {
-                return VDateFieldCalendar.class;
-            }
-        } else if (widgetClass == VSplitPanelHorizontal.class
-                && uidl.hasAttribute("vertical")) {
-            return VSplitPanelVertical.class;
-        }
-
-        return widgetClass;
-
-    }
-
-    public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl,
-            ApplicationConfiguration conf) {
-        return currentWidget.getClass() == resolveWidgetType(uidl, conf);
-    }
-
-    public Class<? extends Paintable> getImplementationByClassName(
-            String fullyqualifiedName,
-            ApplicationConfiguration applicationConfiguration) {
-        Class<? extends Paintable> implementationByServerSideClassName = map
-                .getImplementationByServerSideClassName(fullyqualifiedName,
-                        applicationConfiguration);
-        return implementationByServerSideClassName;
-
-    }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java b/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java
new file mode 100644 (file)
index 0000000..3a18da9
--- /dev/null
@@ -0,0 +1,8 @@
+package com.vaadin.terminal.gwt.client;
+
+/**
+ * A helper class used by WidgetMap implementation. Used by the generated code.
+ */
+interface WidgetInstantiator {
+    public Paintable get();
+}
diff --git a/src/com/vaadin/terminal/gwt/client/WidgetLoader.java b/src/com/vaadin/terminal/gwt/client/WidgetLoader.java
new file mode 100644 (file)
index 0000000..c627106
--- /dev/null
@@ -0,0 +1,18 @@
+package com.vaadin.terminal.gwt.client;
+
+import com.google.gwt.core.client.RunAsyncCallback;
+
+/** A helper class used by WidgetMap implementation. Used by the generated code. */
+abstract class WidgetLoader implements RunAsyncCallback {
+
+    public void onFailure(Throwable reason) {
+        ApplicationConfiguration.endWidgetLoading();
+    }
+
+    public void onSuccess() {
+        addInstantiator();
+        ApplicationConfiguration.endWidgetLoading();
+    }
+
+    abstract void addInstantiator();
+}
index c6e50b0f514608cb522fa011078401c339487c1a..4573a28b964c4a7eaff17808405aa6a8081b42eb 100644 (file)
@@ -3,41 +3,21 @@
  */
 package com.vaadin.terminal.gwt.client;
 
-import com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar;
-import com.vaadin.terminal.gwt.client.ui.VPasswordField;
-import com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical;
-import com.vaadin.terminal.gwt.client.ui.VTextArea;
-import com.vaadin.terminal.gwt.client.ui.VWindow;
+import java.util.HashMap;
 
-public abstract class WidgetMap {
+abstract class WidgetMap {
 
-    public Paintable instantiate(Class<? extends Paintable> classType) {
+    protected static HashMap<Class, WidgetInstantiator> instmap = new HashMap<Class, WidgetInstantiator>();
 
-        /*
-         * Yes, this (including the generated) may look very odd code, but due
-         * the nature of GWT, we cannot do this with reflect. Luckily this is
-         * mostly written by WidgetSetGenerator, here are just some hacks. Extra
-         * instantiation code is needed if client side widget has no "native"
-         * counterpart on client side.
-         */
-        if (VSplitPanelVertical.class == classType) {
-            return new VSplitPanelVertical();
-        } else if (VTextArea.class == classType) {
-            return new VTextArea();
-
-        } else if (VDateFieldCalendar.class == classType) {
-            return new VDateFieldCalendar();
-        } else if (VPasswordField.class == classType) {
-            return new VPasswordField();
-        } else if (VWindow.class == classType) {
-            return new VWindow();
-        } else {
-            return null; // let generated type handle this
-        }
+    public Paintable instantiate(Class<? extends Paintable> classType) {
+        return instmap.get(classType).get();
     }
 
     public abstract Class<? extends Paintable> getImplementationByServerSideClassName(
-            String fullyqualifiedName,
-            ApplicationConfiguration applicationConfiguration);
+            String fullyqualifiedName);
+
+    public abstract Class<? extends Paintable>[] getDeferredLoadedWidgets();
+
+    public abstract void ensureInstantiator(Class<? extends Paintable> classType);
 
 }
index f2a960b950da4a59ae0bf350583651a7a0cc3cf8..d5375114b5a182872d38e3891a9d4a6a00ca6af8 100644 (file)
@@ -4,10 +4,34 @@
 
 package com.vaadin.terminal.gwt.client;
 
-import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ui.VButton;
+import com.vaadin.terminal.gwt.client.ui.VCheckBox;
+import com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar;
+import com.vaadin.terminal.gwt.client.ui.VFilterSelect;
+import com.vaadin.terminal.gwt.client.ui.VListSelect;
+import com.vaadin.terminal.gwt.client.ui.VNativeSelect;
+import com.vaadin.terminal.gwt.client.ui.VOptionGroup;
+import com.vaadin.terminal.gwt.client.ui.VPasswordField;
+import com.vaadin.terminal.gwt.client.ui.VPopupCalendar;
+import com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal;
+import com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical;
+import com.vaadin.terminal.gwt.client.ui.VTextArea;
+import com.vaadin.terminal.gwt.client.ui.VTextField;
+import com.vaadin.terminal.gwt.client.ui.VTwinColSelect;
+import com.vaadin.terminal.gwt.client.ui.VUnknownComponent;
+import com.vaadin.terminal.gwt.client.ui.VView;
+import com.vaadin.terminal.gwt.client.ui.VWindow;
 
-public interface WidgetSet extends EntryPoint {
+public class WidgetSet {
+
+    /**
+     * WidgetSet (and its extensions) delegate instantiation of widgets and
+     * client-server matching to WidgetMap. The actual implementations are
+     * generated with gwts generators/deferred binding.
+     */
+    private WidgetMap widgetMap = GWT.create(WidgetMap.class);
 
     /**
      * Create an uninitialized component that best matches given UIDL. The
@@ -21,7 +45,92 @@ public interface WidgetSet extends EntryPoint {
      * @return New uninitialized and unregistered component that can paint given
      *         UIDL.
      */
-    public Paintable createWidget(UIDL uidl, ApplicationConfiguration conf);
+    public Paintable createWidget(UIDL uidl, ApplicationConfiguration conf) {
+        /*
+         * Yes, this (including the generated code in WidgetMap) may look very
+         * odd code, but due the nature of GWT, we cannot do this any cleaner.
+         * Luckily this is mostly written by WidgetSetGenerator, here are just
+         * some hacks. Extra instantiation code is needed if client side widget
+         * has no "native" counterpart on client side.
+         * 
+         * TODO should try to get rid of these exceptions here
+         */
+
+        final Class<? extends Paintable> classType = resolveWidgetType(uidl,
+                conf);
+        if (classType == null || classType == VUnknownComponent.class) {
+            String serverSideName = conf
+                    .getUnknownServerClassNameByEncodedTagName(uidl.getTag());
+            return new VUnknownComponent(serverSideName);
+        } else if (VSplitPanelVertical.class == classType) {
+            return new VSplitPanelVertical();
+        } else if (VTextArea.class == classType) {
+            return new VTextArea();
+        } else if (VDateFieldCalendar.class == classType) {
+            return new VDateFieldCalendar();
+        } else if (VPasswordField.class == classType) {
+            return new VPasswordField();
+        } else if (VWindow.class == classType) {
+            return new VWindow();
+        } else {
+            /*
+             * let the auto generated code instantiate this type
+             */
+            return widgetMap.instantiate(classType);
+        }
+
+    }
+
+    protected Class<? extends Paintable> resolveWidgetType(UIDL uidl,
+            ApplicationConfiguration conf) {
+        final String tag = uidl.getTag();
+
+        Class<? extends Paintable> widgetClass = conf
+                .getWidgetClassByEncodedTag(tag);
+
+        // add our historical quirks
+
+        if (widgetClass == VButton.class && uidl.hasAttribute("type")) {
+            return VCheckBox.class;
+        } else if (widgetClass == VView.class && uidl.hasAttribute("sub")) {
+            return VWindow.class;
+        } else if (widgetClass == VFilterSelect.class) {
+            if (uidl.hasAttribute("type")) {
+                // TODO check if all type checks are really neede
+                final String type = uidl.getStringAttribute("type").intern();
+                if (type == "twincol") {
+                    return VTwinColSelect.class;
+                } else if (type == "optiongroup") {
+                    return VOptionGroup.class;
+                } else if (type == "native") {
+                    return VNativeSelect.class;
+                } else if (type == "list") {
+                    return VListSelect.class;
+                } else if (uidl.hasAttribute("selectmode")
+                        && uidl.getStringAttribute("selectmode")
+                                .equals("multi")) {
+                    return VListSelect.class;
+                }
+            }
+        } else if (widgetClass == VTextField.class) {
+            if (uidl.hasAttribute("multiline")) {
+                return VTextArea.class;
+            } else if (uidl.hasAttribute("secret")) {
+                return VPasswordField.class;
+            }
+        } else if (widgetClass == VPopupCalendar.class) {
+            if (uidl.hasAttribute("type")
+                    && uidl.getStringAttribute("type").equals("inline")) {
+                return VDateFieldCalendar.class;
+            }
+        } else if (widgetClass == VSplitPanelHorizontal.class
+                && uidl.hasAttribute("vertical")) {
+            return VSplitPanelVertical.class;
+        }
+
+        return widgetClass;
+
+    }
 
     /**
      * Test if the given component implementation conforms to UIDL.
@@ -34,7 +143,9 @@ public interface WidgetSet extends EntryPoint {
      *         class than currentWidget
      */
     public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl,
-            ApplicationConfiguration conf);
+            ApplicationConfiguration conf) {
+        return currentWidget.getClass() == resolveWidgetType(uidl, conf);
+    }
 
     /**
      * Due its nature, GWT does not support dynamic classloading. To bypass this
@@ -46,7 +157,19 @@ public interface WidgetSet extends EntryPoint {
      * @return
      */
     public Class<? extends Paintable> getImplementationByClassName(
-            String fullyQualifiedName,
-            ApplicationConfiguration applicationConfiguration);
+            String fullyqualifiedName) {
+        Class<? extends Paintable> implementationByServerSideClassName = widgetMap
+                .getImplementationByServerSideClassName(fullyqualifiedName);
+        return implementationByServerSideClassName;
+
+    }
+
+    public Class<? extends Paintable>[] getDeferredLoadedWidgets() {
+        return widgetMap.getDeferredLoadedWidgets();
+    }
+
+    public void loadImplementation(Class<? extends Paintable> nextType) {
+        widgetMap.ensureInstantiator(nextType);
+    }
 
 }
index 72bfdd1fd8c7a241e901b39fbeab72927c840640..4da8c0a9251da09ec9dfd26c21ac41232b4ef550 100644 (file)
@@ -7,6 +7,7 @@ import java.io.PrintWriter;
 import java.util.Collection;
 import java.util.Date;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.TreeSet;
 
 import com.google.gwt.core.ext.Generator;
@@ -21,6 +22,7 @@ import com.google.gwt.user.rebind.SourceWriter;
 import com.vaadin.terminal.Paintable;
 import com.vaadin.terminal.gwt.client.ui.VView;
 import com.vaadin.ui.ClientWidget;
+import com.vaadin.ui.ClientWidget.LoadStyle;
 
 /**
  * GWT generator to build WidgetMapImpl dynamically based on
@@ -173,28 +175,26 @@ public class WidgetMapGenerator extends Generator {
      * @return true iff the widget for given component should be lazy loaded by
      *         the client side engine
      */
-    protected boolean isLazyLoaded(Class<? extends Paintable> paintableType) {
+    protected LoadStyle getLoadStyle(Class<? extends Paintable> paintableType) {
         ClientWidget annotation = paintableType
                 .getAnnotation(ClientWidget.class);
-        return annotation.lazyLoad();
+        return annotation.loadStyle();
     }
 
     private void generateInstantiatorMethod(
             SourceWriter sourceWriter,
             Collection<Class<? extends Paintable>> paintablesHavingWidgetAnnotation) {
 
-        sourceWriter
-                .println("public interface Instantiator { public Paintable get();};");
+        Collection<Class<?>> deferredWidgets = new LinkedList<Class<?>>();
 
         // TODO detect if it would be noticably faster to instantiate with a
         // lookup with index than with the hashmap
 
         sourceWriter
-                .println("private HashMap<Class,Instantiator> instmap = new HashMap<Class,Instantiator>();");
-
-        sourceWriter
-                .println("public void ensureInstantiator(Class<? extends Paintable> classType, final ApplicationConfiguration c) {");
+                .println("public void ensureInstantiator(Class<? extends Paintable> classType) {");
         sourceWriter.println("if(!instmap.containsKey(classType)){");
+        boolean first = true;
+
         for (Class<? extends Paintable> class1 : paintablesHavingWidgetAnnotation) {
             ClientWidget annotation = class1.getAnnotation(ClientWidget.class);
             Class<? extends com.vaadin.terminal.gwt.client.Paintable> clientClass = annotation
@@ -203,27 +203,31 @@ public class WidgetMapGenerator extends Generator {
                 // VView's are not instantiated by widgetset
                 continue;
             }
+            if (!first) {
+                sourceWriter.print(" else ");
+            } else {
+                first = false;
+            }
             sourceWriter.print("if( classType == " + clientClass.getName()
                     + ".class) {");
 
-            String instantiator = "new Instantiator() { public Paintable get(){ return GWT.create("
-                    + clientClass.getName() + ".class );}}";
+            String instantiator = "new WidgetInstantiator() {\n public Paintable get() {\n return GWT.create("
+                    + clientClass.getName() + ".class );\n}\n}\n";
 
-            if (isLazyLoaded(class1)) {
-                sourceWriter
-                        .print("c.widgetLoadStart();GWT.runAsync(new RunAsyncCallback() {\n"
-                                + "            public void onSuccess() {");
+            LoadStyle loadStyle = getLoadStyle(class1);
 
-                sourceWriter.print("instmap.put(");
-                sourceWriter.print(clientClass.getName());
-                sourceWriter.print(".class, ");
-                sourceWriter.print(instantiator);
-                sourceWriter.println("); c.widgetLoaded();");
+            if (loadStyle != LoadStyle.EAGER) {
                 sourceWriter
-                        .print("            }\n"
-                                + "\n"
-                                + "            public void onFailure(Throwable reason) {c.widgetLoaded();\n"
-                                + "\n" + "            }\n" + "        });\n");
+                        .print("ApplicationConfiguration.startWidgetLoading();\n"
+                                + "GWT.runAsync( \n"
+                                + "new WidgetLoader() { void addInstantiator() {instmap.put("
+                                + clientClass.getName()
+                                + ".class,"
+                                + instantiator + ");}});\n");
+
+                if (loadStyle == LoadStyle.DEFERRED) {
+                    deferredWidgets.add(class1);
+                }
 
             } else {
                 // widget implementation in initially loaded js script
@@ -241,13 +245,22 @@ public class WidgetMapGenerator extends Generator {
         sourceWriter.println("}");
 
         sourceWriter
-                .println("public Paintable instantiate(Class<? extends Paintable> classType) {");
-        sourceWriter.indent();
-        sourceWriter
-                .println("Paintable p = super.instantiate(classType); if(p!= null) return p;");
-        sourceWriter.println("return instmap.get(classType).get();");
+                .println("public Class<? extends Paintable>[] getDeferredLoadedWidgets() {");
 
-        sourceWriter.outdent();
+        sourceWriter.println("return new Class[] {");
+        first = true;
+        for (Class<?> class2 : deferredWidgets) {
+            if (!first) {
+                sourceWriter.println(",");
+            }
+            first = false;
+            ClientWidget annotation = class2.getAnnotation(ClientWidget.class);
+            Class<? extends com.vaadin.terminal.gwt.client.Paintable> value = annotation
+                    .value();
+            sourceWriter.print(value.getName() + ".class");
+        }
+
+        sourceWriter.println("};");
         sourceWriter.println("}");
     }
 
@@ -262,7 +275,7 @@ public class WidgetMapGenerator extends Generator {
             Collection<Class<? extends Paintable>> paintablesHavingWidgetAnnotation) {
         sourceWriter
                 .println("public Class<? extends Paintable> "
-                        + "getImplementationByServerSideClassName(String fullyQualifiedName, ApplicationConfiguration c) {");
+                        + "getImplementationByServerSideClassName(String fullyQualifiedName) {");
         sourceWriter.indent();
         sourceWriter
                 .println("fullyQualifiedName = fullyQualifiedName.intern();");
@@ -274,7 +287,7 @@ public class WidgetMapGenerator extends Generator {
             sourceWriter.print("if ( fullyQualifiedName == \"");
             sourceWriter.print(class1.getName());
             sourceWriter.print("\" ) { ensureInstantiator("
-                    + clientClass.getName() + ".class, c); return ");
+                    + clientClass.getName() + ".class); return ");
             sourceWriter.print(clientClass.getName());
             sourceWriter.println(".class;}");
             sourceWriter.print("else ");