Skip to main content

Building programmatically managed business components - Part 2

Putting in to action

We have seen the basic theory behind the execution of  entity and view objects in the first part of this article. In the second part , let us put the theory in to action.

Download

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]
Please note this example does not use any API specific to 11.1.2.0 release, so you may be able to reuse the source classes in previous versions also.

A glance at the implementation

This example uses two model objects - Department and Employee. The 'Department' is based on DEPARTMENTS table and it follows usual entity and view object generation steps, whereas Employee is based on custom data source and the steps for generating programmatically managed Employee model object is given below.

Building base classes for your programmatic entity and view objects

While building a programmatic view or entity objects you may need to hook your code to perform CRUD (Create Read Update Delete) operations against the custom data source (as per your use case) by overriding the life cycle methods(by default CRUD is done against database). This example uses generic base classes for doing this job and they are copied below for your reference.


ProgrammaticallyManagedEntityObjectImpl : Abstract entity object which overrides EntityImpl::doDML(...) and related methods.
ProgrammaticallyManagedViewObjectImpl : Abstract view object which overrides ViewObjectImpl::executeQueryForCollection(...) and related methods.
GenericQueryModel : A generic query model class which holds the filtering criteria  for third party services.
GenericRowCollection : A generic data structure to hold the result from the query(data retrieval) execution.
GenericRowData : A generic data structure representing a row in the result set.

Building programmatic entity object

Step 1: Right click the model  project, select New->ADF Business Components-> Entity Objects. You can key in the entity name and leave the default values for the other fields as is, click Next.


Step 2: Add attributes and finish the wizard


Step 3: Select the generated entity object in the editor, go to Java tab and click on edit Java Options. Change the base class for the Entity Object as fmwk.extension.entity.ProgrammaticallyManagedEntityObjectImpl(what we generated initially)
You may need to override ProgrammaticallyManagedEntityObjectImpl::getService() to return GenericDataPersistanceService implementation. Please see Step 4 for the service implementation.

Step 4: Build the business service implementing fmwk.extension.view.GenericDataPersistanceService for updating the data. Please take a look at model.emp.service.MyEmpDataServiceImplementation to get a feel of the implementation.

Building programmatic view object

Step 1: Select the programmatic entity object, right click and then select New Default View Object option from the context menu.


Step 2: Switch to the source mode of the generated view object and set the CustomQuery="true" as shown in the following image. This is very important step as this flag influences the run time to avoid the query execution against data base(which is the default execution path)


Ste 3: Select the generated view object in the editor, go to Java tab and click on edit Java Options. Change the base class for the View Object as fmwk.extension.entity.ProgrammaticallyManagedViewObjectImpl(what we generated initially)


You may need to override ProgrammaticallyManagedViewObjectImpl::getService() to return GenericDataReadServiceInterface implementation. Please see Step 4 for the service implementation.

Step 4: Build the business service to read data by implementing fmwk.extension.view.GenericDataReadService.  Please take a look at model.emp.service.MyEmpDataServiceImplementation to get a feel of the implementation.

Can I reuse this sample source?

Well, the classes what you see in package fmwk.extension.xxx are generic in nature and reusable. If you have similar use cases, then you may need to implement an adapter for your 'data source' calls as shown in model.emp.service.MyEmpDataServiceImplementation. The core run time classes what you see under fmwk.extension.xxx can be reused either as is or with some modifications.

How to run this sample?

This example is based on Department-Employee model. As I said earlier the Department is based on data base table and Employee is programmatically manged. This sample contains three pages illustrating search, update and master-child coordination on programmatic view object.
  • search.jsf - Search page for programmatic view object.
  • masterChild - Master child coordination(Department-Employee) through view link.
  • edit.jsf - Edit page for programmatic entity object.
Learn More ...
There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html

Comments

Renaissance said…
Thanks for this article..has given me an idea to proceed with my work :)
Tuttu said…
Hi,
I have tried to create a programmatic VO without an entity object. But I am stuck up in the end. I have posted a thread in otn regarding this.
forums.oracle.com/forums/thread.jspa?messageID=10750158#10750158
Can you help me with this?
agtl said…
Hi,

I have downloaded the sample but I am struggling to understand what do I need to do and what methods to implement in order to achieve ViewLink functionality between 2 programatically view objects. Can you kindly let me know which methods I need to focus on?
Anonymous said…
Hi, I have a Prog VO. A button click queries a set of flat files to retrieve data. There are bind variables to execute query. I have set rangesize to default. And max size of 250 to ResultSet in the VO. Everything works fine until query returns 25 rows. Once Query returns more than 25 rows,and I re-query, here is what happens
1. Query is executed more than once in the VO.As a result, bind variables are not applied.
2. max size set on VO is also overridden.
3. Scroll on adf table doesn't point to last row.(I have set displayrows=last in page fragment)
4. If I try to scroll the scroll bar on table - VO populates rows - these are not the right set of rows. Precisly, bind variables were not applied.
Could you let me know what am I missing here ?
Also getQueryHitCount() may or may not get executed. It returns wrong #(count) of rows
Hi Jobinesh,

I used your solutions and it works perfectly.

Now I need to add LOV to my programmatically managed view object. The other view object that I am referencing in my LOV is normal view object (not programmatic).

After I added the LOV, added a form of prog. vo into a jsf page, I got the error given below:

incident 10 created with problem key "DFW-99998 [oracle.jbo.KeyNotPopulatedException][oracle.jbo.server.OracleSQLBuilderImpl.buildWhereClause][j2ee-app]"


What can be the problem is?
agtl said…
If you add two programmatic VO using this example, and join them unsing a ViewLink between them, then only way for it to work is not exposing the viewLink in either the source nor destination VO. Also, again with vie links, unexpectedly you may find errors of the kind:

JBO-27122: SQL error during statement preparation. Statement: SELECT FROM WHERE ENTITY.ATTR_ID = :Bind_AttrId

Then, you are going to lose several days until you finally give up because this example works only for what it was created for. Further than that, you may need to modify the classes and to do that, you need a lot of knowledge of the internal classes.

Would be great if Jobinesh could actually create a new updated post like this, providing an skeleton for people like us wanting to use programatically VO correctly and using complete features and not only a set of them.
ivisa pass said…
OCI application form A passport is a travel document,usually issued by the government of a nation,that certifies the identity and nationality of its holder for the purpose of international travel.

Popular posts from this blog

How to set Bind Variable Values at runtime ?

In this post I'm sharing a couple of approaches for programmatically setting bind variables values at run time. This post is an attempt to explain 'When to use what ?'[ In case if you are familiar with 'Bind Variables' in ADF BC, please refer Section 5.10, Working with Bind Variables in Fusion Developer's Guide ]

1. Set the Bind Variable value using RowSet::setNamedWhereClauseParam(...)

You can use use the setNamedWhereClauseParam(...) method on the ViewObject interface (which extends oracle.jbo.RowSet) to set the value for bind variables. Please note this sets the value on default RowSet. In other words, this doesn't have any effect on the secondary RowSets that you/system generates.
ViewObject vo = am.findViewObject("EmployeesView1"); vo.setNamedWhereClauseParam("bindVarDeptId", new Number(10)); vo.executeQuery();
2. Set the Bind Variable value using ViewObject's VariableValueManager::setVariableValue(...)

VariableValueManager Ma…