Monday, February 2, 2015

One Application Module to rule them all?

I was called to help on an ongoing ADF project
There were only one application module.
It is live in production for the past 2 years with around 20000 concurrent users at peak times
It has around 200 view instances.

So I ask:
Me: why only one?
Response: In order to have just 1 connection per user.
Me: Ok, but that could be done by other means
Response: Ok but if not one, how many? Why not only one?

...I had seen various posts in the net, so I took a look again.
I see an old post from Frank that actually suggests one root application module and many nested.

I also see a more resent episode on ADF Architecture TV from Chris.
He states that this is a wrong question and depends on the requirements but actually implies that in most cases it could be done with only one root application module and Task flows transaction management.

So, why not only one root application module (even with many nested)?
It seems to me similar to the question ‘why not only one java class (even with many nested classes)’.
Apart from the obvious:
  • The additional ‘Shared’ module that is suggested for static lists for better performance
  • The Implementation class of the module that will be huge.
  • The frustration to find out which view objects are used in which cases.
  • The  conflicts resolution when many developers works on the same module
Some additional reasons in order not to use only one Application Module
  1. Heavy Rollback operation. When rollback is performed all initiated view objects of the application or nested application modules are requeried by default.
  2. Heavy passivation - activation. Similar to rollback all initiated view objects will be passivated-activated by default.
  3. Handle errors after post. In order to handle errors after posting data there is an application module parameter bo.txn.handleafterpostexc. When this parameter is set to true then the related application module performs passivation before each transaction in order to perform activation in case of exception. I am not sure how and if this works on nested application modules.
  4. In case you want to expose some functionality as web services, a single Application module will create a single web service that will be heavy and coupled. I am not sure how this work with nested application modules.

Alternatively I have used the following approaches with numerous application modules and minimizing the database connections at the same time:
  1. The ‘do connection pooling’ approach
  • 300 root application modules
  • No Task flow transaction management 
  • Set application module properties: jbo.doconnectionpooling="true" and jbo.txn.disconnect_level="1"
With this setup we had less than 5 active connections for 100 concurrent users in production. 

According to the documentation this has a performance overhead for getting and releases the connection each time an application module use it. Yet it is recommended when minimizing the database sessions is a priority.
       2.  The ‘Use existing transaction’ approach
  • numerous root application modules
  • Task flow transaction management with a main task flow that always start a new trasactions and regions that ‘Use existing transaction if possible’
  • The main task flow has one application module that logicaly is used as root, the regions have other application modules that are automatically nested according to usage.
This setup has typically 1 connection per user. Caution is needed on commit and rollback in order for the transaction not to be lost from the main task flow (i.e. use DataControlFrame commit and rollback)

So in my opinion it is not a good practice to have only one application module unless you have only 1 simple business use case.


  1. Hi Michael

    Hope you're well, good to see the AM pooling discussions continues on.

    Regarding your comments on the documentation, as you can guess it hasn't been updated for sometime. Thanks to some well needed prompting from Andrejus & Florin our doc teams are in the process of updating the recommendations.

    Regarding my YouTube video, I'll have to say I feel like I'm being misquoted. In that video we discuss 4 different scenarios and at no point do I infer one and only one solutions fits all! (One size doesn't fit all rings a bell!)

    Only the 1st scenario really considers 1 root AM, it was discussing *transactions* not connections, and to be honest a diligent use of isolated data control scope would address in part your number 1 & 2 concerns. Not inferring it's 100% perfect, & there are different ways to skin a cat, but the 1st scenario was addressing a reason why people used to split root AMs, not have 1 as per the premise of your blog here.

    Scenario 2 & 3 are outliers & not relevant to the discussion here.

    Luckily I see with your second recommendation, it's inline with my 4th scenario & solution, we all agree and can face each other again politely in the virtual corridors without muttering "I'll show you an AM pool you won't forget pal!" ;-) For anyone reading this comment you can explore the further videos on the ADF Architecture TV that considered the connection sharing behaviour of AMs:

    Putting aside the number of root AMs & considering their tuning options which you've recommended, as Florin has posted to the EMG more recently, there's a lot of scope for customers with non clustered ADF apps to tune these parameters. Oracle's tuning recommendations are heavily skewed to assume the application is clustered, & therefore activation/passivation is a necessary (dare I say it) evil. Point being your suggestions around tuning the pool are good ones especially if you start with customers/developers understanding there isn't a 1 size fits all. Too many discussions I find start with taking fault with the recommendations and explaining backwards without covering the basics, which leaves anyone without strong knowledge of the options floundering what is being said & just assuming everything applies to them.

    Hmm, I seriously should of trade marked that quote.

    I gotta question though, the point of having 300 root AMs at "design time"? Is that what you meant rather than runtime? So that's 300 root AMs that at design time can have settings messed with by junior programmers? 300 potentially with mis configured connections (it only takes 1 to screw with your day)? Duplicate code? 300 AM pools at runtime? 300 AM pools to monitor at runtime (in 12c only)?

    Ok, Im guessing your number 300 was an exaggeration, & you conclude with the case for more than 1 and I think that's reasonable if we again agree there's more than 1 way to solve this. But in all cases there is a need for moderation, so the 300 case may be overstating it, particularly for beginners who could accidentally go to such extremes without knowing the implications.

    Btw, what would be a great blog is how you helped the original customer, keen to hear how you injected more DT root AMs while not breaking logical transaction boundaries in the app that the original developers assumed? Was the app logically broken into separate logical areas? Or were they already using isolated data control scope?

    Thanks & regards,


    1. Hello Chris,

      Thank you for the extensive and comprehensive comments.

      Sorry for misquoting your YouTube video. I understand that the scope was different. I was just looking for evidence that having only one application module is not the correct way to go in large projects.

      Concerning your questions about 1 option and 300AM. I was not exaggerating. This was a design decision on the first 11g project that we worked together with Andrejus and Florin. It is still live in many customers with that configuration.
      The idea was to have 1 Application module for each Form (oracle forms migration) and no nesting since the old forms had individual connections...

      >300 root AMs at "design time"? Is that what you meant rather than runtime?
      No there could be 300 root AM at runtime potentially.
      Actually this is a package used by many customers and users and not all users use all modules. So there could be 2 to 20 root application modules per user.

      >AMs that at design time can have settings messed with by junior programmers? 300 potentially with mis configured connections (it only takes 1 to screw with your day)?
      Yes for that reason ‘Quality Checks’ tools were implemented and build scripts for the AM and connection configuration.

      >Duplicate code?
      Yes, even though there is a shared Model with many components, there is a lot of duplicate view objects, code and pages (that could be prevented with a different design)
      In any case if 1AM is not good and 10 is ok for a common application then 300 could be the case for a very large one.

      Still I also prefer the second option. Yet in this case if you have too many concurrent users the number of database connections could still be a limiting factor.

      Concerning your questions about the ‘Original Customer’; I managed to convince them to develop some new functionality as a different application with the option 2 approach, but they are very concerned for the effort and impact of changing their core approach.

    2. We have chosen Oracle ADF in our company for one of our projects. Sadly, this proved to be a big mistake. I personally have used Oracle products, in particular their DB, but as far as fusion middleware is concerned, I would advise you to stay away from it. ADF was by far the worst framework I have ever used as an architect. Some of its features I noticed are: very complex, Oracle just "invents" or forces some development approaches that have been proven as a bad practice by the Java community years ago. ADF is very slow compared to other frameworks. With being slow I mean ADF pages run slow. The reason for this is extremely complex generated html and javascript. You can check this by opening up Firebug and inspecting the generated looks like something from the 90s...Terrible. Not to be overly pedantic, but ADF pages have huge amounts of validation errors causing problems in making them run on all browsers. The architecture of ADF is, in my view, messy. Struts2 for example is a much cleaner framework which makes it very easy to integrate it with 3rd party libraries such jQuery, etc. Oracle advocates ADF as an MVC framework but frankly I failed to see the actual MVC architecture there. ADF uses its own javascript libraries, which are huge, practically impossible to modify, unoptimized and slow in comparison to others such as jQuery or Prototype. The emerging trends in J2EE are lightweight pluggable frameworks that are easily integrated with other tools such a Spring for managing dependencies, jQuery for scripting, CC for continuous integration. ADF is a heavy-weight tightly-integrated framework with other ORacle tools, which makes it very difficult to use it any other way than Oracle devised.

      Not to mention the development tools that you are forced to used when developing ADF - the JDeveloper which is very buggy and crashes regularly. Developing in Eclipse is problematic, because ADF has numerous "specific" files which JDeveloper generates automatically.

      All in all...ADF was a huge disappointment for us. We spent months messing with it, when finally our client decided the application was too slow and difficult for them to support it and the cancelled it altogether.

      Based on my experience i can only say stay away from it. Choose one of the more supported and architecturally clean solutions such as Struts2 or Spring.

    3. This comment has been removed by a blog administrator.

  2. thank you for your comments 8y9o8ouou,
    For start a real name would be useful for people that put their points on the table and want to be accountable.
    I have seen many projects fail for many reasons but usually not because of the tools.
    I have been in many projects, and ADF have not failed no matter the complexity or size of the project as it is discussed above.
    Still we always want more as it is the human nature...

  3. 2. The ‘Use existing transaction’ approach doesnt work in 11.2 and 12.1.3 please give me demo! thanks!

    select t.LOGON_TIME,t.OSUSER, t.* from v$session t order by t.LOGON_TIME desc;

    i use this sql to see the db session! thanks