Showing posts with label Contextual Events. Show all posts
Showing posts with label Contextual Events. Show all posts

Sunday, January 29, 2017

Contextual Event API Improvements in ADF 12.2.1.x

ADF 12.2.1.x brings improved API support for Contextual Event implementation - this should simplify Contextual Event usage. Now Contextual Events can be produced without referencing ActionEvent or SelectionEvent, also there is no need to define Data Control to implement Contextual Event handler. Read more in ADF 12.2.1.x documentation - 46.4 Creating Contextual Events Using Managed Beans. I will provide example and explanation how to use these improvements.

Download sample application - ContextualEventApp.zip. This sample is based on two isolated ADF regions - table and chart. When row is changed in the table, through table selection listener method I generate Contextual Event with Job Id payload and send it over, event is consumed in chart region and it allows to refresh chart by key:


Row is changed in the table - new Contextual Event is produced and consumed - chart is refreshed:


We should check in the log - it prints what happens from event initialization to consumption. This gives useful info to debug Contextual Event flow:


Let's jump into code of event producer - method for table row selection (JSFUtils helper method allows to execute table row selection event programmatically, just before producing Contextual Event, this allows to access information about current row). Event is constructed without any event definition in the bindings, directly using method action and event dispatcher API - we can pass payload information directly - no need to describe it in the definition (this is advantage, as sometimes payload definition expression could execute too late and payload could be empty):


Method action definition doesn't represent any real method, it contains event name and acts as helper for event producer:


Consumer region contains Contextual Event handler mapping - it specifies event name and handler info (this is same as before). There is no need to define handler through data control anymore. Method action points directly to the bean method, through instance name. Payload value is sent through using paramVal name and ${data.payLoad} expression:


Consumer receives payload and re-executes VO:

Tuesday, January 15, 2013

Fragment Template to Fragment Communication with ADF Contextual Events

This post is extended version for my previous post - After Commit Call for Centralized Transaction Management. Previously posted application works as it should, but you may face a bit more complex use case when fragment template will be assigned with page definition file. If there will be page definition file for the fragment template - it will not work to call method by managed bean reference and invoke operation from fragment page definition. The thing is - page definition context will be changed from fragment to fragment template and operations declared in the fragment page definition will be unaccessible. However, we can implement communication between fragment template and fragment itself through ADF Contextual Events functionality.

Here is sample application with ADF Contextual Events enabled - GlobalTransactionControlApp_v3.zip. This sample implements generic communication solution based on contextual events. Global commit/rollback actions are handled from the fragment template, after commit we want to invoke refresh for the iterators declared in our fragment page definition. Each fragment in the application, is designed to pass iterator names through page template tag (we are going to use these names in generic method):


Multiple iterator names can be passed with dash separator:


Global method for commit operation in fragment template is reading template parameter value with iterator names and invoking contextual event to notify subscribers to invoke generic after commit method:


Contextual event is defined to send iterator names using payload parameter. I personally prefer to define contextual event code manually in the source code:


Contextual event subscriber method is reading payload value with iterator names to be refreshed and re-executing each of them in the loop:


You must generate data control on top of contextual event subscriber - this is needed to be able to register it in the same page definition file where our iterators are defined:


Once data control will be generated, we can add contextual event subscriber method to the fragment page definition file (same where we have iterators). Provide value payLoad for the method parameter, this is system keyword, it will pass through payload variable value from incoming contextual event:


Contextual event subscriber was defined manually in the source code:


Department - Employee fragment is defined to pass both iterator names to be refreshed after commit:


We can see that from the log - SQL is executed for Departments and Employees:


Employee fragment is passing only one iterator to be refreshed:


We can see that from the log - contextual event is triggering only one iterator refresh in the context of currently opened fragment:

Sunday, October 17, 2010

Contextual Events Framework and ADF 11g Dynamic Regions

We were discussing in our project, if we should use Contextual Events Framework or not. Part of the team was saying Contextual Events Framework have quite many defects and who knows, may be it will be unsupported in next ADF releases. However, I personally don't think its the case - Oracle is gathering community feedback for Contextual Events Framework improvements, this means it will be stabilized and improved. For now, I would recommend not to use too much fancy functionality, but stick with fundamental parts of Contextual Events Framework, this will ensure easy migration during future ADF 11g releases.

When we would need to use Contextual Events Framework? Its possible to communicate between ADF Regions without it, just by using ADF Task Flow parameters - Communicating Between ADF Regions Without Contextual Events Framework. While its true, there is one important thing - direct dependency between two regions. It would work for static predefined systems, but if would expose our ADF Task Flows as components - consumers will decide what combination and what subset of these components will be used in their systems. In this case, we can't map both ADF Task Flows through parameters. Its when Contextual Events Framework is useful, it allows to implement independent communication between ADF 11g regions, and provide these regions as components to third party applications.

I will describe how you can use Contextual Events Framework in combination with ADF 11g Dynamic Regions.

Download sample application - ContextualDynamicRegions.zip. This application implements one static region to list all departments and additionally it contains dynamic region group with departments and employees information - three ADF 11g Task Flows:


Departments in static region are presented using table component, in the current release it doesn't work to define in declarative way Contextual Event for table selection (well, there is wizard option - but its not functional). In general, I prefer to raise and receive Contextual Events from Java methods. In order to raise Contextual Event, when row in departments table is selected, we need to define Selection Listener for this table:


Selection Listener will process typical Selection Event and raise Contextual Event:


You can see, additionally to Selection Listener, I'm raising another Contextual Event for Save action. So, there are two events produced in my sample application - one for table selection, another for Save button.

In order to raise these events successfully, we need to define event bindings - event name, type and payload. Its important to say, for custom payload you need to use $ expression, because # expression will not be processed on runtime for Contextual Event custom payload:


Employees region will receive and process Contextual Event for table selection - it will display employees based on currently selected department:


You need to generate Data Control for receiver class and register Java method in receiver Page Definition:


In order to catch Contextual Event successfully, event map between event and consumer must be defined. In my case, Java method is specified as receiver.

It would work well already, if we would not have ADF 11g Dynamic Region requirement. When switch between Dynamic Region happens, Contextual Event is not propagated to newly initialized region - this means we need to pass payload value through ADF Task Flow parameter for initial initialization:


When dynamic region for Employees will be first time initialized, it will invoke Method Action to filter employees by department, based on input parameter. All subsequent requests will be handled by Contextual Event framework and processed directly - without triggering Method Action, but calling receiver method directly:


Method Action binding associated with initial action from task flow, gets input value from task flow parameter:


There is another declaration for the same method, where input value is set dynamically, based on Contextual Event payload:


Now we are done with our components part - there are two Contextual Events raised and one of them is handled.

Let's move to third party application, where our provided components (ADF Task Flows) will be used:


Third party application declares one static ADF Task Flow for department list and one Dynamic Region with parameter map:


Also you can see, two receiver methods are declared in third party application:


Receiver methods are implemented in Main bean class, its where Dynamic Region address is handled as well. There is another class to construct Dynamic Region parameters map:


Parameters map implements HashMap and provides setter method to update parameter value:


We came to the key part of the application - Dynamic Region address management code. You can see there are two receiver methods for Contextual Events raised by components. Receiver methods assign Dynamic Region address and store it in PageFlowScope. Then page is refreshed to render current Dynamic Region. We need to refresh page, otherwise Dynamic Region is not updated based on new address. I'm storing Dynamic Region address in PageFlowScope, to preserve it in between Contextual Events, otherwise address will be lost. Dynamic Region address switch is triggered, only in case if Contextual Event delivers new address to be set. If it is table selection event, payload is used to initialize input parameter for Employees flow:


When different Contextual Event is received, Dynamic Region is switched using page refresh code:


On runtime, we can select department from static Master area - dynamic region from Detail area will render employees based on received Contextual Event:


We can select another department, new Contextual Event for table selection will be sent and list of employees will be updated:


When we press Save button, another Contextual Event is triggered - this is a signal to switch Dynamic Region:


When there will be another row selected again, Dynamic Region will switch back based on another Contextual Event. Dynamic Region will be initialized and filtered based on Input Parameter from payload, all subsequent filtering will be done directly based on Contextual Event: