<?php

declare(strict_types=1);
/**
 * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

namespace OC\Files\Search\QueryOptimizer;

use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchOperator;

class QueryOptimizerStep {
	/**
	 * Allow optimizer steps to inspect the entire query before starting processing
	 *
	 * @param ISearchOperator $operator
	 * @return void
	 */
	public function inspectOperator(ISearchOperator $operator): void {
		if ($operator instanceof ISearchBinaryOperator) {
			foreach ($operator->getArguments() as $argument) {
				$this->inspectOperator($argument);
			}
		}
	}

	/**
	 * Allow optimizer steps to modify query operators
	 *
	 * @param ISearchOperator $operator
	 * @return void
	 */
	public function processOperator(ISearchOperator &$operator) {
		if ($operator instanceof ISearchBinaryOperator) {
			foreach ($operator->getArguments() as $argument) {
				$this->processOperator($argument);
			}
		}
	}
}
</option>
<option value='7.4'>7.4</option>
<option value='7.5'>7.5</option>
<option value='7.6'>7.6</option>
<option value='7.7'>7.7</option>
<option value='7.7.45-changelog'>7.7.45-changelog</option>
<option value='8.0'>8.0</option>
<option value='8.1'>8.1</option>
<option value='8.10'>8.10</option>
<option value='8.11'>8.11</option>
<option value='8.12'>8.12</option>
<option value='8.13'>8.13</option>
<option value='8.14'>8.14</option>
<option value='8.2'>8.2</option>
<option value='8.3'>8.3</option>
<option value='8.4'>8.4</option>
<option value='8.5'>8.5</option>
<option value='8.6'>8.6</option>
<option value='8.7'>8.7</option>
<option value='8.8'>8.8</option>
<option value='8.9'>8.9</option>
<option value='JS-RPC-docs-link-syntax' selected='selected'>JS-RPC-docs-link-syntax</option>
<option value='OlliTietavainenVaadin-patch-1'>OlliTietavainenVaadin-patch-1</option>
<option value='OlliTietavainenVaadin-patch-2'>OlliTietavainenVaadin-patch-2</option>
<option value='add-deprecation-warning-20241105'>add-deprecation-warning-20241105</option>
<option value='changelog-7.7.47-changes'>changelog-7.7.47-changes</option>
<option value='changelog-8.27.1'>changelog-8.27.1</option>
<option value='changelog-8.27.2'>changelog-8.27.2</option>
<option value='changelog-8.27.3'>changelog-8.27.3</option>
<option value='changelog-8.27.4'>changelog-8.27.4</option>
<option value='changelog-8.27.6'>changelog-8.27.6</option>
<option value='changelog-8.28.1'>changelog-8.28.1</option>
<option value='chore-mention-8.14.4'>chore-mention-8.14.4</option>
<option value='chore-readme-8-14-4'>chore-readme-8-14-4</option>
<option value='context-menu'>context-menu</option>
<option value='datefield-set-invalid-value'>datefield-set-invalid-value</option>
<option value='declarative'>declarative</option>
<option value='dependabot/maven/org.eclipse.jetty-jetty-server-10.0.14'>dependabot/maven/org.eclipse.jetty-jetty-server-10.0.14</option>
<option value='dependabot/maven/org.eclipse.jetty-jetty-webapp-9.4.44.v20210927'>dependabot/maven/org.eclipse.jetty-jetty-webapp-9.4.44.v20210927</option>
<option value='dependabot/maven/org.eclipse.jgit-org.eclipse.jgit-3.5.3.201412180710-r'>dependabot/maven/org.eclipse.jgit-org.eclipse.jgit-3.5.3.201412180710-r</option>
<option value='dependabot/maven/org.eclipse.jgit-org.eclipse.jgit-7.2.1.202505142326-r'>dependabot/maven/org.eclipse.jgit-org.eclipse.jgit-7.2.1.202505142326-r</option>
<option value='dependabot/maven/org.hsqldb-hsqldb-2.7.1'>dependabot/maven/org.hsqldb-hsqldb-2.7.1</option>
<option value='documentation'>documentation</option>
<option value='documentation-7.6'>documentation-7.6</option>
<option value='downgrade-snapshot-version-20241105'>downgrade-snapshot-version-20241105</option>
<option value='exclude-element-screenshot'>exclude-element-screenshot</option>
<option value='feature/atmosphere-pure-javascript'>feature/atmosphere-pure-javascript</option>
<option value='feature/bootstrap-annotation'>feature/bootstrap-annotation</option>
<option value='feature/combobox-communication'>feature/combobox-communication</option>
<option value='feature/dalvik'>feature/dalvik</option>
<option value='feature/databinding'>feature/databinding</option>
<option value='feature/dnd'>feature/dnd</option>
<option value='feature/elements'>feature/elements</option>
<option value='feature/eventbus'>feature/eventbus</option>
<option value='feature/karaf-feature-file'>feature/karaf-feature-file</option>
<option value='feature/nullrepresentation'>feature/nullrepresentation</option>
<option value='feature/standard-gwt'>feature/standard-gwt</option>
<option value='feature/standard-sass'>feature/standard-sass</option>
<option value='feature/vaadin8'>feature/vaadin8</option>
<option value='feature/vaadin8-book'>feature/vaadin8-book</option>
<option value='feature/vaadin8-book-vol2'>feature/vaadin8-book-vol2</option>
<option value='feature/vaadin8-sass-valo-only'>feature/vaadin8-sass-valo-only</option>
<option value='fileToFilesReplacement'>fileToFilesReplacement</option>
<option value='fix11576'>fix11576</option>
<option value='fix_event_router_prototype'>fix_event_router_prototype</option>
<option value='grid'>grid</option>
<option value='grid_dnd_autoscroller'>grid_dnd_autoscroller</option>
<option value='grid_dragger'>grid_dragger</option>
<option value='issue/8307_select_using_collection'>issue/8307_select_using_collection</option>
<option value='master'>master</option>
<option value='mobile_drag_image_offset'>mobile_drag_image_offset</option>
<option value='pr/11306'>pr/11306</option>
<option value='remote-run/flow-atmosphere-test'>remote-run/flow-atmosphere-test</option>
<option value='snapshot/7.5'>snapshot/7.5</option>
<option value='snapshot/7.6'>snapshot/7.6</option>
<option value='tmattsso-patch-1'>tmattsso-patch-1</option>
<option value='update-minor-deps'>update-minor-deps</option>
<option value='vaadin-icons-3.0.1'>vaadin-icons-3.0.1</option>
<option value='wip-date-time-datatype'>wip-date-time-datatype</option>
<option value='wip-java-10-compat'>wip-java-10-compat</option>
</select> <input type='submit' value='switch'/></form></td></tr>
<tr><td class='sub'>Vaadin 6, 7, 8 is a Java framework for modern Java web applications: https://github.com/vaadin/framework</td><td class='sub right'>www-data</td></tr></table>
<table class='tabs'><tr><td>
<a href='/vaadin-framework.git/about/?h=JS-RPC-docs-link-syntax'>about</a><a href='/vaadin-framework.git/?h=JS-RPC-docs-link-syntax'>summary</a><a href='/vaadin-framework.git/refs/?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>refs</a><a href='/vaadin-framework.git/log/documentation/application/application-lifecycle.asciidoc?h=JS-RPC-docs-link-syntax'>log</a><a class='active' href='/vaadin-framework.git/tree/documentation/application/application-lifecycle.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>tree</a><a href='/vaadin-framework.git/commit/documentation/application/application-lifecycle.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>commit</a><a href='/vaadin-framework.git/diff/documentation/application/application-lifecycle.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>diff</a><a href='/vaadin-framework.git/stats/documentation/application/application-lifecycle.asciidoc?h=JS-RPC-docs-link-syntax'>stats</a></td><td class='form'><form class='right' method='get' action='/vaadin-framework.git/log/documentation/application/application-lifecycle.asciidoc'>
<input type='hidden' name='h' value='JS-RPC-docs-link-syntax'/><input type='hidden' name='id' value='17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'/><select name='qt'>
<option value='grep'>log msg</option>
<option value='author'>author</option>
<option value='committer'>committer</option>
<option value='range'>range</option>
</select>
<input class='txt' type='search' size='10' name='q' value=''/>
<input type='submit' value='search'/>
</form>
</td></tr></table>
<div class='path'>path: <a href='/vaadin-framework.git/tree/?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>root</a>/<a href='/vaadin-framework.git/tree/documentation?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>documentation</a>/<a href='/vaadin-framework.git/tree/documentation/application?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>application</a>/<a href='/vaadin-framework.git/tree/documentation/application/application-lifecycle.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>application-lifecycle.asciidoc</a></div><div class='content'>blob: 657198f71b5e1a619c01be15ba8584be047da6a7 (<a href='/vaadin-framework.git/plain/documentation/application/application-lifecycle.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=17b3f23b0e526250dc134df1f7d2e6cd7f149ba5'>plain</a>)
<table summary='blob content' class='blob'>
<tr><td class='linenumbers'><pre><a id='n1' href='#n1'>1</a>
<a id='n2' href='#n2'>2</a>
<a id='n3' href='#n3'>3</a>
<a id='n4' href='#n4'>4</a>
<a id='n5' href='#n5'>5</a>
<a id='n6' href='#n6'>6</a>
<a id='n7' href='#n7'>7</a>
<a id='n8' href='#n8'>8</a>
<a id='n9' href='#n9'>9</a>
<a id='n10' href='#n10'>10</a>
<a id='n11' href='#n11'>11</a>
<a id='n12' href='#n12'>12</a>
<a id='n13' href='#n13'>13</a>
<a id='n14' href='#n14'>14</a>
<a id='n15' href='#n15'>15</a>
<a id='n16' href='#n16'>16</a>
<a id='n17' href='#n17'>17</a>
<a id='n18' href='#n18'>18</a>
<a id='n19' href='#n19'>19</a>
<a id='n20' href='#n20'>20</a>
<a id='n21' href='#n21'>21</a>
<a id='n22' href='#n22'>22</a>
<a id='n23' href='#n23'>23</a>
<a id='n24' href='#n24'>24</a>
<a id='n25' href='#n25'>25</a>
<a id='n26' href='#n26'>26</a>
<a id='n27' href='#n27'>27</a>
<a id='n28' href='#n28'>28</a>
<a id='n29' href='#n29'>29</a>
<a id='n30' href='#n30'>30</a>
<a id='n31' href='#n31'>31</a>
<a id='n32' href='#n32'>32</a>
<a id='n33' href='#n33'>33</a>
<a id='n34' href='#n34'>34</a>
<a id='n35' href='#n35'>35</a>
<a id='n36' href='#n36'>36</a>
<a id='n37' href='#n37'>37</a>
<a id='n38' href='#n38'>38</a>
<a id='n39' href='#n39'>39</a>
<a id='n40' href='#n40'>40</a>
<a id='n41' href='#n41'>41</a>
<a id='n42' href='#n42'>42</a>
<a id='n43' href='#n43'>43</a>
<a id='n44' href='#n44'>44</a>
<a id='n45' href='#n45'>45</a>
<a id='n46' href='#n46'>46</a>
<a id='n47' href='#n47'>47</a>
<a id='n48' href='#n48'>48</a>
<a id='n49' href='#n49'>49</a>
<a id='n50' href='#n50'>50</a>
<a id='n51' href='#n51'>51</a>
<a id='n52' href='#n52'>52</a>
<a id='n53' href='#n53'>53</a>
<a id='n54' href='#n54'>54</a>
<a id='n55' href='#n55'>55</a>
<a id='n56' href='#n56'>56</a>
<a id='n57' href='#n57'>57</a>
<a id='n58' href='#n58'>58</a>
<a id='n59' href='#n59'>59</a>
<a id='n60' href='#n60'>60</a>
<a id='n61' href='#n61'>61</a>
<a id='n62' href='#n62'>62</a>
<a id='n63' href='#n63'>63</a>
<a id='n64' href='#n64'>64</a>
<a id='n65' href='#n65'>65</a>
<a id='n66' href='#n66'>66</a>
<a id='n67' href='#n67'>67</a>
<a id='n68' href='#n68'>68</a>
<a id='n69' href='#n69'>69</a>
<a id='n70' href='#n70'>70</a>
<a id='n71' href='#n71'>71</a>
<a id='n72' href='#n72'>72</a>
<a id='n73' href='#n73'>73</a>
<a id='n74' href='#n74'>74</a>
<a id='n75' href='#n75'>75</a>
<a id='n76' href='#n76'>76</a>
<a id='n77' href='#n77'>77</a>
<a id='n78' href='#n78'>78</a>
<a id='n79' href='#n79'>79</a>
<a id='n80' href='#n80'>80</a>
<a id='n81' href='#n81'>81</a>
<a id='n82' href='#n82'>82</a>
<a id='n83' href='#n83'>83</a>
<a id='n84' href='#n84'>84</a>
<a id='n85' href='#n85'>85</a>
<a id='n86' href='#n86'>86</a>
<a id='n87' href='#n87'>87</a>
<a id='n88' href='#n88'>88</a>
<a id='n89' href='#n89'>89</a>
<a id='n90' href='#n90'>90</a>
<a id='n91' href='#n91'>91</a>
<a id='n92' href='#n92'>92</a>
<a id='n93' href='#n93'>93</a>
<a id='n94' href='#n94'>94</a>
<a id='n95' href='#n95'>95</a>
<a id='n96' href='#n96'>96</a>
<a id='n97' href='#n97'>97</a>
<a id='n98' href='#n98'>98</a>
<a id='n99' href='#n99'>99</a>
<a id='n100' href='#n100'>100</a>
<a id='n101' href='#n101'>101</a>
<a id='n102' href='#n102'>102</a>
<a id='n103' href='#n103'>103</a>
<a id='n104' href='#n104'>104</a>
<a id='n105' href='#n105'>105</a>
<a id='n106' href='#n106'>106</a>
<a id='n107' href='#n107'>107</a>
<a id='n108' href='#n108'>108</a>
<a id='n109' href='#n109'>109</a>
<a id='n110' href='#n110'>110</a>
<a id='n111' href='#n111'>111</a>
<a id='n112' href='#n112'>112</a>
<a id='n113' href='#n113'>113</a>
<a id='n114' href='#n114'>114</a>
<a id='n115' href='#n115'>115</a>
<a id='n116' href='#n116'>116</a>
<a id='n117' href='#n117'>117</a>
<a id='n118' href='#n118'>118</a>
<a id='n119' href='#n119'>119</a>
<a id='n120' href='#n120'>120</a>
<a id='n121' href='#n121'>121</a>
<a id='n122' href='#n122'>122</a>
<a id='n123' href='#n123'>123</a>
<a id='n124' href='#n124'>124</a>
<a id='n125' href='#n125'>125</a>
<a id='n126' href='#n126'>126</a>
<a id='n127' href='#n127'>127</a>
<a id='n128' href='#n128'>128</a>
<a id='n129' href='#n129'>129</a>
<a id='n130' href='#n130'>130</a>
<a id='n131' href='#n131'>131</a>
<a id='n132' href='#n132'>132</a>
<a id='n133' href='#n133'>133</a>
<a id='n134' href='#n134'>134</a>
<a id='n135' href='#n135'>135</a>
<a id='n136' href='#n136'>136</a>
<a id='n137' href='#n137'>137</a>
<a id='n138' href='#n138'>138</a>
<a id='n139' href='#n139'>139</a>
<a id='n140' href='#n140'>140</a>
<a id='n141' href='#n141'>141</a>
<a id='n142' href='#n142'>142</a>
<a id='n143' href='#n143'>143</a>
<a id='n144' href='#n144'>144</a>
<a id='n145' href='#n145'>145</a>
<a id='n146' href='#n146'>146</a>
<a id='n147' href='#n147'>147</a>
<a id='n148' href='#n148'>148</a>
<a id='n149' href='#n149'>149</a>
<a id='n150' href='#n150'>150</a>
<a id='n151' href='#n151'>151</a>
<a id='n152' href='#n152'>152</a>
<a id='n153' href='#n153'>153</a>
<a id='n154' href='#n154'>154</a>
<a id='n155' href='#n155'>155</a>
<a id='n156' href='#n156'>156</a>
<a id='n157' href='#n157'>157</a>
<a id='n158' href='#n158'>158</a>
<a id='n159' href='#n159'>159</a>
<a id='n160' href='#n160'>160</a>
<a id='n161' href='#n161'>161</a>
<a id='n162' href='#n162'>162</a>
<a id='n163' href='#n163'>163</a>
<a id='n164' href='#n164'>164</a>
<a id='n165' href='#n165'>165</a>
<a id='n166' href='#n166'>166</a>
<a id='n167' href='#n167'>167</a>
<a id='n168' href='#n168'>168</a>
<a id='n169' href='#n169'>169</a>
<a id='n170' href='#n170'>170</a>
<a id='n171' href='#n171'>171</a>
<a id='n172' href='#n172'>172</a>
<a id='n173' href='#n173'>173</a>
<a id='n174' href='#n174'>174</a>
<a id='n175' href='#n175'>175</a>
<a id='n176' href='#n176'>176</a>
<a id='n177' href='#n177'>177</a>
<a id='n178' href='#n178'>178</a>
<a id='n179' href='#n179'>179</a>
<a id='n180' href='#n180'>180</a>
<a id='n181' href='#n181'>181</a>
<a id='n182' href='#n182'>182</a>
<a id='n183' href='#n183'>183</a>
<a id='n184' href='#n184'>184</a>
<a id='n185' href='#n185'>185</a>
<a id='n186' href='#n186'>186</a>
<a id='n187' href='#n187'>187</a>
<a id='n188' href='#n188'>188</a>
<a id='n189' href='#n189'>189</a>
<a id='n190' href='#n190'>190</a>
<a id='n191' href='#n191'>191</a>
<a id='n192' href='#n192'>192</a>
<a id='n193' href='#n193'>193</a>
<a id='n194' href='#n194'>194</a>
<a id='n195' href='#n195'>195</a>
<a id='n196' href='#n196'>196</a>
<a id='n197' href='#n197'>197</a>
<a id='n198' href='#n198'>198</a>
<a id='n199' href='#n199'>199</a>
<a id='n200' href='#n200'>200</a>
<a id='n201' href='#n201'>201</a>
<a id='n202' href='#n202'>202</a>
<a id='n203' href='#n203'>203</a>
<a id='n204' href='#n204'>204</a>
<a id='n205' href='#n205'>205</a>
<a id='n206' href='#n206'>206</a>
<a id='n207' href='#n207'>207</a>
<a id='n208' href='#n208'>208</a>
<a id='n209' href='#n209'>209</a>
<a id='n210' href='#n210'>210</a>
<a id='n211' href='#n211'>211</a>
<a id='n212' href='#n212'>212</a>
<a id='n213' href='#n213'>213</a>
<a id='n214' href='#n214'>214</a>
<a id='n215' href='#n215'>215</a>
<a id='n216' href='#n216'>216</a>
<a id='n217' href='#n217'>217</a>
<a id='n218' href='#n218'>218</a>
<a id='n219' href='#n219'>219</a>
<a id='n220' href='#n220'>220</a>
<a id='n221' href='#n221'>221</a>
<a id='n222' href='#n222'>222</a>
<a id='n223' href='#n223'>223</a>
<a id='n224' href='#n224'>224</a>
<a id='n225' href='#n225'>225</a>
<a id='n226' href='#n226'>226</a>
<a id='n227' href='#n227'>227</a>
<a id='n228' href='#n228'>228</a>
<a id='n229' href='#n229'>229</a>
<a id='n230' href='#n230'>230</a>
<a id='n231' href='#n231'>231</a>
<a id='n232' href='#n232'>232</a>
<a id='n233' href='#n233'>233</a>
<a id='n234' href='#n234'>234</a>
<a id='n235' href='#n235'>235</a>
<a id='n236' href='#n236'>236</a>
<a id='n237' href='#n237'>237</a>
<a id='n238' href='#n238'>238</a>
<a id='n239' href='#n239'>239</a>
<a id='n240' href='#n240'>240</a>
<a id='n241' href='#n241'>241</a>
<a id='n242' href='#n242'>242</a>
<a id='n243' href='#n243'>243</a>
<a id='n244' href='#n244'>244</a>
<a id='n245' href='#n245'>245</a>
<a id='n246' href='#n246'>246</a>
<a id='n247' href='#n247'>247</a>
<a id='n248' href='#n248'>248</a>
<a id='n249' href='#n249'>249</a>
<a id='n250' href='#n250'>250</a>
<a id='n251' href='#n251'>251</a>
<a id='n252' href='#n252'>252</a>
<a id='n253' href='#n253'>253</a>
<a id='n254' href='#n254'>254</a>
<a id='n255' href='#n255'>255</a>
<a id='n256' href='#n256'>256</a>
<a id='n257' href='#n257'>257</a>
<a id='n258' href='#n258'>258</a>
<a id='n259' href='#n259'>259</a>
<a id='n260' href='#n260'>260</a>
<a id='n261' href='#n261'>261</a>
<a id='n262' href='#n262'>262</a>
<a id='n263' href='#n263'>263</a>
<a id='n264' href='#n264'>264</a>
<a id='n265' href='#n265'>265</a>
<a id='n266' href='#n266'>266</a>
<a id='n267' href='#n267'>267</a>
<a id='n268' href='#n268'>268</a>
<a id='n269' href='#n269'>269</a>
<a id='n270' href='#n270'>270</a>
<a id='n271' href='#n271'>271</a>
<a id='n272' href='#n272'>272</a>
<a id='n273' href='#n273'>273</a>
<a id='n274' href='#n274'>274</a>
<a id='n275' href='#n275'>275</a>
<a id='n276' href='#n276'>276</a>
<a id='n277' href='#n277'>277</a>
<a id='n278' href='#n278'>278</a>
<a id='n279' href='#n279'>279</a>
<a id='n280' href='#n280'>280</a>
<a id='n281' href='#n281'>281</a>
<a id='n282' href='#n282'>282</a>
<a id='n283' href='#n283'>283</a>
<a id='n284' href='#n284'>284</a>
<a id='n285' href='#n285'>285</a>
<a id='n286' href='#n286'>286</a>
<a id='n287' href='#n287'>287</a>
<a id='n288' href='#n288'>288</a>
<a id='n289' href='#n289'>289</a>
<a id='n290' href='#n290'>290</a>
<a id='n291' href='#n291'>291</a>
<a id='n292' href='#n292'>292</a>
<a id='n293' href='#n293'>293</a>
<a id='n294' href='#n294'>294</a>
<a id='n295' href='#n295'>295</a>
<a id='n296' href='#n296'>296</a>
<a id='n297' href='#n297'>297</a>
<a id='n298' href='#n298'>298</a>
<a id='n299' href='#n299'>299</a>
<a id='n300' href='#n300'>300</a>
<a id='n301' href='#n301'>301</a>
<a id='n302' href='#n302'>302</a>
<a id='n303' href='#n303'>303</a>
<a id='n304' href='#n304'>304</a>
<a id='n305' href='#n305'>305</a>
<a id='n306' href='#n306'>306</a>
<a id='n307' href='#n307'>307</a>
<a id='n308' href='#n308'>308</a>
<a id='n309' href='#n309'>309</a>
<a id='n310' href='#n310'>310</a>
<a id='n311' href='#n311'>311</a>
<a id='n312' href='#n312'>312</a>
<a id='n313' href='#n313'>313</a>
<a id='n314' href='#n314'>314</a>
<a id='n315' href='#n315'>315</a>
<a id='n316' href='#n316'>316</a>
<a id='n317' href='#n317'>317</a>
<a id='n318' href='#n318'>318</a>
<a id='n319' href='#n319'>319</a>
<a id='n320' href='#n320'>320</a>
<a id='n321' href='#n321'>321</a>
<a id='n322' href='#n322'>322</a>
<a id='n323' href='#n323'>323</a>
<a id='n324' href='#n324'>324</a>
<a id='n325' href='#n325'>325</a>
<a id='n326' href='#n326'>326</a>
<a id='n327' href='#n327'>327</a>
<a id='n328' href='#n328'>328</a>
<a id='n329' href='#n329'>329</a>
<a id='n330' href='#n330'>330</a>
<a id='n331' href='#n331'>331</a>
<a id='n332' href='#n332'>332</a>
<a id='n333' href='#n333'>333</a>
<a id='n334' href='#n334'>334</a>
<a id='n335' href='#n335'>335</a>
<a id='n336' href='#n336'>336</a>
<a id='n337' href='#n337'>337</a>
<a id='n338' href='#n338'>338</a>
<a id='n339' href='#n339'>339</a>
<a id='n340' href='#n340'>340</a>
<a id='n341' href='#n341'>341</a>
<a id='n342' href='#n342'>342</a>
<a id='n343' href='#n343'>343</a>
<a id='n344' href='#n344'>344</a>
<a id='n345' href='#n345'>345</a>
<a id='n346' href='#n346'>346</a>
<a id='n347' href='#n347'>347</a>
<a id='n348' href='#n348'>348</a>
<a id='n349' href='#n349'>349</a>
<a id='n350' href='#n350'>350</a>
<a id='n351' href='#n351'>351</a>
<a id='n352' href='#n352'>352</a>
<a id='n353' href='#n353'>353</a>
<a id='n354' href='#n354'>354</a>
<a id='n355' href='#n355'>355</a>
<a id='n356' href='#n356'>356</a>
<a id='n357' href='#n357'>357</a>
<a id='n358' href='#n358'>358</a>
<a id='n359' href='#n359'>359</a>
<a id='n360' href='#n360'>360</a>
<a id='n361' href='#n361'>361</a>
<a id='n362' href='#n362'>362</a>
<a id='n363' href='#n363'>363</a>
<a id='n364' href='#n364'>364</a>
<a id='n365' href='#n365'>365</a>
<a id='n366' href='#n366'>366</a>
<a id='n367' href='#n367'>367</a>
<a id='n368' href='#n368'>368</a>
<a id='n369' href='#n369'>369</a>
<a id='n370' href='#n370'>370</a>
<a id='n371' href='#n371'>371</a>
<a id='n372' href='#n372'>372</a>
<a id='n373' href='#n373'>373</a>
<a id='n374' href='#n374'>374</a>
<a id='n375' href='#n375'>375</a>
<a id='n376' href='#n376'>376</a>
<a id='n377' href='#n377'>377</a>
<a id='n378' href='#n378'>378</a>
<a id='n379' href='#n379'>379</a>
<a id='n380' href='#n380'>380</a>
<a id='n381' href='#n381'>381</a>
<a id='n382' href='#n382'>382</a>
<a id='n383' href='#n383'>383</a>
<a id='n384' href='#n384'>384</a>
<a id='n385' href='#n385'>385</a>
<a id='n386' href='#n386'>386</a>
<a id='n387' href='#n387'>387</a>
<a id='n388' href='#n388'>388</a>
<a id='n389' href='#n389'>389</a>
<a id='n390' href='#n390'>390</a>
<a id='n391' href='#n391'>391</a>
<a id='n392' href='#n392'>392</a>
<a id='n393' href='#n393'>393</a>
<a id='n394' href='#n394'>394</a>
<a id='n395' href='#n395'>395</a>
<a id='n396' href='#n396'>396</a>
<a id='n397' href='#n397'>397</a>
<a id='n398' href='#n398'>398</a>
<a id='n399' href='#n399'>399</a>
<a id='n400' href='#n400'>400</a>
<a id='n401' href='#n401'>401</a>
<a id='n402' href='#n402'>402</a>
<a id='n403' href='#n403'>403</a>
<a id='n404' href='#n404'>404</a>
<a id='n405' href='#n405'>405</a>
<a id='n406' href='#n406'>406</a>
<a id='n407' href='#n407'>407</a>
<a id='n408' href='#n408'>408</a>
<a id='n409' href='#n409'>409</a>
<a id='n410' href='#n410'>410</a>
<a id='n411' href='#n411'>411</a>
<a id='n412' href='#n412'>412</a>
<a id='n413' href='#n413'>413</a>
<a id='n414' href='#n414'>414</a>
<a id='n415' href='#n415'>415</a>
<a id='n416' href='#n416'>416</a>
<a id='n417' href='#n417'>417</a>
<a id='n418' href='#n418'>418</a>
<a id='n419' href='#n419'>419</a>
<a id='n420' href='#n420'>420</a>
<a id='n421' href='#n421'>421</a>
<a id='n422' href='#n422'>422</a>
<a id='n423' href='#n423'>423</a>
<a id='n424' href='#n424'>424</a>
<a id='n425' href='#n425'>425</a>
<a id='n426' href='#n426'>426</a>
<a id='n427' href='#n427'>427</a>
<a id='n428' href='#n428'>428</a>
<a id='n429' href='#n429'>429</a>
<a id='n430' href='#n430'>430</a>
<a id='n431' href='#n431'>431</a>
<a id='n432' href='#n432'>432</a>
<a id='n433' href='#n433'>433</a>
<a id='n434' href='#n434'>434</a>
<a id='n435' href='#n435'>435</a>
<a id='n436' href='#n436'>436</a>
<a id='n437' href='#n437'>437</a>
<a id='n438' href='#n438'>438</a>
<a id='n439' href='#n439'>439</a>
<a id='n440' href='#n440'>440</a>
<a id='n441' href='#n441'>441</a>
<a id='n442' href='#n442'>442</a>
<a id='n443' href='#n443'>443</a>
<a id='n444' href='#n444'>444</a>
</pre></td>
<td class='lines'><pre><code><style>pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span>---
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
&lt;&lt;dummy/../../../framework/application/application-environment#application.environment,&quot;Deploying
an Application&quot;&gt;&gt;. Deploying reads the servlet classes annotated with the
[literal]#++@WebServlet++# annotation or the [filename]#web.xml#
deployment descriptor 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.


[[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.


[[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.


[[application.lifecycle.session]]
== User Session

(((&quot;session&quot;)))
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
&lt;&lt;dummy/../../../framework/application/application-environment#application.environment.configuration,&quot;Deployment
Configuration&quot;&gt;&gt;.

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

(((&quot;[classname]#SessionInitListener#&quot;)))
(((&quot;[classname]#SessionDestroyListener#&quot;)))
(((&quot;[classname]#VaadinService#&quot;)))
You can handle session initialization and destruction by implementing a
[interfacename]#SessionInitListener# or [interfacename]#SessionDestroyListener#,
respectively, to the [classname]#VaadinService#.
(((&quot;[methodname]#servletInitialized()#&quot;)))
(((&quot;[classname]#VaadinServlet#&quot;)))
You can do that best by extending [classname]#VaadinServlet# and overriding the
[methodname]#servletInitialized()# method, as outlined in
&lt;&lt;application.lifecycle.servlet-service&gt;&gt;.


[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
    }
}
----


[[application.lifecycle.ui]]
== Loading a UI

(((&quot;UI&quot;, &quot;loading&quot;)))
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.

(((&quot;[classname]#UIProvider#&quot;)))
(((&quot;[classname]#DefaultUIProvider#&quot;)))
(((&quot;[classname]#BrowserWindowOpener#&quot;)))
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.

(((&quot;[classname]#VaadinRequest#&quot;)))
(((&quot;[methodname]#init()#&quot;)))
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 &lt;&lt;application.lifecycle.session&gt;&gt;. 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
&lt;&lt;dummy/../../../framework/advanced/advanced-embedding#advanced.embedding,&quot;Embedding
UIs in Web Pages&quot;&gt;&gt;.


[[application.lifecycle.ui.uiprovider]]
=== Custom UI Providers

(((&quot;[interfacename]#UIProvider#&quot;, &quot;custom&quot;)))
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#.


[[application.lifecycle.ui.preserving]]
=== Preserving UI on Refresh

(((&quot;UI&quot;, &quot;preserving on refresh&quot;)))
(((&quot;[classname]#@PreserveOnRefresh#&quot;)))
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

(((&quot;UI&quot;, &quot;expiration&quot;)))
[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
&lt;&lt;dummy/../../../framework/application/application-environment#application.environment.parameters,&quot;Other
Servlet Configuration Parameters&quot;&gt;&gt;.

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

(((&quot;UI&quot;, &quot;closing&quot;)))
(((&quot;[methodname]#close()#&quot;,
&quot;UI&quot;)))
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
&lt;&lt;application.lifecycle.session-closing&gt;&gt;. You can close popup windows by making
JavaScript [methodname]#close()# call for them, as described in
&lt;&lt;dummy/../../../framework/advanced/advanced-windows#advanced.windows.popup-closing,&quot;Closing
Popup Windows&quot;&gt;&gt;.

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

(((&quot;session&quot;, &quot;expiration&quot;)))
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.

(((&quot;closeIdleSessions&quot;)))
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. (((&quot;session&quot;,
&quot;timeout&quot;)))
(((&quot;closeIdleSessions&quot;)))
If the [parameter]#closeIdleSessions# parameter of the servlet is set to
[literal]#++true++# in the [filename]#web.xml#, as described in
&lt;&lt;dummy/../../../framework/application/application-environment#application.environment.web-xml,&quot;Using
a web.xml Deployment Descriptor&quot;&gt;&gt;, 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.
(((&quot;redirection&quot;)))
To avoid the ugly message, you may want to set a redirect URL for the UIs, as described in
&lt;&lt;dummy/../../../framework/application/application-errors#application.errors.systemmessages,&quot;Customizing
System
Messages&quot;&gt;&gt;.

The related configuration parameters are described in
&lt;&lt;dummy/../../../framework/application/application-environment#application.environment.parameters,&quot;Other
Servlet Configuration Parameters&quot;&gt;&gt;.

(((&quot;[interfacename]#SessionDestroyListener#&quot;)))
You can handle session expiration on the server-side with a
[interfacename]#SessionDestroyListener#, as described in
&lt;&lt;application.lifecycle.session&gt;&gt;.


[[application.lifecycle.session-closing]]
== Closing a Session

(((&quot;session&quot;, &quot;closing&quot;)))
(((&quot;[methodname]#close()#&quot;)))
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.
(((&quot;redirection&quot;)))
(((&quot;[methodname]#setLocation()#&quot;)))
(((&quot;Page&quot;,
&quot;[methodname]#setLocation()#&quot;)))
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.

(((&quot;logout&quot;)))

[source, java]
----
public class MyUI extends UI {
    @Override
    protected void init(VaadinRequest request) {
        setContent(new Button(&quot;Logout&quot;, event -&gt; {
            // Redirect this page immediately
            getPage().setLocation(&quot;/myapp/logout.html&quot;);

            // Close the session
            getSession().close();
        }));

        // Notice quickly if other UIs are closed
        setPollInterval(3000);
    }
}
----

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 &quot;Session Expired&quot; message
and, by default, reloads the UI when the message is clicked.
(((&quot;session&quot;, &quot;expiration&quot;)))
(((&quot;redirection&quot;)))
(((&quot;system messages&quot;)))
You can customize the message and the redirect URL in the system messages.

It is described in &lt;&lt;dummy/../../../framework/application/application-errors#application.errors.systemmessages,&quot;Customizing System Messages&quot;&gt;&gt;.

(((&quot;heartbeat&quot;)))
(((&quot;UI&quot;, &quot;heartbeat&quot;)))
(((&quot;push&quot;)))
(((&quot;server push&quot;)))
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
&lt;&lt;dummy/../../../framework/advanced/advanced-push#advanced.push,&quot;Server Push&quot;&gt;&gt;.

[source, java]
----
@Push
public class MyPushyUI extends UI {
    @Override
    protected void init(VaadinRequest request) {
        setContent(new Button(&quot;Logout&quot;, event -&gt; {
            for (UI ui: VaadinSession.getCurrent().getUIs())
                ui.access(() -&gt; {
                    // Redirect from the page
                    ui.getPage().setLocation(&quot;/logout.html&quot;);
                });

            getSession().close();
        }));
    }
}
----

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.
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.39.1</a>) at 2025-08-07 02:42:41 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
