The Task
In this article, we will show how to create a table component (i.e., af:table) using a custom method in the Application Module. This custom method returns a List instance whose items will be displayed as rows in the table.
Here af:table exists in the View layer. Our custom method which provides table contents exists in the Business layer. This custom method is exposed on the client interface of an Application Module and exported to the Model layer as data control and binding object.
In this article, we will show how to achieve this. Before you start, read this companion article first.
The Background
The Table component uses a model to access the data in the underlying list. The specific model class is
oracle.adf.view.rich.model.CollectionModel
. You may also use other model instances, e.g., java.util.List
, array, and javax.faces.model.DataModel
. The Table will automatically convert the instance into a CollectionModel.Normally, you would create table using ADF View Object which is exported to the Model layer. You create an ADF bound ADF Faces table by dragging a collection from the ADF Data Controls panel to a page or page fragment. Using this approach, you can get access to its CollectionModel easily. However, for some cases, creating a View Object can be difficult. For example, our query using Oracle Semantic Technology doesn't allow us to use bind variable.
select postab.post_id, postab.content_value from table(sem_match('(?s <http://xmlns.oracle.com/rdfctx/property/hasXxxOf> <http://xmlns.oracle.com/rdfctx/organization/oracle>)', sem_models('smm_vpd_model_1','smm_ontology_model'), sem_rulebases('owlprime'), null, null)) graph, smm.smm_vpd_rdf_data_1 app, smm.smm_posts postab where app.triple.rdf_p_id=oracle_orardf_res2vid('http://xmlns.oracle.com/rdfctx/property/hasXxxOf') and app.triple.rdf_c_id=oracle_orardf_res2vid('http://xmlns.oracle.com/rdfctx/organization/oracle') and graph.s$RDFVID=app.triple.rdf_s_id and postab.post_id=app.post_id ;Ideally, we would like to make object in the RDF triple a bind variable. Since
sem_match
is an operator and doesn't allow that. The workaround will be creating a custom method which returns a List instance. Within the method, we create a custom query statement based on the name of an object (i.e., "oracle"). The signature of the custom method will be:public List<postobj> positivePostsByBrand(String brandName) { }The Steps
Because of dependencies, we will work from Business Layer back to View Layer. All Fusion Web Applications are created with two projects:
- Model
- ViewController
Step 1: Add Custom Method to the AM
Add our custom method (i.e.,
positivePostsByBrand
) to the Application Module:Shuttle custom method from the available list to the selected list:
In the Data Controls panel, you should find the new custom method listed under your application module.
Step 2: Create MethodAction Binding Object
Select the JSF page to which you want to add the new table. In its Bindings view, create a new binding object using the new data control object (i.e. our custom method
positivePostsByBrand
). By default, the binding objects are named after the data control object that was used to create it.Our new binding object will be methodAction (under Generic Bindings) item type:
On Create Action Binding, select your AM (i.e.,
SemAppModuleDataControl
). No, don't expand its contents. Look underneath for an Operation drop-down list. Select your custom method. Take a note of the name of its parameter (i.e., brandName
) which you need to use later.Step 3: Create a New Getter Method on a Managed Bean
We need a getter method on a managed bean, which will fetch table contents on behave of View layer. For this exercise, we have created a managed bean named
ActionBean
which it has been registered on the ADF's unbounded task flow (i.e., adfc-conf.xml):This managed bean has a session scope. Our getter method in ActionBean.java looks like this:
public List<PostObj> getPositivesByBrand() { if (getBrandName() == null || getBrandName().length() == 0) return new ArrayList<PostObj>(); else { OperationBinding oper = getOperBindings("positivePostsByBrand") ; Map params = oper.getParamsMap(); params.put("brandName", brandName); oper.execute(); return (List<PostObj>)oper.getResult(); } }Within it, it uses a binding object named
positivePostsByBrand
to fetch table contents from the business layer (i.e., via our custom method defined in the Application Module implementation file). To execute our custom method, we also need a parameter named brandName
. We will discuss how to provide this parameter at runtime later.Step 4: Create New Table on JSF Page
Select the component (i.e., af:panelHeader) that you want to insert the new table to and insert a new ADF Faces component (i.e., af:table):
On Insert ADF Faces Item, select Table:
On Create ADF Faces Table, check Bind Data Now and click Browse...:
You will find our variable named
positivesByBrand
(i.e., exposed by the getter method) under ADF Managed Bean > actionBean. Select it and an EL will be created automatically for you.Next we will create new columns mapped to the properties of the List instance object (i.e., PostObj). Click New:
Add new columns as shown. Their values will be mapped to the property's on our List instance object (i.e.,
PostObj
).The Missing Link
As noted above, to execute the custom method we need a parameter (i.e.,
brandName
). To provide that, we need to dynamically select that name from the UI. For example, in a master table, you may display rows with different brand name on each row. The brand name (or the count
in our case) can then be implemented as an af:commandLink
:<af:commandLink id="cl1" actionListener="#{actionsBean.positivePostsByBrand}"> <af:outputText value="#{row.count}" id="ot5"/> <f:attribute name="posBrandName" value="#{row.brand}"/> </af:commandLink>
Upon clicking, it will dispatch an ActionEvent which will be consumed by a listener (i.e.,
positivePostsByBrand
method on our managed bean). Within the method, it will retrieve an attribute named posBrandName
from the event's source object as such:public void positivePostsByBrand( ActionEvent actionEvent){ RichCommandLink _table = (RichCommandLink) actionEvent.getSource(); String brandName = (String) _table.getAttributes().get("posBrandName"); // set brand name to be used in getPositivesByBrand method setBrandName(brandName); getPositivesByBrand(); }
Note that attribute
posBrandName
will be set to be:#{row.brand}as defined in the
af:commandLink
.References
No comments:
Post a Comment