Here is an picture of the category and category_items table I use in this blog. In this example I got for example a category U2 with the some items records like Style and Country and a category week with the weekdays as items.
I will use an local EJB as model because this gives me the Category and CategoryItems classes which I can use in the backing bean and the EJB session bean has a nice merge method which I can use when I send back the changed category.
On the EJB Session bean I created an ADF datacontrol so I can call method actions in the page definition and these methods actions will fill the method iterators.
In the left site of the page I will display all the categories and on the right I have a dynamic task flow region. You can click on a Id this will display the detail form.
When I click on my car then I will call an method action to retrieve this category class. With the items of this category I will open the category items task flow and use af:forEach to display all the items
If I select an other category I first remove the previous inputtext components and display the new items
When I change an item I can press the save button. This will call the merge method action and passes the category with the changed items to the ejb session bean, EJB will update the items values.
Here is the ddl of my examples tables.
create table CATEGORY
(
ID NUMBER not null,
NAME VARCHAR2(30) not null
)
;
alter table CATEGORY
add constraint CATEGORY_PK primary key (ID);
insert into CATEGORY (ID, NAME)
values (1, 'U2');
insert into CATEGORY (ID, NAME)
values (2, 'SEAT LEON');
insert into CATEGORY (ID, NAME)
values (3, 'WEEK');
commit;
create table CATEGORY_ITEMS
(
CAT_ID NUMBER(4) not null,
NAME VARCHAR2(40) not null,
VALUE VARCHAR2(40) not null
)
;
alter table CATEGORY_ITEMS
add constraint CATEGORY_ITEMS_PK primary key (CAT_ID, NAME);
alter table CATEGORY_ITEMS
add constraint CATEGORY_ITEMS_CATEGORY_FK1 foreign key (CAT_ID)
references CATEGORY (ID);
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (1, 'Style', 'Pop');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (1, 'Country', 'Ireland');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (1, 'Albums', 'War,Rattle and hum');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (2, 'Color', 'Black');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (2, '4WD', 'No');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (2, 'HorsePower', '140');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (2, 'Transmission', 'Automatic');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (3, 'day1', 'Monday');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (3, 'day2', 'Tuesday');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (3, 'day3', 'Wednesday');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (3, 'day4', 'Thursday');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (3, 'day5', 'Friday');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (3, 'day6', 'Saturday');
insert into CATEGORY_ITEMS (CAT_ID, NAME, VALUE)
values (3, 'day7', 'Sunday');
commit;
My backing which calls the method action and retrieves the Category from the method iterator.
package nl.whitehorses.dynamic.beans;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.event.ActionEvent;
import nl.whitehorses.dynamic.form.model.entities.Category;
import nl.whitehorses.dynamic.form.model.entities.CategoryItems;
import oracle.adf.controller.TaskFlowId;
import oracle.adf.model.BindingContext;
import oracle.adf.model.bean.DCDataRow;
import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCIteratorBinding;
import oracle.adf.view.rich.component.rich.layout.RichPanelFormLayout;
import oracle.adfinternal.view.faces.model.binding.FacesCtrlActionBinding;
import oracle.jbo.Row;
public class Main {
private Long catId;
private DCBindingContainer dc;
private Category category;
private String emptyTaskFlowId = "/WEB-INF/empty-task-flow-definition.xml#empty-task-flow-definition";
private String categoryTaskFlowId = "/WEB-INF/category-task-flow-definition.xml#category-task-flow-definition";
private String taskFlowId;
ListcatItemList;
private RichPanelFormLayout categoryItemForm;
public Main() {
dc = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
}
public void categoryTableLink(ActionEvent actionEvent) {
// Add event code here...
// the category pk is already set
// now get the category
FacesCtrlActionBinding categoryFindByKey = (FacesCtrlActionBinding)dc.getControlBinding("queryCategoryFindByKey");
categoryFindByKey.execute();
// adf executed the method action
// now get the result and put this in the category variable
DCIteratorBinding categoryBinding= (DCIteratorBinding)dc.get("queryCategoryFindByKeyIter");
Row[] categoryRows = categoryBinding.getAllRowsInRange();
for (Row row : categoryRows) {
category = (Category)((DCDataRow)row).getDataProvider();
}
// remove old childern when a other category is selected
if ( categoryItemForm != null ) {
int size = categoryItemForm.getChildren().size();
for ( int i = 0 ; i < size ; i++ ) {
categoryItemForm.getChildren().remove(0);
}
}
catItemList = category.getCategoryItemsList();
// set category taskflow
taskFlowId = categoryTaskFlowId;
}
public void saveCategoryItems(ActionEvent actionEvent) {
// Add event code here...
FacesCtrlActionBinding merge = (FacesCtrlActionBinding)dc.getControlBinding("mergeEntity");
merge.execute();
}
public TaskFlowId getDynamicTaskFlowId() {
if ( taskFlowId == null ) taskFlowId = emptyTaskFlowId;
return TaskFlowId.parse(taskFlowId);
}
public void setCatId(Long catId) {
this.catId = catId;
}
public Long getCatId() {
return catId;
}
public String getCategoryFragment() {
return category.getName();
}
public void setCatItemsList(ListcatItemList) {
this.catItemList = catItemList;
}
public ListgetCatItemsList() {
return catItemList;
}
public void setCategoryItemForm(RichPanelFormLayout categoryItemForm) {
this.categoryItemForm = categoryItemForm;
}
public RichPanelFormLayout getCategoryItemForm() {
return categoryItemForm;
}
public void setCategory(Category category) {
this.category = category;
}
public Category getCategory() {
return category;
}
}
and as last the category items jsf page code
<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
xmlns:f="http://java.sun.com/jsf/core">
<af:subform>
<af:panelHeader text="Category #{MainBean.categoryFragment}">
<af:panelFormLayout binding="#{MainBean.categoryItemForm}">
<af:forEach var="row" items="#{MainBean.catItemsList}">
<af:inputText label="#{row.name}" value="#{row.value}"/>
</af:forEach>
<f:facet name="footer">
<af:commandButton text="Save"
actionListener="#{MainBean.saveCategoryItems}"/>
</f:facet>
</af:panelFormLayout>
</af:panelHeader>
</af:subform>
</jsp:root>
Here is my 11g example workspace
Clear and thorough article, thanks.
ReplyDeletethank you ... its was a good example and usefull too
ReplyDeletehusam.obaid@gmail.com
Hi Edwin, thanks for your post.
ReplyDeleteWe also have a vertical design in the database and now we are planning the design of the ADF application for this EAV pattern.
We are working with JDev 12.1.3. Now, do you still recommend this implementation for a big application with EAV pattern in ADF?
Exists other way using ADF BC?
Thank in advance