My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

miercuri, 21 octombrie 2015

What are FacesContext and ExternalContext?

What is ExternalContext ?

Well, ExternalContext class "allows the Faces API to be unaware of the nature of its containing application environment. In particular, this class allows JavaServer Faces based applications to run in either a Servlet or a Portlet environment" - official documentation.

You can easily intuit the role of ExternalContext if you check the methods it offers in contrast with FacesContext. Basically, FacesContext provides methods specific to JSF and needed for accessing the JSF specific artifacts (e.g. converters, validators, components, EL expressions, view root, resource handlers, exception handlers, supported locales, phase listeners, view handlers, system event listeners, etc). Practically everything is present in JSF API is exposed via FacesContext.

By the other hand, JavaServer Faces based applications run in either a Servlet or a Portlet environment and take advantage of the environment artifacts. For example, if your JSF application run in a Servlet environment (most probably) then you may need to access the HTTP servlet request, response, HTTP sessions, Servlet context and so on. These are available via ExternalContext, NOT via FacesContext!

So, FacesContext provides methods for accessing the JSF API, while ExternalContext provides methods for accessing the Servlet/Portlet environment in which your JSF application run.

The FacesContext is accessible via:
FacesContext fc = FacesContext.getCurrentInstance();

OmniFaces provides a shortcut for the above code as: FacesContext fc = Faces.getContext();. Moreover, in JSF 2.3 FacesContext is injectable as: @Inject private FacesContext fc;.

The ExternalContext is available via FacesContext as below:
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();

OmniFaces provides a shortcut for the above code as: ExternalContext ec = Faces.getExternalContext();. Moreover, in JSF 2.3 ExternalContext is injectable as: @Inject private ExternalContext ec;.

Notice that these two contexts doesn't provide any common artifact!

What is FacesContext ?

As you probably know, a JSF request typically passes through six phases as in the below sketch:


As I said above, FacesContext is responsible to the entire JSF API access. Via FacesContext, you can access (access = create, destroy, init, modify, etc):

·         lifecycle
·         converters
·         validators
·         components
·         EL expressions
·         view root
·         contexts
·         render kits
·         renderers
·         event listeners
·         resource handlers
·         exception handlers
·         supported locales
·         phase listeners
·         view handlers
·         system event listeners
·         tag handlers
·         etc ...

FacesContext is created per request (a single instance per request). The initialization of FacesContext take place at each request in FacesServlet (see javax.faces.webapp.FacesServlet source code). The relevant code is listed below:

// Mojarra 2.2.9 source code, FacesServlet class
public final class FacesServlet implements Servlet {

 // factory of FacesContext instances
 private FacesContextFactory facesContextFactory = null;

// JSF lifecycle
private Lifecycle lifecycle = null;

 public void init(ServletConfig servletConfig) throws ServletException {
  ...
  // init the FacesContextFactory which is capable to provide FacesContext instances
  facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory
                        (FactoryFinder.FACES_CONTEXT_FACTORY);
  ...
  //init JSF lifecycle
  ...
 }
 ...
 @Override
 public void service(ServletRequest req, ServletResponse resp)
                     throws IOException, ServletException {
  HttpServletRequest request = (HttpServletRequest) req;
  HttpServletResponse response = (HttpServletResponse) resp;
  ...
  // Acquire the FacesContext instance for this request
  FacesContext context = facesContextFactory.getFacesContext
      (servletConfig.getServletContext(), request, response, lifecycle);
  ...
 }
}

After FacesContext is created it will be used by the JSF Lifecycle to successfully accomplish the JSF six phases. During this process, you can obtain the FacesContext of the current JSF request via FacesContext#getCurrentInstance() from different places (e.g. from a custom component, a phase listener, even a custom FacesContext). The JSF lifecycle is triggered from FacesServlet as below (this is happening in the FacesServlet#service() method):

lifecycle.execute(context); // first 5 JSF phases
lifecycle.render(context);  // Render Response phase

After the current request was processed the FacesContext should be released (it will be created again at the next request). This take place in the same FacesServlet#service() method in a in a finally clause (this ensures that the FacesContext will be always released, even when an error occurred during JSF lifecycle).

So, the JSF FacesContext lifespan spreads over a JSF request-response cycle.

finally {
 // Release the FacesContext instance for this request
 context.release();
}

The below image expose the FacesContext lifespan:

Finally, all resources are released (among others FacesContextFactory and Lifecycle):

public void destroy() {
 facesContextFactory = null;
 lifecycle = null;
 ...
}

The FacesContext#getCurrentIntance() returns the FacesContext instance of the current request created as you saw above. The view (or current view) is associated in JSF API with the current view root (UIViewRoot instance). The current view (or view root) can be obtained in page via the implicit object #{view} or programmatically as below:

UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();

! OmniFaces provides a shortcut for the above code as: UIViewRoot viewRoot = Faces.getViewRoot();. Moreover, in JSF 2.3 UIViewRoot is injectable as: @Inject private UIViewRoot uiViewRoot;.

From the same view (page/browser tab) you can trigger as many requests as you want. Each of these requests will have associate an FacesContext initialized and released in FacesServlet. So, FacesContext#getCurrentIntance() returns the FacesContext associated with the current request fired from the current view, not the view itself. The view is just an JSF API artifact (is true, one of the most important) that FacesContext manages.

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

OmniFaces/JSF Fans

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors