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.