Thursday, August 9, 2012

Red Samurai Performance Audit Tool - Runtime Diagnosis for ADF Applications

To tune ADF application, we need to know exactly what is the reason for performance bottleneck. In Red Samurai we are helping our customer to be happy with ADF. How we do that? Yes - hard quality work (and no bla bla talking) is one of the most important things. But also we use tools - one of such tools is in house developed ADF Runtime Performance Audit tool.

Before blaming ADF is slow, make sure to check the way data is retrieved from DB, also SQL execution performance. I agree, its not always easy to monitor DB/SQL performance for ADF applications. This is the main reason we have developed this tool.

Our tool splits into two parts - Audit Engine (6 KB JAR file) and Performance Audit Dashboard. Customer application needs to include only Audit Engine, the rest happens as magic - information about slow SQL starts to come to dashboard automatically. Tool is universal and runs in development, test and production environments.

Performance Audit Dashboard interface:


Main areas for performance bottleneck and tuning related to DB/SQL in ADF:

1. SQL time execution in DB. While SQL executes, ADF waits for response - we want as fast SQL execution as possible.

2. Duplicate SQL execution. Obviously we want to avoid duplicate SQL execution.

3. SQL count query execution. ADF invokes separate SQL count query to estimate rowset size, this may slow down performance for complex queries.

4. Resultset Fetch size. When fetching lots of records from DB, ADF is using more memory to create and maintain rowset, this potentially slows down application.

5. Passivation/Activation time. One of the slowest operations - need to monitor and avoid as much as possible.

Performance Audit Dashboard offers two charts for performance audit overview:

1. Type of Issues pie chart with selection in time

2. Monthly Issues tracking linear chart

List with issues displays:

1. Issue type
2. SQL execution time
3. Issue details
4. Issue date
5. Application/View Object name related to the issue
6. User name, ADF Web user who was triggering SQL from ADF application

Details section displays more detailed info, such as SQL query or complete info about large rowset fetch.

There is option to change audit parameters on the fly.

We are on track to innovate and improve ADF applications quality, this tool is newest addition to our other tools:

1. Red Samurai MDS Cleaner V2.0

2. JDeveloper 11g Extension to Validate ADF Code Quality

Red Samurai Performance Audit is available free of charge (existing/future Red Samurai customers).

Tuesday, August 7, 2012

Difference Between ADF BC Groovy Old Value and Posted Attribute

To keep it short - ADF BC Groovy keyword "oldValue" and ADF BC API method getPostedAttribute(index) are not the same thing. I spoke with ADF developer today, who have spent around 5 days debugging and hitting validation bug related to incorrect usage of "oldValue" by Groovy. Both approached - "oldValue" and getPostedAttribute(index) are valid for its own use cases. But you should clearly understand the difference, otherwise may hit some painful bugs in validation rules.

How it works in ADF 11g R2:

1. "oldValue" Groovy keyword returns last valid value
2. getPostedAttribute(index) returns value from database

In most of the cases, we need to compare user input against original value from the database. This makes Groovy "oldValue" keyword pretty useless in such use cases where we want to validate data against original one.

Download sample application where both cases are demonstrated - OldNewValueValidationApp.zip.

Sample application defines one validation rule for CommissionPct attribute:


This rule is using Groovy oldValue and newValue keywords:


Second validation rule is defined for Salary attribute, its based on Java method. We are going to call getPostedAttribute(index) method from there:


Here is the code sample for getPostedAttribute(index) invocation:


1. Test for Groovy oldValue keyword

Initial value for CommissionPct is 0.1:


Change it to negative -0.1, this will trigger validation rule:


Old value is reported to be 0.1, this is correct. Now enter positive valid value 0.2:


Type -0.2 now, old value is reported as 0.2 - this is last valid value, but not the original value from database (we didn't commited yet our change to database):


2. Test for getPostedAttribute(index) method

Initial value for Salary is 16000:


Change it to 300, validation error is shown and you can check that old value is reported as 1600 (correct):


Change to new valid value 17000 now:


Again change back to invalid 400 - old value is reported correctly, the one original from database 16000:


Sunday, August 5, 2012

Resolving Invalid ADF BC Library Import in JDeveloper 11g R2

This week I came across ADF BC library import problem onsite. ADF BC library was very large, around 1000 EO's. EO's were not visible through JDeveloper wizard from consuming project after import. At first I was this is related to library size - too many ADF BC objects, JDeveloper fails to list them through ADF library import. But this proved to be false assumption, when I tested with smaller library. At the end I found there was duplicate definition for EO package path inside consuming project, it was duplicate to the one from ADF library. This was a reason why JDeveloper wizard was not resolving imported ADF BC. I will describe this case in a bit more detail, I believe this might be helpful (JDeveloper version - 11g R2 (11.1.2.x)).

Download working sample application with ADF BC library import - adflibimport.zip.

ADF BC library contains one EO object - com.redsamurai.common.model.entities package:


Project is deployed as ADF library and connected through JDeveloper resource catalog - EO object for Employees is included:


All is correct ay this point. But in my case imported ADF lib JAR file was showing imported package, but content was empty. Exactly as you can see in this screenshot - no content for com.redsamurai.common.model.entities package:


It seems like JDeveloper randomly may register package from imported library inside local Model.jpx ADF BC configuration file. When this happens - there will be duplicate package on class path and no ADF library objects shown in JDeveloper wizards. Its what I had in my case - imported package name was populated as well into local Model.jpx file:


After imported package name entry was removed from local Model.jpx, JDeveloper wizard instantly started to show imported EO object name:


If you will encounter the same situation - no ADF BC objects visible from imported library, make sure to double check local Model.jpx file, may be you will find duplicate entry for package name from imported library.

Thursday, August 2, 2012

ADF BC Passivation/Activation and SQL Execution Tuning

Passivation/activation in ADF BC is designed to keep temporary user data across requests, when there are more online users than application pool can handle. If you are new to this, please read from Oracle developer guide - 40 Application State Management. There is added cost to passivation/activation - additional SQL execution. During activation event, its not only temporary data gets initialized - but complete VO SQL gets executed again. This means system could suffer significant performance issues, if there are lots of passivation/activation events happening. In order to avoid frequent passivation/activation, make sure to tune referenced pool size properly for your environment - Stress Testing Oracle ADF BC Applications - Passivation and Activation.

This post demonstrates additional SQL execution during activation event. Download sample application - ActivationSQLApp_v2.zip.

Form is loaded for the first time:


One SQL execution happens as it should:


We are running test with AM pooling disabled, this allows to simulate stress test environment and trigger activation/passivation events:


With AM pool disabled, without closing screen, press Next button in the form - this will navigate to the next record:


SQL will execute one more time:


From the detail log, we can see that SQL execution event is logged as well, when there is activation event:


During normal scenarios, SQL is executed once and data stays in memory. Keep attention, how often passivation/activation happens in your system - this can affect performance significantly.

Friday, July 27, 2012

LOV Implementation with ADF BC Service-Enabled Entity Objects

I had a question about use case related to ADF architecture for different databases access. ADF system was running on multiple databases (Oracle, Microsoft SQL Server, IBM DB2) at once. Part of the data was coming from Oracle DB, LOV's data from Microsoft SQL Server, the rest from IBM DB2. ADF BC 11g connects to all three databases and can work without issues. However, from architecture point of view - ADF BC Model project is configured with database type, means ADF BC Model can connect to only one DB type. If we want to connect to other DB type, need to have separate ADF BC Model project. No problem with that - only one question. How we can integrate all these projects with different DB types together. One of the possible solutions for this scenario I will describe in today post -  ADF BC Service-Enabled Entity Objects. I have blogged about it back in 2009, always nice to revisit same topic after couple of years - Web Service Interface for ADF BC Application Module in Oracle Fusion 11g and Service-Enabled Entity Objects in Oracle Fusion 11g.

Download sample application, it incudes both - LOV service and consuming application - LOVService.zip. The idea is pretty simple - LOV service and consuming application both are implemented with ADF BC. You can imagine that LOV service works with Microsoft SQL Server and  consuming application connects to Oracle DB (in this sample, both connect to Oracle DB). LOV Service is exposing View Object through Web Service. Exposed View Object is accessed in consuming application through Service-Enabled Entity.

LOV service defines LOV view object, this view object is registered under service interface. At least one operation must be defined to expose view object through the service interface - Find in my case:


Business Components Service Interface must be defined in deployment profiles - this allows to deploy Service-Enabled entities successfully:


Make sure only MiddleTier is selected for deployment from Application Deployment profile assembly:


Thats all about LOV service, now we go to consuming application. Here we can generate EO's based on view object exposed through LOV Web Service. Create EO based on Service Interface:


In order to run project with EO based on Service Interface, you will need to add common JAR from LOV service (add it to Model project as well, if you want to run ADF BC browser utility):


Define Web Service connection information in connection.xml file:


Next you can create VO from generated EO - create it as read-only (in other scenarios you can use updateable VO as well), because it will render read-only LOV data:


I noticed interesting custom property generated for VO created based on service interface EO - DeferEstimatedRowCountProperty. I will test this, how it affects standard VO in future posts. From Oracle API - "A custom property name that indicates if this VO should defer calling estimatedRowCount in the 'getDeferredEstimatedRowCount' method.". Here is custom property:


Define LOV in usual way for JobId attribute - LOV list will come from Web Service:


Choice list LOV is rendered on runtime:


LOV list data is retrieved from Web Service - Service-Enabled Entity:


Thursday, July 26, 2012

Refreshing ADF Page Template from ADF Fragment Template

I had a blog about how to refresh ADF template content from fragment - ADF Page Template Refresh From ADF Page Fragment. There I was describing you can apply Partial Trigger to the template. There is another scenario for template refresh. Let's say we have two templates - page and fragment templates. Those two templates are completely unrelated on design time and only on runtime are rendered as one. When building custom UI Shell, you may require to refresh components available in page template from fragment template. How to do this - if two templates are just separate files and there are no references. Well - keep in mind on runtime all templates are just one JSF tree. This means we can reach Page template from nested Fragment template through JSF tree. I will describe how.

Download sample application - TemplateRefreshApp_v2.zip. This application is simple use case for potentially more complex implementations. Page template contains two tabs, fragment template contains Switch button. This button allows to manage tabs from page template and switch between tabs.

Sample application contains two fragments, implemented based on fragment template. There is main page, it is implemented based on page template:


Page template implements two tabs - each tab contains facet definition. Later we drag and drop regions into these facets:


Fragment template contains Switch Tab button and facet definition for content:


Fragments are based on fragment template:


Main page is based on page template and includes two regions:


I will describe now how refresh between fragment and page templates is implemented. Root component from fragment template - panel stretch layout, contains binding reference:


Binding reference points to the fragment template bean - the same bean, where refresh method is implemented:


Here is main part now - refresh method. This method firstly gets panel stretch layout binding instance and retrieves parent of this component. Parent will be UI template component - fragment template tag. But it doesn't end here - you can get next parent - parent of UI template. Its how you will move into the area of page template - it surrounds fragment template. It will return instance of the tab, if you get parent of the tab - it returns panel tabbed UI component. With panel tabbed, its easy to iterate over tabs from page template and set disclosed property. Once disclosed property was set, we perform partial refresh of page template from fragment template:


Here is how it looks on runtime - two tabs from page template, Switch Tab button from fragment template and finally region content included through fragment template facet:


Press Switch Tab - current tab will be closed, second tab will be opened:


Fragment template is able to refresh page template by acquiring instance of page template UI components through JSF tree.

Sunday, July 22, 2012

Lightweight ADF Task Flow for BPM Human Tasks Overview

We can customize and include available Oracle BPM Workspace task flows into our own ADF 11g application. Additionally to out-of-the-box task flows in Oracle BPM 11g, we can use Oracle BPM 11g Worklist API and build custom ADF task flows. While there can be different requirements and scenarios, in typical case I would suggest to use customized out of the box Oracle BPM 11g provided task flows for core requirements and additionally implement your own custom task flows based on available Worklist API. Most likely custom task flows based on Worklist API would cover less functional, but more lightweight requirements.

I have implemented such sample lightweight task flow - it shows a list with assigned tasks. Download sample application - IntegratedBPMWorklistApp_v4.zip. Here is how this task flow looks - simple table with assigned tasks:


Same application includes BPM Workspace task flow with complete functionality for Human tasks:


In order to implement your own ADF task flow with access to BPM context, you should follow instructions from Oracle documentation - 33 Building a Custom Worklist Client. I'm using sample application from previous post - Tips & Tricks How to Run Oracle BPM 11g PS5 Workspace from Custom ADF 11g Application. This application is extended with additional libraries required to access BPM API:


You can access BPM functionality through BPM context. It takes time to initialize BPM context, its why Oracle says to create it ones and keep in session scope. Ideal place to create BPM context is Login method. Check - initBPMContext(username, password) method, it authenticated to BPM environment and when context is created - stores it into session scope:


ADF task flow contains one fragment with read-only table to list assigned tasks:


Table is created from data control generated on top of Java class, where we are accessing BPM context and retrieving assigned tasks:


Data control class is responsible to construct a list of tasks, with task state - assigned. I'm reusing BPM context from session scope:


Tasks query is created, iterating over results and populating list of tasks:


Task list construction method is executed automatically, when table is rendered on the UI. For refresh functionality to work, we need to re-execute retrieveAssignedUserTasks() method and refresh iterator. Here is page definition for the fragment:


Refresh invokes task list construction and at the end calls iterator refresh: