Saturday, September 7, 2013

Understanding ADF Task Flow Page Flow Scope Lifetime

I would say its a bit confusing to understand - how long objects stored in Page Flow Scope really reside in memory. This is a reason I implemented small sample application and did a test. Summary for the results (see detailed description below):

1. Every ADF task flow instance is granted with its own Page Flow Scope

2. Page Flow Scope is not destroyed when you navigate away from the task flow, unless you use Task Flow Return activity and finalizer is invoked

3. You can access previously left Page Flow Scope only by using Task Flow Return activity

This allows me to presume that is not really good to have many small ADF task flows in the system, as theoretically there will be a lot of wasted Page Flow Scope entries, especially when navigating without retuning back. On contrary, when using larger ADF task flows and less of them - there will be less Page Flow Scope memory wasted - since less different Task Flows opened. On other hand, you should not implement just one big task flow - there must be proper reuse on design time, proper architecture requires clever separation into task flows.

There is nothing wrong in using multiple small ADF task flows, in this post I'm pointing out about lifetime of Page Flow Scope. You should clearly understand - Page Flow Scope is not destroyed when navigating away from ADF task flow. You should use shared Data Control as much as possible and avoid storing too much of temporary data into Page Flow Scope and pass it across different ADF task flows.

This is very true for UI Shell type of architecture - many task flows are opened from the menu, without really closing them. You should be aware of this and store variables in Page Flow Scope when its necessary only.

Sample application is available for download - PageFlowScopeApp.zip. It implements two ADF task flows. Task flow A contains one fragment, task flow B call and return activity:


Task flow B contains one fragment, return activity. There is one trick here - task flow B contains a call to calling task flow A. This is done on purpose, to simulate second instance for the task flow A:


Task flow A defines input parameter - backRendered. This is needed to distinguish, if task flow instance is opened from task flow B or no:


Task flow A call from task flow B sets parameter value:


Based on this parameter value, we can render components conditionally in task flow A fragment. For example, Back button is hidden if parameter is not set (which means A task flow instance was created not through a task flow call from B):


Below are the steps for the test. Task flow A is loaded and fragment is rendered, here user types some text and saves it in Page Flow Scope:


Press Navigate button to open instance of task flow B:


Page Flow Scope for task flow B is created now. You are in the task flow B Page Flow Scope, set text here also:


Press Next to open second instance of task flow A, new Page Flow Scope is created:


In the second instance of task flow A - type different text, not the same you was typing while in the first instance initially:


You should notice Back button rendered, this is because of passed parameter. Now when different text was set, what would you expect to see when coming back to the first instance of the same task flow? As every task flow instance maintains its own Page Flow Scope - you should expect to see original text. Press Back button - this will navigate to calling task flow B:


Task flow B still displays previously set text - this means when you navigate away from task flow - page flow scope is not lost and remains in memory. You should keep this in mind when designing ADF task flows, implementing your forms - make sure you don't store garbage in Page Flow Scope - this may waste memory, especially when having many ADF task flows and navigating between them, without returning or opening from UI Shell. Page Flow Scope from task flow B keeps its value, press Back button to navigate to the first instance of task flow A:


Task flow A keeps its original Page Flow Scope - text value is saved and displayed:


This means - we can return back through task flow return activity and access previously initialised Page Flow Scope - it is not gone.

If you press Navigate button in the task flow A and go to task flow B - new instance of task flow B will be created with new Page Flow Scope:


If you open task flow A by task flow call from task flow B - new instance is created for task flow A, new Page Flow Scope is initialised:


Navigate back to the task flow B and from task flow B to the original task flow A instance:


You will see that Page Flow Scope of original first task flow A instance is available:

Summary - it seems like Page Flow Scope is nothing more as more advanced Session Scope extended with Hash Map. This Hash Map contains references to Task Flow instances, entries in the Hash Map can be cleared only when calling Task Flow Return activity.

Friday, September 6, 2013

Red Samurai Performance Audit Tool - OOW 2013 release (v 1.1)

We are running our Red Samurai Performance Audit tool and monitoring ADF performance in various projects already for about one year and the half. It helps us a lot to understand ADF performance bottlenecks and tune slow ADF BC View Objects or optimise large ADF BC fetches from DB.

There is special update implemented for OOW'13 - advanced ADF BC statistics are collected directly from your application ADF BC runtime and later displayed as graphical information in the dashboard. I will be attending OOW'13 in San Francisco, feel free to stop me and ask about this tool - I will be happy to give it away and explain how to use it in your project.

Original audit screen with ADF BC performance issues, this is part of our Audit console application:


Audit console v1.1 is improved with one more tab - Statistics. This tab displays all SQL Selects statements produced by ADF BC over time, logged users, AM access load distribution and number of AM activations along with user sessions.

Available graphs:

1. Daily Queries  - total number of SQL selects per day

2. Hourly Queries - Last 48 Hours

3. Logged Users - total number of user sessions per day

4. SQL Selects per Application Module - workload per Application Module

5. Number of Activations and User sessions - last 48 hours - displays stress load


6. Daily Transactions - insert, update and delete statements per day

7. Hourly Transactions - Last 48 Hours


See you at OOW'13 !

Saturday, August 31, 2013

ADF Task Flow Template Improvements in 12c

There are great improvements in ADF task flow templates in 12c release. We can use ADF task flow template based on other template and what is even more amazing - JDeveloper 12c ADF task flow diagram window displays template contents when editing actual consuming task flow. There is option to substitute activity in the consuming ADF task flow for the generic activity from the template. I'm going to explain how you can do this.

Here is sample application for ADF task flow template in 12c - TaskFlowTemplateApp.zip. This application implements following ADF task flow template:


As you can see template contains generic router activity - it check how task flow should be loaded and if new row should be inserted. There are method calls for Commit and Rollback operations, meaning no need to add Commit and Rollback operations into Page Definition, will be called directly from the task flow. Activity - fragmentView is defined, but not created, we are going to substitute if the real fragment a bit later in the consuming task flow.

There are three page definitions created for activities in the template: create, commit and rollback operations:


We can create our task flow, based on available ADF task flow template:


Here you can see 12c new feature - task flow editor displays contents from the template. This is amazing and very useful feature:


All the activities can be reused from the template. Only page fragment is substituted with the real one, meaning every consuming task flow can have its own fragment. In order to substitute the fragment you need to go to the source code mode and override activity ID from the template (fragmentView in this example) pointing to fragment you want to load in this particular ADF task flow:


Fragment can be created in the same way as in ADF 11g:


Page is loaded and user can commit/rollback through generic activity methods implemented in the ADF task flow template:

Wednesday, August 28, 2013

ADF 12c - Target Tag to Enhance PPR Rendering

There is new tag in ADF 12c called target. This tag in some use cases can substitute PPR dependencies effectively and help to avoid unwanted validation errors in data entry process. More about this tag you can read from ADF Faces 12c documentation - 8.3 Using the Target Tag to Execute PPR.

I will demo use case of LOV and dependent mandatory input text field. Selected value from LOV should update mandatory text value. With ADF 11g PPR dependency you will get validation error for required field, before LOV will be loaded - since LOV will try to refresh dependent input text even on load, not only during return.

Here you can see typical PPR dependency between LOV and input field. LOV is set with auto submit and there is partial trigger specified for input text:


We insert new row to make all fields to be blank:


Try to open LOV, validation error for dependent mandatory field will be displayed:


Let's use target tag as per documentation referenced in above link. There is no need to set auto submit and partial trigger dependencies. Only define target tag to be applied for LOV and render changes in text field:


LOV opens without triggering validation errors in required field:


Selected value is returned from LOV and set for dependent text field automatically:


Placeholder - another new feature in ADF Faces 12c. We can provide help text describing empty field:


This is just another property for the input text component:


Download sample application - TargetRefreshApp.zip.

Thursday, August 22, 2013

ADF Essentials 12c ADF BC 'BO_SP' ORA-01086 Error

It seems like there are differences running same ADF application on WebLogic and on Glassfish runtime. These differences are minor but could cause some headache to the developers. In this particular case, I would like to describe ORA-01086: savepoint 'BO-SP' never established error. Typically this error could happen, if PS_TXN table is unavailable. However, this is not the case with ADF Essentials 12c - PS_TXN table exists and application is able to access it. 'BO_SP' error is generated when DB constraint is triggered, instead of returning DB error message - ADF Essentials 12c displays ORA-01086: savepoint 'BO-SP' never established error.

How to reproduce: set Salary attribute value to -1, there is constraint in the DB to check for positive values. Constraint is invoked, but instead of getting constraint message - 'BO_SP' error happens:


Workaround is to enable DB pooling for the Application Module, by setting Disconnect Application Module Upon Release property:


This is recommended setting for ADF BC performance and Data Source connections usage optimization: Stress Testing Oracle ADF BC Applications - Do Connection Pooling and TXN Disconnect Level. Is hard to say why exactly setting DB pooling fixes 'BO_SP' error for ADF Essentials 12c, I guess is related to DB driver used in Glassfish. With DB pooling enabled, DB connection is released after request - perhaps this allows to avoid rolling back transaction to BO_SP and in turn fixes the error.

DB constraint is displayed correctly with DB pooling enabled:


Download sample application - ListViewAppEssentials.zip.

Wednesday, August 21, 2013

ADF BC Locking Lifetime and Application Module Pooling

ADF BC API provides method to lock current row, but lock lifetime can be short. Lock method issues SQL lock and locks the record for current user. If your use case is to keep lock for longer period of time, in other words to reserve record by the user until commit or rollback - this is not the method you should use. Lock issued from ADF BC can be released automatically, before user will be committing his changes. This happens when DB pooling is enabled or when there are more concurrent users than AM pool can handle. If you want to make sure that record will be reserved by the user for certain period of time, you must implement custom flag column in the DB and update it separately.

In this post I will demo, why you should avoid using ADF BC lock method to reserve current row by the user. Here you can download sample application - LockApp.zip.

VO implements a custom method exposed to the Data Control, where ADF BC API lock() method is called for current row - this issues SQL lock in the DB for current row:


User A opens ADF form, selects record with ID = 102 and invokes our method to lock the record:


We can see SQL statement executed in the DB - lock is set successfully:


User B opens ADF form, selects record with ID = 102 and invokes lock method - error is generated. Since user A still holds a lock:


We can see this from SQL log - lock attempt was not successful:


Lock remains for user A only in perfect scenario. In real life, when more users will be accessing your system, at some point AM pooling will start working and AM instances will be switching between users. When AM instance is switched, DB connection is reset and current lock will be lost.

In order to simulate loosing of lock, I set Referenced Pool Size = 1. This means AM will support only 1 user, if there will be more users - AM pooling will be working and AM instance will be shared between users:


User B can set a lock now, even before user A releases his lock. This means user A will be loosing reserved row before doing a commit/rollback:

Friday, August 16, 2013

WebCenter Portal - New Name for WebCenter Spaces in 11.1.1.8

There is a name change in WebCenter with the recent 11.1.1.8 release. WebCenter Spaces is not a fancy name anymore, Spaces is renamed to Portal. Simply speaking, if you are running Spaces - means you will be running now WebCenter Portal. On other hand, if you are running custom application built with WebCenter Portal Framework - this is also a Portal, just custom made.

WebCenter Portal (previously Spaces) UI is improved in 11.1.1.8 and performance wise is quite well responsive. Here is main login screen:


WebCenter Content access works from WebCenter Portal only if Content Server is configured with Folders_g component, it still doesn't work with new FrameworkFolders:


In terms of UI - all popups are removed from WebCenter Portal interface, this makes UI look cleaner. For example, preferences can be edited now in the same window, without opening separate popup:


There is Portal Builder wizard - central place to import/export and manage portals:


Portal template grouping and description is more user friendly: