summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/vaadinBootstrap.js8
-rw-r--r--server/src/com/vaadin/Application.java341
-rw-r--r--server/src/com/vaadin/UIRequiresMoreInformationException.java37
-rw-r--r--server/src/com/vaadin/annotations/PreserveOnRefresh.java28
-rw-r--r--server/src/com/vaadin/annotations/Title.java38
-rw-r--r--server/src/com/vaadin/server/AbstractApplicationPortlet.java9
-rw-r--r--server/src/com/vaadin/server/AbstractCommunicationManager.java36
-rw-r--r--server/src/com/vaadin/server/BootstrapFragmentResponse.java13
-rw-r--r--server/src/com/vaadin/server/BootstrapHandler.java107
-rw-r--r--server/src/com/vaadin/server/BootstrapPageResponse.java14
-rw-r--r--server/src/com/vaadin/server/BootstrapResponse.java40
-rw-r--r--server/src/com/vaadin/server/CommunicationManager.java7
-rw-r--r--server/src/com/vaadin/server/DefaultUIProvider.java3
-rw-r--r--server/src/com/vaadin/server/PortletCommunicationManager.java7
-rw-r--r--server/src/com/vaadin/server/UIProvider.java3
-rw-r--r--server/src/com/vaadin/server/WrappedRequest.java9
-rw-r--r--server/src/com/vaadin/ui/UI.java50
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java28
-rw-r--r--uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java4
-rw-r--r--uitest/src/com/vaadin/tests/application/RefreshStatePreserve.java7
-rw-r--r--uitest/src/com/vaadin/tests/application/ThreadLocalInstances.java19
-rw-r--r--uitest/src/com/vaadin/tests/components/loginform/LoginFormWithMultipleWindows.java13
-rw-r--r--uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java44
-rw-r--r--uitest/src/com/vaadin/tests/components/ui/UIsInMultipleTabs.java4
-rw-r--r--uitest/src/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java5
-rw-r--r--uitest/src/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java42
-rw-r--r--uitest/src/com/vaadin/tests/vaadincontext/TestAddonContextListener.java5
27 files changed, 440 insertions, 481 deletions
diff --git a/WebContent/VAADIN/vaadinBootstrap.js b/WebContent/VAADIN/vaadinBootstrap.js
index 1f5f3fa973..36cf2ec8eb 100644
--- a/WebContent/VAADIN/vaadinBootstrap.js
+++ b/WebContent/VAADIN/vaadinBootstrap.js
@@ -153,15 +153,11 @@
var bootstrapApp = function(mayDefer) {
var themeUri = getConfig('themeUri');
- if (themeUri) {
- loadTheme(themeUri);
- }
+ loadTheme(themeUri);
var widgetsetBase = getConfig('widgetsetBase');
var widgetset = getConfig('widgetset');
- if (widgetset && widgetsetBase) {
- loadWidgetset(widgetsetBase, widgetset);
- }
+ loadWidgetset(widgetsetBase, widgetset);
if (getConfig('uidl') === undefined) {
if (mayDefer) {
diff --git a/server/src/com/vaadin/Application.java b/server/src/com/vaadin/Application.java
index fb2691c6d3..b1a9ae1d26 100644
--- a/server/src/com/vaadin/Application.java
+++ b/server/src/com/vaadin/Application.java
@@ -28,7 +28,6 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.EventObject;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -36,14 +35,15 @@ import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
-import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.vaadin.annotations.EagerInit;
+import com.vaadin.annotations.PreserveOnRefresh;
import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Title;
import com.vaadin.annotations.Widgetset;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.ConverterFactory;
@@ -210,15 +210,16 @@ public class Application implements Terminal.ErrorListener, Serializable {
* This implementation simulates the way of finding a window for a
* request by extracting a window name from the requested path and
* passes that name to {@link #getWindow(String)}.
- *
+ * <p>
* {@inheritDoc}
- *
- * @see #getWindow(String)
- * @see Application#getUI(WrappedRequest)
*/
-
@Override
- public UI.LegacyWindow getUI(WrappedRequest request) {
+ protected <T extends UI> T createUIInstance(WrappedRequest request,
+ Class<T> uiClass) {
+ return uiClass.cast(getUIInstance(request));
+ }
+
+ private UI getUIInstance(WrappedRequest request) {
String pathInfo = request.getRequestPathInfo();
String name = null;
if (pathInfo != null && pathInfo.length() > 0) {
@@ -236,6 +237,19 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
/**
+ * This implementation simulates the way of finding a window for a
+ * request by extracting a window name from the requested path and
+ * passes that name to {@link #getWindow(String)}.
+ *
+ * <p>
+ * {@inheritDoc}
+ */
+ @Override
+ public Class<? extends UI> getUIClass(WrappedRequest request) {
+ return getUIInstance(request).getClass();
+ }
+
+ /**
* Sets the application's theme.
* <p>
* Note that this theme can be overridden for a specific UI with
@@ -269,9 +283,9 @@ public class Application implements Terminal.ErrorListener, Serializable {
* <p>
* {@inheritDoc}
*/
-
@Override
- public String getThemeForUI(UI uI) {
+ public String getThemeForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
return theme;
}
@@ -476,15 +490,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
private final EventRouter eventRouter = new EventRouter();
- /**
- * Keeps track of which uIs have been inited.
- * <p>
- * TODO Investigate whether this might be derived from the different states
- * in getUIForRrequest.
- * </p>
- */
- private Set<Integer> initedUIs = new HashSet<Integer>();
-
private List<UIProvider> uiProviders = new LinkedList<UIProvider>();
private GlobalResourceHandler globalResourceHandler;
@@ -1577,67 +1582,98 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
/**
- * Gets a UI for a request for which no UI is already known. This method is
- * called when the framework processes a request that does not originate
- * from an existing UI instance. This typically happens when a host page is
- * requested.
- *
+ * Gets the UI class for a request for which no UI is already known. This
+ * method is called when the framework processes a request that does not
+ * originate from an existing UI instance. This typically happens when a
+ * host page is requested.
* <p>
* Subclasses of Application may override this method to provide custom
- * logic for choosing how to create a suitable UI or for picking an already
- * created UI. If an existing UI is picked, care should be taken to avoid
- * keeping the same UI open in multiple browser windows, as that will cause
- * the states to go out of sync.
- * </p>
- *
+ * logic for choosing what kind of UI to use.
* <p>
- * If {@link BrowserDetails} are required to create a UI, the implementation
- * can throw a {@link UIRequiresMoreInformationException} exception. In this
- * case, the framework will instruct the browser to send the additional
- * details, whereupon this method is invoked again with the browser details
- * present in the wrapped request. Throwing the exception if the browser
- * details are already available is not supported.
- * </p>
+ * The default implementation in {@link Application} uses the
+ * {@value #UI_PARAMETER} parameter from web.xml for finding the name of the
+ * UI class. If {@link DeploymentConfiguration#getClassLoader()} does not
+ * return <code>null</code>, the returned {@link ClassLoader} is used for
+ * loading the UI class. Otherwise the {@link ClassLoader} used to load this
+ * class is used.
*
- * <p>
- * The default implementation in {@link Application} creates a new instance
- * of the UI class returned by {@link #getUIClassName(WrappedRequest)},
- * which in turn uses the {@value #UI_PARAMETER} parameter from web.xml. If
- * {@link DeploymentConfiguration#getClassLoader()} for the request returns
- * a {@link ClassLoader}, it is used for loading the UI class. Otherwise the
- * {@link ClassLoader} used to load this class is used.
* </p>
*
* @param request
* the wrapped request for which a UI is needed
* @return a UI instance to use for the request
- * @throws UIRequiresMoreInformationException
- * may be thrown by an implementation to indicate that
- * {@link BrowserDetails} are required to create a UI
*
- * @see #getUIClassName(WrappedRequest)
* @see UI
- * @see UIRequiresMoreInformationException
* @see WrappedRequest#getBrowserDetails()
*
* @since 7.0
*/
- protected UI getUI(WrappedRequest request)
- throws UIRequiresMoreInformationException {
-
- // Iterate in reverse order - test check newest provider first
- for (int i = uiProviders.size() - 1; i >= 0; i--) {
+ public Class<? extends UI> getUIClass(WrappedRequest request) {
+ // Iterate in reverse order - check newest provider first
+ int providersSize = uiProviders.size();
+ if (providersSize == 0) {
+ throw new IllegalStateException("There are no UI providers");
+ }
+ for (int i = providersSize - 1; i >= 0; i--) {
UIProvider provider = uiProviders.get(i);
Class<? extends UI> uiClass = provider.getUIClass(this, request);
if (uiClass != null) {
- return provider.instantiateUI(this, uiClass, request);
+ return uiClass;
+ }
+ }
+
+ throw new RuntimeException(
+ "No UI provider returned an UI class for request");
+ }
+
+ /**
+ * Creates an UI instance for a request for which no UI is already known.
+ * This method is called when the framework processes a request that does
+ * not originate from an existing UI instance. This typically happens when a
+ * host page is requested.
+ * <p>
+ * Subclasses of Application may override this method to provide custom
+ * logic for choosing how to create a suitable UI or for picking an already
+ * created UI. If an existing UI is picked, care should be taken to avoid
+ * keeping the same UI open in multiple browser windows, as that will cause
+ * the states to go out of sync.
+ * </p>
+ *
+ * @param request
+ * @param uiClass
+ * @return
+ */
+ protected <T extends UI> T createUIInstance(WrappedRequest request,
+ Class<T> uiClass) {
+ int providersSize = uiProviders.size();
+ if (providersSize == 0) {
+ throw new IllegalStateException("There are no UI providers");
+ }
+
+ for (int i = providersSize - 1; i >= 0; i--) {
+ UIProvider provider = uiProviders.get(i);
+
+ Class<? extends UI> providerClass = provider.getUIClass(this,
+ request);
+ if (providerClass != null) {
+ if (providerClass != uiClass) {
+ getLogger().warning(
+ "Mismatching UI classes. Expected " + uiClass
+ + " but got " + providerClass + " from "
+ + provider);
+ // Try with next provider if we didn't get the expected
+ // class
+ continue;
+ }
+ return uiClass.cast(provider.instantiateUI(this, uiClass,
+ request));
}
}
throw new RuntimeException(
- "No UI providers available or providers are not able to find UI instance");
+ "No UI provider created an UI instance for request");
}
/**
@@ -1653,8 +1689,9 @@ public class Application implements Terminal.ErrorListener, Serializable {
*
* @since 7.0
*/
- public String getThemeForUI(UI uI) {
- Theme uiTheme = getAnnotationFor(uI.getClass(), Theme.class);
+ public String getThemeForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Theme uiTheme = getAnnotationFor(uiClass, Theme.class);
if (uiTheme != null) {
return uiTheme.value();
} else {
@@ -1665,18 +1702,22 @@ public class Application implements Terminal.ErrorListener, Serializable {
/**
* Finds the widgetset to use for a specific UI. If no specific widgetset is
* required, <code>null</code> is returned.
+ * <p>
+ * The default implementation uses the @{@link Widgetset} annotation if it's
+ * defined for the UI class.
*
- * TODO Tell what the default implementation does once it does something.
- *
- * @param uI
- * the UI to get a widgetset for
+ * @param request
+ * the wrapped request for which to get a widgetset
+ * @param uiClass
+ * the UI class to get a widgetset for
* @return the name of the widgetset, or <code>null</code> if the default
* widgetset should be used
*
* @since 7.0
*/
- public String getWidgetsetForUI(UI uI) {
- Widgetset uiWidgetset = getAnnotationFor(uI.getClass(), Widgetset.class);
+ public String getWidgetsetForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Widgetset uiWidgetset = getAnnotationFor(uiClass, Widgetset.class);
if (uiWidgetset != null) {
return uiWidgetset.value();
} else {
@@ -1818,8 +1859,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
*/
private static final ThreadLocal<Application> currentApplication = new ThreadLocal<Application>();
- private boolean uiPreserved = false;
-
/**
* Gets the currently used application. The current application is
* automatically defined when processing requests to the server. In other
@@ -1894,17 +1933,12 @@ public class Application implements Terminal.ErrorListener, Serializable {
* @param request
* the request for which a UI is desired
* @return a UI belonging to the request
- * @throws UIRequiresMoreInformationException
- * if no existing UI could be found and creating a new UI
- * requires additional information from the browser
*
- * @see #getUI(WrappedRequest)
- * @see UIRequiresMoreInformationException
+ * @see #createUI(WrappedRequest)
*
* @since 7.0
*/
- public UI getUIForRequest(WrappedRequest request)
- throws UIRequiresMoreInformationException {
+ public UI getUIForRequest(WrappedRequest request) {
UI uI = UI.getCurrent();
if (uI != null) {
return uI;
@@ -1917,69 +1951,75 @@ public class Application implements Terminal.ErrorListener, Serializable {
&& browserDetails.getUriFragment() != null;
uI = uIs.get(uiId);
+ Class<? extends UI> uiClass = null;
+
+ if (uI == null && hasBrowserDetails
+ && !retainOnRefreshUIs.isEmpty()) {
+ uiClass = getUIClass(request);
- if (uI == null && isUiPreserved()) {
// Check for a known UI
- if (!retainOnRefreshUIs.isEmpty()) {
- Integer retainedUIId;
- if (!hasBrowserDetails) {
- throw new UIRequiresMoreInformationException();
- } else {
- String windowName = browserDetails.getWindowName();
- retainedUIId = retainOnRefreshUIs.get(windowName);
- }
+ @SuppressWarnings("null")
+ String windowName = browserDetails.getWindowName();
+ Integer retainedUIId = retainOnRefreshUIs.get(windowName);
- if (retainedUIId != null) {
+ if (retainedUIId != null) {
+ UI retainedUI = uIs.get(retainedUIId);
+ // We've had the same UI instance in a window with this
+ // name, but should we still use it?
+ if (retainedUI.getClass() == uiClass) {
uiId = retainedUIId;
- uI = uIs.get(uiId);
+ uI = retainedUI;
+ } else {
+ getLogger().info(
+ "Not using retained UI in " + windowName
+ + " because retained UI was of type "
+ + retainedUIId.getClass() + " but "
+ + uiClass
+ + " is expected for the request.");
}
}
}
- if (uI == null) {
- // Throws exception if UI can not yet be created
- uI = getUI(request);
+ } // end synchronized block
- // Initialize some fields for a newly created UI
- if (uI.getApplication() == null) {
- uI.setApplication(this);
- }
- if (uI.getUIId() < 0) {
+ UI.setCurrent(uI);
- if (uiId == null) {
- // Get the next id if none defined
- uiId = Integer.valueOf(nextUIId++);
- }
- uI.setUIId(uiId.intValue());
- uIs.put(uiId, uI);
- }
- }
+ return uI;
+ }
- // Set thread local here so it is available in init
- UI.setCurrent(uI);
+ public UI createUI(WrappedRequest request) {
+ Class<? extends UI> uiClass = getUIClass(request);
- if (!initedUIs.contains(uiId)) {
- boolean initRequiresBrowserDetails = isUiPreserved()
- || !uI.getClass().isAnnotationPresent(EagerInit.class);
- if (!initRequiresBrowserDetails || hasBrowserDetails) {
- uI.doInit(request);
+ UI ui = createUIInstance(request, uiClass);
- // Remember that this UI has been initialized
- initedUIs.add(uiId);
+ // Initialize some fields for a newly created UI
+ if (ui.getApplication() == null) {
+ ui.setApplication(this);
+ }
+ // Get the next id
+ Integer uiId = Integer.valueOf(nextUIId++);
- // init() might turn on preserve so do this afterwards
- if (isUiPreserved()) {
- // Remember this UI
- String windowName = request.getBrowserDetails()
- .getWindowName();
- retainOnRefreshUIs.put(windowName, uiId);
- }
- }
+ uIs.put(uiId, ui);
+
+ // Set thread local here so it is available in init
+ UI.setCurrent(ui);
+
+ ui.doInit(request, uiId.intValue());
+
+ if (isUiPreserved(request, uiClass)) {
+ // Remember this UI
+ String windowName = request.getBrowserDetails().getWindowName();
+ if (windowName == null) {
+ getLogger().warning(
+ "There is no window.name available for UI " + uiClass
+ + " that should be preserved.");
+ } else {
+ retainOnRefreshUIs.put(windowName, uiId);
}
- } // end synchronized block
+ }
- return uI;
+ return ui;
}
/**
@@ -2003,53 +2043,22 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
/**
- * Sets whether the same UI state should be reused if the framework can
- * detect that the application is opened in a browser window where it has
- * previously been open. The framework attempts to discover this by checking
- * the value of window.name in the browser.
- * <p>
- * NOTE that you should avoid turning this feature on/off on-the-fly when
- * the UI is already shown, as it might not be retained as intended.
- * </p>
- *
- * @param uiPreserved
- * <code>true</code>if the same UI instance should be reused e.g.
- * when the browser window is refreshed.
- */
- public void setUiPreserved(boolean uiPreserved) {
- this.uiPreserved = uiPreserved;
- if (!uiPreserved) {
- retainOnRefreshUIs.clear();
- }
- }
-
- /**
* Checks whether the same UI state should be reused if the framework can
* detect that the application is opened in a browser window where it has
* previously been open. The framework attempts to discover this by checking
* the value of window.name in the browser.
*
+ * @param request
+ * @param uiClass
+ *
* @return <code>true</code>if the same UI instance should be reused e.g.
* when the browser window is refreshed.
*/
- public boolean isUiPreserved() {
- return uiPreserved;
- }
-
- /**
- * Checks whether there's a pending initialization for the UI with the given
- * id.
- *
- * @param uiId
- * UI id to check for
- * @return <code>true</code> of the initialization is pending,
- * <code>false</code> if the UI id is not registered or if the UI
- * has already been initialized
- *
- * @see #getUIForRequest(WrappedRequest)
- */
- public boolean isUIInitPending(int uiId) {
- return !initedUIs.contains(Integer.valueOf(uiId));
+ public boolean isUiPreserved(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ PreserveOnRefresh preserveOnRefresh = getAnnotationFor(uiClass,
+ PreserveOnRefresh.class);
+ return preserveOnRefresh != null;
}
/**
@@ -2268,4 +2277,20 @@ public class Application implements Terminal.ErrorListener, Serializable {
return globalResourceHandler;
}
+
+ public String getPageTitleForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Title titleAnnotation = getAnnotationFor(uiClass, Title.class);
+ if (titleAnnotation == null) {
+ return null;
+ } else {
+ return titleAnnotation.value();
+ }
+ }
+
+ public boolean isEagerInit(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ EagerInit eagerInit = getAnnotationFor(uiClass, EagerInit.class);
+ return eagerInit != null;
+ }
}
diff --git a/server/src/com/vaadin/UIRequiresMoreInformationException.java b/server/src/com/vaadin/UIRequiresMoreInformationException.java
deleted file mode 100644
index 76a31d88ef..0000000000
--- a/server/src/com/vaadin/UIRequiresMoreInformationException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.vaadin;
-
-import com.vaadin.server.WrappedRequest;
-import com.vaadin.server.WrappedRequest.BrowserDetails;
-
-/**
- * Exception that is thrown to indicate that creating or initializing the UI
- * requires information detailed from the web browser ({@link BrowserDetails})
- * to be present.
- *
- * This exception may not be thrown if that information is already present in
- * the current WrappedRequest.
- *
- * @see Application#getUI(WrappedRequest)
- * @see WrappedRequest#getBrowserDetails()
- *
- * @since 7.0
- */
-public class UIRequiresMoreInformationException extends Exception {
- // Nothing of interest here
-}
diff --git a/server/src/com/vaadin/annotations/PreserveOnRefresh.java b/server/src/com/vaadin/annotations/PreserveOnRefresh.java
new file mode 100644
index 0000000000..59c4abb723
--- /dev/null
+++ b/server/src/com/vaadin/annotations/PreserveOnRefresh.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PreserveOnRefresh {
+
+}
diff --git a/server/src/com/vaadin/annotations/Title.java b/server/src/com/vaadin/annotations/Title.java
new file mode 100644
index 0000000000..fcd5d986a8
--- /dev/null
+++ b/server/src/com/vaadin/annotations/Title.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.vaadin.ui.UI;
+
+/**
+ * Defines the HTML page title for a {@link UI}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Title {
+ /**
+ * Gets the HTML title that should be used if the UI is used on it's own.
+ *
+ * @return a page title string
+ */
+ public String value();
+}
diff --git a/server/src/com/vaadin/server/AbstractApplicationPortlet.java b/server/src/com/vaadin/server/AbstractApplicationPortlet.java
index e47e00577b..e8151462aa 100644
--- a/server/src/com/vaadin/server/AbstractApplicationPortlet.java
+++ b/server/src/com/vaadin/server/AbstractApplicationPortlet.java
@@ -56,7 +56,6 @@ import com.liferay.portal.kernel.util.PropsUtil;
import com.vaadin.Application;
import com.vaadin.Application.ApplicationStartEvent;
import com.vaadin.Application.SystemMessages;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.server.AbstractCommunicationManager.Callback;
import com.vaadin.ui.UI;
@@ -501,12 +500,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
// Both action requests and render requests are ok
// without a UI as they render the initial HTML
// and then do a second request
- try {
- uI = application
- .getUIForRequest(wrappedRequest);
- } catch (UIRequiresMoreInformationException e) {
- // Ignore problem and continue without UI
- }
+ uI = application.getUIForRequest(wrappedRequest);
break;
case BROWSER_DETAILS:
// Should not try to find a UI here as the
@@ -902,7 +896,6 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
throws PortletException {
try {
final Application application = getApplicationClass().newInstance();
- application.setUiPreserved(true);
return application;
} catch (final IllegalAccessException e) {
throw new PortletException("getNewApplication failed", e);
diff --git a/server/src/com/vaadin/server/AbstractCommunicationManager.java b/server/src/com/vaadin/server/AbstractCommunicationManager.java
index 08ad48ff3d..72406e629d 100644
--- a/server/src/com/vaadin/server/AbstractCommunicationManager.java
+++ b/server/src/com/vaadin/server/AbstractCommunicationManager.java
@@ -60,13 +60,11 @@ import javax.servlet.http.HttpServletResponse;
import com.vaadin.Application;
import com.vaadin.Application.SystemMessages;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.annotations.JavaScript;
import com.vaadin.annotations.StyleSheet;
import com.vaadin.external.json.JSONArray;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
-import com.vaadin.server.BootstrapHandler.BootstrapContext;
import com.vaadin.server.ComponentSizeValidator.InvalidLayout;
import com.vaadin.server.RpcManager.RpcInvocationException;
import com.vaadin.server.StreamVariable.StreamingEndEvent;
@@ -1512,7 +1510,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
private String getTheme(UI uI) {
- String themeName = uI.getApplication().getThemeForUI(uI);
+ String themeName = uI.getTheme();
String requestThemeName = getRequestTheme();
if (requestThemeName != null) {
@@ -2410,36 +2408,22 @@ public abstract class AbstractCommunicationManager implements Serializable {
WrappedResponse response, Application application)
throws IOException {
- // if we do not yet have a currentUI, it should be initialized
- // shortly, and we should send the initial UIDL
- boolean sendUIDL = UI.getCurrent() == null;
+ assert UI.getCurrent() == null;
try {
CombinedRequest combinedRequest = new CombinedRequest(request);
- UI uI = application.getUIForRequest(combinedRequest);
response.setContentType("application/json; charset=UTF-8");
- // Use the same logic as for determined UIs
- BootstrapHandler bootstrapHandler = getBootstrapHandler();
- BootstrapContext context = bootstrapHandler.createContext(
- combinedRequest, response, application, uI.getUIId());
-
- String widgetset = context.getWidgetsetName();
- String theme = context.getThemeName();
- String themeUri = bootstrapHandler.getThemeUri(context, theme);
+ UI uI = application.getUIForRequest(combinedRequest);
+ if (uI == null) {
+ uI = application.createUI(combinedRequest);
+ }
- // TODO These are not required if it was only the init of the UI
- // that was delayed
JSONObject params = new JSONObject();
- params.put("widgetset", widgetset);
- params.put("themeUri", themeUri);
- // UI id might have changed based on e.g. window.name
params.put(UIConstants.UI_ID_PARAMETER, uI.getUIId());
- if (sendUIDL) {
- String initialUIDL = getInitialUIDL(combinedRequest, uI);
- params.put("uidl", initialUIDL);
- }
+ String initialUIDL = getInitialUIDL(combinedRequest, uI);
+ params.put("uidl", initialUIDL);
// NOTE! GateIn requires, for some weird reason, getOutputStream
// to be used instead of getWriter() (it seems to interpret
@@ -2452,10 +2436,6 @@ public abstract class AbstractCommunicationManager implements Serializable {
// NOTE GateIn requires the buffers to be flushed to work
outWriter.flush();
out.flush();
- } catch (UIRequiresMoreInformationException e) {
- // Requiring more information at this point is not allowed
- // TODO handle in a better way
- throw new RuntimeException(e);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
diff --git a/server/src/com/vaadin/server/BootstrapFragmentResponse.java b/server/src/com/vaadin/server/BootstrapFragmentResponse.java
index 16f7bc653b..149f59e7a5 100644
--- a/server/src/com/vaadin/server/BootstrapFragmentResponse.java
+++ b/server/src/com/vaadin/server/BootstrapFragmentResponse.java
@@ -21,6 +21,7 @@ import java.util.List;
import org.jsoup.nodes.Node;
import com.vaadin.Application;
+import com.vaadin.ui.UI;
/**
* A representation of a bootstrap fragment being generated. The bootstrap
@@ -37,7 +38,7 @@ public class BootstrapFragmentResponse extends BootstrapResponse {
* Crate a new bootstrap fragment response.
*
* @see BootstrapResponse#BootstrapResponse(BootstrapHandler,
- * WrappedRequest, Application, Integer)
+ * WrappedRequest, Application, Class)
*
* @param handler
* the bootstrap handler that is firing the event
@@ -47,16 +48,16 @@ public class BootstrapFragmentResponse extends BootstrapResponse {
* @param application
* the application for which the bootstrap page should be
* generated
- * @param uiId
- * the generated id of the UI that will be displayed on the page
+ * @param uiClass
+ * the class of the UI that will be displayed on the page
* @param fragmentNodes
* a mutable list containing the DOM nodes that will make up the
* application HTML
*/
public BootstrapFragmentResponse(BootstrapHandler handler,
- WrappedRequest request, Application application, Integer uiId,
- List<Node> fragmentNodes) {
- super(handler, request, application, uiId);
+ WrappedRequest request, Application application,
+ Class<? extends UI> uiClass, List<Node> fragmentNodes) {
+ super(handler, request, application, uiClass);
this.fragmentNodes = fragmentNodes;
}
diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java
index 280372a5e5..2b31d5d3bc 100644
--- a/server/src/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/com/vaadin/server/BootstrapHandler.java
@@ -37,12 +37,10 @@ import org.jsoup.nodes.Node;
import org.jsoup.parser.Tag;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.shared.Version;
-import com.vaadin.shared.ui.ui.UIConstants;
import com.vaadin.ui.UI;
public abstract class BootstrapHandler implements RequestHandler {
@@ -74,30 +72,20 @@ public abstract class BootstrapHandler implements RequestHandler {
return bootstrapResponse.getApplication();
}
- public Integer getUIId() {
- return bootstrapResponse.getUIId();
- }
-
- public UI getUI() {
- return bootstrapResponse.getUI();
+ public Class<? extends UI> getUIClass() {
+ return bootstrapResponse.getUiClass();
}
public String getWidgetsetName() {
if (widgetsetName == null) {
- UI uI = getUI();
- if (uI != null) {
- widgetsetName = getWidgetsetForUI(this);
- }
+ widgetsetName = getWidgetsetForUI(this);
}
return widgetsetName;
}
public String getThemeName() {
if (themeName == null) {
- UI uI = getUI();
- if (uI != null) {
- themeName = findAndEscapeThemeName(this);
- }
+ themeName = findAndEscapeThemeName(this);
}
return themeName;
}
@@ -120,23 +108,11 @@ public abstract class BootstrapHandler implements RequestHandler {
WrappedRequest request, WrappedResponse response)
throws IOException {
- // TODO Should all urls be handled here?
- Integer uiId = null;
try {
- UI uI = application.getUIForRequest(request);
- if (uI == null) {
- writeError(response, new Throwable("No UI found"));
- return true;
- }
+ Class<? extends UI> uiClass = application.getUIClass(request);
- uiId = Integer.valueOf(uI.getUIId());
- } catch (UIRequiresMoreInformationException e) {
- // Just keep going without uiId
- }
-
- try {
BootstrapContext context = createContext(request, response,
- application, uiId);
+ application, uiClass);
setupMainDiv(context);
BootstrapFragmentResponse fragmentResponse = context
@@ -166,8 +142,8 @@ public abstract class BootstrapHandler implements RequestHandler {
Map<String, Object> headers = new LinkedHashMap<String, Object>();
Document document = Document.createShell("");
BootstrapPageResponse pageResponse = new BootstrapPageResponse(
- this, request, context.getApplication(), context.getUIId(),
- document, headers);
+ this, request, context.getApplication(),
+ context.getUIClass(), document, headers);
List<Node> fragmentNodes = fragmentResponse.getFragmentNodes();
Element body = document.body();
for (Node node : fragmentNodes) {
@@ -242,10 +218,11 @@ public abstract class BootstrapHandler implements RequestHandler {
head.appendElement("meta").attr("http-equiv", "X-UA-Compatible")
.attr("content", "chrome=1");
- UI uI = context.getUI();
- String title = ((uI == null || uI.getCaption() == null) ? "" : uI
- .getCaption());
- head.appendElement("title").appendText(title);
+ String title = context.getApplication().getPageTitleForUI(
+ context.getRequest(), context.getUIClass());
+ if (title != null) {
+ head.appendElement("title").appendText(title);
+ }
head.appendElement("style").attr("type", "text/css")
.appendText("html, body {height:100%;margin:0;}");
@@ -267,11 +244,12 @@ public abstract class BootstrapHandler implements RequestHandler {
body.addClass(ApplicationConstants.GENERATED_BODY_CLASSNAME);
}
- public BootstrapContext createContext(WrappedRequest request,
- WrappedResponse response, Application application, Integer uiId) {
+ private BootstrapContext createContext(WrappedRequest request,
+ WrappedResponse response, Application application,
+ Class<? extends UI> uiClass) {
BootstrapContext context = new BootstrapContext(response,
- new BootstrapFragmentResponse(this, request, application, uiId,
- new ArrayList<Node>()));
+ new BootstrapFragmentResponse(this, request, application,
+ uiClass, new ArrayList<Node>()));
return context;
}
@@ -290,10 +268,10 @@ public abstract class BootstrapHandler implements RequestHandler {
protected abstract String getApplicationId(BootstrapContext context);
public String getWidgetsetForUI(BootstrapContext context) {
- UI uI = context.getUI();
WrappedRequest request = context.getRequest();
- String widgetset = uI.getApplication().getWidgetsetForUI(uI);
+ String widgetset = context.getApplication().getWidgetsetForUI(
+ context.getRequest(), context.getUIClass());
if (widgetset == null) {
widgetset = request.getDeploymentConfiguration()
.getConfiguredWidgetset(request);
@@ -413,14 +391,9 @@ public abstract class BootstrapHandler implements RequestHandler {
protected JSONObject getApplicationParameters(BootstrapContext context)
throws JSONException, PaintException {
Application application = context.getApplication();
- Integer uiId = context.getUIId();
JSONObject appConfig = new JSONObject();
- if (uiId != null) {
- appConfig.put(UIConstants.UI_ID_PARAMETER, uiId);
- }
-
if (context.getThemeName() != null) {
appConfig.put("themeUri",
getThemeUri(context, context.getThemeName()));
@@ -433,18 +406,18 @@ public abstract class BootstrapHandler implements RequestHandler {
appConfig.put("widgetset", context.getWidgetsetName());
- if (uiId == null || application.isUIInitPending(uiId.intValue())) {
- appConfig.put("initialPath", context.getRequest()
- .getRequestPathInfo());
-
- Map<String, String[]> parameterMap = context.getRequest()
- .getParameterMap();
- appConfig.put("initialParams", parameterMap);
- } else {
+ if (application.isEagerInit(context.getRequest(), context.getUIClass())) {
+ throw new RuntimeException(
+ "Eager UI init is currently not supported");
// write the initial UIDL into the config
- appConfig.put("uidl",
- getInitialUIDL(context.getRequest(), context.getUI()));
+ // appConfig.put("uidl",
+ // getInitialUIDL(context.getRequest(), context.getUI()));
}
+ appConfig.put("initialPath", context.getRequest().getRequestPathInfo());
+
+ Map<String, String[]> parameterMap = context.getRequest()
+ .getParameterMap();
+ appConfig.put("initialParams", parameterMap);
return appConfig;
}
@@ -532,7 +505,8 @@ public abstract class BootstrapHandler implements RequestHandler {
* @return
*/
public String getThemeName(BootstrapContext context) {
- return context.getApplication().getThemeForUI(context.getUI());
+ return context.getApplication().getThemeForUI(context.getRequest(),
+ context.getUIClass());
}
/**
@@ -561,21 +535,4 @@ public abstract class BootstrapHandler implements RequestHandler {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
e.getLocalizedMessage());
}
-
- /**
- * Gets the initial UIDL message to send to the client.
- *
- * @param request
- * the originating request
- * @param ui
- * the UI for which the UIDL should be generated
- * @return a string with the initial UIDL message
- * @throws PaintException
- * if an exception occurs while painting the components
- * @throws JSONException
- * if an exception occurs while formatting the output
- */
- protected abstract String getInitialUIDL(WrappedRequest request, UI ui)
- throws PaintException, JSONException;
-
}
diff --git a/server/src/com/vaadin/server/BootstrapPageResponse.java b/server/src/com/vaadin/server/BootstrapPageResponse.java
index d6df145728..a5fdfe4707 100644
--- a/server/src/com/vaadin/server/BootstrapPageResponse.java
+++ b/server/src/com/vaadin/server/BootstrapPageResponse.java
@@ -21,6 +21,7 @@ import java.util.Map;
import org.jsoup.nodes.Document;
import com.vaadin.Application;
+import com.vaadin.ui.UI;
/**
* A representation of a bootstrap page being generated. The bootstrap page
@@ -39,7 +40,7 @@ public class BootstrapPageResponse extends BootstrapResponse {
* Crate a new bootstrap page response.
*
* @see BootstrapResponse#BootstrapResponse(BootstrapHandler,
- * WrappedRequest, Application, Integer)
+ * WrappedRequest, Application, Class)
*
* @param handler
* the bootstrap handler that is firing the event
@@ -49,17 +50,18 @@ public class BootstrapPageResponse extends BootstrapResponse {
* @param application
* the application for which the bootstrap page should be
* generated
- * @param uiId
- * the generated id of the UI that will be displayed on the page
+ * @param uiClass
+ * the class of the UI that will be displayed on the page
* @param document
* the DOM document making up the HTML page
* @param headers
* a map into which header data can be added
*/
public BootstrapPageResponse(BootstrapHandler handler,
- WrappedRequest request, Application application, Integer uiId,
- Document document, Map<String, Object> headers) {
- super(handler, request, application, uiId);
+ WrappedRequest request, Application application,
+ Class<? extends UI> uiClass, Document document,
+ Map<String, Object> headers) {
+ super(handler, request, application, uiClass);
this.headers = headers;
this.document = document;
}
diff --git a/server/src/com/vaadin/server/BootstrapResponse.java b/server/src/com/vaadin/server/BootstrapResponse.java
index 962b48dc31..3173569059 100644
--- a/server/src/com/vaadin/server/BootstrapResponse.java
+++ b/server/src/com/vaadin/server/BootstrapResponse.java
@@ -19,7 +19,6 @@ package com.vaadin.server;
import java.util.EventObject;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.ui.UI;
/**
@@ -32,7 +31,7 @@ import com.vaadin.ui.UI;
public abstract class BootstrapResponse extends EventObject {
private final WrappedRequest request;
private final Application application;
- private final Integer uiId;
+ private final Class<? extends UI> uiClass;
/**
* Creates a new bootstrap event.
@@ -45,15 +44,15 @@ public abstract class BootstrapResponse extends EventObject {
* @param application
* the application for which the bootstrap page should be
* generated
- * @param uiId
- * the generated id of the UI that will be displayed on the page
+ * @param uiClass
+ * the class of the UI that will be displayed on the page
*/
public BootstrapResponse(BootstrapHandler handler, WrappedRequest request,
- Application application, Integer uiId) {
+ Application application, Class<? extends UI> uiClass) {
super(handler);
this.request = request;
this.application = application;
- this.uiId = uiId;
+ this.uiClass = uiClass;
}
/**
@@ -89,32 +88,13 @@ public abstract class BootstrapResponse extends EventObject {
}
/**
- * Gets the UI id that has been generated for this response. Please note
- * that if {@link Application#isUiPreserved()} is enabled, a previously
- * created UI with a different id might eventually end up being used.
+ * Gets the class of the UI that will be displayed on the generated
+ * bootstrap page.
*
- * @return the UI id
+ * @return the class of the UI
*/
- public Integer getUIId() {
- return uiId;
+ public Class<? extends UI> getUiClass() {
+ return uiClass;
}
- /**
- * Gets the UI for which this page is being rendered, if available. Some
- * features of the framework will postpone the UI selection until after the
- * bootstrap page has been rendered and required information from the
- * browser has been sent back. This method will return <code>null</code> if
- * no UI instance is yet available.
- *
- * @see Application#isUiPreserved()
- * @see Application#getUI(WrappedRequest)
- * @see UIRequiresMoreInformationException
- *
- * @return The UI that will be displayed in the page being generated, or
- * <code>null</code> if all required information is not yet
- * available.
- */
- public UI getUI() {
- return UI.getCurrent();
- }
}
diff --git a/server/src/com/vaadin/server/CommunicationManager.java b/server/src/com/vaadin/server/CommunicationManager.java
index 9b56e20fd4..3c594eaf02 100644
--- a/server/src/com/vaadin/server/CommunicationManager.java
+++ b/server/src/com/vaadin/server/CommunicationManager.java
@@ -22,7 +22,6 @@ import java.net.URL;
import javax.servlet.ServletContext;
import com.vaadin.Application;
-import com.vaadin.external.json.JSONException;
import com.vaadin.ui.UI;
/**
@@ -107,12 +106,6 @@ public class CommunicationManager extends AbstractCommunicationManager {
}
return themeName;
}
-
- @Override
- protected String getInitialUIDL(WrappedRequest request, UI uI)
- throws PaintException, JSONException {
- return CommunicationManager.this.getInitialUIDL(request, uI);
- }
};
}
diff --git a/server/src/com/vaadin/server/DefaultUIProvider.java b/server/src/com/vaadin/server/DefaultUIProvider.java
index d4490b1642..93128aad28 100644
--- a/server/src/com/vaadin/server/DefaultUIProvider.java
+++ b/server/src/com/vaadin/server/DefaultUIProvider.java
@@ -17,14 +17,13 @@
package com.vaadin.server;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.ui.UI;
public class DefaultUIProvider extends AbstractUIProvider {
@Override
public Class<? extends UI> getUIClass(Application application,
- WrappedRequest request) throws UIRequiresMoreInformationException {
+ WrappedRequest request) {
Object uiClassNameObj = application
.getProperty(Application.UI_PARAMETER);
diff --git a/server/src/com/vaadin/server/PortletCommunicationManager.java b/server/src/com/vaadin/server/PortletCommunicationManager.java
index f7d9371022..697095d691 100644
--- a/server/src/com/vaadin/server/PortletCommunicationManager.java
+++ b/server/src/com/vaadin/server/PortletCommunicationManager.java
@@ -138,13 +138,6 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
}
@Override
- protected String getInitialUIDL(WrappedRequest request, UI uI)
- throws PaintException, JSONException {
- return PortletCommunicationManager.this.getInitialUIDL(request,
- uI);
- }
-
- @Override
protected JSONObject getApplicationParameters(
BootstrapContext context) throws JSONException,
PaintException {
diff --git a/server/src/com/vaadin/server/UIProvider.java b/server/src/com/vaadin/server/UIProvider.java
index 890809fdd5..36bb164845 100644
--- a/server/src/com/vaadin/server/UIProvider.java
+++ b/server/src/com/vaadin/server/UIProvider.java
@@ -17,12 +17,11 @@
package com.vaadin.server;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.ui.UI;
public interface UIProvider {
public Class<? extends UI> getUIClass(Application application,
- WrappedRequest request) throws UIRequiresMoreInformationException;
+ WrappedRequest request);
public UI instantiateUI(Application application, Class<? extends UI> type,
WrappedRequest request);
diff --git a/server/src/com/vaadin/server/WrappedRequest.java b/server/src/com/vaadin/server/WrappedRequest.java
index 8ae5335763..e95b2d599b 100644
--- a/server/src/com/vaadin/server/WrappedRequest.java
+++ b/server/src/com/vaadin/server/WrappedRequest.java
@@ -26,8 +26,6 @@ import javax.portlet.PortletRequest;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
-import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.annotations.EagerInit;
import com.vaadin.ui.UI;
@@ -218,11 +216,8 @@ public interface WrappedRequest extends Serializable {
* for instance using javascript in the browser.
*
* This information is only guaranteed to be available in some special
- * cases, for instance when
- * {@link Application#getUIForRequest(WrappedRequest)} is called again after
- * throwing {@link UIRequiresMoreInformationException} or in
- * {@link UI#init(WrappedRequest)} for a UI class not annotated with
- * {@link EagerInit}
+ * cases, for instance in {@link UI#init(WrappedRequest)} for a UI class not
+ * annotated with {@link EagerInit}
*
* @return the browser details, or <code>null</code> if details are not
* available
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index d86d46c155..b6ac271942 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -85,7 +85,7 @@ import com.vaadin.tools.ReflectTools;
* </p>
*
* @see #init(WrappedRequest)
- * @see Application#getUI(WrappedRequest)
+ * @see Application#createUI(WrappedRequest)
*
* @since 7.0
*/
@@ -98,7 +98,6 @@ public abstract class UI extends AbstractComponentContainer implements
* window in Vaadin 6 with {@link com.vaadin.Application.LegacyApplication}
*/
@Deprecated
- @EagerInit
public static class LegacyWindow extends UI {
private String name;
@@ -710,28 +709,6 @@ public abstract class UI extends AbstractComponentContainer implements
}
/**
- * Sets the id of this UI within its application. The UI id is used to route
- * requests to the right UI.
- * <p>
- * This method is mainly intended for internal use by the framework.
- * </p>
- *
- * @param uiId
- * the id of this UI
- *
- * @throws IllegalStateException
- * if the UI id has already been set
- *
- * @see #getUIId()
- */
- public void setUIId(int uiId) {
- if (this.uiId != -1) {
- throw new IllegalStateException("UI id has already been defined");
- }
- this.uiId = uiId;
- }
-
- /**
* Gets the id of the UI, used to identify this UI within its application
* when processing requests. The UI id should be present in every request to
* the server that originates from this UI.
@@ -748,8 +725,8 @@ public abstract class UI extends AbstractComponentContainer implements
* Adds a window as a subwindow inside this UI. To open a new browser window
* or tab, you should instead use {@link open(Resource)} with an url
* pointing to this application and ensure
- * {@link Application#getUI(WrappedRequest)} returns an appropriate UI for
- * the request.
+ * {@link Application#createUI(WrappedRequest)} returns an appropriate UI
+ * for the request.
*
* @param window
* @throws IllegalArgumentException
@@ -831,6 +808,8 @@ public abstract class UI extends AbstractComponentContainer implements
private boolean resizeLazy = false;
+ private String theme;
+
/**
* This method is used by Component.Focusable objects to request focus to
* themselves. Focus renders must be handled at window level (instead of
@@ -959,8 +938,16 @@ public abstract class UI extends AbstractComponentContainer implements
*
* @param request
* the initialization request
+ * @param uiId
+ * the id of the new ui
*/
- public void doInit(WrappedRequest request) {
+ public void doInit(WrappedRequest request, int uiId) {
+ if (this.uiId != -1) {
+ throw new IllegalStateException("UI id has already been defined");
+ }
+ this.uiId = uiId;
+ theme = getApplication().getThemeForUI(request, getClass());
+
getPage().init(request);
// Call the init overridden by the application developer
@@ -1352,4 +1339,13 @@ public abstract class UI extends AbstractComponentContainer implements
public void setLastUidlRequestTime(long lastUidlRequest) {
this.lastUidlRequest = lastUidlRequest;
}
+
+ /**
+ * Gets the theme that was used when the UI was initialized.
+ *
+ * @return the theme name
+ */
+ public String getTheme() {
+ return theme;
+ }
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java b/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java
index 906d6ccebd..89da55a31f 100644
--- a/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java
+++ b/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java
@@ -10,7 +10,6 @@ import org.easymock.EasyMock;
import com.vaadin.Application;
import com.vaadin.Application.ApplicationStartEvent;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.server.DefaultUIProvider;
import com.vaadin.server.DeploymentConfiguration;
import com.vaadin.server.WrappedRequest;
@@ -56,8 +55,11 @@ public class CustomUIClassLoader extends TestCase {
application.start(new ApplicationStartEvent(null,
createConfigurationMock(), null));
- UI uI = application.getUIForRequest(createRequestMock(null));
- assertTrue(uI instanceof MyUI);
+ DefaultUIProvider uiProvider = new DefaultUIProvider();
+ Class<? extends UI> uiClass = uiProvider.getUIClass(application,
+ createRequestMock(null));
+
+ assertEquals(MyUI.class, uiClass);
}
private static DeploymentConfiguration createConfigurationMock() {
@@ -101,9 +103,11 @@ public class CustomUIClassLoader extends TestCase {
application.start(new ApplicationStartEvent(null,
createConfigurationMock(), null));
- UI uI = application
- .getUIForRequest(createRequestMock(loggingClassLoader));
- assertTrue(uI instanceof MyUI);
+ DefaultUIProvider uiProvider = new DefaultUIProvider();
+ Class<? extends UI> uiClass = uiProvider.getUIClass(application,
+ createRequestMock(loggingClassLoader));
+
+ assertEquals(MyUI.class, uiClass);
assertEquals(1, loggingClassLoader.requestedClasses.size());
assertEquals(MyUI.class.getName(),
loggingClassLoader.requestedClasses.get(0));
@@ -112,10 +116,6 @@ public class CustomUIClassLoader extends TestCase {
private Application createStubApplication() {
return new Application() {
- {
- addUIProvider(new DefaultUIProvider());
- }
-
@Override
public String getProperty(String name) {
if (name.equals(UI_PARAMETER)) {
@@ -124,14 +124,6 @@ public class CustomUIClassLoader extends TestCase {
return super.getProperty(name);
}
}
-
- @Override
- public UI getUIForRequest(WrappedRequest request)
- throws UIRequiresMoreInformationException {
- // Always create a new root for testing (can't directly use
- // getRoot as it's protected)
- return getUI(request);
- }
};
}
}
diff --git a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
index e05979ede0..bceecaf35a 100644
--- a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
+++ b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
@@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.server.AbstractApplicationServlet;
import com.vaadin.server.AbstractUIProvider;
import com.vaadin.server.WrappedHttpServletRequest;
@@ -116,8 +115,7 @@ public class ApplicationRunnerServlet extends AbstractApplicationServlet {
@Override
public Class<? extends UI> getUIClass(
- Application application, WrappedRequest request)
- throws UIRequiresMoreInformationException {
+ Application application, WrappedRequest request) {
return (Class<? extends UI>) classToRun;
}
});
diff --git a/uitest/src/com/vaadin/tests/application/RefreshStatePreserve.java b/uitest/src/com/vaadin/tests/application/RefreshStatePreserve.java
index 3013659ed7..8962f5de9a 100644
--- a/uitest/src/com/vaadin/tests/application/RefreshStatePreserve.java
+++ b/uitest/src/com/vaadin/tests/application/RefreshStatePreserve.java
@@ -1,7 +1,7 @@
package com.vaadin.tests.application;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
+import com.vaadin.annotations.PreserveOnRefresh;
import com.vaadin.server.AbstractUIProvider;
import com.vaadin.server.WrappedRequest;
import com.vaadin.tests.components.AbstractTestApplication;
@@ -9,6 +9,7 @@ import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
public class RefreshStatePreserve extends AbstractTestApplication {
+ @PreserveOnRefresh
public static class RefreshStateUI extends UI {
@Override
public void init(WrappedRequest request) {
@@ -22,12 +23,10 @@ public class RefreshStatePreserve extends AbstractTestApplication {
@Override
public void init() {
super.init();
- setUiPreserved(true);
addUIProvider(new AbstractUIProvider() {
@Override
public Class<? extends UI> getUIClass(Application application,
- WrappedRequest request)
- throws UIRequiresMoreInformationException {
+ WrappedRequest request) {
return RefreshStateUI.class;
}
});
diff --git a/uitest/src/com/vaadin/tests/application/ThreadLocalInstances.java b/uitest/src/com/vaadin/tests/application/ThreadLocalInstances.java
index 0e7dd1b242..89cbf5d3ff 100644
--- a/uitest/src/com/vaadin/tests/application/ThreadLocalInstances.java
+++ b/uitest/src/com/vaadin/tests/application/ThreadLocalInstances.java
@@ -1,9 +1,9 @@
package com.vaadin.tests.application;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.server.DownloadStream;
import com.vaadin.server.PaintException;
+import com.vaadin.server.UIProvider;
import com.vaadin.server.WrappedRequest;
import com.vaadin.tests.components.AbstractTestApplication;
import com.vaadin.tests.integration.FlagSeResource;
@@ -73,12 +73,19 @@ public class ThreadLocalInstances extends AbstractTestApplication {
@Override
public void init() {
reportCurrentStatus("app init");
- }
+ addUIProvider(new UIProvider() {
+ @Override
+ public UI instantiateUI(Application application,
+ Class<? extends UI> type, WrappedRequest request) {
+ return mainWindow;
+ }
- @Override
- protected UI getUI(WrappedRequest request)
- throws UIRequiresMoreInformationException {
- return mainWindow;
+ @Override
+ public Class<? extends UI> getUIClass(Application application,
+ WrappedRequest request) {
+ return mainWindow.getClass();
+ }
+ });
}
@Override
diff --git a/uitest/src/com/vaadin/tests/components/loginform/LoginFormWithMultipleWindows.java b/uitest/src/com/vaadin/tests/components/loginform/LoginFormWithMultipleWindows.java
index ac4c3c8ea3..84c14763ab 100644
--- a/uitest/src/com/vaadin/tests/components/loginform/LoginFormWithMultipleWindows.java
+++ b/uitest/src/com/vaadin/tests/components/loginform/LoginFormWithMultipleWindows.java
@@ -1,6 +1,7 @@
package com.vaadin.tests.components.loginform;
import com.vaadin.Application;
+import com.vaadin.server.AbstractUIProvider;
import com.vaadin.server.WrappedRequest;
import com.vaadin.ui.LoginForm;
import com.vaadin.ui.LoginForm.LoginEvent;
@@ -12,11 +13,17 @@ import com.vaadin.ui.UI.LegacyWindow;
public class LoginFormWithMultipleWindows extends Application {
@Override
- protected UI getUI(WrappedRequest request) {
- return new LoginFormWindow();
+ public void init() {
+ addUIProvider(new AbstractUIProvider() {
+ @Override
+ public Class<? extends UI> getUIClass(Application application,
+ WrappedRequest request) {
+ return LoginFormWindow.class;
+ }
+ });
}
- public class LoginFormWindow extends LegacyWindow {
+ public static class LoginFormWindow extends LegacyWindow {
public LoginFormWindow() {
super();
diff --git a/uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java b/uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java
index 34bf8f6715..4cd786593a 100644
--- a/uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java
+++ b/uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java
@@ -1,10 +1,10 @@
package com.vaadin.tests.components.ui;
-import com.vaadin.UIRequiresMoreInformationException;
+import com.vaadin.Application;
import com.vaadin.annotations.EagerInit;
import com.vaadin.server.ExternalResource;
+import com.vaadin.server.UIProvider;
import com.vaadin.server.WrappedRequest;
-import com.vaadin.server.WrappedRequest.BrowserDetails;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.tests.components.AbstractTestApplication;
import com.vaadin.ui.Label;
@@ -22,23 +22,33 @@ public class LazyInitUIs extends AbstractTestApplication {
}
@Override
- public UI getUI(WrappedRequest request)
- throws UIRequiresMoreInformationException {
+ public void init() {
+ addUIProvider(new UIProvider() {
+
+ @Override
+ public UI instantiateUI(Application application,
+ Class<? extends UI> type, WrappedRequest request) {
+ return getUI(request);
+ }
+
+ @Override
+ public Class<? extends UI> getUIClass(Application application,
+ WrappedRequest request) {
+ return getUI(request).getClass();
+ }
+ });
+ }
+
+ private UI getUI(WrappedRequest request) {
if (request.getParameter("lazyCreate") != null) {
// UI created on second request
- BrowserDetails browserDetails = request.getBrowserDetails();
- if (browserDetails == null
- || browserDetails.getUriFragment() == null) {
- throw new UIRequiresMoreInformationException();
- } else {
- UI uI = new UI() {
- @Override
- protected void init(WrappedRequest request) {
- addComponent(getRequestInfo("LazyCreateUI", request));
- }
- };
- return uI;
- }
+ UI uI = new UI() {
+ @Override
+ protected void init(WrappedRequest request) {
+ addComponent(getRequestInfo("LazyCreateUI", request));
+ }
+ };
+ return uI;
} else if (request.getParameter("eagerInit") != null) {
// UI inited on first request
return new EagerInitUI();
diff --git a/uitest/src/com/vaadin/tests/components/ui/UIsInMultipleTabs.java b/uitest/src/com/vaadin/tests/components/ui/UIsInMultipleTabs.java
index 022db1bf3e..fe2fe16d93 100644
--- a/uitest/src/com/vaadin/tests/components/ui/UIsInMultipleTabs.java
+++ b/uitest/src/com/vaadin/tests/components/ui/UIsInMultipleTabs.java
@@ -1,7 +1,6 @@
package com.vaadin.tests.components.ui;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
import com.vaadin.server.AbstractUIProvider;
import com.vaadin.server.WrappedRequest;
import com.vaadin.tests.components.AbstractTestApplication;
@@ -26,8 +25,7 @@ public class UIsInMultipleTabs extends AbstractTestApplication {
addUIProvider(new AbstractUIProvider() {
@Override
public Class<? extends UI> getUIClass(Application application,
- WrappedRequest request)
- throws UIRequiresMoreInformationException {
+ WrappedRequest request) {
return TabUI.class;
}
});
diff --git a/uitest/src/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java b/uitest/src/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java
index a96b8957c6..cfb24c732f 100644
--- a/uitest/src/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java
+++ b/uitest/src/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java
@@ -16,9 +16,10 @@
package com.vaadin.tests.minitutorials.v7a1;
+import com.vaadin.annotations.PreserveOnRefresh;
import com.vaadin.server.WrappedRequest;
-import com.vaadin.ui.UI;
import com.vaadin.ui.TextField;
+import com.vaadin.ui.UI;
/**
* Mini tutorial code for
@@ -28,6 +29,7 @@ import com.vaadin.ui.TextField;
* @author Vaadin Ltd
* @since 7.0.0
*/
+@PreserveOnRefresh
public class CreatingPreserveState extends UI {
private static int windowCounter = 0;
@@ -36,7 +38,6 @@ public class CreatingPreserveState extends UI {
TextField tf = new TextField("Window #" + (++windowCounter));
tf.setImmediate(true);
getContent().addComponent(tf);
- getApplication().setUiPreserved(true);
}
}
diff --git a/uitest/src/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java b/uitest/src/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java
index ba3042c48e..54cf8a94e0 100644
--- a/uitest/src/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java
+++ b/uitest/src/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java
@@ -17,10 +17,9 @@
package com.vaadin.tests.minitutorials.v7a1;
import com.vaadin.Application;
-import com.vaadin.UIRequiresMoreInformationException;
+import com.vaadin.server.UIProvider;
import com.vaadin.server.WebBrowser;
import com.vaadin.server.WrappedRequest;
-import com.vaadin.server.WrappedRequest.BrowserDetails;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
@@ -35,21 +34,32 @@ import com.vaadin.ui.UI;
public class DifferentFeaturesForDifferentClients extends Application {
@Override
- protected UI getUI(WrappedRequest request)
- throws UIRequiresMoreInformationException {
- BrowserDetails browserDetails = request.getBrowserDetails();
- // This is a limitation of 7.0.0.alpha1 that there is no better way to
- // check if WebBrowser has been fully initialized
- if (browserDetails.getUriFragment() == null) {
- throw new UIRequiresMoreInformationException();
- }
+ public void init() {
+ super.init();
+ addUIProvider(new UIProvider() {
+ @Override
+ public Class<? extends UI> getUIClass(Application application,
+ WrappedRequest request) {
+ // could also use browser version etc.
+ if (request.getHeader("user-agent").contains("mobile")) {
+ return TouchRoot.class;
+ } else {
+ return DefaultRoot.class;
+ }
+ }
- // could also use screen size, browser version etc.
- if (browserDetails.getWebBrowser().isTouchDevice()) {
- return new TouchRoot();
- } else {
- return new DefaultRoot();
- }
+ // Must override as default implementation isn't allowed to
+ // instantiate our non-public classes
+ @Override
+ public UI instantiateUI(Application application,
+ Class<? extends UI> type, WrappedRequest request) {
+ try {
+ return type.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
}
}
diff --git a/uitest/src/com/vaadin/tests/vaadincontext/TestAddonContextListener.java b/uitest/src/com/vaadin/tests/vaadincontext/TestAddonContextListener.java
index 9f3019b21c..1f50110330 100644
--- a/uitest/src/com/vaadin/tests/vaadincontext/TestAddonContextListener.java
+++ b/uitest/src/com/vaadin/tests/vaadincontext/TestAddonContextListener.java
@@ -42,9 +42,8 @@ public class TestAddonContextListener implements AddonContextListener {
}
private boolean shouldModify(BootstrapResponse response) {
- UI uI = response.getUI();
- boolean shouldModify = uI != null
- && uI.getClass() == BootstrapModifyUI.class;
+ Class<? extends UI> uiClass = response.getUiClass();
+ boolean shouldModify = uiClass == BootstrapModifyUI.class;
return shouldModify;
}