This blog is obsolete.
Check new posts at ADF How To! !!

Sunday, September 13, 2009

Accessing the ADF Client Interface in a JSF Backing Bean when Application is splitted.

And by "ADF Client Interface" I mean the ADF Model layer for UI clients or Application Module, View Objects , Entities etc...

Solution:
"The problem was solved when I made a method call that had its own pageDef. Then the code worked like a charm (see initialBadCall_with_pageDef in the task-flow-definition-remote). ...

In the demo app, the use of the Client interface is also demonstrated. Client interface is the API that ADF BC exposes in order to be used in the client side, in our case the backing bean."



Story (or how I got there...):
Based on the excellent post of Andrejus for splitting the ADF Application, I was trying to find why when accessing AppModule through
RemoteModuleImpl am = (RemoteModuleImpl)ADFUtils.getApplicationModuleForDataControl("RemoteModuleDataControl");
the splitted application was breaking.
Specially, cos ADFUtils were written by Duncan Mills and Steve Muench and these guys know what there're doing!

One thing that seemed not good, is that in the above code there trying to accessing the implementation of the Client Interface and not the interface it self. And maybe this was forbidden by the ADF framework (as it should be cos it is not...).

First, I tried to access the Client interface "RemoteModule" and not the implementation. This SHOULD be accessible in the backing bean, at least that's what the ADF documentation says!?!
But this was not the problem that caused the splitted application to break (cos in a not-splitted app this code works fine).

The problem was solved when I made a method call that had its own pageDef. Then the code worked like a charm (see initialBadCall_with_pageDef in the task-flow-definition-remote). The only thing need it to access it in both ways (from ADFUtils or the way that is given in Fusion Developer's Guide) is to have a pageDef probably in order to be able to resolve the expression through FacesContext (see code for more).

In the demo app, the use of the Client interface is also demonstrated. Client interface is the API that ADF BC exposes in order to be used in the client side, in our case the backing bean.

The demo app is a modified demo app of Andrejus' (thank you again Andrejus for providing the original sample). Other options a also there which can be tested by changing the Default Activity of the task-flow-definition-remote. It is "shipped" with the initialBadCall_with_pageDef as the Default activity.

Enjoy

spido

PS:

Here's a sneak peak:

and some code:
/**
*bad call. Breaks the split.
* @return
*/
public String direct_action() {
RemoteModuleImpl am = (RemoteModuleImpl)ADFUtils.getApplicationModuleForDataControl("RemoteModuleDataControl");
am.initMethod();

return "open";
}

/**
* Uses the ADF utils to get App module, that means resolving an expression
* through FacesContext. ADFUtils were written by Duncan Mills and Steve Muench and these guys know what there're doing!
* @return
*/
public String direct_action3() {
ApplicationModule am = (RemoteModule)ADFUtils.getApplicationModuleForDataControl("RemoteModuleDataControl");
// 5. Cast the AM to call methods on the custom client interface
RemoteModule rs = (RemoteModule)am;
//the following line break with no pageDef
exploitClientInterface(rs);
return "open";
}


/**
* Uses FacesContext to get bindings and from them it gets an iterator and
* then tah app module.
* @return
*/
public String direct_action2() {
ApplicationModule am = (ApplicationModule)this.getApplicationModuleFromIterator("EmployeesView1Iterator");
// 5. Cast the AM to call methods on the custom client interface
RemoteModule rs = (RemoteModule)am;
// 6. Call a method on the client interface
exploitClientInterface(rs);

return "open";
}

/**
*Method to demonstate how we can exploit the Client interface that ADF BC provide.
* @param rs
*/
private void exploitClientInterface(RemoteModule rs) {
System.out.println("In backing bean!!!");

//use api of ApplicationModule (default) client interface
oracle.jbo.ViewObject vo = rs.findViewObject("EmployeesView1");
//use api of Custom implementation of ApplicationModule (your implementation) client inteface
rs.initMethod();

//use api of VO client interface
vo.setOrderByClause("Employees.FIRST_NAME");
//use api of Custom implementation of VO (your imlementation) client interface
EmployeesView employees = (EmployeesView)vo;
employees.exposeMe();

//use api of RowSet client interface
vo.executeQuery();
System.out.println("Estimated # of employees= " + vo.getEstimatedRowCount());

//use api of RowSetIterator client interface
//...

}

/**
* Helper method to get the bindings. Fusion Develop's Guides way to get the bindings.
* @return
*/
private BindingContainer getBindings() {
if (this.bindings == null) {
FacesContext fc = FacesContext.getCurrentInstance();
this.bindings = (BindingContainer)fc.getApplication().evaluateExpressionGet(fc, "#{bindings}", BindingContainer.class);
}
return this.bindings;
}

/**
* Get the App module from iterator. The Fusion Develop's Guides way to get the AppModule interface.
* @param iteratorName
* @return
*/
private ApplicationModule getApplicationModuleFromIterator(String iteratorName) {
DCBindingContainer bc = (DCBindingContainer)getBindings();
// 2. Find a named iterator binding
DCIteratorBinding iter = bc.findIteratorBinding(iteratorName);
// 3. Get the data control from the iterator binding
DCDataControl dc = iter.getDataControl();
// 4. Access the data control's application module data provider
return (ApplicationModule)dc.getDataProvider();

}