31 May 2015

Understanding ADF Bindings in ADF Lifecycle

In this post I am going to focus on ADF Bindings layer and explore how it works when an ADF page with some data is initially requested from a browser.
Oracle ADF provides its own extended version of JSF lifecycle. Actually, ADF extends standard JSF lifecycle implementation class and provides ADF phase listener which gets notified with before and after phase events. Here is the list of JSF lifecycle phases extended with corresponding ADF phases:
  • Restore View
    • ADF Init Context
    • ADF Prepare Model
  • Apply Request Values
  • Process Validation
  • Update Model Values
    • ADF Validate Model Updates
  • Invoke Application
    • ADF Metadata Commit
  • Render Response
    • ADF Prepare Render
There are two types of the request: initial request and postback. During the initial request the lifecycle is pretty short. Right after the Restore View phase the lifecycle jumps to the Render Response phase skipping the rest of the phases. 

When a user initially requests an ADF page from a browser the application server performs some preprocessing of the request with a chain of servlet filters. One of them is ADFBindingFilter.  This filter is defined in Web.xml file and it is required to put ADF Bindings into action. So, when this filter handles the request it looks for the Binding Context in the current session and if it is not there a new instance is going to be created. The Binding Context, as a run-time representation of DataBindings.cpx file, contains a mapping between pages and their Page Definition files. It also contains a list of Data Controls that are used in the application. Having all that, the framework investigates what Data Controls and what Binding Containers are going to participate in the request.  ADFBindingFilter finds or creates an instance of each required Data Control and invokes its beginRequest method.

As the Binding Context is initialized the control is returned to the faces servlet which is responsible for processing JSF Lifecycle phases. When JSF Lifecycle is processing the Restore View phase it notifies ADF Phase Listener with the beforePhase event. ADF Phase Listener in its turn dispatches the event to all internal phase listeners such as Update Binding Listener. And this one initializes the required Binding Container by invoking findBindingContainerByPath on the Binding Context.

So, the Binding Context, the Data Control and the Binding Container have been created at the very beginning of the request. The framework uses ADF PageLifeCycle class in order to extend the JSF lifecycle with ADF phases. ADF Phase Listener listens to the afterPhase event of the Restore View phase and invokes appropriate methods on the ADF PageLifeCycle class. In that way the standard JSF restoreView phase has been extended with two ADF phases – InitContext and PrepareModel. During the PrepareModel phase ADF PageLifecycle invokes the refresh method on the Binding Container passing the phase identifier as a parameter.

The Binding Container during the Prepare Model executes any executable entry (iterators, actions, ...) whose refresh property is set to prepareModel. The refresh property is covered in details in this post.

As we are considering an initial request for the page, we're going to skip next lifecycle phases and jump to the render response phase.

ADF Phase Listener listens to the beforePhase event of the Render Response phase and extends it with ADF phase Prepare Render by invoking a corresponding method one ADF PageLifeCycle class. The Prepare Render phase is also called Render Model. During this phase the framework again invokes refresh method on the Binding Container and those iterators whose refresh property is set to renderModel get executed at this moment.
The JSF Lifecycle forwards the control to the page renderer and here while UI components are being rendered they require data from the underlying model. Those iterators whose refresh property is set to deferred (default value) are going to be executed here.
At the very end of the request ADF Binding Filter invokes endRequest method on each Data Control participating in the request. This causes the underlying application modules to be released back to the application module pool.

That's it!