Red Samurai Consulting logo and web site became available, thanks to my friend and colleague - Sasha Stojanovich. He is professional Web designer and skilled Oracle ADF developer, you can check his company - Avantools.
Red Samurai web site - http://www.redsamuraiconsulting.com
Tuesday, July 28, 2009
Saturday, July 25, 2009
Integration in Oracle ADF Through ADF Libraries and ADF Task Flows
Last year June, I was blogging about how to use ADF Libraries for calling remote ADF Task Flows - How To Call Remote Task Flow in JDeveloper 11g. Recently in our project we decided to split one big application into smaller ones and to create separate ViewController projects per each module implemented by Model projects. Splitting was divided into two steps - extract modules into separate ADF applications and then integrate all those applications back. Key requirement is to have one deployment archive, centralized security and at the same time to work on separate applications without any interruption. In order to implement this task, I decided to revisit ADF Libraries topic and actually I saw that in new JDeveloper 11g release integration can be implemented much easier than before. I will not focus in this post on ADF Libraries and ADF Task Flows description, you can check my older post for this. I will describe today how integration could be done now and one problem I faced (with solution of course :).
Developed sample application - ADFIntegration.zip, contains three ADF applications - LocalApp, RemoteApp and RemoteSecondApp. LocalApp acts as main application, where other two are integrated. I'm integrating two applications, because problem I faced is not reproduced in basic case - when integrating only one.
For overview purpose, main application contains one page and two ADF Task Flow calls defined. Its calling two integrated applications through ADF Task Flows:
You can see that two ADF Task Flow calls are just usual calls:
This means that we can integrated separate application through ADF Task Flow in so called plug and play way. Both ADF Task Flows are integrated through ADF Libraries generated from separate applications:
You can just drag and drop ADF Task Flow from ADF Library and it works fine - it can access your ADF BC, Bindings and Web pages. When libraries are added into your main application, you can see them listed under ADF Library definition:
And perfect news, when main application is starting, WebLogic loads all three DataBindings files (just provide different names for them and dont forget to update adfc-config.xml also). You can see from the log that DataBindings.cpx from main application is loaded first, then DataBindings from integrated libraries are loaded - DataBindings1.cpx and DataBindings2.cpx accordingly:
Along with DataBindings, all Page Definition entries are loaded.
Everything seems fine, but during integration in my project I have faced a problem (as usual :)). When loading one of ADF Task Flows from integrated application I got NullPointerException. I reproduced this in my sample, you can see it from the log:
From the first line of log, you can see that it tries to load RemoteModuleDataControl from DataBindings2.cpx file, which is incorrect - RemoteModuleDataControl is defined in first ADFLibrary, inside DataBindings1.cpx file. After some thinking, I saw in previous log message with DataBindings load order, that DataBindings2.cpx is loaded the last. This means, my integrated form was trying to use incorrect DataBindings.cpx file. I was even more sure about this, when I saw that form from second application was working, its because its based on last load DataBindings2.cpx file. At first I was thinking may be its Oracle bug, but then I found its actually was our bug - we were calling Application Modules from default Method Call activities in our ADF Task Flows directly, bypassing Binding layer. Let's describe a best practice how it should be done.
I fixed this integration error, by going to ADF Task Flow from application I was integrating:
I have opened selected ADF Task Flow and it looks like this - Method Call is defined as default activity, and it was cause of problem. We are using Method Calls as default activities, because we are invoking specific actions before opening page, I believe its common requirement:
I have checked what is invoked from this Method Call - its Backing bean method:
Then I opened this method and I saw it calls Application Module directly, bypassing Bindings layer - which is bad practice. We always should access Application Module through Bindings in ModelViewController type applications. Bad practice example:
In general, we should get DataBindings and invoke method from Application Module, this method also should be defined in Page Definition. However, in this specific case, we even don't need method in Backing bean. Better we can declare Method Call through Binding layer in ADF Task Flow directly:
Separate Page Definition file was created for this Method Call and action from Application Module defined:
We are invoking custom method from Application Module using Method Call declared as default ADF Task Flow activity:
After fix, don't forget to redeploy ADF Library, main application will pick-up changes automatically. On runtime, when opening form from first integrated ADF Library, correct DataBindings1.cpx is loaded now:
Form screen from integrated application is successfully loaded:
It seems, application splitting and integration is pretty good in latest JDeveloper 11g release.
Developed sample application - ADFIntegration.zip, contains three ADF applications - LocalApp, RemoteApp and RemoteSecondApp. LocalApp acts as main application, where other two are integrated. I'm integrating two applications, because problem I faced is not reproduced in basic case - when integrating only one.
For overview purpose, main application contains one page and two ADF Task Flow calls defined. Its calling two integrated applications through ADF Task Flows:
You can see that two ADF Task Flow calls are just usual calls:
This means that we can integrated separate application through ADF Task Flow in so called plug and play way. Both ADF Task Flows are integrated through ADF Libraries generated from separate applications:
You can just drag and drop ADF Task Flow from ADF Library and it works fine - it can access your ADF BC, Bindings and Web pages. When libraries are added into your main application, you can see them listed under ADF Library definition:
And perfect news, when main application is starting, WebLogic loads all three DataBindings files (just provide different names for them and dont forget to update adfc-config.xml also). You can see from the log that DataBindings.cpx from main application is loaded first, then DataBindings from integrated libraries are loaded - DataBindings1.cpx and DataBindings2.cpx accordingly:
Along with DataBindings, all Page Definition entries are loaded.
Everything seems fine, but during integration in my project I have faced a problem (as usual :)). When loading one of ADF Task Flows from integrated application I got NullPointerException. I reproduced this in my sample, you can see it from the log:
From the first line of log, you can see that it tries to load RemoteModuleDataControl from DataBindings2.cpx file, which is incorrect - RemoteModuleDataControl is defined in first ADFLibrary, inside DataBindings1.cpx file. After some thinking, I saw in previous log message with DataBindings load order, that DataBindings2.cpx is loaded the last. This means, my integrated form was trying to use incorrect DataBindings.cpx file. I was even more sure about this, when I saw that form from second application was working, its because its based on last load DataBindings2.cpx file. At first I was thinking may be its Oracle bug, but then I found its actually was our bug - we were calling Application Modules from default Method Call activities in our ADF Task Flows directly, bypassing Binding layer. Let's describe a best practice how it should be done.
I fixed this integration error, by going to ADF Task Flow from application I was integrating:
I have opened selected ADF Task Flow and it looks like this - Method Call is defined as default activity, and it was cause of problem. We are using Method Calls as default activities, because we are invoking specific actions before opening page, I believe its common requirement:
I have checked what is invoked from this Method Call - its Backing bean method:
Then I opened this method and I saw it calls Application Module directly, bypassing Bindings layer - which is bad practice. We always should access Application Module through Bindings in ModelViewController type applications. Bad practice example:
In general, we should get DataBindings and invoke method from Application Module, this method also should be defined in Page Definition. However, in this specific case, we even don't need method in Backing bean. Better we can declare Method Call through Binding layer in ADF Task Flow directly:
Separate Page Definition file was created for this Method Call and action from Application Module defined:
We are invoking custom method from Application Module using Method Call declared as default ADF Task Flow activity:
After fix, don't forget to redeploy ADF Library, main application will pick-up changes automatically. On runtime, when opening form from first integrated ADF Library, correct DataBindings1.cpx is loaded now:
Form screen from integrated application is successfully loaded:
It seems, application splitting and integration is pretty good in latest JDeveloper 11g release.
TrackQueryPerformed Property Usage and ADF Task Flows
I will describe following scenario - two ADF Task Flows, second ADF Task Flow is opened as Isolated. First ADF Task Flow provides query functionality implemented as View Criteria, and second ADF Task Flow accepts current row key value and allows to edit data. Scenario is pretty simple, and can be implemented in Oracle ADF very fast. However, there is one trick if you open second ADF Task Flow as Isolated. I will describe it and provide solution.
At first, download sample application I have developed - TrackQueryPerformed.zip. First ADF Task Flow provides query screen and calls second ADF Task Flow. Nothing specific here:
Second ADF Task Flow is also basic, just using Method Call for setCurrentRowWithKeyValue action:
Only one thing, second ADF Task Flow is defined with Isolated Data Control Scope:
In some systems, its usual requirement to open CRUD style ADF Task Flow in Isolated mode, in order to get a new DataControlFrame for CRUD operations.
Ok, so far everything is simple and good. Let's open query page and select third record in results table:
When record is selected, press Edit button to navigate to a second ADF Task Flow, selected record is opened for editing:
Change First Name value, press Save to commit changes and navigate back by pressing Close. Data was updated, but when navigating back to query page it was not refreshed there (same data in third row as before):
In order to requery data correctly when navigating back, we need to change TrackQueryPerformed property value in Page Definition file for Query Criteria binding:
Change it from default PageFlow to Page:
This means, Query Criteria will be initialized and performed automatically each time query page will be opened, its what we need in our case. With this setting, when navigating back from Isolated scope CRUD ADF Task Flow to query ADF Task Flow, data changes will be retrieved and shown automatically (data in third row is up-to-date):
At first, download sample application I have developed - TrackQueryPerformed.zip. First ADF Task Flow provides query screen and calls second ADF Task Flow. Nothing specific here:
Second ADF Task Flow is also basic, just using Method Call for setCurrentRowWithKeyValue action:
Only one thing, second ADF Task Flow is defined with Isolated Data Control Scope:
In some systems, its usual requirement to open CRUD style ADF Task Flow in Isolated mode, in order to get a new DataControlFrame for CRUD operations.
Ok, so far everything is simple and good. Let's open query page and select third record in results table:
When record is selected, press Edit button to navigate to a second ADF Task Flow, selected record is opened for editing:
Change First Name value, press Save to commit changes and navigate back by pressing Close. Data was updated, but when navigating back to query page it was not refreshed there (same data in third row as before):
In order to requery data correctly when navigating back, we need to change TrackQueryPerformed property value in Page Definition file for Query Criteria binding:
Change it from default PageFlow to Page:
This means, Query Criteria will be initialized and performed automatically each time query page will be opened, its what we need in our case. With this setting, when navigating back from Isolated scope CRUD ADF Task Flow to query ADF Task Flow, data changes will be retrieved and shown automatically (data in third row is up-to-date):
LOV Query Validation in Query Criteria
I have noticed in latest JDeveloper 11g release, LOV components present in Query Criteria are not validated by default. In order to make it work correctly, you need to change attribute property in View Object.
Here I'm describing how to validate LOV components in Query Criteria. Download sample application - LOVQueryValidation.zip.
By default, if you enable LOV's in Query Criteria, there is no validation applied. For example, if to type values not available in LOV list and press Tab button to navigate out of LOV, invalid value is accepted and LOV popup is not raised:
Definitely you can notice that auto submit action is not done - its why validation is not invoked. In order to make it work, open View Object and for those attributes defined as LOV components:
Open Control Hints section and change Auto Submit property to true:
Now LOV validation works for both - String type attributes:
And Number type:
Here I'm describing how to validate LOV components in Query Criteria. Download sample application - LOVQueryValidation.zip.
By default, if you enable LOV's in Query Criteria, there is no validation applied. For example, if to type values not available in LOV list and press Tab button to navigate out of LOV, invalid value is accepted and LOV popup is not raised:
Definitely you can notice that auto submit action is not done - its why validation is not invoked. In order to make it work, open View Object and for those attributes defined as LOV components:
Open Control Hints section and change Auto Submit property to true:
Now LOV validation works for both - String type attributes:
And Number type:
Friday, July 17, 2009
Oracle ADF BC Deployment and Imported Libraries
Last year July, I was writing about ADF BC sharing through JAR libraries across entire application. It works the same in current JDeveloper 11g release, however during deployment on standalone WebLogic server I have noticed some problems. When application with imported ADF BC libraries was deployed, shared ADF BC components were not found on the classpath and page wasn't loaded. For more info about importing shared ADF BC libraries you can find in my previous post - Import Functionality in Oracle ADF BC.
I have tried to deploy my previously developed application directly from JDeveloper 11g to standalone WebLogic server:
However, after application was successfully deployed and when I have tried to access it, I got oracle.jbo.NoDefException for lt.andrejusb.model.shared.entities.Countries entity:
This Entity Object should come from imported ADF BC library:
But for some reason shared package wasn't included into EAR. When I have extracted EAR package, I didn't found it there:
But as usual, solution is easy. If you have application with shared and imported ADF BC libraries, make sure you didn't forgot to set dependencies properly. In order shared package to be included into deployment WAR and then EAR archives, make sure you have set dependencies in ViewController:
In my case, ModelShared wasn't set with dependency, it's why this package wasn't included. I have set dependency and redeployed - got shared package included now:
Now application with shared and imported ADF BC components works just fine as well when it is deployed on standalone WebLogic:
Download sample application prepared for deployment - ADFBC_Import_Deploy.zip.
Spanish Summary:
En anteriores post, se mostró como hacer uso de una libreria ADF BC en otros proyectos usando Jdeveloper 10g. Sin embargo, en la actual versión de la herramienta 11g existen algunos inconvenientes que son resueltos en el siguiente post.
I have tried to deploy my previously developed application directly from JDeveloper 11g to standalone WebLogic server:
However, after application was successfully deployed and when I have tried to access it, I got oracle.jbo.NoDefException for lt.andrejusb.model.shared.entities.Countries entity:
This Entity Object should come from imported ADF BC library:
But for some reason shared package wasn't included into EAR. When I have extracted EAR package, I didn't found it there:
But as usual, solution is easy. If you have application with shared and imported ADF BC libraries, make sure you didn't forgot to set dependencies properly. In order shared package to be included into deployment WAR and then EAR archives, make sure you have set dependencies in ViewController:
In my case, ModelShared wasn't set with dependency, it's why this package wasn't included. I have set dependency and redeployed - got shared package included now:
Now application with shared and imported ADF BC components works just fine as well when it is deployed on standalone WebLogic:
Download sample application prepared for deployment - ADFBC_Import_Deploy.zip.
Spanish Summary:
En anteriores post, se mostró como hacer uso de una libreria ADF BC en otros proyectos usando Jdeveloper 10g. Sin embargo, en la actual versión de la herramienta 11g existen algunos inconvenientes que son resueltos en el siguiente post.
Tuesday, July 14, 2009
Red Samurai Consulting - First Project Reference
On Oracle JDeveloper / ADF Customers list, MedNet International Ltd. (MNI) project profile with credits to Red Samurai Consulting was listed today.
Customer - MedNet International Ltd. (MNI), is doing Oracle Forms 6i re-write project to Oracle Fusion 11g. I'm happy to be a part of this project and provide Oracle Fusion 11g consulting.
I will describe technical aspects of Oracle Forms to Oracle Fusion 11g conversion during my Oracle OpenWorld 2009 session on Oracle Develop track - Oracle OpenWorld San Francisco 2009.
Customer - MedNet International Ltd. (MNI), is doing Oracle Forms 6i re-write project to Oracle Fusion 11g. I'm happy to be a part of this project and provide Oracle Fusion 11g consulting.
I will describe technical aspects of Oracle Forms to Oracle Fusion 11g conversion during my Oracle OpenWorld 2009 session on Oracle Develop track - Oracle OpenWorld San Francisco 2009.
Sunday, July 5, 2009
Improving Performance in ADF Applications - Page Load Time in CRUD Forms
This February I was blogging about how to improve performance in Query type forms - Improving Performance in ADF Applications - Page Load Time in Query Forms. It came time to revisit this topic again, and describe performance tuning in CRUD type applications. Especially, because Oracle JDeveloper 11g Release 1 became available this week. In this release runtime performance improved significantly - Oracle ADF 11g Release 1 - Runtime Page Load Performance Improved ! We are able to run our forms against large data sets without any delay, as it was before. In this post I will describe one of potential designes, how CRUD type applications can be implemented, in order to minimize performance overhead completely.
Download sample application - CRUDPerformance.zip, it contains logic I'm describing in this post.
If you open View Object tuning section, you can see there among other options - No Rows (i.e. used only for inserting new rows). This option means, View Object will not generate any Select statements and will not query database:
In other words, main form query will not be executed and form will be opened only for insert mode - page load performance will be optimal because no initial communication with database. That's sounds exactly what we need, however then how use same form for data editing, if we can only insert. Answer is simple - we can do this also. We should keep in mind, that when No Rows option is set, this means MaxFetchSize is set to 0. This means, on runtime when needed we can programatically change it to -1, it will allow to retrieve data from database then using same View Object. I have implemented MaxFetchSize change in Application Module class:
When form will switch from insert to edit mode and back, I will call this method accordingly.
In ViewController, I have used ADF Task Flow with fragments - default activity is Create action Method Call. It create new row and opens form without database query. There is also fragment for data editing:
On runtime it looks like this, form is opened in insert mode without database query:
I can type data and store it to database:
When record is successfully inserted, form is returned back to data insert mode:
User can press Edit button and navigate to data editing mode. When this button is pressed, action method is called where Rollback is invoked in order to remove new empty row and change MaxFetchSize parameter value to query database:
Data editing fragment is opened with Query Criteria on top and it prevents default query execution:
I can put parameter and find newly entered record, can modify it and save changes to database:
When Create button is pressed in this fragment, action method is call as well and it puts View Object into No Rows mode:
Finally, data insert fragment is opened again:
Spanish Summary:
Andrejus en esta entrega, nos brinda un tip para mejorar la performance de los mantenimientos con ADF. Para ello, realiza configuraciones a nivel de View Objects que evitan un acceso innecesario a la base de datos en los procesos de Creación, Actualización y Eliminación de datos.
Download sample application - CRUDPerformance.zip, it contains logic I'm describing in this post.
If you open View Object tuning section, you can see there among other options - No Rows (i.e. used only for inserting new rows). This option means, View Object will not generate any Select statements and will not query database:
In other words, main form query will not be executed and form will be opened only for insert mode - page load performance will be optimal because no initial communication with database. That's sounds exactly what we need, however then how use same form for data editing, if we can only insert. Answer is simple - we can do this also. We should keep in mind, that when No Rows option is set, this means MaxFetchSize is set to 0. This means, on runtime when needed we can programatically change it to -1, it will allow to retrieve data from database then using same View Object. I have implemented MaxFetchSize change in Application Module class:
When form will switch from insert to edit mode and back, I will call this method accordingly.
In ViewController, I have used ADF Task Flow with fragments - default activity is Create action Method Call. It create new row and opens form without database query. There is also fragment for data editing:
On runtime it looks like this, form is opened in insert mode without database query:
I can type data and store it to database:
When record is successfully inserted, form is returned back to data insert mode:
User can press Edit button and navigate to data editing mode. When this button is pressed, action method is called where Rollback is invoked in order to remove new empty row and change MaxFetchSize parameter value to query database:
Data editing fragment is opened with Query Criteria on top and it prevents default query execution:
I can put parameter and find newly entered record, can modify it and save changes to database:
When Create button is pressed in this fragment, action method is call as well and it puts View Object into No Rows mode:
Finally, data insert fragment is opened again:
Spanish Summary:
Andrejus en esta entrega, nos brinda un tip para mejorar la performance de los mantenimientos con ADF. Para ello, realiza configuraciones a nivel de View Objects que evitan un acceso innecesario a la base de datos en los procesos de Creación, Actualización y Eliminación de datos.
Friday, July 3, 2009
Oracle ADF 11g Release 1 - Runtime Page Load Performance Improved !
Since yesterday, when Oracle Fusion Middleware 11g became available, I have done quite extensive testing on previously known ADF problematic areas.
Cool thing is that page load time even for complex pages is much faster now on runtime. Its because previously on page load, SQL queries for all available LOV components were sent to database. So, if page contains 20 LOV components, means 20 SQL statements were sent to database, it was killing performance especially when working on larger datasets. Now its fixed, and on page load SQL queries for LOV components are not pre-executed anymore - only main SQL statement is executed. Means - page load performance improved significantly.
In my next post I will describe how to tune your ADF application design in order to get high performance in CRUD applications.
Cool thing is that page load time even for complex pages is much faster now on runtime. Its because previously on page load, SQL queries for all available LOV components were sent to database. So, if page contains 20 LOV components, means 20 SQL statements were sent to database, it was killing performance especially when working on larger datasets. Now its fixed, and on page load SQL queries for LOV components are not pre-executed anymore - only main SQL statement is executed. Means - page load performance improved significantly.
In my next post I will describe how to tune your ADF application design in order to get high performance in CRUD applications.
Wednesday, July 1, 2009
Oracle Fusion Middleware 11g Release 1 - Performance Improved !
Today is a great day - Oracle Fusion Middleware 11g Release 1 became reality ! I remember, 3 years ago when Fusion development was started, not all my colleagues were sure that it will be finished successfully ! But today we can see a proof - we have Release 1 of working product !
I'm excited to see in Oracle Fusion:
And finally, I have noticed - JDeveloper 11g Release 1 IDE performance is greatly improved, that cool news. I have tested and tool seems to work now more predictable and dialogs are opening with better response, thats good work. Also, performance bug described in my previous post is fixed - JDeveloper 11g IDE Performance Problem - Reproduced.
I'm excited to see in Oracle Fusion:
- Oracle WebLogic Suite 11g
- Oracle SOA Suite 11g
- Oracle Identity Management 11g
- Oracle WebCenter Suite 11g
- Oracle Metadata Services (MDS)
- Oracle ADF Desktop Integration
- Oracle SOA Suite
- Oracle WebCenter Framework and Services
- Oracle Team Productivity Center (TPC)
And finally, I have noticed - JDeveloper 11g Release 1 IDE performance is greatly improved, that cool news. I have tested and tool seems to work now more predictable and dialogs are opening with better response, thats good work. Also, performance bug described in my previous post is fixed - JDeveloper 11g IDE Performance Problem - Reproduced.