]> source.dussan.org Git - vaadin-framework.git/commitdiff
Remove classloader field to make Application serializable (#8644)
authorLeif Åstrand <leif@vaadin.com>
Mon, 16 Apr 2012 10:00:52 +0000 (13:00 +0300)
committerLeif Åstrand <leif@vaadin.com>
Mon, 16 Apr 2012 10:00:52 +0000 (13:00 +0300)
The ClassLoader for loading Root instances is instead fetched using
request.getDeploymentConfiguration().getClassLoader();

src/com/vaadin/Application.java
src/com/vaadin/terminal/DeploymentConfiguration.java
src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
tests/server-side/com/vaadin/tests/server/TransactionListenersConcurrency.java
tests/server-side/com/vaadin/tests/server/component/root/CustomRootClassLoader.java
tests/testbench/com/vaadin/tests/components/customcomponent/CustomLayoutUsingTemplate.java

index 448daea4c0f1b9f84f47099695525dc68d17b223..4da1d52c00769276f63bb63db3af482d17e463ee 100644 (file)
@@ -40,6 +40,7 @@ import com.vaadin.service.ApplicationContext;
 import com.vaadin.terminal.AbstractErrorMessage;
 import com.vaadin.terminal.ApplicationResource;
 import com.vaadin.terminal.CombinedRequest;
+import com.vaadin.terminal.DeploymentConfiguration;
 import com.vaadin.terminal.RequestHandler;
 import com.vaadin.terminal.Terminal;
 import com.vaadin.terminal.VariableOwner;
@@ -343,8 +344,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
 
         private final boolean productionMode;
 
-        private final ClassLoader classLoader;
-
         /**
          * @param applicationUrl
          *            the URL the application should respond to.
@@ -356,19 +355,14 @@ public class Application implements Terminal.ErrorListener, Serializable {
          * @param productionMode
          *            flag indicating whether the application is running in
          *            production mode.
-         * @param classLoader
-         *            class loader to use for loading Root classes,
-         *            <code>null</code> indicates that the default class loader
-         *            should be used.
          */
         public ApplicationStartEvent(URL applicationUrl,
                 Properties applicationProperties, ApplicationContext context,
-                boolean productionMode, ClassLoader classLoader) {
+                boolean productionMode) {
             this.applicationUrl = applicationUrl;
             this.applicationProperties = applicationProperties;
             this.context = context;
             this.productionMode = productionMode;
-            this.classLoader = classLoader;
         }
 
         /**
@@ -417,19 +411,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
         public boolean isProductionMode() {
             return productionMode;
         }
-
-        /**
-         * Gets the class loader to use for loading Root classes,
-         * <code>null</code> indicates that the default class loader should be
-         * used.
-         * 
-         * @return the class loader, or <code>null</code> if not defined.
-         * 
-         * @see Application#getClassLoader()
-         */
-        public ClassLoader getClassLoader() {
-            return classLoader;
-        }
     }
 
     private final static Logger logger = Logger.getLogger(Application.class
@@ -521,11 +502,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
      */
     private Set<Integer> initedRoots = new HashSet<Integer>();
 
-    /**
-     * The classloader that is used to load {@link Root} classes.
-     */
-    private ClassLoader classLoader;
-
     /**
      * Gets the user of the application.
      * 
@@ -640,7 +616,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
         productionMode = event.isProductionMode();
         properties = event.getApplicationProperties();
         context = event.getContext();
-        classLoader = event.getClassLoader();
         init();
         applicationIsRunning = true;
     }
@@ -1867,9 +1842,9 @@ public class Application implements Terminal.ErrorListener, Serializable {
      * The default implementation in {@link Application} creates a new instance
      * of the Root class returned by {@link #getRootClassName(WrappedRequest)},
      * which in turn uses the {@value #ROOT_PARAMETER} parameter from web.xml.
-     * If {@link #getClassLoader()} returns a {@link ClassLoader}, it is used
-     * for loading the Root class. Otherwise the {@link ClassLoader} used to
-     * load this class is used.
+     * If {@link DeploymentConfiguration#getClassLoader()} for the request
+     * returns a {@link ClassLoader}, it is used for loading the Root class.
+     * Otherwise the {@link ClassLoader} used to load this class is used.
      * </p>
      * 
      * @param request
@@ -1890,7 +1865,8 @@ public class Application implements Terminal.ErrorListener, Serializable {
             throws RootRequiresMoreInformationException {
         String rootClassName = getRootClassName(request);
         try {
-            ClassLoader classLoader = getClassLoader();
+            ClassLoader classLoader = request.getDeploymentConfiguration()
+                    .getClassLoader();
             if (classLoader == null) {
                 classLoader = getClass().getClassLoader();
             }
@@ -1909,16 +1885,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
         }
     }
 
-    /**
-     * Get the class loader to use for loading Root classes. <code>null</code>
-     * indicates that the default class loader should be used.
-     * 
-     * @return the class loader to use, or <code>null</code>
-     */
-    protected ClassLoader getClassLoader() {
-        return classLoader;
-    }
-
     /**
      * Provides the name of the <code>Root</code> class that should be used for
      * a request. The class must have an accessible no-args constructor.
index 403a6d68b748e0cbff0228359edeb82409a7d8d1..02a3f0200fceb1737d2808348f814d61cd327084 100644 (file)
@@ -74,4 +74,13 @@ public interface DeploymentConfiguration extends Serializable {
      */
     public String getApplicationOrSystemProperty(String propertyName,
             String defaultValue);
+
+    /**
+     * Get the class loader to use for loading classes loaded by name, e.g.
+     * custom Root classes. <code>null</code> indicates that the default class
+     * loader should be used.
+     * 
+     * @return the class loader to use, or <code>null</code>
+     */
+    public ClassLoader getClassLoader();
 }
index 72a0432f4bf92dbc3fdef425a29985b34ae3a6fc..8235859758a5a384d686cc2343352c14f4c51cfb 100644 (file)
@@ -287,6 +287,12 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
                 return "/html";
             }
         }
+
+        public ClassLoader getClassLoader() {
+            // Custom class loaders not currently supported in portlets (see
+            // #8574)
+            return null;
+        }
     };
 
     @Override
@@ -857,7 +863,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
             application.setLocale(locale);
             // No application URL when running inside a portlet
             application.start(new ApplicationStartEvent(null,
-                    applicationProperties, context, isProductionMode(), null));
+                    applicationProperties, context, isProductionMode()));
         }
     }
 
index c295e05ed733d59fda060bcda602082ab492d122..18cc3f97f405575ab2257fa20d50b76fb9a6b58f 100644 (file)
@@ -171,6 +171,14 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
         public boolean isStandalone(WrappedRequest request) {
             return true;
         }
+
+        public ClassLoader getClassLoader() {
+            try {
+                return AbstractApplicationServlet.this.getClassLoader();
+            } catch (ServletException e) {
+                throw new RuntimeException(e);
+            }
+        }
     };
 
     static final String UPLOAD_URL_PREFIX = "APP/UPLOAD/";
@@ -1037,7 +1045,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
             application.setLocale(locale);
             application.start(new ApplicationStartEvent(applicationUrl,
                     applicationProperties, webApplicationContext,
-                    isProductionMode(), getClassLoader()));
+                    isProductionMode()));
         }
     }
 
index e430cb6103a7b3e73212a333a8f39df610b67799..8cc26a5c7f148f9350d5c8cee1df5fae6e135915 100644 (file)
@@ -73,7 +73,7 @@ public class TransactionListenersConcurrency extends TestCase {
 
                         app.start(new ApplicationStartEvent(new URL(
                                 "http://localhost/"), new Properties(),
-                                context, true, null));
+                                context, true));
                     } catch (MalformedURLException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
index 99b77b0d2976c675556b4176106e38f3ef32acca..aa9753ebcc58a7e2e11920ec809cb1f4f92d71a6 100644 (file)
@@ -6,9 +6,12 @@ import java.util.Properties;
 
 import junit.framework.TestCase;
 
+import org.easymock.EasyMock;
+
 import com.vaadin.Application;
 import com.vaadin.Application.ApplicationStartEvent;
 import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.terminal.DeploymentConfiguration;
 import com.vaadin.terminal.WrappedRequest;
 import com.vaadin.ui.Root;
 
@@ -50,12 +53,28 @@ public class CustomRootClassLoader extends TestCase {
     public void testWithNullClassLoader() throws Exception {
         Application application = createStubApplication();
         application.start(new ApplicationStartEvent(null, new Properties(),
-                null, false, null));
+                null, false));
 
-        Root root = application.getRootForRequest(null);
+        Root root = application.getRootForRequest(createRequestMock(null));
         assertTrue(root instanceof MyRoot);
     }
 
+    private static WrappedRequest createRequestMock(ClassLoader classloader) {
+        // Mock a DeploymentConfiguration to give the passed classloader
+        DeploymentConfiguration configurationMock = EasyMock
+                .createMock(DeploymentConfiguration.class);
+        EasyMock.expect(configurationMock.getClassLoader()).andReturn(
+                classloader);
+
+        // Mock a WrappedRequest to give the mocked deployment configuration
+        WrappedRequest requestMock = EasyMock.createMock(WrappedRequest.class);
+        EasyMock.expect(requestMock.getDeploymentConfiguration()).andReturn(
+                configurationMock);
+
+        EasyMock.replay(configurationMock, requestMock);
+        return requestMock;
+    }
+
     /**
      * Tests that the ClassLoader passed in the ApplicationStartEvent is used to
      * load Root classes.
@@ -68,9 +87,10 @@ public class CustomRootClassLoader extends TestCase {
 
         Application application = createStubApplication();
         application.start(new ApplicationStartEvent(null, new Properties(),
-                null, false, loggingClassLoader));
+                null, false));
 
-        Root root = application.getRootForRequest(null);
+        Root root = application
+                .getRootForRequest(createRequestMock(loggingClassLoader));
         assertTrue(root instanceof MyRoot);
         assertEquals(1, loggingClassLoader.requestedClasses.size());
         assertEquals(MyRoot.class.getName(),
index 5bd2dc6c4f999b32ff04f7a9a234bd3e16fdd34c..2dc3063b0c79c97817e1529edde110449a1891a7 100644 (file)
@@ -23,7 +23,8 @@ public class CustomLayoutUsingTemplate extends TestBase implements
         thisPackage = thisPackage.replaceAll(
                 CustomLayoutUsingTemplate.class.getSimpleName() + "$", "");
         String template = thisPackage + "template.htm";
-        InputStream is = getClassLoader().getResourceAsStream(template);
+        InputStream is = getClass().getClassLoader().getResourceAsStream(
+                template);
         try {
             layout = new CustomLayout(is);
             layout.addComponent(new Button(