{"id":1283,"date":"2020-07-18T19:16:03","date_gmt":"2020-07-18T19:16:03","guid":{"rendered":"https:\/\/jan.schnasse.org\/blog\/?p=1283"},"modified":"2026-09-28T11:38:45","modified_gmt":"2026-09-28T09:38:45","slug":"learning-jsf","status":"publish","type":"post","link":"https:\/\/jan.schnasse.org\/blog\/2020\/07\/18\/learning-jsf\/","title":{"rendered":"Learning JSF &#8211; The JSF Lifecycle"},"content":{"rendered":"<p>1. There is only one user interaction &#8211; it is called &#8222;the Request&#8220;. Please forget about GET,POST,PUT,DELETE. It is just &#8222;the request&#8220;. The request in general is not of your concern. Everything is handled by the framework. <strong>You don&#8217;t have to write controller code. In fact, you can not<\/strong>! The controller is already there. It is called &#8222;FacesServlet&#8220;.<\/p>\n<p>2. The Framework handles all aspects of HTTP with\u00a0 &#8222;the request lifecycle&#8220;.<\/p>\n<p>3. You have to learn the request lifecycle.<\/p>\n<h3>The Request Lifecycle<\/h3>\n<ol>\n<li>\u00a0User <strong>Request<\/strong> goes in.<\/li>\n<li>\u00a0<strong>FacesServlet<\/strong> (Controller) asks the <strong>Facelet<\/strong>(View) to build the view<\/li>\n<li>\u00a0The Facelet asks the <strong>BackingBean<\/strong> (Model) to provide data, e.g. from database.<\/li>\n<li>\u00a0For that the <strong>BackingBean<\/strong> often uses additional <strong>Beans<\/strong>.<\/li>\n<li>\u00a0The Facelet does a &#8222;<strong>Restore View<\/strong>&#8222;. Now the View is up to date. But&#8230;. only internally. Nothing is rendered yet because&#8230;<\/li>\n<li>\u00a0Now the &#8222;<strong>Apply Request Values<\/strong>&#8220; phase is entered. For that more data is fetched from the BackingBean.\u00a0 The Request Values are applied. And an &#8222;<strong>ActionEvent<\/strong>&#8220; is queued.<\/li>\n<li>\u00a0Get data from BackingBean to &#8222;<strong>Process Validations<\/strong>&#8222;<\/li>\n<li>Now a &#8222;<strong>ValueChangeEvent<\/strong>&#8220; is queued. This tells the FacesServlet that something has happend. Please notice, that the Servlet was the thing that originally startet the &#8222;postback request&#8220;.<\/li>\n<li>FacesServlet. Eventually invokes <strong>ValueChangeEvent<\/strong> at the Backing Bean. But wait, first it fetches again the old version of the BackingBean compares it to the new version, and only if changes where detected the &#8222;ValueChangeEvent&#8220; is sent.<\/li>\n<li>Now &#8211; tada &#8211; &#8222;<strong>Update Model Values<\/strong>&#8220; in the Facelet.<\/li>\n<li>Which then sets the values to the BackingBean. This hopefully applies, and&#8230;<\/li>\n<li>now an &#8222;<strong>ActionEvent<\/strong>&#8220; is invoked by the framework &#8211; because something might have happended. This is the point where all sort of registered Listeners are informed and can start running&#8230;1,2,3 go!<\/li>\n<li>This also gets noticed by the BackingBean which is now used in a phase named &#8222;<strong>Obtain Navigation Outcome<\/strong>&#8222;. Sure, because after all &#8211; how in the world should the controller know what view to render next? No, it is not determined by the controller endpoint, it is determined by a String that is send after each action in the BackingBean. Hopefully the String points to an existing <strong>xhtml\u00a0<\/strong> page (Facelet)! What should go wrong? Now everything is prepared and&#8230;.<\/li>\n<li>&#8222;<strong>Render Response<\/strong>&#8220; is done by the Facelet &#8211; No not the one you invoked inititally but the one that referenced by the last action of the BackingBean.<\/li>\n<li>&#8222;<strong>Generate HTML output<\/strong>&#8220; is sent to FacesServlet<\/li>\n<li><strong>Response<\/strong> is send the user.<\/li>\n<\/ol>\n<p>Advantages<\/p>\n<ul>\n<li>You can hook additional Beans into every phase and register listeners to the emitted events. This makes the framework very powerful and flexible.<\/li>\n<li>The whole thing works heavily with Dependency Injection. You can easily provide different implementations for different contexts. This is especially useful for testing purposes and provides a mechanism to reuse components in different scenarios.<\/li>\n<li>You can completely focus on the framework. You don&#8217;t have to care about working directly with HTTP or the database. Therefore the application can interact in different scenarios. Components can be reused.<\/li>\n<\/ul>\n<p>Disadvantages<\/p>\n<ul>\n<li>It is not possible to create a standard HTTP based webapp with the framework.<\/li>\n<li>You won&#8217;t get citeable and stable URLs. There is only one hard implemented controller endpoint that handles all requests.<\/li>\n<li>It is almost not possible to create an app that stays stateless. The result is an application that almost always depends on a server session. This makes the framework susceptible for polluted sessions, dangling sessions and is by principle not thread safe. Programmers really have to take care.<\/li>\n<li>The navigation concept is a real mess. It is implicit, not safe and from client perspective unpredictable.<\/li>\n<li>It is hard to google. Since JSF can be combined with different implementations CDI, EJB, JPA<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. There is only one user interaction &#8211; it is called &#8222;the Request&#8220;. Please forget about GET,POST,PUT,DELETE. It is just &#8222;the request&#8220;. The request in general is not of your concern. Everything is handled by the framework. You don&#8217;t have to write controller code. In fact, you can not! The controller is already there. It [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-1283","post","type-post","status-publish","format-standard","hentry","category-development"],"_links":{"self":[{"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/posts\/1283","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/comments?post=1283"}],"version-history":[{"count":1,"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/posts\/1283\/revisions"}],"predecessor-version":[{"id":4135,"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/posts\/1283\/revisions\/4135"}],"wp:attachment":[{"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/media?parent=1283"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/categories?post=1283"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jan.schnasse.org\/blog\/wp-json\/wp\/v2\/tags?post=1283"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}