Sunday, September 29, 2013

Conditional Task Flow Activation in ADF 12c/11g

I will talk about tabs and ADF regions. Depending on the use case, you may want to ensure always only one region is loaded - the one which is displayed. If user opens another tab - region from previously open tab should be destroyed. We can achieve such functionality with combination of conditional region activation and ADF task flow isolated scope. Every time when different tab will be opened - ADF will open referenced region as the first time, data will not be cached.

Feel free to download sample application this post is based on - The key part is to enable conditional activation for every region included into tabs, see here example based on EL:

Every tab must have property listener defined to set tab identifier, the same is used from Page Definition EL to conditionally activate currently displayed region:

Region will be deactivated successfully, only if Isolated data control scope is set. Make sure Isolated scope is set for every region:

Deactivated region custom resources should be cleaned through finalizer, Page Flow Scope is cleaned along with Data Control entry, and AM instance - automatically:

Let's open one of the tabs from the sample for the first time - Employees:

Employees data is fetched from DB initially:

Go to the first tab - Departments and then open Employees tab again:

You will notice Employees data fetched again, as region was created from scratch, as it was destroyed before:

This approach could work as optimization for some of the use cases, when you don't want to hold data for the long time, when user is not working with the region from inactive tab.

Tuesday, September 24, 2013

Enabling UI Shell 12c/11g Multitasking Behavior

The main goal of this post is to describe how to enable multitasking functionality in out of the box UI Shell template for ADF applications. Different UI Shell tabs could run different transactions and allow user to commit/rollback data in the scope of individual tab. Every UI Shell tab runs different ADF task flow loaded from the menu.

Here is sample application, enabled with multitasking UI Shell - This application is built with single AM module, serving three VO's - Departments, Employees and Jobs. There will be separate ADF task flows, for each of these data objects, loaded in UI Shell tabs. AM module:

There is single data control defined:

Perhaps you would wonder - how this could work in multitasking environment and run multiple transactions, as there is single AM. This would work with ADF isolated task flows, as for each ADF isolated task flow, there is new AM instance created on runtime automatically. As there will be three ADF isolated task flows, one per VO - there will be three (at least three) AM instances created on runtime. One AM instance per ADF isolated task flow:

This is a key part to enable multitasking in UI Shell - make sure to use ADF isolated task flow loaded from the menu.

Firstly, let's run ADF task flows in UI Shell with default - shared mode. Two tabs are opened, modify Department Name in the first task flow:

Go to the second tab and modify First Name:

Press Save in the same tab - Employees. Check the log and you will see that data from both tabs (ADF shared task flows) was commited:

This is not what we want, ideally only data from current tab should be commited. To achieve that, go and set Isolated mode for the ADF task flows (if using ADF task flow template, this can be done centrally):

With isolated mode enabled, when you open new UI Shell tab and load ADF task flow:

New AM instance is created automatically, meaning new transaction is assigned for the ADF task flow loaded in UI Shell tab. We can observe new AM instance creation from the log:

With isolated mode turned on, changes made in UI Shell tabs are commited only for currently active tab:

Even if there are changes made in multiple tabs, changes only from currently active tab are commited. We can observe this from the log - commit is executed for currently active tab AM instance only:

To prove this, we can open second UI Shell tab, where changes were made previously - press Cancel and changes will be reverted:

Multitasking is working, but we need to test another aspect - validation handling. Ideally user should be able to navigate between UI Shell tabs, without being blocked by validation errors. When commiting data in active tab, there should be no validation errors displayed from other UI Shell tab.

Go to the first UI Shell tab - Departments and press Create button to insert new record:

Without typing any data, try to go to the second UI Shell tab - there will be validation errors reported and user will be blocked in the current tab:

In order to resolve this and allow navigation to the different tab, we need to set Immediate = true property for the tab item. This is UI Shell, you could get source code and modify it. This would require change UI Shell library in your project. There is another way - use MDS Seeded Customization to modify out of the box UI Shell, this is what I'm using in this sample application.

Enable MDS Seeded Customization for the project in ADF View section:

Don't forget to define SiteCC class in adf-config.xml, this class handles site level customizations global for all users:

To perform actual MDS Seeded Customization, switch JDeveloper to the Customization mode:

Once JDeveloper restarts in Customization mode, select Show Libraries option for your application, this will list all the libraries attached:

You can go and browse through the library contents, in this example - Oracle Extended Page Templates (it contains UI Shell). Open template page - dynamicTabShell and set Immediate = true for the tab item, this would allow to switch between tabs ignoring validation errors in the current UI Shell tab:

JDeveloper generates new file - MDS Seeded Customization file, this is where customization is stored and applied later on runtime:

Let's repeat the same test - insert new record in Departments tab:

We can navigate to the different UI Shell tab, but there are validation errors rendered from the first tab, when trying to submit data in the current tab - not good:

This can be fixed with a hint from my previous blog post - Skip Validation for ADF Required Tabs. You should set SkipValidation = true in the main page definition, the one which implemented UI Shell page:

It works now - data from second tab can be saved successfully, independently from validation state in the first tab:

Go to the first tab, you can see there are validation messages available. These messages are displayed in the scope of currently opened tab only:

One more good thing, I want to share with you - closing ADF task flows in UI Shell. When tab is closed in UI Shell, ADF task flow is destroyed automatically and finalizer is invoked, where you could release custom resources used by the ADF task flow. Closing tab in UI Shell:

Finalizer is invoked - we can see this from the log:

Finalizer must be defined in the ADF task flow properties:

Finalizer bean is defined in the same ADF task flow, request scope:

Tuesday, September 17, 2013

ADF Query Saved Search in ADF 12c

ADF Query Saved Search functionality exists starting from ADF 11g - Persisting Query Criteria Results Across Sessions with Oracle MDS. Same works in ADF 12c, and more - from UI point behaviour improved. There are nicer and cleaner dialogs prompting user to save search after changes were applied. You need to remember few tricks to enable Saved Search functionality, I will list all of them in this post.

Firstly goes quite obvious step - enable user customizations across sessions using MDS in ADF View configuration. With this setting, application is enabled to store user personalizations into MDS repository (it can be file system or DB):

It is important to enable ADF Security, as user personalizations must be stored for every user under user name context. MDS engine retrieves user name from ADF Security automatically. Screen to enable ADF Security:

One of the last bits - open adf-config.xml and in MDS section specify UserCC class from ADF library:

Specifically for ADF Query Saved Search functionality, make sure to add persistence config into MDS configuration section:

I noticed, when running MDS enabled application for the first time in 12c environment, it may fail with error: metadata store mapped to the namespace / BASE DEFAULT is read only. This can be fixed by adding MDS store class into config. For example, if you are using file store, define FileMetadataStore class as per this example:

Different class should be used in case when MDS repository is created in DB: oracle.mds.persistence.stores.db.DBMetadataStore.

Here how it looks on runtime. Let's assume you go to Advanced mode and add new query field (Email in this example). On the next action, ADF Query is going to ask you one time, if this change needs to be saved:

If you decide to save ADF Query changes, there is nice dialog to provide customization name, set it to be activated by default and executed automatically without pressing Search button again:

Saved search personalization is available in the list and can be selected any time:

Personalization is saved and available after logout/login - it renders added field and remembers entered criteria value:

Saved search personalization can be easily removed through ADF Query dialog:

This functionality is very important for the users, as it allows to perform search faster without entering parameters again and again. It improves application performance, as search is executed with parameters from the start, limiting results list.

Sunday, September 15, 2013

Dynamic Task Flow Template Actions in ADF 12c/11g

This will be update for my previous post - ADF Task Flow Template Improvements in 12c, describing how to use dynamic actions in ADF task flow template. Similar dynamic actions can be applied in ADF 11g, this is not limited only to 12c. Dynamic actions allow to build completely reusable ADF task flow template and use it for common use cases, without implementing same actions again and again.

Updated sample application -, is improved with new parameters defined for ADF task flow template. There are two new parameters added - dataControlName and iteratorName, these parameters allow to pass current Data Control Name and Iterator Name for the task flow dynamically:

Create, Commit and Rollback actions are linked with Page Definition files, we can change underlying ADF bindings to be retrieved dynamically based on ADF task flow template parameters:

Action binding for CreateInsert is updated to use dynamic Binds and DataControl properties from parameters:

Action binding for Commit is updated to use dynamic DataControl name property:

Action binding for Rollback is updated to use dynamic DataControl name property:

Region must be configured to pass Data Control and Iterator names for ADF task flow template to be able to provide dynamic actions. These names in real use case scenario can be loaded from DB along with the menu structure:

Sample application is configured to open form in Create mode initially, dynamic action works perfectly:

User can press Undo and navigate to Edit mode - change one of the fields:

Save changes to the DB with dynamic action from ADF task flow template: