Introduction
I like inheritance feature of ADF BC. It allows to create inheritance tree of entity objects and view objects. The feature is good described in Developer's Guide. Using this approach we can build really elegant business model. But how to use it in ViewConroller layer in the same way? How to use inheritance instead of copy-pasting?
Use Case
I have in my database three tables:
Model
In my model I've created three read-only VO's:
ViewController
Let's create TaskFlow template to work with our model. In real life the taskflow is going to contain number of different activities, but, just to simplify this post, my taskflow consists of one view activity only. FormView activity contains some form to show record from VLoan or VForex.
Ok. TaskFlow template is created in draft.
Task flows that implements this template are going to attach some real page fragment to the FormView view activity in order to show a record of corresponding deal (Loan or Forex). Obviously, some of fields are common and it's preferable to have the same look-and-feel and UI logic for these fields in every implementation. I'm going to create page fragment template and put all common fields on it .
From the DataControls palette I'm dragging VDeal and dropping it on the page as ADF Read-only Form:
After adding facet "extendFacet" for pages implementing this template and fixing some "design" issues I got the following page:
Everything seems to be OK. But!!! Let's have a look at the page definition file for our template page. The iterator binding points to VDeal view object:
Actually VDeal is just ancestor definition. Its instance will hardly be created. Pages implementing our template will have their own real VO instances of VLoan and VForex. To fix the problem I'm going to add some managed bean to my task flow template:
The DealFlowBean has method getDealVOName. This method is going to be overridden and it is responsible to return correct name of the corresponding VO:
The next step is to change a little bit page definition file for page template:
I used EL expression to resolve VO's name.
Ok. Let's create taskflow to work with loans:
We have to add manually on the Loan taskflow view activity and give it the same name FormView. We are implementing it by creating new page fragment based on the DealViewTemplate.
We put loan specific extra fields (using drag-n-drop from the Data Controls palette) on the extendFacet of our page:
After that, we have to change PageDef for the new page fragment: change Binds="VLoan" to Binds="#{DealFlowBean.dealVOName}" and change given by default iterator ID from VLoanIterator to VDealIterator.
Off-course we have to extend DealFlowBean and override the getDealVOName method.
And we need to define LoanFlow class for DealFlowBean in the definition of our taskflow.
Finishing... Task flow for loans is complete and ready to be used. Using the same approach we create task flow for forex deals.
As a reward for our work we can enjoy the following working(!) pages for loan and forex deals:
That's it!
You can download sample application for this post.
I like inheritance feature of ADF BC. It allows to create inheritance tree of entity objects and view objects. The feature is good described in Developer's Guide. Using this approach we can build really elegant business model. But how to use it in ViewConroller layer in the same way? How to use inheritance instead of copy-pasting?
Use Case
I have in my database three tables:
- Deal - contains some common fields of some agreement with some customer
- Loan - contains some extra fields specific for loan agreements
- Forex - contains some extra fields specific for forex agreements
Model
In my model I've created three read-only VO's:
- VDeal - selects all fields from Deal table
- VLoan - extends VDeal. Selects all fields from Deal and Loan tables
- VForex - extends VDeal. Selects all fields from Deal and Forex tables
ViewController
Let's create TaskFlow template to work with our model. In real life the taskflow is going to contain number of different activities, but, just to simplify this post, my taskflow consists of one view activity only. FormView activity contains some form to show record from VLoan or VForex.
Ok. TaskFlow template is created in draft.
Task flows that implements this template are going to attach some real page fragment to the FormView view activity in order to show a record of corresponding deal (Loan or Forex). Obviously, some of fields are common and it's preferable to have the same look-and-feel and UI logic for these fields in every implementation. I'm going to create page fragment template and put all common fields on it .
From the DataControls palette I'm dragging VDeal and dropping it on the page as ADF Read-only Form:
After adding facet "extendFacet" for pages implementing this template and fixing some "design" issues I got the following page:
Everything seems to be OK. But!!! Let's have a look at the page definition file for our template page. The iterator binding points to VDeal view object:
Actually VDeal is just ancestor definition. Its instance will hardly be created. Pages implementing our template will have their own real VO instances of VLoan and VForex. To fix the problem I'm going to add some managed bean to my task flow template:
FormView DealFlowBean com.cs.blog.inherit.view.DealFlow request
The DealFlowBean has method getDealVOName. This method is going to be overridden and it is responsible to return correct name of the corresponding VO:
package com.cs.blog.inherit.view; public class DealFlow { public DealFlow() { super(); } /*Extenders override this method and return correct name * of the corresponding VO * */ public String getDealVOName() { return "VDeal"; } }
The next step is to change a little bit page definition file for page template:
I used EL expression to resolve VO's name.
Ok. Let's create taskflow to work with loans:
We have to add manually on the Loan taskflow view activity and give it the same name FormView. We are implementing it by creating new page fragment based on the DealViewTemplate.
We put loan specific extra fields (using drag-n-drop from the Data Controls palette) on the extendFacet of our page:
After that, we have to change PageDef for the new page fragment: change Binds="VLoan" to Binds="#{DealFlowBean.dealVOName}" and change given by default iterator ID from VLoanIterator to VDealIterator.
Off-course we have to extend DealFlowBean and override the getDealVOName method.
package com.cs.blog.inherit.view; public class LoanFlow extends DealFlow { public LoanFlow() { super(); } public String getDealVOName() { return "VLoan"; } }
And we need to define LoanFlow class for DealFlowBean in the definition of our taskflow.
/WEB-INF/deal-flow-template.xml deal-flow-template FormView DealFlowBean com.cs.blog.inherit.view.LoanFlow request /LoanFormView.jsff
Finishing... Task flow for loans is complete and ready to be used. Using the same approach we create task flow for forex deals.
As a reward for our work we can enjoy the following working(!) pages for loan and forex deals:
That's it!
You can download sample application for this post.