Friday, June 29, 2012

Immediate Effect for ADF Table Content Delivery

During stress load, we noticed complex ADF pages on load may produce more than one ADF passivation/activation events. This may decrease performance, because passivation/activation involves additional database calls plus ADF framework rendering functionality gets slower. We managed to debug one of such complex pages - this page was rendering many small tables in the same single page. During page load, it stress load environment, it was producing multiple activation/passivation events.

The trick was in Content Delivery setting for ADF Table component. By default this setting is set with whenAvailable value. While it works correctly, in some cases it may bring side effects for performance.  If you notice slow performance for ADF table rendering - double check Content Delivery property for ADF table. We would recommend to set it to immediate.

This is not only ADF table performance rendering, there might be additional huge side effect for system performance based on ADF table configuration. Imagine - ADF table rendering is triggering multiple activation/passivation events. In turn this triggers multiple prepareSession() method invocations. Very often we call DB PL/SQL initialization logic from prepareSession() method. If invoked PL/SQL logic is complex, it will be invoked multiple times with table rendering and this will make your system slow.

Download sample application - MultiTaskFlowApp_v2.zip.

Sample application is set with disabled AM pooling, to spot how it will be have in stress load environment:


prepareSession() is overriden in AM implementation class to track how many times AM is initialized (during activation/passivation events):


Sample application contain standard JSF page with out-of-the box readonly table component (all property settings are default):


Run sample application, it will load and invoke prepareSession() two times:


Set table ContentDelivery to Immediate - it will invoke prepareSession() only once on stress load and complete only one activation/passivation event:


Wednesday, June 27, 2012

ADF 11g PS5 Application with Customized BPM Worklist Task Flow (MDS Seeded Customization)

What is great about Oracle BPM - it offers reusable ADF Task Flows to handle BPM Worklist functionality. BPM ADF Task Flows are consumed from standard BPM Worklist application, from WebCenter and same ADF Task Flows can be consumed from custom ADF application (so, you don't need to run WebCenter for this). Here is documentation chapter, it explains all step by step how to integrated BPM ADF Task Flows into custom ADF application - Creating Custom ADF Applications with Oracle Business Process Management Workspace Task Flows.

In this article I'm going one step further and investigating how you can customize standard BPM Task Flow through MDS Seeded customization. This means you will be able to adapt standard BPM Task Flow to your specific requirements. If requirements are very custom - there is a way to access BPM Human Task functionality through Java API (topic for future posts). Additionally to BPM Worklist, I have tested access to all ADF Task Flows related to BPM from WebCenter Spaces - it all works inside custom ADF application as well (requires some customizations as well, topic for future posts).

Download basic ADF 11g PS5 application with customized BPM Task Flow - IntegratedBPMWorklistApp.zip. This application imports Worklist Task Flow, also there is custom button included - Register (suppose it takes selected task ID and calls custom ADF BC method to register task info in database):


This button - Register, is not available with standard BPM Worklist Task Flow - it was added by me, through MDS Seeded Customization applied for ADF application. Task is registered:


Firstly, let me refresh your knowledge a bit and walk trough most important steps described in documentation for including BPM Task Flows into custom ADF application.

BPM Task Flows are imported through added library - BPM Worklist Components:


Must register oracle.soa.workflow library inside weblogic-application.xml:


Include BPM Worklist ADF Task Flow, set taskFlowMode=worklist (if you set workspace, it will render same BPM Worklist task flow as in WebCenter Spaces, plus additional configurations), showViewsPanel=true (accordion on the left) and showTaskDetailsPanel=true (inline window for task details):


Thats all about including BPM Worklist into custom ADF application. Now will talk about how to customize it.

Sample application implements ADF BC and one custom method in AM Impl class - registerTaskWithDb(taskId):


This is dummy method, in real life you would call ADF BC logic from here. Method is exposed through Client Interface - means accessible in Data Control:


There is backing bean declared, it calls custom method from AM Impl. Action Listener from this bean will be invoked from standard BPM Worklist ADF Task Flow through MDS Seeded Customization:


Will cover every MDS Seeded Customization defined in sample application. BPM Worklist page contains page definition, I have customized it to include AM Impl custom method reference (because this method will be called from BPM Worklist context):


Data Bindings file is customized to include reference to HR AM from our custom application:


Task List toolbar is updated to include our custom button - Register. You should notice Action Listener points to Helper Bean:


Helper Bean is registered inside BPM Worklist Task Flow as well - this definition is stored inside MDS Seeded Customization:


MDS Seeded Customization is enabled from ADF View section on ViewController project:


ADF SiteCC customization class must be set in adf-config.xml, otherwise Site customization will not be applied:


Restart JDeveloper in Customization Developer mode:


Here how it looks BPM Worklist ADF Task Flow in customization mode:


Thursday, June 21, 2012

Radio Group List Support by ADF BC

Radio Group List is frequently used in Oracle Forms application screens. Same construct is supported out of the box in ADF BC. ADF BC together with ADF Faces UI perhaps is one of the best frameworks to modernize legacy enterprise applications and enable them for the Web. I will show you today how easy it is to enable Radio Group List in ADF 11g.

Sample application - RadioTableApp.zip, implements static VO with 3 values for Low, Average and High (L, A and H):


Main VO - JobsView, contains one transient field - Status. I'm using this transient field for demo purposes to assign Radio Group List. Transient field value is calculated using Groovy expression, it returns (L, A or H):


LOV is defined for Status field, it maps with static VO and returns Id into Status:


We want to display this LOV as Radio Group List - just set list type to be Radio Group, framework will take care for the rest:


Radio Group List is rendered for every row inside ADF table:


Sample applications doesn't process displayed Radio Group List changes, but you can do it easily based on specific use case requirements.

Wednesday, June 20, 2012

Running Pre-built Virtual Machine for SOA Suite and BPM Suite 11g PS5 on Mac OS X Snow Leopard (10.6.8)

Actually this is not about Virtual Machine for SOA and BPM Suite 11g PS5 - it works great, but rather about how to run Virtual Box on Mac OS X Snow Leopard (10.6.8). Virtual Box grants memory based on host computer settings, this means if host computer is 32-bit - you are not able to grant more than 3.5 GB - this is not enough to run pre-build image.

My MacBook Pro is 64-bit machine, it runs Mac OS X Snow Leopard (10.6.8). This OS starts by default in 32-bit mode, even hardware is capable to run in 64-bit mode. If someone runs similar environment, it may confuse you when trying to use Virtual Box - pre-built image will not take more than 3.5 GB memory. But there is a trick, during Mac OS X Snow Leopard (10.6.8) booting, press 6 and 4 keyboard buttons - it will load Mac OS X Snow Leopard (10.6.8) kernel in 64-bit mode, you will be able to grant much more memory. Read more about this on Apple support site.


From System Software Overview you can check in which mode your MacBook is running, in my case by default 64-bit mode is not enabled:




With default config, Virtual Box is able to access only 3.5 GB memory:


After MacBook reboot with 6 and 4 keys - 64-bit mode becomes enabled:


I'm able to grant required memory - 6 GB:

Saturday, June 16, 2012

Troubleshooting ADF Security 11g Login Page Failure

ADF Security 11g login page failure is fairly common problem - I'm getting questions about this time to time and facing it myself from project to project. One of the most common problems - during first page access, ADF Security redirects to login page and it starts infinite redirect loop - login page is not loaded and application is blocked. If you are getting this error, make sure Anonymous application role is granted to login page definition, this means ADF will be able to load it for unauthenticated users. Read more about it here - Things You Must Know About ADF Faces Login Page. But there is something more to this, if you are still getting infinite loop when trying to login into ADF application - I will describe today what else you should check.

ADF 11g login page failure might be happening if page definition files were refactored incorrectly. Specifically, if login page definition property - package, points to the wrong package structure. ADF Security configuration wizard - jazn-data.xml is reading page definition file location by scanning package property, not by real package structure. If this property is set with incorrect value, there are no errors during design time, but there will be runtime errors - login page will not be loaded, protected ADF pages will return unauthorized error. ADF developer may spend quite a lot of time troubleshooting this, reason for such problem is not obvious. I will try to save your time :)

Download sample application where ADF Security works and login page is loading correctly - SecurityFormLogin_v5.zip.

Let's describe it in detail - if you are facing something like this, ADF login page redirect is in infinite loop:


Go to ADF security configuration wizard - jazn-data.xml and first thing make sure Anonymous role is granted to login page:


If Anonymous role is not graned, grant it:


Now double check previous screenshot. Do you see something tricky? Please think 5 minutes and read further if you managed to spot a trick. Just joking - let me describe it.

Take a look into application package structure in the left side. You will see that page definition folder is under folder name - custom. Now take a look and check jazn-data.xml Resources section - you can see there com.redsamurai.view.pageDefs package definition. Same name is available from the source view of jazn-data.xml:


Name - custom is not included and there is no error on design time. But on runtime, login page infinite loop will happen:


In my case, developers were refactoring their project and moving page definitions into different folder - its why package structure was changed. However, not all occurrences of package naming was refactored by JDeveloper automatically - refactoring is always a tough task.

I opened page definition for login page and package property was pointing to the old folder structure without custom folder name:


Fixed it to point to the correct folder structure:


Reopened jazn-data.xml wizard screen - now it shows correct package names for page definition files, because package property was updated:


Before granting permissions, make sure to cleanup previous invalid entries. Open source mode for jazn-data.xml and delete permissions defined based on invalid page definition structure:


Grant required permissions now:


Double check it is granted correctly from the source mode also:


Login page is loaded successfully:


Protected ADF page is loaded for authorized users:


Must-Attend Oracle Event in Europe - Fusion Middleware Summer Camps–advanced partner trainings

Make sure not to miss Fusion Middleware Summer Camps organized by Juergen Kress. I can confirm - Oracle training events organized by Juergen are the best. These training events are typically very well structured and consist lots of technical information. If you are looking for no marketing, but real technical training - go to Fusion Middleware Summer Camps.

More info and registration details read on Juergen's blog - Fusion Middleware Summer Camps & advanced partner trainings.

Available seats are limited - my advice is to register fast.

Thursday, June 14, 2012

Design Mode is Broken in JDeveloper 11g R2 IDE (11.1.2.2.0)

If you are using Design mode to edit ADF Faces screens in JDeveloper 11g IDE - keep in mind that Design mode is not functioning properly in the latest JDev 11g R2 (11.1.2.2.0). It breaks when you try to display ADF Faces screen in Design mode - renders blank white. It happens randomly, but quite often. If you are not using Design mode - no problem, but I know some developers who prefer to work in Design mode while editing ADF Faces screens. If so - you should stay on JDev 11g R2 (11.1.2.1.0) or wait for the next version.

Blank screen of the death for Design mode in JDev 11g R2 (11.1.2.2.0):


But there are good news also. Wrong bean scope assignment bug is fixed in JDev 11g R2 (11.1.2.2.0). Read more about it - JDeveloper 11g R2 Bug - Wrong Scope for Managed Bean.

Tuesday, June 12, 2012

ADF Query Search and Results Form

This post is update for promised additional functionality based on my previous post - CRUD Use Case Implementation and ADF Query Search. I will describe use case to display search results, when ADF Query is implemented together with ADF Form. This is just one of possible implementations, but I believe it can be useful when planning Oracle Forms migration to ADF 11g.

You can download updated sample application - ADFPageOpening_v3.zip.

In previous version of this sample, when searching result was presented in single row. In order to see additional results, user was using Next/Previous buttons to navigate through result set. This is not user friendly:


Much better can be to open popup with multiple results after performing search operation - this will allow user to select required row from the list and see it displayed in the single record form block in the background:


There is Show More button displayed in the form block. User can open same multiple results block later using this button and select another record from the list.

If there is only one result record - popup will not be displayed and Show More button is hidden:


This logic is implemented inside overriden search action listener, where we check how many rows are in result set. If there are more than 1 row found, it will open multiple results popup immediately after search operation is completed:


There is Show More button, it opens same popup and is rendered if there is more than 1 row in result set:


All described enhancements are available with sample application - enjoy!

Thursday, June 7, 2012

CRUD Use Case Implementation and ADF Query Search

One of the most important topics to research when rewriting legacy Oracle Forms system into Oracle ADF 11g/Oracle Fusion is how to implement CRUD operations in smooth way for the new system. CRUD operations play one of the central roles for Oracle Forms and Oracle ADF applications, because most of the applications implemented with Oracle Forms and Oracle ADF are designed to process/maintain data. CRUD implementation should be efficient for usability and performance. With today post I will provide updated sample application based on old post from 2009 - Oracle ADF Tuning: Preventing SQL Query Execution on Page Load. I have improved handling of Rollback operation when executing ADF Query search operation.

Download sample application - ADFPageOpening_v2.zip.

Generally I would recommend such flow for CRUD implementation:

1. CRUD screen must have ADF Query block and CRUD operations
2. CRUD screen must be opened with applied executeEmptyRowSet() - to prevent default SQL query
3. On page load CRUD screen must insert new blank record
4. ADF Query must rollback pending changes

Updated sample application implements all 4 recommendations, it handles 4th recommendation in much better way comparing to original from 2009. With my next posts, I will provide more improvements for CRUD use case implementation - stay tuned. Below is description for current updated sample app.

As per original sample app, users would get standard ADF validation errors when hitting Search and having form with newly inserted blank row. This is logical - ADF Query would try to refresh new row and it will fail because of validation errors:


Let's look how we can fix it and implement better user experience for CRUD/Search. There are number of steps to follow how to refactor original application - I will describe now step by step.

Firstly select ADF Query component in Structure window:


With ADF Query component selected - clear ResultComponentId property value. This will prevent declarative refresh of CRUD form and will not trigger early validation for required fields - its what we need for this specific use case:


Refresh for results block will be triggered later - programmatically.

Next make sure we are using CreateInsert operation to insert blank empty row, and now Create operation (original app is using Create). With CreateInsert applied, there will be no validation errors after executing ADF Query:


Once user invokes search operation from ADF Query, we want to intercept this action and call Rollback (to clear inserted blank row). We can do this through ADF Query Listener, it can be overriden in the backing bean:


Here we have overriden ADF Query Listener code in backing bean. It checks if there are any pending transactions available and executes Rollback operation only in the case of dirty data present. Next it calls original ADF Query operation to perform Search action and triggers programmatic refresh for the results block:


It works perfectly now. CRUD screen is opened with blank row - optimized for fast page load:


User press Search button - Rollback operation is called from custom ADF Query Listener, blank row is removed and Search result is displayed: