Skip to main content

ADF 11g Contextual Event Framework: An Example

Often a page or a region within a page needs information from somewhere else on the page or from a different region. While you can pass parameters to obtain that information, doing so makes sense only when the parameters are well known and the inputs are EL-accessible to the page. Parameters are also useful when a task flow may need to be restarted if the parameter value changes.

However, suppose you have a task flow with multiple page fragments that contain various interesting values that could be used as input on one of the pages in the flow. If you were to use parameters to pass the value, the task flow would need to surface output parameters for the union of each of the interesting values on each and every fragment. Instead, for each fragment that contains the needed information, you can define a contextual event that will be raised when the page is submitted. The page or fragment that requires the information can then subscribe to the various events and receive the information through the event.

Events are configured in the page definition file for the page or region that will raise the event (the producer). In order to associate the producer with the consumer that will do something based on the event, you create an event map also in the page definition (when using events between regions, the page definition file which holds both the regions contains the event map).

The Contextual Event Framework in action.

Let’s start with a simple example. Take a look at the following situation: There is a page (PAGE-1) containing two 2 regions (these regions where created by dropping taskflows on PAGE-1). The first region (“edit employees”) will publish an event, and the second region (“show information”) is a subscriber to this event.
In other words, as soon as an event is published by “edit employees”, “show information” will respond to that event for instance by displaying the action performed in “edit employees”.

When the user clicks NEXT, a contextual event with a payLoad parameter is broadcasted by the edit employee task flow. This event is then consumed by the show information task flow and its handler, the getInformationByEmail() method which is derives the Email address.

The situation is shown in this simple diagram:



This example uses an event published by a command button. So how is this example implemented?

Adding an event to a action component.

To implement the above example the next button has to publish an event when the button is pressed by the user. There are two requirements to achieve this functionality. First of all an event has to be available in the producer page (or page fragment). This event can be created in the “contextual events tab” of the overview editor for the producer page definition.

In the Events section, click the Add icon. Now it is possible to enter the name of the event and define the payload data for the event. For example, if you want to pass an attribute value from the producer page to the consumer page, you can select Page Data and select the attribute from the tree structure. In this case the “input value” of the Email field is used, as displayed in this figure:



After creating this event it is not published automatically. There still need for a actual “publisher” So to be able to actually publish the event, it has to be associated by with the NEXT button.
To associate the NEXT button with the event, select the “NEXT” button, open the Contextual Events pane in the Property Inspector, and click the Add icon. Now it is possible to select an existing event. In this case select the “nextButtonPressed” event that was created previously, from the tree structure, as is shown here:



The event is now ready for publishing. In plain code the result of the above actions for the published event looks like this in the pageDefintion file of the “edit employees” page fragment:

 <action IterBinding="EmployeesView1Iterator" id="Next"  
RequiresUpdateModel="true" Action="next">
<events xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
<event name="nextButtonPressed"
customPayLoad="${bindings.Email.inputValue}"
eventType="button pressed event"/>
</events>
</action>
…………
</bindings>
<events xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
<event name="nextButtonPressed"
customPayLoad="${bindings.Email.inputValue}"
eventType="button pressed event"/>
</events>


Now that the event is published still nothing will happen at runtime because no component has subscribed to the event. Subscribing to the event is pretty straightforward.

Subscribing to an event.

First of all the “subscriber” needs a handler process. In this case the handler method is a method on the application module that returns a valid Email address; getInformationByEmail().
When this handler method is published to the client, it’s output can be dropped on the page fragment as an output text. By doing this a method action is created in the page definition of the information page. Now the action method can subscribe to the event published in the “edit employee” page.
The actual subscribing needs to be configured in the PAGE-1. This is the page where both fragments (“edit employees” and “show information”) are present. In the “page definition” overview tab of PAGE-1 it is possible to select the event to subscribe to. After selecting that event there is the possibility to add a subscription in the “subscribers” tab.
With the “Subscribe to Contextual Event” dialog open the subscription can be configured. Select the producer from the Publisher dropdown list. To add the handler, click the Search icon next to the Handler field and select the event handler (getInformationByEmail) from the tree. Finally add the parameters for the handler method:



What was just described with a lot of words is actually the creation of a very simple publish/subscribe mechanism: There is a published event (NextButtonPressed) that has a payload (email value) which is used as parameter (mailadress) by the subscriber (getInformationByEmail).

This is just a very simple example of what can be done with the Contextual Event Framework. An action component is not the only component that can publish an event. Also components like input components, table components can publish events. Events can also be published from a managed bean, and indirectly from javascript.

Comments

Unknown said…
I would to publish button events in region-1 and consume them in region-2. This is little different from publishing the valueChange event. I have raised the button event. I have created the consumer method as shown below to get the text of the button event. I am failing to read the event. I am not sure if it is being published. I am not if I can find that through debugging.

In our business usecase, I have Purchase request in region-1 with create Item and SubItem buttons. I have a taskflow in region-2 with a

router to display item or subitem creation screen based on the action event in region-1.


public void receiveButtonEvent (ActionEvent actionEvent03){

RichCommandButton rcb = (RichCommandButton)actionEvent03.getComponent();
System.out.println("Action Text = "+rcb.getText());
String prAction = rcb.getText();
ADFUtil.setEL("#{requestScope.prAction}",prAction);
}

Is this correct? Where is the missing link? I really appreciate your insight to resolve this issue.
Anonymous said…
Hi Luc,
I have problem regarding Contextual event, which is described at OTN JDeveloper forum. Can you please take a look at this forum thread ?


https://forums.oracle.com/forums/thread.jspa?threadID=2379248&tstart=15

Thanks in advance...

Popular posts from this blog

ADF 12.1.3 : Implementing Default Table Filter Values

In one of my projects I ran into a requirement where the end user needs to be presented with default values in the table filters. This sounds like it is a common requirement, which is easy to implement. However it proved to be not so common, as it is not in the documentation nor are there any Blogpost to be found that talk about this feature. In this blogpost I describe how to implement this. The Use Case Explained Users of the application would typically enter today's date in a table filter in order to get all data that is valid for today. They do this each and every time. In order to facilitate them I want to have the table filter pre-filled with today's date (at the moment of writing July 31st 2015). So whenever the page is displayed, it should display 'today' in the table filter and execute the query accordingly. The problem is to get the value in the filter without the user typing it. Lets first take a look at how the ADF Search and Filters are implemented by

How to: Adding Speech to Oracle Digital Assistant; Talk to me Goose

At Oracle Code One in October, and also on DOAG in Nurnberg Germany in November I presented on how to go beyond your regular chatbot. This presentation contained a part on exposing your Oracle Digital Assistant over Alexa and also a part on face recognition. I finally found the time to blog about it. In this blogpost I will share details of the Alexa implementation in this solution. Typically there are 3 area's of interest which I will explain. Webhook Code to enable communication between Alexa and Oracle Digital Assistant Alexa Digital Assistant (DA) Explaining the Webhook Code The overall setup contains of Alexa, a NodeJS webhook and an Oracle Digital Assistant. The webhook code will be responsible for receiving and transforming the JSON payload from the Alexa request. The transformed will be sent to a webhook configured on Oracle DA. The DA will send its response back to the webhook, which will transform into a format that can be used by an Alexa device. To code

ADF 11g Quicky 3 : Adding Error, Info and Warning messages

How can we add a message programatically ? Last week I got this question for the second time in a months time. I decided to write a short blogpost on how this works. Adding messages is very easy, you just need to know how it works. You can add a message to your faces context by creating a new FacesMessage. Set the severity (ERROR, WARNING, INFO or FATAL ), set the message text, and if nessecary a message detail. The fragment below shows the code for an ERROR message. 1: public void setMessagesErr(ActionEvent actionEvent) { 2: String msg = "This is a message"; 3: AdfFacesContext adfFacesContext = null; 4: adfFacesContext = AdfFacesContext.getCurrentInstance(); 5: FacesContext ctx = FacesContext.getCurrentInstance(); 6: FacesMessage fm = 7: new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, ""); 8: ctx.addMessage(null, fm); 9: } I created a simple page with a couple of buttons to show the result of setting the message. When the but