Friday 29 July 2011

Task Flows: Sayonara automated nesting of Application Modules JDev 11.1.2.0.0?

-- Post edit --

Any readers of this post should also read the following follow-up post.

-- End post edit --

In a previous blog post I discussed the concept of automated nesting of Application Modules (AMs) when using Bounded Task Flows (BTFs) with a combination of the transactional options Always Begin New Transaction, Always Use Existing Transaction and Use Existing Transaction if possible. The automated nesting of AMs is a very important feature as when you have a page made up of disparate regions containing task flows, and those regions have their own AMs, without the auto-nesting feature you end up with the page creating as many connections as there are independent region-AMs. Thus your application is less scalable, and architectural your application must be built in a different manner to avoid this issue in the first place.

This automated nesting of AMs is exhibited in the 11.1.1.X.0 series of JDeveloper and the ADF framework including JDev 11.1.1.4.0 & 11.1.1.5.0. Unfortunately, either by error or design this feature is gone in 11.1.2.0.0. Having checked the JDev 11.1.2.0.0 release notes and what's new notes, I can't see any mention of this change.

In turn I don't believe (please correct me if I'm wrong) there to be a section in the Fusion Guide that specifically talks about the interactions of the task flow transaction options and Application Module creation. The documentation talks about one or the other, not both in combination. This is somewhat of a frustrating documentation omission to me because it means Oracle can change the behaviour without being held accountable to any documentation stating how it was meant to work in the first place. All I have is a number of separate posts and discussions with Oracle Product Managers describing the behaviour which cannot be considered official.

In the rest of this post I'll demonstrate the changing behaviour between versions. It would be appreciated if any readers find errors in both the code, or even factual errors that you follow up with a comment on this blog please. I'm always wary of misleading others, I write my blog to inform and educate, not lead people down the garden path.

4 test applications

For this post you can download a single zip containing 4 different test applications to demonstrate the changing behaviour:

a) ByeByeAutoAMNestingJSPX111140
b) ByeByeAutoAMNestingJSPX111150
c) ByeByeAutoAMNestingJSPX111200
d) ByeByeAutoAMNestingFacelets111200

Why so many versions? My current client site is using 11.1.1.4.0, not 11.1.1.5.0, so I wanted to check there was consistent behaviour in the pre-11.1.2.0.0 releases. For this blog post I'll talk about the 11.1.1.5.0 version, but the exactly same behaviour is demonstrated under 11.1.1.4.0.

In addition I know that in the 11.1.2.0.0 release because of the support for JSPX & Facelets, that the controllers have different implementations, so it is necessary to see if the issue is different between the two VDL implementations.

Besides the support for 4 different versions of JDev, and in the 11.1.2.0.0 the different VDLs, each application is constructed in exactly the same fashion, using a near identical Model and ViewController setup. The following sections describe what has been setup in both these projects across all the example applications.

The Model project

Each application has exactly the same ADF BC setup connecting to Oracle's standard HR schema. The Model project in each application includes EOs and VOs that map to the employees and locaitons tables in the HR schema. The tables and the data they store are not consequential to this post, we simply need some Entity Objects (EOs) and View Objects (VOs) to expose through our Application Modules (AMs) to describe the AM nesting behaviour.

In the diagram above you can see the EOs and VOs. In addition I've defined 2 root level AMs EmployeesAppModule and LocationsAppModule. The EmployeesAppModule exposes the EmployeesView VO and the LocationsAppModule exposes the LocationsView.

To be clear, note I've defined these as separate root level AMs. So at the ADF BC level there is no nesting of the AMs defined. What we'll attempt to do is show the automatic nesting of AMs at the task flow level, or not, as the case might be.

In order to comprehend if the automated AM nesting is working at runtime, it's useful to add some logging to the ADF Business Components to show us such things as:

1) When our Application Modules are being created
2) If the AMs are created as root AMs or nested AMs

As such in each of the AMs we'll include the following logging code. The following example shows the EmployeesAppModuleImpl changes. Exactly the same would be written into the LocationsAppModuleImpl, with the exception of changing the log messages:
public class EmployeesAppModuleImpl extends ApplicationModuleImpl {
// Other generated methods

public static ADFLogger logger = ADFLogger.createADFLogger(EmployeesAppModuleImpl.class);

@Override
protected void create() {
super.create();
if (isRoot())
logger.info("EmployeesAppModuleImpl created as ROOT AM");
else
logger.info("EmployeesAppModuleImpl created as NESTED AM under " + this.getRootApplicationModule().getName());
}

@Override
protected void prepareSession(Session session) {
super.prepareSession(session);
if (isRoot())
logger.info("EmployeesAppModuleImpl prepareSession() called as ROOT AM");
else
logger.info("EmployeesAppModuleImpl prepareSession() called as NESTED AM under " + this.getRootApplicationModule().getName());
}
}
View Controller project

Each application has a near identical ViewController project with the same combination of task flows, pages & fragments. The only exception being the 11.1.2.0.0 applications, where the Facelets application doesn't use JSPX pages or fragments, but rather Facelets equivalents. This section describes the commonalities across all applications.

Each application essentially is made up of 3 parts:

a) A Start page
b) A Bounded Task Flow (BTF) named ParentTaskFlow comprised of a single page ParentPage
c) A BTF named ChildTaskFlow comprised of a single fragment ChildFragment

Start Page

1) The start page is designed to call the ParentTaskFlow through a task flow call.

ParentTaskFlow

1) The ParentTaskFlow is set to Always Begin New Transaction and Isolated data control scope.

2) The ParentTaskFlow page contains an af:table showing data from the EmployeesView of the EmployeesAppModuleDataControl.

3) The ParentTaskFlow page also contains a region that embeds the ChildTaskFlow

ChildTaskFlow

1) The ChildTaskFlow is set to Use Existing Transaction if Possible and Shared data control scope

2) The ChildFragment fragment contains an af:table showing data from the LocationsView of the LocationsAppModuleDataControl

The behaviour under 11.1.1.5.0

When we run our 11.1.1.5.0 application, and navigate from the Start Page to the ParentTaskFlow BTF showing the ParentPage, in the browser we see a page showing data from both the Employees VO and Locations VO. Of more interest this is what we see in the logs:
<EmployeesAppModuleImpl> <create> EmployeesAppModuleImpl created as ROOT AM
<EmployeesAppModuleImpl> <prepareSession> EmployeesAppModuleImpl prepareSession() called as ROOT AM
<EmployeesAppModuleImpl> <create> EmployeesAppModuleImpl created as NESTED AM under EmployeesAppModule
<LocationsAppModuleImpl> <create> LocationsAppModuleImpl created as NESTED AM under EmployeesAppModule
Based on my previous blog post on investigating and explaining the automated Application Module nesting feature in the 11.1.1.X.0 JDeveloper series, this is what I believe is occurring.

As the ParentTaskFlow is designed to start a new transaction, when the first binding in the page exercises the EmployeesAppModule via the associated Fata Control and View Object embedded in the table, ADF instantiates the AM as the root AM and attaches it to the Data Control Frame.

The Data Control Frame exists for chained BTFs who are joining transactions. So in this example the Employees AM is the first AM to join the Data Control Frame and it becomes the root AM. A little oddly we see the EmployeesAppModuleImpl then created again and nested under a root instance of itself. I'm not really sure why this occurs, but it might just be some sort of algorithmic consistency required for the Data Control Frame. Maybe readers might have something to share on this point?

It's worth noting the significance of a root AM unlike a nested AM, is only the root AM connects to the database and manages the transactions through commits and rollbacks. Nested AMs delegate these responsibilities back to the root AM. This is why we can see the prepareSession() call for the EmployeesAppModule.

When the page processing gets to the bindings associated with the ChildTaskFlow, within the fragment of the ChildTaskFlow it discovers the LocationsAppModule via the associated Data Control and View Object embedded in the table. Now we must remember that the ChildTaskFlow has the Use Existing Transaction if Possible and Shared data control scope options set. From the Fusion Guide this transaction option says:

"Use Existing Transaction if possible - When called, the bounded task flow either participates in an existing transaction if one exists, or starts a new transaction upon entry of the bounded task flow if one doesn't exist."

In order for the BTF to be part of the same transaction, it must use the same database connection too. As such regardless in the ADF Business Components where we defined the two separate Application Modules as root AMs (which by definition implies they have separate transactions & database connections), it's expected the task flow transaction options overrides this and forces the second AM to "nest" AM under the first AM as it wants to "participate in the existing transaction if it exists."

So to be clear, this is the exact behaviour we see in the logs of our 11.1.1.X.0 JDeveloper series of applications. The end result is our application takes 1 connection out with the database rather than 2.

The behaviour under 11.1.2.0.0

Under JDeveloper 11.1.1.2.0.0 regardless if we run the JSPX or Facelets application, with exactly the same combination of task flow elements and transaction options, this is what we see in the log:
<EmployeesAppModuleImpl> <create> EmployeesAppModuleImpl created as ROOT AM
<EmployeesAppModuleImpl> <prepareSession> EmployeesAppModuleImpl prepareSession() called as ROOT AM
<LocationsAppModuleImpl> <create> LocationsAppModuleImpl created as ROOT AM
<LocationsAppModuleImpl> <prepareSession> LocationsAppModuleImpl prepareSession() called as ROOT AM
As such regardless that the Oracle task flow documentation for the latest release says that the second task flow with the Use Existing Transaction if Possible option should join the transaction of the calling BTF, it doesn't. As can see from the logs both AMs are now treated as root and are preparing their own session/connection with the database.

The effect of this is our application now uses 2 connections rather than 1, and in turn the BTF transaction options don't appear to be working as prescribed.

Is it just a case of philosophy?

Maybe this is just a case of philosophy? Prior to JDev 11.1.2.0.0 the ADFc controller (who implements the task flows) was the winner in how the underlying ADF BC Application Modules were created and nested. Maybe in 11.1.2.0.0 Oracle has decided that no, in fact the ADFm model layer should control its own destiny?

Who knows – I don't see any documentation in the release notes or what's new notes to tell me this has changed. The task flow transaction option documentation is all I have. As such if you've relied on this feature, your architecture is built on this feature as we have, we're now in a position we can't upgrade our application to 11.1.2.0.0 without major rework.

To get clarification from Oracle I'll lodge an SR and will keep the blog up to date on any information discovered.

-- Post edit --

Any readers of this post should also read the following follow-up post.

-- End post edit --

Wednesday 27 July 2011

"The Year of the ADF developer" at Oracle Open World 2011

What's one of the worst things about attending Oracle Open World? From my point of view it's the huge amount of marketing. Booooorrrring. I'm a developer, I want to hear technical stuff, not sales talk!!

For ADF developers attending OOW in 2011 this is all set to change. Not only has Oracle lined up a number of ADF presentations during the mainstream conference, but the ADF Enterprise Methodology Group (ADF EMG) has a whole day of sessions on the user group Sunday October 2nd!

Think about it. That's a mini ADF conference just for ADF programmers! Even better it will be hosted by ADF experts from around the world to share their day-to-day ADF experiences with you, not just in a brief 1hr session, but 6 sessions in total. That's a lot of ADF content and an addition for no extra cost to your OOW tickets.

So I officially declare OOW'11 "The Year of the ADF developer".


Who have we got lined up for you? I'm glad you asked. We have such A1 ADF presenters as:

* Sten Vesterli - Oracle ACE Director, author of the latest ADF book "Oracle ADF Enterprise Application Development - Made Simple" and best speaker at the 2010 ODTUG Kscope conference.

* Frank Nimphius - Oracle Corp's own superstar ADF product manager who produces near-1000 blog posts a day, the ADF code harvests, articles in Oracle Magazine and is a top contributor to the OTN forums in assisting others write successful ADF applications.

* Maiko Rocha - part of Oracle Corp's own WebCenter A-Team who solves some of the most complex and challenging issues Oracle customers throw at ADF and WebCenter.

* Andrejus Baranovskis - ADF blogging wiz whose detailed posts on ADF architecture & best practices has shown many an ADF novice how to put together a working, optimised application using a huge range of ADF features.

* Wilfred van der Deijl - the author of potentially the most important ADF plug-in OraFormsFaces, which gives you the ability to integrate Oracle Forms & ADF into the same running web pages.

* Steven Davelaar - one of the key brains behind Oracle's JHeadstart, and a well known ADF presenter who shows how to push ADF to the extreme for productive development.

* Lucas Jellema - the Fusion Middleware blogging powerhouse from AMIS in the Netherlands, showing how to solve just a
bout any problem in the ADF and FMW space.


Excited? You should be.

But more importantly what are they presenting?


- 09:00 - Sten - Session 32460 - Oracle ADF Enterprise Methodology Group: Starting an Enterprise Oracle ADF Project

- 10:15 - Frank & Maiko - Session 32480 - Oracle ADF Enterprise Methodology Group: Learn Oracle ADF Task Flows in Only 60 Minutes

- 11:30 - Andrejus - Session 32481 - Oracle ADF Enterprise Methodology Group: A+-Quality Oracle ADF Code

- 12:45 - Wilfred - Session 32500 - Oracle ADF Enterprise Methodology Group: Transitioning from Oracle Forms to Oracle ADF

- 14:00 - Steven - Session 32501 - Oracle ADF Enterprise Methodoloy Group: Empower Multitasking with an Oracle ADF UI Powerhouse

- 15:15 - Lucas - Session 32502 - Oracle ADF Enterprise Methodology Group: Gold Nuggets in Oracle ADF Faces



All sessions will be held on Sunday October 2nd, so you need to make sure you turn up a day earlier if you only traditionally attend the main part of the conference.

All sessions are in Moscone West room 2000, though remember to check on the day in case the sessions have been moved.

I hope you’re excited as we are in the ADF EMG sessions at Oracle Open World 2011. We really hope you can attend and spread the word about what we’ve got going this year. Remember the ADF EMG is only as good as it’s members’ participation – it’s your group.

(Thanks must go to Bambi Price and the APOUC for giving us the room to hold these presentations at OOW'11).