1. There is only one user interaction – it is called “the Request”. Please forget about GET,POST,PUT,DELETE. It is just “the request”. The request in general is not of your concern. Everything is handled by the framework. You don’t have to write controller code. In fact, you can not! The controller is already there. It is called “FacesServlet”.
2. The Framework handles all aspects of HTTP with “the request lifecycle”.
3. You have to learn the request lifecycle.
The Request Lifecycle
- User Request goes in.
- FacesServlet (Controller) asks the Facelet(View) to build the view
- The Facelet asks the BackingBean (Model) to provide data, e.g. from database.
- For that the BackingBean often uses additional Beans.
- The Facelet does a “Restore View“. Now the View is up to date. But…. only internally. Nothing is rendered yet because…
- Now the “Apply Request Values” phase is entered. For that more data is fetched from the BackingBean. The Request Values are applied. And an “ActionEvent” is queued.
- Get data from BackingBean to “Process Validations“
- Now a “ValueChangeEvent” is queued. This tells the FacesServlet that something has happend. Please notice, that the Servlet was the thing that originally startet the “postback request”.
- FacesServlet. Eventually invokes ValueChangeEvent 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 “ValueChangeEvent” is sent.
- Now – tada – “Update Model Values” in the Facelet.
- Which then sets the values to the BackingBean. This hopefully applies, and…
- now an “ActionEvent” is invoked by the framework – because something might have happended. This is the point where all sort of registered Listeners are informed and can start running…1,2,3 go!
- This also gets noticed by the BackingBean which is now used in a phase named “Obtain Navigation Outcome“. Sure, because after all – 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 xhtml page (Facelet)! What should go wrong? Now everything is prepared and….
- “Render Response” is done by the Facelet – No not the one you invoked inititally but the one that referenced by the last action of the BackingBean.
- “Generate HTML output” is sent to FacesServlet
- Response is send the user.
- You can hook additional Beans into every phase and register listeners to the emitted events. This makes the framework very powerful and flexible.
- 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.
- You can completely focus on the framework. You don’t have to care about working directly with HTTP or the database. Therefore the application can interact in different scenarios. Components can be reused.
- It is not possible to create a standard HTTP based webapp with the framework.
- You won’t get citeable and stable URLs. There is only one hard implemented controller endpoint that handles all requests.
- 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.
- The navigation concept is a real mess. It is implicit, not safe and from client perspective unpredictable.
- It is hard to google. Since JSF can be combined with different implementations CDI, EJB, JPA