Wednesday 26 February 2014

Executing an ADF operation binding programmatically

It's often needed to invoke an operation binding inside a taskflow, but sometimes the binding container that we expect to be ready for us to reference, is not ready for us yet.

If the taskflow is already showing a view activity, then the bindings variable will be populated with the binding container specific for the fragment, so it will be possible to lookup a binding programmatically:

BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry(); 
OperationBinding method = bindings.getOperationBinding("methodAction");  
Object result = method.execute();  

Otherwise we can use the findOperation utility method defined inside the commonly used ADFUtils class:

OperationBinding getTaskoperation = ADFUtils.findOperation("setVinAndVehicleIdForVehicle");
getTaskoperation.getParamsMap().put("instanceId", instanceId);
getTaskoperation.getParamsMap().put("autoaidVehicleId", autoaidVehicleId);
Object result = getTaskoperation.execute();

Now let's consider this scenario:

Inside a taskflow we use a method call (highlighted in the figure below) that invokes an operation binding, which is defined in the bindings section of fragment (the third activity in the figure below) that is still not shown:


In case we are inside a taskflow, but the fragment containing the operation bindings we need has not been shown yet, then the solution it's a bit more tricky, as the call above to getOperationBinding will return null: the binding container we need it's not been created yet.

In this case, we can access the data variable via EL, that gives us full access to all binding containers across the application: it can be a binding container defined for a fragment, a page or the binding container defined for an method call activity inside a taskflow:

JUFormBinding fb =
 (JUFormBinding) ADFUtils.resolveExpression("#{data.com_trw_id_adapters_scanResultsLivePageDef}");
JSFUtils.setExpressionValue("#{sessionScope.diagSession.diagnosticState}", state);
OperationBinding opb = fb.getOperationBinding("getEcusList");
opb.getParamsMap().put("session", JSFUtils.resolveExpression("#{sessionScope.diagSession}"));
opb.getParamsMap().put("diagnosisId", state.getCurrentDiagnosisId());
opb.getParamsMap().put("modifyTime", null);
opb.getParamsMap().put("weightThreshold", null);
Object result = opb.execute();

To figure out the correct EL expression you need to pass to 'resolveExpression' in order to retrieve the JUFormBinding object, then you need to go in DataBindings.cpx file; in here you will find 2 sections, one (pageMap) mapping the page/fragment/tf activity to an ID, and another (pageDefinitionUsages), mapping this ID to the fully qualified path of the page definition file:

<pageMap>
  [...]
  <page path="/WEB-INF/taskflows/connectionStateTF.xml#autoaidWS-connectionStateTF@getCurrentStatus"
           usageId="com_trw_id_adapters_connectionStateTF_connectionStateTF_getCurrentStatusPageDef"/>
 
  <page path="/fragments/ws/scanResultsLiveTF/scanResultsLive.jsff"
           usageId="com_trw_id_adapters_scanResultsLivePageDef"/>
  [...]
</pageMap>

<pageDefinitionUsages>
  [...]
  <page id="com_trw_id_adapters_connectionStateTF_connectionStateTF_getCurrentStatusPageDef"
           path="com.trw.id.adapters.autoaid.taskflows.connectionStateTF_connectionStateTF_getCurrentStatusPageDef"/>
   
  <page id="com_trw_id_adapters_scanResultsLivePageDef"
           path="fragments.ws.scanResultsLiveTF.scanResultsLivePageDef"/>
  [...]
</pageDefinitionUsages>

As you can see, the method call operation is mapped using the pattern:
<fragment or page name>#<taskflow ID>@<operation name>

What we actually need is the usageId itself (e.g. com_trw_id_adapters_scanResultsLivePageDef) and build the EL expression prefixing the string 'data.' to it:

#{data.com_trw_id_adapters_scanResultsLivePageDef}

No comments:

Post a Comment