You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

application-lifecycle.asciidoc 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. ---
  2. title: Application Lifecycle
  3. order: 8
  4. layout: page
  5. ---
  6. [[application.lifecycle]]
  7. = Application Lifecycle
  8. In this section, we look into more technical details of application deployment,
  9. user sessions, and UI instance lifecycle. These details are not generally needed
  10. for writing Vaadin applications, but may be useful for understanding how they
  11. actually work and, especially, in what circumstances their execution ends.
  12. [[application.lifecycle.deployment]]
  13. == Deployment
  14. Before a Vaadin application can be used, it has to be deployed to a Java web
  15. server, as described in
  16. <<dummy/../../../framework/application/application-environment#application.environment,"Deploying
  17. an Application">>. Deploying reads the servlet classes annotated with the
  18. [literal]#++@WebServlet++# annotation (Servlet 3.0) or the [filename]#web.xml#
  19. deployment descriptor (Servlet 2.4) in the application to register servlets for
  20. specific URL paths and loads the classes. Deployment does not yet normally run
  21. any code in the application, although static blocks in classes are executed when
  22. they are loaded.
  23. [[application.lifecycle.deployment.redeployment]]
  24. === Undeploying and Redeploying
  25. Applications are undeployed when the server shuts down, during redeployment, and
  26. when they are explicitly undeployed. Undeploying a server-side Vaadin
  27. application ends its execution, all application classes are unloaded, and the
  28. heap space allocated by the application is freed for garbage-collection.
  29. If any user sessions are open at this point, the client-side state of the UIs is
  30. left hanging and an Out of Sync error is displayed on the next server request.
  31. [[application.lifecycle.deployment.serialization]]
  32. === Redeployment and Serialization
  33. Some servers, such as Tomcat, support __hot deployment__, where the classes are
  34. reloaded while preserving the memory state of the application. This is done by
  35. serializing the application state and then deserializing it after the classes
  36. are reloaded. This is, in fact, done with the basic Eclipse setup with Tomcat
  37. and if a UI is marked as [classname]#@PreserveOnRefresh#, you may actually need
  38. to give the [literal]#++?restartApplication++# URL parameter to force it to
  39. restart when you reload the page. Tools such as JRebel go even further by
  40. reloading the code in place without need for serialization. The server can also
  41. serialize the application state when shutting down and restarting, thereby
  42. preserving sessions over restarts.
  43. Serialization requires that the applications are __serializable__, that is, all
  44. classes implement the [interfacename]#Serializable# interface. All Vaadin
  45. classes do. If you extend them or implement interfaces, you can provide an
  46. optional serialization key, which is automatically generated by Eclipse if you
  47. use it. Serialization is also used for clustering and cloud computing, such as
  48. with Google App Engine.
  49. ifdef::web[]
  50. For more about that topic, see
  51. <<dummy/../../../framework/advanced/advanced-gae#advanced.gae,"Google App Engine
  52. Integration">>.
  53. endif::web[]
  54. [[application.lifecycle.servlet-service]]
  55. == Vaadin Servlet, Portlet, and Service
  56. The [classname]#VaadinServlet#, or [classname]#VaadinPortlet# in a portal,
  57. receives all server requests mapped to it by its URL, as defined in the
  58. deployment configuration, and associates them with sessions. The sessions
  59. further associate the requests with particular UIs.
  60. When servicing requests, the Vaadin servlet or portlet handles all tasks common
  61. to both servlets and portlets in a [classname]#VaadinService#. It manages
  62. sessions, gives access to the deployment configuration information, handles
  63. system messages, and does various other tasks. Any further servlet or portlet
  64. specific tasks are handled in the corresponding
  65. [classname]#VaadinServletService# or [classname]#VaadinPortletService#. The
  66. service acts as the primary low-level customization layer for processing
  67. requests.
  68. [[application.lifecycle.servlet-service.servletcustomization]]
  69. === Customizing Vaadin Servlet
  70. Many common configuration tasks need to be done in the servlet class, which you
  71. already have if you are using the [literal]#++@WebServlet++# annotation for
  72. Servlet 3.0 to deploy the application. You can handle most customization by
  73. overriding the [methodname]#servletInitialized()# method, where the
  74. [classname]#VaadinService# object is available with [methodname]#getService()#
  75. (it would not be available in a constructor). You should always call
  76. [methodname]#super.servletInitialized()# in the beginning.
  77. [source, java]
  78. ----
  79. public class MyServlet extends VaadinServlet {
  80. @Override
  81. protected void servletInitialized()
  82. throws ServletException {
  83. super.servletInitialized();
  84. ...
  85. }
  86. }
  87. ----
  88. To add custom functionality around request handling, you can override the
  89. [methodname]#service()# method.
  90. To use the custom servlet class in a Servlet 2.4 project, you need to define it
  91. in the [filename]#web.xml# deployment descriptor instead of the regular
  92. [classname]#VaadinServlet# class, as described in
  93. <<dummy/../../../framework/application/application-environment#application.environment.web-xml,"Using
  94. a web.xml Deployment Descriptor">>.
  95. ifdef::web[]
  96. [[application.lifecycle.servlet-service.portletcustomization]]
  97. === Customizing Vaadin Portlet
  98. __To Be Done__
  99. endif::web[]
  100. ifdef::web[]
  101. [[application.lifecycle.servlet-service.servicecustomization]]
  102. === Customizing Vaadin Service
  103. To customize [classname]#VaadinService#, you first need to extend the
  104. [classname]#VaadinServlet# or - [classname]#Portlet# class and override the
  105. [methodname]#createServletService()# to create a custom service object.
  106. endif::web[]
  107. [[application.lifecycle.session]]
  108. == User Session
  109. ((("session")))
  110. A user session begins when a user first makes a request to a Vaadin servlet or
  111. portlet by opening the URL for a particular [classname]#UI#. All server requests
  112. belonging to a particular UI class are processed by the
  113. [classname]#VaadinServlet# or [classname]#VaadinPortlet# class. When a new
  114. client connects, it creates a new user session, represented by an instance of
  115. [classname]#VaadinSession#. Sessions are tracked using cookies stored in the
  116. browser.
  117. You can obtain the [classname]#VaadinSession# of a [classname]#UI# with
  118. [methodname]#getSession()# or globally with
  119. [methodname]#VaadinSession.getCurrent()#. It also provides access to the
  120. lower-level session objects, [interfacename]#HttpSession# and
  121. [interfacename]#PortletSession#, through a [classname]#WrappedSession#. You can
  122. also access the deployment configuration through [classname]#VaadinSession#, as
  123. described in
  124. <<dummy/../../../framework/application/application-environment#application.environment.configuration,"Deployment
  125. Configuration">>.
  126. A session ends after the last [classname]#UI# instance expires or is closed, as
  127. described later.
  128. [[application.lifecycle.session.init]]
  129. === Handling Session Initialization and Destruction
  130. ((("[classname]#SessionInitListener#")))
  131. ((("[classname]#SessionDestroyListener#")))
  132. ((("[classname]#VaadinService#")))
  133. You can handle session initialization and destruction by implementing a
  134. [interfacename]#SessionInitListener# or [interfacename]#SessionDestroyListener#,
  135. respectively, to the [classname]#VaadinService#.
  136. ((("[methodname]#servletInitialized()#")))
  137. ((("[classname]#VaadinServlet#")))
  138. You can do that best by extending [classname]#VaadinServlet# and overriding the
  139. [methodname]#servletInitialized()# method, as outlined in
  140. <<application.lifecycle.servlet-service>>.
  141. [source, java]
  142. ----
  143. public class MyServlet extends VaadinServlet
  144. implements SessionInitListener, SessionDestroyListener {
  145. @Override
  146. protected void servletInitialized() throws ServletException {
  147. super.servletInitialized();
  148. getService().addSessionInitListener(this);
  149. getService().addSessionDestroyListener(this);
  150. }
  151. @Override
  152. public void sessionInit(SessionInitEvent event)
  153. throws ServiceException {
  154. // Do session start stuff here
  155. }
  156. @Override
  157. public void sessionDestroy(SessionDestroyEvent event) {
  158. // Do session end stuff here
  159. }
  160. }
  161. ----
  162. If using Servlet 2.4, you need to configure the custom servlet class in the
  163. [parameter]#servlet-class# parameter in the [filename]#web.xml# descriptor
  164. instead of the [classname]#VaadinServlet#, as described in
  165. <<dummy/../../../framework/application/application-environment#application.environment.web-xml,"Using
  166. a web.xml Deployment Descriptor">>.
  167. [[application.lifecycle.ui]]
  168. == Loading a UI
  169. ((("UI", "loading")))
  170. When a browser first accesses a URL mapped to the servlet of a particular UI
  171. class, the Vaadin servlet generates a loader page. The page loads the
  172. client-side engine (widget set), which in turn loads the UI in a separate
  173. request to the Vaadin servlet.
  174. ((("[classname]#UIProvider#")))
  175. ((("[classname]#DefaultUIProvider#")))
  176. ((("[classname]#BrowserWindowOpener#")))
  177. A [classname]#UI# instance is created when the client-side engine makes its
  178. first request. The servlet creates the UIs using a [classname]#UIProvider#
  179. registered in the [classname]#VaadinSession# instance. A session has at least a
  180. [classname]#DefaultUIProvider# for managing UIs opened by the user. If the
  181. application lets the user open popup windows with a
  182. [classname]#BrowserWindowOpener#, each of them has a dedicated special UI
  183. provider.
  184. ((("[classname]#VaadinRequest#")))
  185. ((("[methodname]#init()#")))
  186. Once a new UI is created, its [methodname]#init()# method is called. The method
  187. gets the request as a [classname]#VaadinRequest#.
  188. [[application.lifecycle.ui.loaderpage]]
  189. === Customizing the Loader Page
  190. The HTML content of the loader page is generated as an HTML DOM object, which
  191. can be customized by implementing a [interfacename]#BootstrapListener# that
  192. modifies the DOM object. To do so, you need to extend the
  193. [classname]#VaadinServlet# and add a [interfacename]#SessionInitListener# to the
  194. service object, as outlined in <<application.lifecycle.session>>. You can then
  195. add the bootstrap listener to a session with
  196. [methodname]#addBootstrapListener()# when the session is initialized.
  197. Loading the widget set is handled in the loader page with functions defined in a
  198. separate [filename]#vaadinBootstrap.js# script.
  199. You can also use entirely custom loader code, such as in a static HTML page, as
  200. described in
  201. <<dummy/../../../framework/advanced/advanced-embedding#advanced.embedding,"Embedding
  202. UIs in Web Pages">>.
  203. [[application.lifecycle.ui.uiprovider]]
  204. === Custom UI Providers
  205. ((("[interfacename]#UIProvider#", "custom")))
  206. You can create UI objects dynamically according to their request parameters,
  207. such as the URL path, by defining a custom [interfacename]#UIProvider#. You need
  208. to add custom UI providers to the session object which calls them. The providers
  209. are chained so that they are requested starting from the one added last, until
  210. one returns a UI (otherwise they return null). You can add a UI provider to a
  211. session most conveniently by implementing a custom servlet and adding the UI
  212. provider to sessions in a [interfacename]#SessionInitListener#.
  213. You can find an example of custom UI providers in
  214. <<dummy/../../../mobile/mobile-features#mobile.features.fallback,"Providing a
  215. Fallback UI">>.
  216. [[application.lifecycle.ui.preserving]]
  217. === Preserving UI on Refresh
  218. ((("UI", "preserving on refresh")))
  219. ((("[classname]#@PreserveOnRefresh#")))
  220. Reloading a page in the browser normally spawns a new [classname]#UI# instance
  221. and the old UI is left hanging, until cleaned up after a while. This can be
  222. undesired as it resets the UI state for the user. To preserve the UI, you can
  223. use the [classname]#@PreserveOnRefresh# annotation for the UI class. You can
  224. also use a [classname]#UIProvider# with a custom implementation of
  225. [methodname]#isUiPreserved()#.
  226. [source, java]
  227. ----
  228. @PreserveOnRefresh
  229. public class MyUI extends UI {
  230. ----
  231. Adding the ?restartApplication parameter in the URL tells the Vaadin servlet to
  232. create a new [classname]#UI# instance when loading the page, thereby overriding
  233. the [classname]#@PreserveOnRefresh#. This is often necessary when developing
  234. such a UI in Eclipse, when you need to restart it after redeploying, because
  235. Eclipse likes to persist the application state between redeployments. If you
  236. also include a URI fragment, the parameter should be given before the fragment.
  237. [[application.lifecycle.ui-expiration]]
  238. == UI Expiration
  239. ((("UI", "expiration")))
  240. [classname]#UI# instances are cleaned up if no communication is received from
  241. them after some time. If no other server requests are made, the client-side
  242. sends keep-alive heartbeat requests. A UI is kept alive for as long as requests
  243. or heartbeats are received from it. It expires if three consecutive heartbeats
  244. are missed.
  245. The heartbeats occur at an interval of 5 minutes, which can be changed with the
  246. [parameter]#heartbeatInterval# parameter of the servlet. You can configure the
  247. parameter in [classname]#@VaadinServletConfiguration# or in [filename]#web.xml#
  248. as described in
  249. <<dummy/../../../framework/application/application-environment#application.environment.parameters,"Other
  250. Servlet Configuration Parameters">>.
  251. When the UI cleanup happens, a [classname]#DetachEvent# is sent to all
  252. [classname]#DetachListener#s added to the UI. When the [classname]#UI# is
  253. detached from the session, [methodname]#detach()# is called for it.
  254. [[application.lifecycle.ui-closing]]
  255. == Closing UIs Explicitly
  256. ((("UI", "closing")))
  257. ((("[methodname]#close()#",
  258. "UI")))
  259. You can explicitly close a UI with [methodname]#close()#. The method marks the
  260. UI to be detached from the session after processing the current request.
  261. Therefore, the method does not invalidate the UI instance immediately and the
  262. response is sent as usual.
  263. Detaching a UI does not close the page or browser window in which the UI is
  264. running and further server request will cause error. Typically, you either want
  265. to close the window, reload it, or redirect it to another URL. If the page is a
  266. regular browser window or tab, browsers generally do not allow closing them
  267. programmatically, but redirection is possible. You can redirect the window to
  268. another URL with [methodname]#setLocation()#, as is done in the examples in
  269. <<application.lifecycle.session-closing>>. You can close popup windows by making
  270. JavaScript [methodname]#close()# call for them, as described in
  271. <<dummy/../../../framework/advanced/advanced-windows#advanced.windows.popup-closing,"Closing
  272. Popup Windows">>.
  273. If you close other UI than the one associated with the current request, they
  274. will not be detached at the end of the current request, but after next request
  275. from the particular UI. You can make that occur quicker by making the UI
  276. heartbeat faster or immediately by using server push.
  277. [[application.lifecycle.session-expiration]]
  278. == Session Expiration
  279. ((("session", "expiration")))
  280. A session is kept alive by server requests caused by user interaction with the
  281. application as well as the heartbeat monitoring of the UIs. Once all UIs have
  282. expired, the session still remains. It is cleaned up from the server when the
  283. session timeout configured in the web application expires.
  284. ((("closeIdleSessions")))
  285. If there are active UIs in an application, their heartbeat keeps the session
  286. alive indefinitely. You may want to have the sessions timeout if the user is
  287. inactive long enough, which is the original purpose of the session timeout
  288. setting. ((("session",
  289. "timeout")))
  290. ((("closeIdleSessions")))
  291. If the [parameter]#closeIdleSessions# parameter of the servlet is set to
  292. [literal]#++true++# in the [filename]#web.xml#, as described in
  293. <<dummy/../../../framework/application/application-environment#application.environment.web-xml,"Using
  294. a web.xml Deployment Descriptor">>, the session and all of its UIs are closed
  295. when the timeout specified by the [parameter]#session-timeout# parameter of the
  296. servlet expires after the last non-heartbeat request. Once the session is gone,
  297. the browser will show an Out Of Sync error on the next server request.
  298. ((("redirection")))
  299. To avoid the ugly message, you may want to set a redirect URL for the UIs
  300. ifdef::web[]
  301. , as described in
  302. <<dummy/../../../framework/application/application-errors#application.errors.systemmessages,"Customizing
  303. System
  304. Messages">>
  305. endif::web[]
  306. .
  307. The related configuration parameters are described in
  308. <<dummy/../../../framework/application/application-environment#application.environment.parameters,"Other
  309. Servlet Configuration Parameters">>.
  310. ((("[interfacename]#SessionDestroyListener#")))
  311. You can handle session expiration on the server-side with a
  312. [interfacename]#SessionDestroyListener#, as described in
  313. <<application.lifecycle.session>>.
  314. [[application.lifecycle.session-closing]]
  315. == Closing a Session
  316. ((("session", "closing")))
  317. ((("[methodname]#close()#")))
  318. You can close a session by calling [methodname]#close()# on the
  319. [classname]#VaadinSession#. It is typically used when logging a user out and the
  320. session and all the UIs belonging to the session should be closed. The session
  321. is closed immediately and any objects related to it are not available after
  322. calling the method.
  323. When closing the session from a UI, you typically want to redirect the user to
  324. another URL.
  325. ((("redirection")))
  326. ((("[methodname]#setLocation()#")))
  327. ((("Page",
  328. "[methodname]#setLocation()#")))
  329. You can do the redirect using the [methodname]#setLocation()# method in
  330. [classname]#Page#. This needs to be done before closing the session, as the UI
  331. or page are not available after that. In the following example, we display a
  332. logout button, which closes the user session.
  333. ((("logout")))
  334. [source, java]
  335. ----
  336. public class MyUI extends UI {
  337. @Override
  338. protected void init(VaadinRequest request) {
  339. setContent(new Button("Logout", event -> {// Java 8
  340. // Redirect this page immediately
  341. getPage().setLocation("/myapp/logout.html");
  342. // Close the session
  343. getSession().close();
  344. }));
  345. // Notice quickly if other UIs are closed
  346. setPollInterval(3000);
  347. }
  348. }
  349. ----
  350. See the http://demo.vaadin.com/book-examples-vaadin7/book#application.lifecycle.closing[on-line example, window="_blank"].
  351. This is not enough. When a session is closed from one UI, any other UIs attached
  352. to it are left hanging. When the client-side engine notices that a UI and the
  353. session are gone on the server-side, it displays a "Session Expired" message
  354. and, by default, reloads the UI when the message is clicked. ((("session",
  355. "expiration")))
  356. ((("redirection")))
  357. ((("system
  358. messages")))
  359. You can customize the message and the redirect URL in the system messages
  360. ifdef::web[]
  361. , as described in
  362. <<dummy/../../../framework/application/application-errors#application.errors.systemmessages,"Customizing
  363. System
  364. Messages">>
  365. endif::web[]
  366. .
  367. ((("heartbeat")))
  368. ((("UI",
  369. "heartbeat")))
  370. ((("push")))
  371. ((("server
  372. push")))
  373. The client-side engine notices the expiration when user interaction causes a
  374. server request to be made or when the keep-alive heartbeat occurs. To make the
  375. UIs detect the situation faster, you need to make the heart beat faster, as was
  376. done in the example above. You can also use server push to close the other UIs
  377. immediately, as is done in the following example. Access to the UIs must be
  378. synchronized as described in
  379. <<dummy/../../../framework/advanced/advanced-push#advanced.push,"Server Push">>.
  380. [source, java]
  381. ----
  382. @Push
  383. public class MyPushyUI extends UI {
  384. @Override
  385. protected void init(VaadinRequest request) {
  386. setContent(new Button("Logout", event -> {// Java 8
  387. for (UI ui: VaadinSession.getCurrent().getUIs())
  388. ui.access(() -> {
  389. // Redirect from the page
  390. ui.getPage().setLocation("/logout.html");
  391. });
  392. getSession().close();
  393. }));
  394. }
  395. }
  396. ----
  397. See the http://demo.vaadin.com/book-examples-vaadin7/book#application.lifecycle.closingall[on-line example, window="_blank"].
  398. In the above example, we assume that all UIs in the session have push enabled
  399. and that they should be redirected; popups you might want to close instead of
  400. redirecting. It is not necessary to call [methodname]#close()# for them
  401. individually, as we close the entire session afterwards.