summaryrefslogtreecommitdiffstats
path: root/documentation/application/application-lifecycle.asciidoc
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/application/application-lifecycle.asciidoc')
-rw-r--r--documentation/application/application-lifecycle.asciidoc502
1 files changed, 502 insertions, 0 deletions
diff --git a/documentation/application/application-lifecycle.asciidoc b/documentation/application/application-lifecycle.asciidoc
new file mode 100644
index 0000000000..269f3d75b5
--- /dev/null
+++ b/documentation/application/application-lifecycle.asciidoc
@@ -0,0 +1,502 @@
+---
+title: Application Lifecycle
+order: 8
+layout: page
+---
+
+[[application.lifecycle]]
+= Application Lifecycle
+
+In this section, we look into more technical details of application deployment,
+user sessions, and UI instance lifecycle. These details are not generally needed
+for writing Vaadin applications, but may be useful for understanding how they
+actually work and, especially, in what circumstances their execution ends.
+
+[[application.lifecycle.deployment]]
+== Deployment
+
+Before a Vaadin application can be used, it has to be deployed to a Java web
+server, as described in
+<<dummy/../../../framework/application/application-environment#application.environment,"Deploying
+an Application">>. Deploying reads the servlet classes annotated with the
+[literal]#++@WebServlet++# annotation (Servlet 3.0) or the [filename]#web.xml#
+deployment descriptor (Servlet 2.4) in the application to register servlets for
+specific URL paths and loads the classes. Deployment does not yet normally run
+any code in the application, although static blocks in classes are executed when
+they are loaded.
+
+[[application.lifecycle.deployment.redeployment]]
+=== Undeploying and Redeploying
+
+Applications are undeployed when the server shuts down, during redeployment, and
+when they are explicitly undeployed. Undeploying a server-side Vaadin
+application ends its execution, all application classes are unloaded, and the
+heap space allocated by the application is freed for garbage-collection.
+
+If any user sessions are open at this point, the client-side state of the UIs is
+left hanging and an Out of Sync error is displayed on the next server request.
+
+
+[[application.lifecycle.deployment.serialization]]
+=== Redeployment and Serialization
+
+Some servers, such as Tomcat, support __hot deployment__, where the classes are
+reloaded while preserving the memory state of the application. This is done by
+serializing the application state and then deserializing it after the classes
+are reloaded. This is, in fact, done with the basic Eclipse setup with Tomcat
+and if a UI is marked as [classname]#@PreserveOnRefresh#, you may actually need
+to give the [literal]#++?restartApplication++# URL parameter to force it to
+restart when you reload the page. Tools such as JRebel go even further by
+reloading the code in place without need for serialization. The server can also
+serialize the application state when shutting down and restarting, thereby
+preserving sessions over restarts.
+
+Serialization requires that the applications are __serializable__, that is, all
+classes implement the [interfacename]#Serializable# interface. All Vaadin
+classes do. If you extend them or implement interfaces, you can provide an
+optional serialization key, which is automatically generated by Eclipse if you
+use it. Serialization is also used for clustering and cloud computing, such as
+with Google App Engine.
+
+ifdef::web[]
+For more about that topic, see
+<<dummy/../../../framework/advanced/advanced-gae#advanced.gae,"Google App Engine
+Integration">>.
+endif::web[]
+
+
+
+[[application.lifecycle.servlet-service]]
+== Vaadin Servlet, Portlet, and Service
+
+The [classname]#VaadinServlet#, or [classname]#VaadinPortlet# in a portal,
+receives all server requests mapped to it by its URL, as defined in the
+deployment configuration, and associates them with sessions. The sessions
+further associate the requests with particular UIs.
+
+When servicing requests, the Vaadin servlet or portlet handles all tasks common
+to both servlets and portlets in a [classname]#VaadinService#. It manages
+sessions, gives access to the deployment configuration information, handles
+system messages, and does various other tasks. Any further servlet or portlet
+specific tasks are handled in the corresponding
+[classname]#VaadinServletService# or [classname]#VaadinPortletService#. The
+service acts as the primary low-level customization layer for processing
+requests.
+
+[[application.lifecycle.servlet-service.servletcustomization]]
+=== Customizing Vaadin Servlet
+
+Many common configuration tasks need to be done in the servlet class, which you
+already have if you are using the [literal]#++@WebServlet++# annotation for
+Servlet 3.0 to deploy the application. You can handle most customization by
+overriding the [methodname]#servletInitialized()# method, where the
+[classname]#VaadinService# object is available with [methodname]#getService()#
+(it would not be available in a constructor). You should always call
+[methodname]#super.servletInitialized()# in the beginning.
+
+
+[source, java]
+----
+public class MyServlet extends VaadinServlet {
+ @Override
+ protected void servletInitialized()
+ throws ServletException {
+ super.servletInitialized();
+
+ ...
+ }
+}
+----
+
+To add custom functionality around request handling, you can override the
+[methodname]#service()# method.
+
+To use the custom servlet class in a Servlet 2.4 project, you need to define it
+in the [filename]#web.xml# deployment descriptor instead of the regular
+[classname]#VaadinServlet# class, as described in
+<<dummy/../../../framework/application/application-environment#application.environment.web-xml,"Using
+a web.xml Deployment Descriptor">>.
+
+
+ifdef::web[]
+[[application.lifecycle.servlet-service.portletcustomization]]
+=== Customizing Vaadin Portlet
+
+__To Be Done__
+
+endif::web[]
+
+ifdef::web[]
+[[application.lifecycle.servlet-service.servicecustomization]]
+=== Customizing Vaadin Service
+
+To customize [classname]#VaadinService#, you first need to extend the
+[classname]#VaadinServlet# or - [classname]#Portlet# class and override the
+[methodname]#createServletService()# to create a custom service object.
+
+endif::web[]
+
+
+[[application.lifecycle.session]]
+== User Session
+
+((("session")))
+A user session begins when a user first makes a request to a Vaadin servlet or
+portlet by opening the URL for a particular [classname]#UI#. All server requests
+belonging to a particular UI class are processed by the
+[classname]#VaadinServlet# or [classname]#VaadinPortlet# class. When a new
+client connects, it creates a new user session, represented by an instance of
+[classname]#VaadinSession#. Sessions are tracked using cookies stored in the
+browser.
+
+You can obtain the [classname]#VaadinSession# of a [classname]#UI# with
+[methodname]#getSession()# or globally with
+[methodname]#VaadinSession.getCurrent()#. It also provides access to the
+lower-level session objects, [interfacename]#HttpSession# and
+[interfacename]#PortletSession#, through a [classname]#WrappedSession#. You can
+also access the deployment configuration through [classname]#VaadinSession#, as
+described in
+<<dummy/../../../framework/application/application-environment#application.environment.configuration,"Deployment
+Configuration">>.
+
+A session ends after the last [classname]#UI# instance expires or is closed, as
+described later.
+
+[[application.lifecycle.session.init]]
+=== Handling Session Initialization and Destruction
+
+((("[classname]#SessionInitListener#")))
+((("[classname]#SessionDestroyListener#")))
+((("[classname]#VaadinService#")))
+You can handle session initialization and destruction by implementing a
+[interfacename]#SessionInitListener# or [interfacename]#SessionDestroyListener#,
+respectively, to the [classname]#VaadinService#.
+((("[methodname]#servletInitialized()#")))
+((("[classname]#VaadinServlet#")))
+You can do that best by extending [classname]#VaadinServlet# and overriding the
+[methodname]#servletInitialized()# method, as outlined in
+<<application.lifecycle.servlet-service>>.
+
+
+[source, java]
+----
+public class MyServlet extends VaadinServlet
+ implements SessionInitListener, SessionDestroyListener {
+
+ @Override
+ protected void servletInitialized() throws ServletException {
+ super.servletInitialized();
+ getService().addSessionInitListener(this);
+ getService().addSessionDestroyListener(this);
+ }
+
+ @Override
+ public void sessionInit(SessionInitEvent event)
+ throws ServiceException {
+ // Do session start stuff here
+ }
+
+ @Override
+ public void sessionDestroy(SessionDestroyEvent event) {
+ // Do session end stuff here
+ }
+}
+----
+
+If using Servlet 2.4, you need to configure the custom servlet class in the
+[parameter]#servlet-class# parameter in the [filename]#web.xml# descriptor
+instead of the [classname]#VaadinServlet#, as described in
+<<dummy/../../../framework/application/application-environment#application.environment.web-xml,"Using
+a web.xml Deployment Descriptor">>.
+
+
+
+[[application.lifecycle.ui]]
+== Loading a UI
+
+((("UI", "loading")))
+When a browser first accesses a URL mapped to the servlet of a particular UI
+class, the Vaadin servlet generates a loader page. The page loads the
+client-side engine (widget set), which in turn loads the UI in a separate
+request to the Vaadin servlet.
+
+((("[classname]#UIProvider#")))
+((("[classname]#DefaultUIProvider#")))
+((("[classname]#BrowserWindowOpener#")))
+A [classname]#UI# instance is created when the client-side engine makes its
+first request. The servlet creates the UIs using a [classname]#UIProvider#
+registered in the [classname]#VaadinSession# instance. A session has at least a
+[classname]#DefaultUIProvider# for managing UIs opened by the user. If the
+application lets the user open popup windows with a
+[classname]#BrowserWindowOpener#, each of them has a dedicated special UI
+provider.
+
+((("[classname]#VaadinRequest#")))
+((("[methodname]#init()#")))
+Once a new UI is created, its [methodname]#init()# method is called. The method
+gets the request as a [classname]#VaadinRequest#.
+
+[[application.lifecycle.ui.loaderpage]]
+=== Customizing the Loader Page
+
+The HTML content of the loader page is generated as an HTML DOM object, which
+can be customized by implementing a [interfacename]#BootstrapListener# that
+modifies the DOM object. To do so, you need to extend the
+[classname]#VaadinServlet# and add a [interfacename]#SessionInitListener# to the
+service object, as outlined in <<application.lifecycle.session>>. You can then
+add the bootstrap listener to a session with
+[methodname]#addBootstrapListener()# when the session is initialized.
+
+Loading the widget set is handled in the loader page with functions defined in a
+separate [filename]#vaadinBootstrap.js# script.
+
+You can also use entirely custom loader code, such as in a static HTML page, as
+described in
+<<dummy/../../../framework/advanced/advanced-embedding#advanced.embedding,"Embedding
+UIs in Web Pages">>.
+
+
+[[application.lifecycle.ui.uiprovider]]
+=== Custom UI Providers
+
+((("[interfacename]#UIProvider#", "custom")))
+You can create UI objects dynamically according to their request parameters,
+such as the URL path, by defining a custom [interfacename]#UIProvider#. You need
+to add custom UI providers to the session object which calls them. The providers
+are chained so that they are requested starting from the one added last, until
+one returns a UI (otherwise they return null). You can add a UI provider to a
+session most conveniently by implementing a custom servlet and adding the UI
+provider to sessions in a [interfacename]#SessionInitListener#.
+
+You can find an example of custom UI providers in
+<<dummy/../../../mobile/mobile-features#mobile.features.fallback,"Providing a
+Fallback UI">>.
+
+
+[[application.lifecycle.ui.preserving]]
+=== Preserving UI on Refresh
+
+((("UI", "preserving on refresh")))
+((("[classname]#@PreserveOnRefresh#")))
+Reloading a page in the browser normally spawns a new [classname]#UI# instance
+and the old UI is left hanging, until cleaned up after a while. This can be
+undesired as it resets the UI state for the user. To preserve the UI, you can
+use the [classname]#@PreserveOnRefresh# annotation for the UI class. You can
+also use a [classname]#UIProvider# with a custom implementation of
+[methodname]#isUiPreserved()#.
+
+
+[source, java]
+----
+@PreserveOnRefresh
+public class MyUI extends UI {
+----
+
+Adding the ?restartApplication parameter in the URL tells the Vaadin servlet to
+create a new [classname]#UI# instance when loading the page, thereby overriding
+the [classname]#@PreserveOnRefresh#. This is often necessary when developing
+such a UI in Eclipse, when you need to restart it after redeploying, because
+Eclipse likes to persist the application state between redeployments. If you
+also include a URI fragment, the parameter should be given before the fragment.
+
+
+
+[[application.lifecycle.ui-expiration]]
+== UI Expiration
+
+((("UI", "expiration")))
+[classname]#UI# instances are cleaned up if no communication is received from
+them after some time. If no other server requests are made, the client-side
+sends keep-alive heartbeat requests. A UI is kept alive for as long as requests
+or heartbeats are received from it. It expires if three consecutive heartbeats
+are missed.
+
+The heartbeats occur at an interval of 5 minutes, which can be changed with the
+[parameter]#heartbeatInterval# parameter of the servlet. You can configure the
+parameter in [classname]#@VaadinServletConfiguration# or in [filename]#web.xml#
+as described in
+<<dummy/../../../framework/application/application-environment#application.environment.parameters,"Other
+Servlet Configuration Parameters">>.
+
+When the UI cleanup happens, a [classname]#DetachEvent# is sent to all
+[classname]#DetachListener#s added to the UI. When the [classname]#UI# is
+detached from the session, [methodname]#detach()# is called for it.
+
+
+[[application.lifecycle.ui-closing]]
+== Closing UIs Explicitly
+
+((("UI", "closing")))
+((("[methodname]#close()#",
+"UI")))
+You can explicitly close a UI with [methodname]#close()#. The method marks the
+UI to be detached from the session after processing the current request.
+Therefore, the method does not invalidate the UI instance immediately and the
+response is sent as usual.
+
+Detaching a UI does not close the page or browser window in which the UI is
+running and further server request will cause error. Typically, you either want
+to close the window, reload it, or redirect it to another URL. If the page is a
+regular browser window or tab, browsers generally do not allow closing them
+programmatically, but redirection is possible. You can redirect the window to
+another URL with [methodname]#setLocation()#, as is done in the examples in
+<<application.lifecycle.session-closing>>. You can close popup windows by making
+JavaScript [methodname]#close()# call for them, as described in
+<<dummy/../../../framework/advanced/advanced-windows#advanced.windows.popup-closing,"Closing
+Popup Windows">>.
+
+If you close other UI than the one associated with the current request, they
+will not be detached at the end of the current request, but after next request
+from the particular UI. You can make that occur quicker by making the UI
+heartbeat faster or immediately by using server push.
+
+
+[[application.lifecycle.session-expiration]]
+== Session Expiration
+
+((("session", "expiration")))
+A session is kept alive by server requests caused by user interaction with the
+application as well as the heartbeat monitoring of the UIs. Once all UIs have
+expired, the session still remains. It is cleaned up from the server when the
+session timeout configured in the web application expires.
+
+((("closeIdleSessions")))
+If there are active UIs in an application, their heartbeat keeps the session
+alive indefinitely. You may want to have the sessions timeout if the user is
+inactive long enough, which is the original purpose of the session timeout
+setting. ((("session",
+"timeout")))
+((("closeIdleSessions")))
+If the [parameter]#closeIdleSessions# parameter of the servlet is set to
+[literal]#++true++# in the [filename]#web.xml#, as described in
+<<dummy/../../../framework/application/application-environment#application.environment.web-xml,"Using
+a web.xml Deployment Descriptor">>, the session and all of its UIs are closed
+when the timeout specified by the [parameter]#session-timeout# parameter of the
+servlet expires after the last non-heartbeat request. Once the session is gone,
+the browser will show an Out Of Sync error on the next server request.
+((("redirection")))
+To avoid the ugly message, you may want to set a redirect URL for the UIs
+
+ifdef::web[]
+, as described in
+<<dummy/../../../framework/application/application-errors#application.errors.systemmessages,"Customizing
+System
+Messages">>
+endif::web[]
+.
+
+The related configuration parameters are described in
+<<dummy/../../../framework/application/application-environment#application.environment.parameters,"Other
+Servlet Configuration Parameters">>.
+
+((("[interfacename]#SessionDestroyListener#")))
+You can handle session expiration on the server-side with a
+[interfacename]#SessionDestroyListener#, as described in
+<<application.lifecycle.session>>.
+
+
+[[application.lifecycle.session-closing]]
+== Closing a Session
+
+((("session", "closing")))
+((("[methodname]#close()#")))
+You can close a session by calling [methodname]#close()# on the
+[classname]#VaadinSession#. It is typically used when logging a user out and the
+session and all the UIs belonging to the session should be closed. The session
+is closed immediately and any objects related to it are not available after
+calling the method.
+
+When closing the session from a UI, you typically want to redirect the user to
+another URL.
+((("redirection")))
+((("[methodname]#setLocation()#")))
+((("Page",
+"[methodname]#setLocation()#")))
+You can do the redirect using the [methodname]#setLocation()# method in
+[classname]#Page#. This needs to be done before closing the session, as the UI
+or page are not available after that. In the following example, we display a
+logout button, which closes the user session.
+
+((("logout")))
+
+[source, java]
+----
+public class MyUI extends UI {
+ @Override
+ protected void init(VaadinRequest request) {
+ setContent(new Button("Logout", event -> {// Java 8
+ // Redirect this page immediately
+ getPage().setLocation("/myapp/logout.html");
+
+ // Close the session
+ getSession().close();
+ }));
+
+ // Notice quickly if other UIs are closed
+ setPollInterval(3000);
+ }
+}
+----
+See the http://demo.vaadin.com/book-examples-vaadin7/book#application.lifecycle.closing[on-line example, window="_blank"].
+
+This is not enough. When a session is closed from one UI, any other UIs attached
+to it are left hanging. When the client-side engine notices that a UI and the
+session are gone on the server-side, it displays a "Session Expired" message
+and, by default, reloads the UI when the message is clicked. ((("session",
+"expiration")))
+((("redirection")))
+((("system
+messages")))
+You can customize the message and the redirect URL in the system messages
+
+ifdef::web[]
+, as described in
+<<dummy/../../../framework/application/application-errors#application.errors.systemmessages,"Customizing
+System
+Messages">>
+endif::web[]
+.
+
+((("heartbeat")))
+((("UI",
+"heartbeat")))
+((("push")))
+((("server
+push")))
+The client-side engine notices the expiration when user interaction causes a
+server request to be made or when the keep-alive heartbeat occurs. To make the
+UIs detect the situation faster, you need to make the heart beat faster, as was
+done in the example above. You can also use server push to close the other UIs
+immediately, as is done in the following example. Access to the UIs must be
+synchronized as described in
+<<dummy/../../../framework/advanced/advanced-push#advanced.push,"Server Push">>.
+
+
+[source, java]
+----
+@Push
+public class MyPushyUI extends UI {
+ @Override
+ protected void init(VaadinRequest request) {
+ setContent(new Button("Logout", event -> {// Java 8
+ for (UI ui: VaadinSession.getCurrent().getUIs())
+ ui.access(() -> {
+ // Redirect from the page
+ ui.getPage().setLocation("/logout.html");
+ });
+
+ getSession().close();
+ }));
+ }
+}
+----
+See the http://demo.vaadin.com/book-examples-vaadin7/book#application.lifecycle.closingall[on-line example, window="_blank"].
+
+In the above example, we assume that all UIs in the session have push enabled
+and that they should be redirected; popups you might want to close instead of
+redirecting. It is not necessary to call [methodname]#close()# for them
+individually, as we close the entire session afterwards.
+
+
+
+