Wednesday, August 24, 2011

Proactively Controlling ADF Query Execution with Estimated Row Count

In ADF BC we can configure how many rows VO should return, however in the background it still will execute entire SQL statement without attaching rownum < X to it. We can prevent this by overriding executeQueryForCollection method and checking estimated row count, before invoking actual SQL statement:


As you can see, if estimated row count is higher than expected limit - we are throwing our custom JboException. This exception is handled in overriden DCErrorHandler class and reported nicely to the user:


You can declare your custom DCErrorHandler class through DataBindings:


VO contains View Criteria, where we are checking for Salary attribute to be > X. Criteria attributes are set to be selectively required as well, to prevent blank searches:


Blank searches will be restricted:


If user enters such criteria, which will bring result set exceeding predefined limit, application will terminate SQL execution and show warning message to the user:


In case if search criteria brings less results than predefined limit, SQL is completed successfully:


Download sample application - ADFProactiveQueryPerformance.zip

Sunday, August 14, 2011

Further Customizing WebCenter PS3/PS4 RSS Task Flow - RSS Items List

I have received request from blog reader, based on my previous blog post - Extending WebCenter 11g PS3/PS4 ADF Task Flows - RSS Example. Standard WebCenter PS3/PS4 RSS task flow is missing one very important property - number of RSS items to be rendered in the list. Request was about how to add such property and extend existing RSS task flow.

Download sample application, it extends WebCenter RSS task flow through seeded MDS customizations and provides ability to specify number of RSS items to be rendered - EnterprisePortalApp_v6.zip.

There is no option to add new RSS task flow parameter with seeded MDS customization, so we should follow different approach. What we can do is to append RSS feed URL with number of RSS items we want to render. I will describe below, how to customize standard WebCenter RSS task flow, in order to be able to append this property to RSS feed URL. For example, if we want to render 3 items, we will append ?rss=3:


For 7 items, append ?rss=7:


For 10 items, append ?rss=10 and so on:


Two RSS feeds are rendered, using extended WebCenter RSS task flow, different number of RSS items (3 and 7 as it was defined above):


Another RSS view, with 10 items as defined above:


How we can extend WebCenter RSS task flow? For basic steps and JDeveloper configuration, follow this blog. Once you understand basic steps, we can move forward. Let's define managed bean in request scope, it will act as RSS helper bean and will be used to parse RSS feed URL:


This bean defines two methods. GetRSSFeedLocation() method is to parse RSS feed URL and remove all custom parameters - otherwise original WebCenter RSS task flow functionality will not work. GetRSSItemsNum() method is to retrieve number of RSS items to be shown:


Once we have our custom methods in place, as per previous blog post - ensure that seeded MDS customizations are enabled:


Switch to Customization Developer mode, we will modify WebCenter RSS library:


Make sure site level customization context is enabled:


First customization we should apply is for RSS link:


Make sure that RSS destination is set to point to RSS feed location retrieved from our RSS helper bean:


In order to control how many items we want to show in RSS list, we should change original RSS task flow implementation and switch af:table component with af:iterator:


Make sure that Rows property for af:iterator point to our RSS helper bean method - it will parse RSS feed URL added parameters and return how many RSS items should be shown:


Page definition for RSS viewer, contains method which constructs RSS items list. RSS feed location URL must be changed here as well to point to custom RSS helper bean:


In order to review applied customizations, you can go to ADF Library Customization package and expand it:


You will see applied customization for page definition file of RSS viewer, RSS list construction method:


RSS viewer UI customizations are stored in MDS as well - table switch with iterator:


RSS link customization, to retrieve RSS feed URL from custom RSS helper bean:


Wednesday, August 10, 2011

How to Control Long SQL Execution Time in ADF BC with VO Timeout

Who likes, when ADF screen hangs on long running SQL query? I guess no one, so today I will describe how to take control on long running SQL queries and bring ADF screen back to life. ADF BC allows to set VO query execution timeout, we can apply this approach to limit SQL query execution time and make it predictable.

We need to simulate long running query, for this purpose I have created PL/SQL function with conditionally infinite loop. Based on function parameter, if parameter value is greater than 0, loop is terminated. This function is simulating both cases - long and fast running queries:


PL/SQL function code, you can find it inside sample application, Model project. In order to run sample application (ADFSQLTimeoutSample.zip) you can compile given PL/SQL function inside HR schema:


We can define new transient attribute on VO level to invoke PL/SQL function (Query Expression) with infinite loop and slow down entire VO query:


VO query statement to be executed:


PL/SQL function accepts input parameter, this parameter is initialized from View Criteria bind variable, but for default VO query execution we need to make it to be required - so SQL query will not fail, when running with empty bind variable:


Because bind variable is marked as Required, it will appear in the UI, so let's set Display Hint = Hide:


We have View Criteria, it will be used to execute search operation and assign bind variable value (Salary):


Thats almost it about VO, AM contains one custom method, this method will be used to set VO query execution timeout limit:


VO query timeout execution limit is set for VO instance, by calling setQueryTimeOut(milliseconds) method:


It is important to catch SQL exception inside executeQueryForCollection method, defined inside VO implementation class. If we don't catch exception inside this method, once timeout will happen - UI will be broken. Exception will be handled by code and reported by JboException that will be rendered in UI:


On controller layer, bounded ADF task flow should invoke default Method Call, it will set query timeout for certain VO instance (as described above):


Sample application is set with maximum VO query execution time to be 6 seconds (6000 milliseconds = 6 seconds * 1000). This means, if query will be running longer than 6 seconds, it will be terminated and control will return back to the user.

Here I'm doing a test now, search is done without specifying value for bind variable (Salary), this means PL/SQL procedure will enter infinite loop. However, because query execution timeout is defined for 6 seconds, it will stop and inform user about terminated long running query:


Provide value for Salary field, we will not enter into infinite loop and results will be returned:


With results rendered, lets try again to execute infinite loop. Again long running query will be terminated nicely:


Let's do a search again, including Salary value - results are returned:


If we would not use query timeout, it would run forever (or at least as long, as it needs to run) and consume all server resources:


Monday, August 8, 2011

Solving WCUserProfile Class Loader Error for WebCenter PS3/PS4 ADF Applications

While helping to migrate several WebCenter applications to WebCenter PS3/PS4, several times I saw same issue related to WebCenter User Profile - WebLogic Class Loader was failing to load WCUserProfile class. Symptoms: when opening any WebCenter task flow with embedded User Profile functionality, it throws loader constraint violation: loader (instance of weblogic/utils/classloaders/GenericClassLoader) previously initiated loading for a different type with name "oracle/webcenter/peopleconnections/ profile/WCUserProfile" error:


In both cases, when I looked through weblogic.xml configuration file available in WEB-INF folder, I found that "Prefer loading classes from WEB-INF" setting was set:


This is not default setting for WebCenter applications, developers usually are setting it themselves for class loading optimization purposes. It prefers to load local WEB-INF classes, instead of global WebLogic domain registered classes. While this setting works well with pure J2EE applications, its mixing WebCenter classes and prevents correct class loading. You should be careful, when changing weblogic.xml settings.

Make it default:


With "Prefer loading classes from WEB-INF" = false, WCUserProfile class is loaded correctly, profile information is returned successfully:


If you want to test WCUserProfile class load error with WEB-INF classes = true, download sample application - WebCenterUserProfileApp_v2.zip.

Thursday, August 4, 2011

ADF Dialog Framework and ADF Task Flow Re-Initialization

This post is targeted for ADF beginners, I was discussing today in the office with developers who are just starting with ADF. Its always interesting to see new developers perspective, how they understand framework and what questions they ask. One of the questions I got was about how to reset shuttle component rendered inside ADF dialog framework. By default, ADF task flow rendered inside dialog framework is set to share Data Controls with calling ADF task flow - this preserves statefull state and keeps selected shuttle values. The question was - how we can re-initialize ADF task flow, each time when dialog windows is being opened. We should set ADF task flow rendered inside dialog to be isolated and not to share Data Control with calling task flow - this will force re-initialization of the dialog. We also should explain to new developers to be careful and not to overuse this setting, because it can break transactional logic, use more application module connections than expected, etc. General rule - use isolated scope, when you really need to use it and it doesn't conflict with application logic.

Download sample application - ShuttleAccessApp_v2.zip.

This sample contains landing ADF task flow, implemented as ADF region with fragment. It calls ADF dialog framework to render ADF task flow with pages:


Dialog page is opened, shuttle component is rendered - user selects several items:


Now if we close and then reopen same dialog, shuttle component will keep previously selected values. Depending on use case, may be its what you need, but sometimes you would need just the opposite - each time dialog is opened, it should be re-initialized.

Open ADF task flow, which implements dialog element:


Go to Behavior section, Transaction group and uncheck "Share data controls with calling task flow" - this will make ADF task flow to run in isolated mode:


Run application again, select values from shuttle component:


Close/open dialog window - shuttle will be re-initialized: