Disclaimer

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Showing posts with label ADF BC. Show all posts
Showing posts with label ADF BC. Show all posts

Tuesday, December 4, 2012

ADF 11g: Lessons Learned in View Object refactoring

Though this is not a common usecase and a lot of you might think why someone will ever do that? But, while implementing solutions which are not tried earlier by developer there might be switches from creating a entity based view object to transient view object or other way round that is, starting with a transient view object and then later decide to make it entity based. Lets take the later case:

Converting a Transient View Object to Entity base View Object: Overall not a very commonly done activity but for those who may need to do it in future to save some efforts. It is just to go to 'Entity Objects' section on your view definition and then to shuttle the required entity object on which you want to base your view object. After this you may add required attributes from your entity using the option 'Add from entity' and can delete the transient attributes no longer needed.

So, what't the issue?

Well, if you go ahead with that view object definition and create a table based on a view instance of this view object you will see if coming nice. Try CRUD operations like create, update etc. and should be working as expected.  However, when I tried deleting a row it didn't work at all! So, I decided to debug it and one of the obvious way is set a debug point at remove() method of View object's row impl class and entity object's impl class. On debugging, what I found was: it was hitting the remove method in View Object's row Impl but was not stopping at entity object's impl. This indicated me some sort of configuration issues and I decided to create another view object based on the same entity object but this time in the natural expected way. On doing so in less than 2 minutes and spending some 5 minutes in comparing both the VO definitions carefully I found that in my original view object a property is set in the EntityUsages as follows:


    Name="CreditReceiverEO"
    Entity="myapps.model.entity.CreditReceiverEO"
    DeleteParticipant="false"/>

And this explained everything. So, this property was probably set during the transient view creation and didnt get removed when I switched the VO to base on an entity object.

Conclusions:  

1. Avoid shortcuts in creating ADF BC objects unless you really understand the in and out of xml files generated.

2. Whenever you see and awkward behavior try to do the things in natural way by keeping a backup of your existing app so that you can revert back later if needed.

3. If point 2 is not a valid option all the time then just to create a copy or sample project with the same setup but in the natural manner and compare the generated xmls to see if you can find a clue.

Tuesday, March 20, 2012

ADF Library to ViewController or to Model ?

Very recently, I got into the conversation when a friend got an external ADF library which had BC4J components and he wanted to use it to create a UI page.

As the library contained BC4J components or you can say an ApplicationModule so the first thought came was  to add the library to the model project and expecting the AM bundled in the library to show up in Data Controls. And when it was tried this way the AM did not show up in the Data controls. Refreshing, rebuilding the project or even restart did not help.

So, trying to dig further when we opened the model project properties and went to the business components import we could see the EOs,VOs and AM from the ADF library.

After a while, when the library was added to the ViewController project and the ApplicationModule immediately showed up in the data controls. So, what was actually happening here?


Well, that's actually how it should have been done. As a thumb rule, if you want to build UI based on the ADF library jar provided by third party then it should be a dependency of UI project not the model project. However, if you want to extend your BC4J components based on the provided components in the adf library then you should add it to the model project.

Friday, May 20, 2011

Possible bug in ADF 11g when exposing AM methods

Last week I was trying to expose a AM method to the client for calling from my View layer and I hit an issue. Every thing what I did to expose the AM method at design time worked fine but the code failed to compile saying


  • Error(17,8): vik.tools.changeNotifier.model.applicationModule.client.ChangeManagerAMClient is not abstract and does not override abstract method store(java.util.List<map<string, string in vik.tools.changeNotifier.model.applicationModule.common.ChangeManagerAM /li>
I investigated all the involved files and found no clue why it is so. After some hit and trials finally I found that the one of the parameter pased in the method signature was causing the issue.  In the above case the method was:

public void store(List<map<string, string>> myData){}

And the issue was using the generic type here. To fix it I had to use the old style and had to change it to

public void store(List<map> myData){}

to make it work. I have logged a bug for the same and will update the post if I get some resolution on this from Oracle.

UPDATE: This was turned out to be a bug which is fixed and should be available in some future release of jdeveloper.

Friday, March 25, 2011

Optimistic or Pessimistic Locking for ADF 11g Web Applications?

You would be knowing that ADF supports both type of locking mechanisms for ADF web applications. By default the locking mode is set to pessimistic. However, the recommended mode for web applications is Optimistic for performance reasons.

The reason is pessimistic lock creates pending transactional states in the database in the from of row level locks. And if in the background an application module recycling will happen it will call a rollback on the associated jdbc connection thus, causing all the locks to be released. This will cause unexpected behavior for pessimistic locking mode.

On the other hand, with optimistic locking as soon as page will terminate associated AM will be released immediately and without any burden of possible database level locks.

Andrejus has explain with a demo app the difference on these here

Friday, February 4, 2011

A note about in memory filtering on View Objects in ADF 11g

Very recently a friend encountered following issue in his adf 11g based fusion web application development. He wanted to fetch the rows from the db table just once and there after wanted to do in memory searching. His view object was a sql based view object.

Issue: He could see after first vo.executeQuery()  showing some row count. But after applying a view criteria programmatically and setting vo query mode to QUERY_MODE_SCAN_VIEW_ROWS the row count after vo.executeQuery() was coming 0. 

Solution: Well he missed to set the VO tuning to fetch all rows at once. Without this, VO query was fetching only few rows from db when query was executing for the first time. And there were no rows in the VO cache matching to his filter criteria.

Tuesday, December 28, 2010

Row STATUS_INITIALIZED and STATUS_NEW behavior in ADF 11g

When an entity row is created it's row status is STATUS_NEW . This means row is added in the transaction's list of changes to be validated or posted or committed. This is fine and expected in most of the cases. However, during complex business objects like master-detail there comes the situation where you may want to turn off these validations until both master and detail are available. For such situations to remove the row from transactions's list of changes ADF exposes an api setNewRowStatus(ROW.STATUS_INITIALIZED).

This is specifically helpful when master-detail association is a composite association and situation demands to create the detail rows before the master row. In that case without setting the row status to STATUS_INITIALIZED you will face:


JBO-25030: Detail entity with row key null cannot find or invalidate its owning entity.


There is no harm programatically changing the row status to STATUS_INITIALIZED or STATUS_NEW using the setNewRowStatus api as long as you understand its implications.

Tuesday, December 21, 2010

ADF 11g: My XSD does not include Child VO details

I very recently started working on ADF BC based webservices and had to create a web service in which I can pass a master detail stuff.

After generating the client proxy I could see the parent VO SDO but it was missing the child VO SDO to pass child details. So, in such situations the most obvious place to look for is the parent xsd generated by jdeveloper. I looked into it and to my surprise the child vo details were not included in the parent vo xsd.

I retried the process of generating the service interface of my application module number of times and every time it failed to generate the child vo details in the parent vo xsd. The natural thing came to my mind was a bug in jdeveloper in this case. I was about to do that and by chance I just navigated to child VO details and saw that child vo is not exposed as a service. So, I manually did that and bingo!!!  The smart jdeveloper automatically updated my parent vo xsd to include its details.

So, I would conclude it saying that when I generated the service interface for my AM at that time while including parent vo it should automatically take care to generate the child vo xsd as well.

Tuesday, November 16, 2010

Things to care while storing BLOB/CLOB types via VO

When you need to store a BLOB or CLOB type object into your database table via view objects (based on entity object) you need to make sure following two things should be there:

1. EO Batch mode must be turned off. Make sure there is no BatchUpdate tag is present in the EO.xml as sometimes jdeveloper fails to remove it and things looks fine on Entity object overview page.

2. Make sure there is no programmatic  or declaratively in view object tuning  section vo.setForwardOnly(true) set. BLOB and CLOB type object saving needs some special processing and need to go back to the same row in VO more than once. So setting this will fail to store these objects.

Monday, September 7, 2009

Performance tuning : Fault-in behavior in ADF

Well these days I got some interest in performance improvements in ADF applications.
So, here is an interesting term 'fault-in'. Before, I tell what it is the thumb rule is "Try to avoid it.".

Normally, when you build your Model or business components you start with building entity objects. On an entity object you build one or more view depending upon the UI requirements.

If you go with default options of creating an updatable view object based on an entity object you get a sql query which is selecting all the entity attributes with no where clause which is called 'Deafult VO query'. So, say you have an entity object EmpEO based on an employee table with selected attributes empId, empName, empSalary and mgrId then you will get something like

SELECT EmpEO.empId, EmpEO.empName, EmpEO.emoSalary, EmpEO.mgrId
FROM employee

However, in real life we create VOs depending upon the UI page requirements. So, say we create VO choosing only empId, empName and empSalary. While creating UI say it is just required to show empId and empSalary from the VO instance. On running the page, which has a VO instance of this VO as a table, ADF framework queries all the rows from the employee table and create entity instances one per row having information about empId, and empSalary. It will not populate empName and mgrId from DB. The VO instance will have pointer for each vo instance row to the actual EO instance having data.

This is pretty smart as most of the times you might be only viewing data and in that case it saves time and memory by not populating entity instances with data you don't need. Now, imagine there is a update page based on this vo instance where you try to update the emp record with id 486. In the entity object you define a validation rule that empSalary of the employee being updated should not be higher than the salary of any of the employee under his manager. So, here fault-in comes to the picture. As mgrId is mentioned in the validation rule which is missing from VO definition so while checking for this validation on record commit, framework will fire the default VO query and hence will populate all the missing EO attribute information from DB for that row . That could cause performance overhead at run time. It may be fine for a case where there is just one missing attribute and your entity is based on a few attribute based table. But in a scenario where say your entity has 100 or more attributes in that case default VO query may be big performance overhead. Situation could be worse when some of the attributes may be of type CLOBs or BLOBs.

To avoid fault-in you can look up for such cases and add such attributes to your VO. This way, while executing the VO query for the first time it will automatically populate such attributes as well in the entity instances.

Another way is slicing your entity object into multiple entity objects and creating composite VOs. For example say you have a Emp table with 30 columns some of being CLOB and BLOB types or very less used. So, you can create two Entity Objects one with mostly used columns and another with rest of the attributes. Depending upon your business requirements you can create VOs either on just one of the two EOs or a composite VO based on both the EOs.


Friday, September 4, 2009

Fine tuning your Application Module in ADF

A lot of performance problems occurs because we leave the stuff as soon as it starts working as per the requirement.

We simply do not care at the performance issues it might create later in system testing or in production environment with real life load. I am not a guru of performance tuning but here is a little I learned from my experience:

1. Carefully investigate each and every instance you added in the Application module of your view objects. Go to the tunning tab and there set the batch size equals to 1 more than the expected number of rows the VO is expected to get from DB in most of the cases. This will save un-necessary db trips. So, say a VO instance is supposed to retrieve 20 rows from db then change the batch size to 21. By default it is 1.

2. Iterating over View objects is fairly easy and we easily get into the habit of copy paste the code to iterate over the View object to look for some particular row. Avoid that. Where ever possible have a view criteria with bind variables and use it in your code to fetch the desired row.

3. One of the most neglected area is executables sometimes left in pageDefinition files and un-used. During development we try various options when something does not work and forget to remove the dead code. So, those executables run at the page load time automatically and slow down the page load time even it does not have any other side-effects on the functionality of your app. So, remember to analyze bindings and executable in your pageDef and cleanup if needed.


Wednesday, September 2, 2009

Difference between getRowCount and getEstimatedRowCount in ADFount

In ADF applications where a VO is working on large amount of data it is could be a bad impact on using getRowCount to find the number of rows in the VO. The reason is it query the database table every time it is used. So, it incurs you a DB trip.

However, getEstimatedRowCount is a bit different. For the first time it queries to DB table using a select * from table query and store the count in the Middle-tier. After that it keeps on adjusting the count within the middle tier whenever row insertion or deletion are performed on the view object.

This way it prevents the db trip and is much faster.

The downside of this method is it may not be accurate sometimes. Specially, in the scenarios where there are possibilities of data insertion or deletion from backend by some other application at the same time.

Wednesday, August 19, 2009

Multiple EO based VOs in ADF 11g

It is very common to have a data model where you have a table jobs with fields jobid, jobname and another table say emp table with empId, empName , jobId where jobid is a ref to job table.

On the UI you usually need to show empName, and the job he is associated rather the job id.
So, to fulfill such requirement you can model you BC4J as following:

Create EmpEO entity over emp table and create JobEO enitity over Jov table. Now, you can create a single VO say EmpJobVO which is based on EmpEO and JobEO. You can shuttle all the attributes from EmpEO and only jobName from the JobEO while creating the VO.

One thing to take care is in the query step is to make sure that the join condition is specified in the where clause. If this will not be specified it will perform a Cartesian join.