Its very frequent requirement in Oracle ADF applications, when developer needs to implement Master-Detail relationship with Create functionality. Actually, its very easy to implement Master-Detail in ADF, the same is for Create operation. However, there is one thing you should know, especially if you are new to ADF. Let's say you are implementing functionality to allow users to insert data into Master and into Detail, its fine - you can just drag and drop Create or CreateInsert action from Data Control. But you will face a problem, when user will try to insert Master and Detail record during the same transaction:
There will be a problem, because framework will try to commit Detail record without any value for foreign key. There will be no value for foreign key, because Master record is still not committed and sequence number is not assigned for Master record primary key. When user will try to close transaction by committing new records from Master and Detail, integrity constraint violation error will be thrown by database:
From my practice, its quite common problem and many developers are facing this. However, there is one feature in Oracle ADF, that helps to solve described problem. You just need to open Entity Association wizard for those Entities involved into Master-Detail relationship:
And basically to select one checkbox in Behavior group, this checkbox is Composition Association. By selecting this option, you will force framework to use so called strong association between two Entities. With strong association, framework automatically will ensure correct foreign key value propagation for Detail record:
And there is no additional changes, Create functionality now will work for both - Master and Detail in the same transaction. Just make sure you didn't forgot to set DBSequence type for Primary Keys in your Entities. Both new records, Master and Detail, now can be commited together:
It works, but its important to know - when you are using Composite Association, you can't use Detail Entity without Master Entity in the same page. You can try to put Detail (in my case Departments Entity) into separate page and to invoke any CRUD operation, you will get Invalid Owner Exception:
More about this case you can read from Steve Muench blog - Why Do I Get the InvalidOwnerException?.
You can download and run my sample application - CreateMasterDetail.zip, developed with JDeveloper 11g for this post.
Spanish Summary:
El desarrollo de pantallas master-detail son comunes y sencillas de realizar usando ADF. Sin embargo, si se pretende grabar simultaneamente ambos registros, saldrá un error debido a que requerirá grabar primer la información que esta en cabecerá y luego la información que se encuentra en el detalle. Para evitar la salida de un error indecifrable, Andrejus nos muestra un tip muy útil en este post.
Sunday, March 22, 2009
Saturday, March 21, 2009
Extension for ADF Development Quality Testing in JDeveloper 11g
In my Oracle Fusion Middleware project we are using ADF BC, ADF Task Flows and ADF Faces Rich Client. Its a cool set of technologies that allows to speed up development process. Additionally, what is also very important, it allows to control quality of developed code in more easier ways comparing to plain J2EE development. Oracle ADF framework is based on XML definitions, this means we can validate generated/developed XML against agreed development standards.
We have found interesting way to control and keep project quality on high level - by implementing JDeveloper 11g extension for automatic development quality testing. Based on our development practice, we have selected most common quality violations comparing to defined project rules, and have implemented testing tool that can be plugged-in into JDeveloper 11g. What is important to mention, our tool is not static, we always can add new rules for quality tests when its needed.
In order to run quality test, its enough to select any project in JDeveloper 11g workspace and invoke developed extension:
Wizard will open and will ask what rule we want to check:
Let's select first one - 'Entity attribute label missing', where we can scan all Entities and check if localized labels are assigned for attributes. As result, report is generated where we can see attribute names per Entities without assigned labels:
PhoneNumber attribute is not included into report, and its correct, because this attribute have assigned label:
Another check we can do for ADF BC, is to verify Primary Keys on LOV View Objects. If for example, DepartmentsView LOV will not have Primary Key defined:
And we will run quality test for related rule:
Information about rule violation will be included into report:
We are doing automatic checks not only for ADF BC part, but for ADF Faces Rich Client and ADF Task Flows as well. For example, we can check if developer didn't forgot to put af:table into af:panelCollection. And if there will be violation:
We can invoke automatic test for this rule:
And get report for any violations:
Spanish Summary:
El control de calidad de las aplicaciones desarrolladas con ADF BC son faciles de realizar gracias al uso de archivos descriptores (XML) que el framework utiliza. En este post Andrejus muestra un plugged-in que ha desarrollado para validar el cumplimiento de algunas carateristicas que aseguren la calidad de los desarrollos con ADF BC.
We have found interesting way to control and keep project quality on high level - by implementing JDeveloper 11g extension for automatic development quality testing. Based on our development practice, we have selected most common quality violations comparing to defined project rules, and have implemented testing tool that can be plugged-in into JDeveloper 11g. What is important to mention, our tool is not static, we always can add new rules for quality tests when its needed.
In order to run quality test, its enough to select any project in JDeveloper 11g workspace and invoke developed extension:
Wizard will open and will ask what rule we want to check:
Let's select first one - 'Entity attribute label missing', where we can scan all Entities and check if localized labels are assigned for attributes. As result, report is generated where we can see attribute names per Entities without assigned labels:
PhoneNumber attribute is not included into report, and its correct, because this attribute have assigned label:
Another check we can do for ADF BC, is to verify Primary Keys on LOV View Objects. If for example, DepartmentsView LOV will not have Primary Key defined:
And we will run quality test for related rule:
Information about rule violation will be included into report:
We are doing automatic checks not only for ADF BC part, but for ADF Faces Rich Client and ADF Task Flows as well. For example, we can check if developer didn't forgot to put af:table into af:panelCollection. And if there will be violation:
We can invoke automatic test for this rule:
And get report for any violations:
Spanish Summary:
El control de calidad de las aplicaciones desarrolladas con ADF BC son faciles de realizar gracias al uso de archivos descriptores (XML) que el framework utiliza. En este post Andrejus muestra un plugged-in que ha desarrollado para validar el cumplimiento de algunas carateristicas que aseguren la calidad de los desarrollos con ADF BC.
Thursday, March 12, 2009
ADF Faces Rich Client PopUp and Master-Detail
In documentation and tutorials you will usually find classical example of Master-Detail relationship separated into two pages. However, with JDeveloper/ADF 11g more and more frequently we are moving to ADF Faces Rich Client popup based approach. This approach allows us to use Ajax popup for one part of Master-Detail relationship instead of separate page. Of course, frequently Master-Details are implemented on the same page, but I will write in this post about two pages approach transformation into page and Ajax popup.
You can download developed sample application where described approach is demonstrated - PopUpRefreshBackground.zip. When you will run main page, and will press Departments button, you should get similar screen:
In this sample application I have Detail records in the background on main page and Master records are in popup. When user scrolls through Master set and selects row, Detail row set is refreshed in the background automatically. I think such approach is definitely better comparing to two pages. ADF Faces Rich Client popup can applied not only for Master-Detail relationships, you implement in popup search functionality using ADF Query with a short list of results and display full set of results in the background.
In sample application, I have created a form for Detail records and table for Master:
In order to refresh Detail record set from ADF Faces Rich Client popup, you just need to set PartialTrigger on Detail form based on ID of Master table - this means when user will change selection in Master table, Detail form will be refreshed with correct row set.
But, as always there is one trick, I want to tell you about. In 11g, Oracle have introduced automatic PPR functionality defined on Iterator in Page Definition:
I have noticed, when you drag and drop ADF Table from Data Control, JDeveloper sets automatic PPR feature on Iterator:
However, its not always good - there is side effect of this when using row selection functionality in ADF table. Let's say user will scroll to the middle of the table and will select a row:
With PPR feature set on Iterator, ADF table will be automatically refreshed after selection event, and first row of the table will be automatically shown. This behavior is not good, because user will need to scroll to his selected row again:
In order to avoid described side effect, unselect PPR feature on Iterator for this case.
User selects Master row, Detail data is refreshed in the background:
Update 2009/03/13:
I have received very useful hint from Steve Muench today, regarding described side effect of automatic PPR feature. Its just enough to set DisplayRow = selected property for af:table and framework will automatically refocus table for currently selected row, even if it will be in the middle. Here is this property:
Spanish Summary:
En este ejemplo, Andrejus muestra el uso de Lista de Valores para obtener un valor de una Lista. Bien, en estos casos se detalla un comportamiento no deseado debido a una configuración que genera el asistente por default. Por ello Andrejus brinda un tip para solucionar este inconveniente.
You can download developed sample application where described approach is demonstrated - PopUpRefreshBackground.zip. When you will run main page, and will press Departments button, you should get similar screen:
In this sample application I have Detail records in the background on main page and Master records are in popup. When user scrolls through Master set and selects row, Detail row set is refreshed in the background automatically. I think such approach is definitely better comparing to two pages. ADF Faces Rich Client popup can applied not only for Master-Detail relationships, you implement in popup search functionality using ADF Query with a short list of results and display full set of results in the background.
In sample application, I have created a form for Detail records and table for Master:
In order to refresh Detail record set from ADF Faces Rich Client popup, you just need to set PartialTrigger on Detail form based on ID of Master table - this means when user will change selection in Master table, Detail form will be refreshed with correct row set.
But, as always there is one trick, I want to tell you about. In 11g, Oracle have introduced automatic PPR functionality defined on Iterator in Page Definition:
I have noticed, when you drag and drop ADF Table from Data Control, JDeveloper sets automatic PPR feature on Iterator:
However, its not always good - there is side effect of this when using row selection functionality in ADF table. Let's say user will scroll to the middle of the table and will select a row:
With PPR feature set on Iterator, ADF table will be automatically refreshed after selection event, and first row of the table will be automatically shown. This behavior is not good, because user will need to scroll to his selected row again:
In order to avoid described side effect, unselect PPR feature on Iterator for this case.
User selects Master row, Detail data is refreshed in the background:
Update 2009/03/13:
I have received very useful hint from Steve Muench today, regarding described side effect of automatic PPR feature. Its just enough to set DisplayRow = selected property for af:table and framework will automatically refocus table for currently selected row, even if it will be in the middle. Here is this property:
Spanish Summary:
En este ejemplo, Andrejus muestra el uso de Lista de Valores para obtener un valor de una Lista. Bien, en estos casos se detalla un comportamiento no deseado debido a una configuración que genera el asistente por default. Por ello Andrejus brinda un tip para solucionar este inconveniente.
Saturday, March 7, 2009
ORA-01000: maximum open cursors exceeded - How To Avoid
When you will develop relatively complex form with a big set of View Objects and multiple Master-Detail relationships in the Model, there is a chance during testing you will get ORA-01000: maximum open cursors exceeded exception. It will happen, because there will be too many open row sets, especially in the case of complex Master-Detail relationships. However, its possible to avoid this problem.
Its described in Oracle Fusion Middleware Java API Reference for Oracle ADF Model 11g Release 1 (11.1.1.0.0) for ViewObjectImpl class, setFetchMode(byte) method. Documentation says that there are two modes to fetch data - FETCH_AS_NEEDED and FETCH_ALL. By default, FETCH_AS_NEEDED is set. However, with this setting, if user will scroll through Master, for each Detail group will be opened new row set and not closed (because most probably user will not navigate to the end in the list). This means, many ResultSet's will be created and there will be no available cursors. As documentation recommends, in this case FETCH_ALL should be used.
This setting can be configured declaratively, in View Object wizard. In Tuning section, Retrieve from the Database group, set All at Once instead of As Needed.
JDeveloper automatically will set FETCH_ALL setting in View Object XML:
In order to describe how it works on runtime, let's take an example of Master-Detail form:
In this case, with default FETCH_AS_NEEDED setting, only visible 25 rows will be fetched when Master record with DeartmentId=50 is selected:
If user will not scroll to last record, RecordSet will not be closed.
But, when FETCH_ALL is set, all Detail records for Master record with DepartmentId=50 will be fetched and ResultSet will be closed:
Of course, this can decrease application performance. So, you should use this setting smart.
Download sample application - OpenCursors.zip.
Spanish Summary:
Si se esta desarrollando páginas con acceso a múltiples View Objets, es posible que te topes con problemas asociados a la apertura de muchos cursores en la Base de Datos. Andrejus nos explica en este tópico la manera de evitar este problema, haciendo uso de las personalizaciones a nivel de View Object.
Its described in Oracle Fusion Middleware Java API Reference for Oracle ADF Model 11g Release 1 (11.1.1.0.0) for ViewObjectImpl class, setFetchMode(byte) method. Documentation says that there are two modes to fetch data - FETCH_AS_NEEDED and FETCH_ALL. By default, FETCH_AS_NEEDED is set. However, with this setting, if user will scroll through Master, for each Detail group will be opened new row set and not closed (because most probably user will not navigate to the end in the list). This means, many ResultSet's will be created and there will be no available cursors. As documentation recommends, in this case FETCH_ALL should be used.
This setting can be configured declaratively, in View Object wizard. In Tuning section, Retrieve from the Database group, set All at Once instead of As Needed.
JDeveloper automatically will set FETCH_ALL setting in View Object XML:
In order to describe how it works on runtime, let's take an example of Master-Detail form:
In this case, with default FETCH_AS_NEEDED setting, only visible 25 rows will be fetched when Master record with DeartmentId=50 is selected:
If user will not scroll to last record, RecordSet will not be closed.
But, when FETCH_ALL is set, all Detail records for Master record with DepartmentId=50 will be fetched and ResultSet will be closed:
Of course, this can decrease application performance. So, you should use this setting smart.
Download sample application - OpenCursors.zip.
Spanish Summary:
Si se esta desarrollando páginas con acceso a múltiples View Objets, es posible que te topes con problemas asociados a la apertura de muchos cursores en la Base de Datos. Andrejus nos explica en este tópico la manera de evitar este problema, haciendo uso de las personalizaciones a nivel de View Object.