Thursday, May 31, 2012

Don't Use Oracle's Driver (Thin XA) to Define WebLogic Data Source for ADF Applications

In recent days/weeks I'm getting multiple requests with questions of following type: I have a problem with the rollback, I'm working with weblogic 10.3.6. In my application back when I do a rollback, but at the launch of the back gives me this error - java.sql.SQLException: Statement cancelled, probably by transaction timing out and similar. People are facing this issue when they move application to production or test server, on development environment embedded WebLogic everything works fine.

But really this is not an issue at all. What happens is - WebLogic administrators define wrong data source (XA data source). Error is not reproduced on embedded WebLogic, because data source is created automatically for you in development environment. XA data source should be never user with ADF/Fusion applications because it closes all cursors upon commit. Read more here from ADF developer guide - 41.3.7 What You May Need to Know About JDBC Data Source for Oracle WebLogic Server.

Make sure to select proper driver for Instance Connections:


Wednesday, May 30, 2012

ADF 11g R2 Model Layer Validation Functionality

There is new functionality available in ADF 11g R2 - ADF Model layer validation. In the most of the cases, we define validation in ADF directly inside ADF BC, on Entity objects. Depending on the use case, not all fields rendered on UI can be based on ADF BC attributes. We can define validations inside Page Definition for any attribute, but specifically it can be useful for transient attributes defined directly in Model layer and displayed on UI. This allows to minimize Java code to control business logic validation for transient fields defined in UI. In this post I will describe how to implement UI fields to capture values for ExecuteWithParams operation and apply Model validation for these fields.

Sample application - ADFModelValidationApp.zip, is designed to demonstrate why ADF Model layer validation concept is useful. Example is based on the concept of transient variables defined in Page Definition, read more here - Page Definition Variables to Store Temporary Page Values.

There will be two validation rules defined in ADF Model for searchable Salary value:

1. Salary value must be positive for lower range
2. Salary should not exceed 30000 for upper range

I have implemented View Criteria to search based on Salary attribute in range.


As per previous blog mentioned above, in Page Definition there are two variables defined to keep values entered by the user for lower and upper ranges:


There is custom UI created to simulate Search form:


Search form is wrapped into ADF subform with DefaultCommand to handle Enter keyboard action when user wants to execute search - it will invoke Search button automatically for the user:


Subform is set with DefaultCommand property:


Small hint - if you want to render validation error inline for input field, you must define validator tag and point to the attribute validator:


Validator property should point to the attribute from Page Definition (in our case this attribute points to Page Definition variable):


Finally input field is mapped with the same attribute from Page Definition:


Now let's move to the main topic - ADF Model layer validation. We can define validation rule directly for attribute binding in Page Definition - select attribute, choose More from Property Inspector and invoke Edit Validation Rule:


I have already one rule defined, to check for Salary value to be positive:


There are other validation rule types available - Compare, Length, List, Range, Regular Expression and Required:


Here how it looks on UI. Type negative value into Salary search From field, it will trigger ADF Model layer validation rule and show inline error message:


Same is true for Salary search To field, which is compared against maximum 30000:


When validation is passed successfully, search action is executed:


Sunday, May 27, 2012

Proactively Monitoring JDeveloper 11g IDE Heap Memory

There is possibility to monitor during runtime consumed heap and permgen memory by JDeveloper IDE process. It will show consumed memory, also allows to force garbage collection. This can be extremely useful when running JDev on less powerful hardware - developer could force garbage collection, just before entire memory is consumed and JDeveloper is freezing.

This post is based on JDev 11g R2 (but same applies for other JDev 11g versions).

Its fairly easy to enable JDeveloper 11g Heap Memory Monitor, add this property to jdev.conf file (located under JDEV_INSTALL/jdev/bin/ folder) and restart IDE:

AddVMOption -DMainWindow.MemoryMonitorOn=true



You will see in the IDE lower right corner - heap and permgen memory statistics will be available, along with garbage collector button:


I did a quick test - opened one JSPX file in Designer mode. Heap memory consumption increased from 90M to 256M, PermGen from 82M to 124M:


Next I invoked garbage collection process by clicking recycle bin icon:


Heap memory usage instantly dropped to 176M:


Don't worry, memory consumption is quite stable and not growing over time. I was trying to open multiple complex pages, close and open again - IDE was acquiring and then after some time releasing memory. It was consuming around 300M - 400M heap and 200M PermGen memory, when working with complex pages/fragments and ADF BC wizards:


Maximum range for heap memory is set in ide.conf file (located under JDEV_INSTALL/ide/bin/ folder). Default value of 800M is usually enough for ADF development:


Saturday, May 26, 2012

How To Disable SELECT COUNT Execution for ADF Table Rendering

If you analyze SQL execution, you will see there is difference between ADF form and ADF table rendering. When rendering ADF form - there is one SQL statement executed, to retrieve data. Things are a bit different for ADF table - framework executes two SQL statements while rendering ADF table. First it executes SELECT COUNT to retrieve number of rows to be returned and only after that it executes actual SQL statement to bring data. ADF needs to know estimated row count, in order to render table scrollbar properly. Perhaps this part can be optimized by ADF team, they could count retrieved rows based on fact (based on SQL to retrieve rows), without executing initial SELECT COUNT. However, if you want to optimize ADF table rendering and disable initial SELECT COUNT execution - there is a way, I will describe it now (thanks to my Red Samurai colleague - Florin Marcus, who figure it out).

Download sample application - QueryOptimizationTableApp.zip.

When ADF table is rendered with default settings, it gets information from initial SELECT COUNT query about estimated number of rows - you can see that based on table scrollbar, it knows how many rows are there:


We can track executed SQL statements, both SELECT COUNT and actual SQL to retrieve data invoked:


To disable SELECT COUNT execution, go to Page Definition and select table iterator:


Open Property Inspector and locate RowCountThreshold property. Read description for this property, by default its value equal to 0. This means it executes SELECT COUNT:


You can change it to be -1, it will not execute SELECT COUNT anymore, this will allow to render ADF table a bit faster:


There will be no SELECT COUNT executed for this table anymore. But you will see the difference as well - ADF table scrollbar is not adjusted to the total number of records in the table. If you user will scroll to the end of range size - ADF will fetch next range size and scrollbar size will change. Compare scrollbar appearance with the one when SELECT COUNT was executed:


SELECT COUNT execution might be quite slow, depending on data structure - it can be good optimization technique to disable it. But as always, there is no golden rule and all depends on specific use case and requirements. Its important to know tuning techniques and apply them smartly.

We can double check - indeed, SELECT COUNT was not executed anymore with RowCountThreshold = -1:


Keep in mind, RowCountThreshold tuning property is not applied if your ADF table is enabled with AutoHeightRowsRowCountThreshold will be ignored and framework will force SELECT COUNT execution. AutoHeightRows property allows to render table height dynamically, based on current number of rows:

Wednesday, May 23, 2012

Solution for Sharing Global User Data in ADF BC

This post will describe solution how to share custom user data in ADF BC. There is a way to access HTTP session scope directly from ADF BC - Bad Practice for Session Scope Access in ADF BC, while you can follow this approach in exceptional cases, this is not recommended from enterprise architecture point of view. Mainly because you may face snow ball effect - there will be more and more ADF BC and ADF UI dependency introduced over time and at the end will make system not maintainable. Solution is generic and will cover following requirements:

1. Custom user data will be initialized for every AM instance automatically
2. Custom user data will be preserved between passivation/activation requests

Download sample application - UserDataADFBCSample.zip. Implemented solution is based on such architecture:


Where on the higher level we have user preferences variables stored in HTTP session. For each Data Control, where we want associated Application Module to be initialized with custom variables for User Data, is defined custom Data Control factory class. Data Control factory class is calling generic Application Module implementation class, where it invokes generic method to populate User Data. Every AM extends from generic Application Module implementation class - this means it gets User Data set. There are standard methods for passivation and activation overriden inside generic Application Module implementation class - this allows to preserve custom User Data between passivation/activation requests.

From developer perspective, in order to use this solution for specific AM - only one configuration thing is required - set custom Data Control factory class, the rest will be handled by implemented generic classes. Select Data Control usage from DataBindings.cpx:


Set Data Control factory class to our custom class:


I will describe now, what happens behind the scenes - how this solution works based on proposed architecture.

1. Make sure Model project is configured with Base Classes, specifically in this case with generic Application Module class (responsible for extended activation/passivation process and User Data initialization):


Generic Application Module class overrides ADF BC framework passivateState(...) method - its the place, where we store custom variables from User Data along with standard ADF BC data into PS_TXN table:


activateState(...) method is overriden as well - to initialize activated custom variables back into User Data:


Generic User Data initialization method is pretty simple in this example, it stores only one variable:


Every AM should extend from generic class. For test purpose, I have implemented custom method to print User Data entry - you will see that it will be preserved across passivation/activation requests thanks to the Application Module implementation generic class - CustomAMImpl:



2. There is custom Data Control factory class defined. This class substitutes Data Control class with our own custom class:


Custom Data Control class overrides only one method - setSessionCookie(...). This method is called by the framework only once, when Data Control gets initialized (Data Control may get initialized multiple times during the same session, if you are using isolated Task Flows (not recommended)). From setSessionCookie(...) method, we are getting instance of generic Application Module implementation class (by casting Data Provider) and initializing User Data with user preferences variable value stored in HTTP session scope. This is completely generic, because action is done through generic class without touching underlying AM for selected Data Control:


3. Time to test. You should test with AM pooling OFF - means will simulate stress test environment and force AM instance to passivate/activate on each request:


With jbo detail logging enabled, we can see that passivation request stores into PS_TXN table along with standard ADF BC data, our own custom User Data also (because overriden method in CustomAMImpl):


Tags for custom entry and other data is declared inside CustomAMImpl. There is limitation of max 10 entries for custom User Data passivation is set, you can increase it (its safer to control this, in case someone will start to enter hundreds of entries into User Data):


When fragment is loaded, based on our test - passivation/activation happens (AM pooling is OFF). With default implementation of User Data - values will be lost, but now CustomAMImpl takes care for this. Press Print Uset Data Entry to test if variable from User Data is retrieved correctly:


Variable data is printed:


4. Task Flow isolated mode. This solution works for Task Flow isolated mode:


When task flow is opened in isolated mode - setSessionCookie(...) method from Data Control class gets invoked again:


This mean, there is new fresh AM instance created of the same Application Module. But, because setSessionCookie(...) method is called - user data gets initialized for that new instance. User data can be initialized not only during login process, but during session lifetime as well.

We can test this by opening isolated task flow:


Print user data variable:


Data is printed successfully:


5. Test without passivation/activation for custom User Data. Comment out custom code for User Data passivation inside CustomAMImpl class:


There will be no custom data added into passivation package:


User data will be NULL, after passivation/activation request: