Communication between taskflows and pages, beans and other components in ADF Faces applications is in many cases ideally implemented using contextual events. These events are published from a producer component – a page, taskflow or associated bean – and made available to all interested parties. Events are handed over by the ADF run time infrastructure to any registered consumer in the current scope. This includes any taskflow or enclosing page which has been configured as such. This publish/subscribe model helps achieve interaction and reuse in a decoupled way. I like the principle. I have applied it on several occasions. And today I needed it again in a WebCenter Portal application with custom ADF 11g components. And once again I could not remember exactly how to implement the contextual events, the publication and subscription. This article therefore is primarily for me – so I can quickly recall how to do this in similar subsequent situations. However, if it is useful to you too, that is even better!
The use case discussed in this article is as follows:
The section in the red rectangle is a taskflow that has been embedded as a region in the page. This taskflow has indicated that it is capable of consuming contextual events of type SaveEvent. What exactly it will do with such events is not fully disclosed (this example is taken from a use case where the taskflow has functionality to perform special validation of the values entered in the taskflow’s form). The enclosing page has a button in it. When that button is pressed by the user, the associated code will publish a Contextual Event of the type SaveEvent. The ADF runtime infrastructure takes this event and invokes the event consumer in the taskflow. Without knowing more about the taskflow than the fact that it listens to SaveEvents, the developer of the page could hook up the button with whatever action the taskflow will perform based on the event.
This article describes the few quick steps required to accomplish this and also provides a simple ADF application to download.
Creating the Taskflow
The taskflow consists of a single page fragment – detailsPage.jsff. It shows three values taken from the pageFlowScope bean detailsBean. It also shows the value of the input parameter that is passed into the taskflow.
The taskflow itself is configured with a single input parameter
and a single bean – detailsBean:
This bean is extremely simple. Three properties with getters and setters and a single method – process() – that could be quite spectacular but is in fact very straightforward:
Declaring the taskflow’s interest in the SaveEvent
The interest in the SaveEvent in this taskflow – or more specifically, in the detailsPage.jsff – is declared in the Page Definition for this fragment.
The eventMap element contains entries for each event that this fragment is capable of consuming. In this case, only events that have been published as “SaveEvent” are subscribed to. It does not matter who is the producer of the event – hence the region=”*” setting. When the SaveEvent has been published, it should be propagated to the handleEvent method binding – as is specified through the handler attribute on the consumer element.
The handleEvent method binding has been configured in the Page Definition file for the method handleEvent on the Data Control EventHandlerBean.
This Data Control has been created for a POJO called EventHandlerBean, a simple class with a method handleEvent that sort of processes the event:
when the event is detected, the ADF Framework will call the handleEvent method on an instance of the EventHandlerBean – passing the event’s payload to the payload input parameter of this method. The method gets hold of the pageFlowScope managed bean detailsBean and invokes its process() method – apparently the appropriate action in this taskflow in response to the SaveEvent.
Publishing the SaveEvent
The subscription and processing side of the Contextual Events story was described above. The question to be answered next is: how do we publish SaveEvent instances? There are several ways to publish events – some are entirely declarative. All use bindings in the Page Definition file of a taskflow or page in whose context the event should be published. The cleanest, purely programmaitc approach, is discussed here.
A POJO is created – a simple class with a simple method that returns an Object that will be the payload for the event.
This class – EventPublisherBean – is exposed as a Data Control, through the same action as was applied to the EventHandlerBean.
When we want to publish the contextual event SaveEvent, we can create a MethodBinding in the current PageDefinition for the publishEvent method on this Data Control. We can then invoke this method binding from a page component or from custom logic in some managed bean. In this example, the page that contains the taskflow discussed above also contains a button. When this button is pressed, we want the SaveEvent to be published. The button has an actionListener:
The referenced bean – parentBean – is defined in the adfc-config.xml file in this application:
The class ParentBean is a POJO. It has two properties and the method buttonPressedEvent that is the action listener for the button in the page.
The buttonPressedEvent method locates the operation binding publishEvent in the current Binding Container. This will turn out to be based on the method binding of the publishEvent method on the EventPublisherBean Data Control that we have seen before. This method returns the payload object that is passed into it. At that point, the ADF framework kicks in to actually publish the SaveEvent. It is triggered to do so by the event element that is configured inside the method action in the PageDefinition file:
this configuration of events and event inside the method action instruct ADF to publish a contextual event of type SaveEvent whenever the publishEvent method action is invoked. The result of the method action is to be used as the payload for the SaveEvent – and will therefore be passed to all subscribed event handlers.
The above structure is visualized in the next figure:
When the parentPage.jspx is run, the user can press the button and the taskflow is notified of the SaveEvent, allowing it to take appropriate action. All very loosely coupled. Note: if the taskflow would not be interested in the SaveEvent, the button press would still cause it to be published, but to no avail.
Download the JDeveloper 11gR1 PS5 application with the code discussed in this article: taskflowRefreshTest.zip.