Understanding Application Module Pooling Concepts and Configuration Parameters
Oracle JDeveloper Tip
Understanding Application
Module Pooling Concepts and Configuration Parameters
Author: Steve Muench, BC4J Development
Team Date: March 30, 2006Abstract
Oracle ADF provides a sophisticated and high-performance solution for
managing pools of lightweight application module components. This article
describes the pooling behavior and the different configuration parameters that
allow you to control how the pools behaves at
runtime.
| NOTE: |
This article is valid for
ADF Business Components in JDeveloper 10g and beyond, as well as for Business
Components for Java (BC4J) in JDeveloper 9.0.4 and earlier.
|
Overview
At its most simple, an application module pool is
a collection of instances of a single application module type which are shared
by multiple application clients. For example, the
ADF
Toy Store application has an application module named
toystore.model.services.ToyStoreService. An application
module pool supporting the Toy Store demo would have one or more instances of
this application module component in it, based on the number of users that are
visiting the site.
This pool of AM instances is shared by multiple
browser clients whose typical "think time" between submitting web pages allows
optimizing the number of AM components to be effectively smaller than the total
number of "active" users working on the system. That is, twenty users shopping
the web site from their browser might be able to be serviced by 5 or 10
application module instances instead of having as many AM instances as you have
browser users.
Application module components can be used to support
web application scenarios that are completely stateless, or they can be used to
support a unit of work which spans multiple browser pages. Just imagine a
scenario where an application user needs to accomplish the task of:
- Defining the details for a new warehouse
- Adding contact information for multiple
contacts for this new warehouse
- Adding a
number of initial inventory items to this new
warehouse
Each of these steps might be
accomplished using the popular "Step-by-Step" or "Wizard-Style" user interface
that leads the user through a logical sequence of pages to complete the task,
and allows them to iterate through the steps as many times as necessary to
finish the application task. When the task is done, the user can commit
everything or cancel the entire unit of work. Since this is a web application
using the stateless HTTP protocol, implementing a sophisticated web application
that builds up pending state over many web pages requires some state management
strategy and software infrastructure to implement it. ADF application modules
provides the ability to snapshot and reactivate their pending state to XML
(stored on the file system or in the database), and the ADF application module
pooling mechanism leverages this capability to deliver a "managed state" option
to web application developers that simplifies building applications like the
example just given.
As a performance optimization, when an instance
of an AM is returned to the pool in "managed state" mode, the pool keeps track
that the AM is referenced by that particular session. The AM instance is still
in the pool and available for use, but it would prefer to
be used by the same session that was using it last time because maintaining
this so-called "session affinity" improves performance.
So, at any
one moment in time, the instances of application modules in the pool are
logically partitioned into three groups, reflecting their state:
- Unconditionally available for use
- Available for use, but referenced for session
affinity reuse by an active user session
XYZ
-
Unavailable, inasmuch as it's currently in use (at
that very moment!) by some thread in the web container.
The next
section describes the application module pool configuration parameters and how
they affect the behavior of the pool.
Setting Pool Configuration
Parameters
You control the runtime behavior of an application
module pool by setting appropriate configuration parameters. The simplest way
to assign values to these parameters is to use the application
Configuration Manager. This dialog appears when you select
an application module in the JDeveloper Application
Navigator, and choose Configurations... from
the right-mouse menu. While editing a configuration using this dialog, the
Pooling and Scalability tab shown in
Figure 1 lets you see and set the parameters described in
this document.
| TIP: |
We'll explain in the Database Connection Pool Parameters section
below why it is best practice to leave the Connection Pool
parameters in this dialog at their defaults and to set your desired values for
them globally using Java System Parameters.
|
 Figure 1: Pooling and Scalability Tab of the Configuration Manager
The values that you supply
through the Configuration Manager are saved in an XML file
named bc4j.xcfg. All of the configurations for all of the
application modules in a single Java package are saved in the same file. For
example, if you have a EmployeeReviewModule and a
BonusAssignment application module which both live in the
com.yourcompany.hr package, then the configuration
information for both of these modules will be saved in the
bc4j.xcfg file in the
./com/yourcompany/hr/common directory in your project's
source path. When your project is compiled, this bc4j.xcfg
file gets copied to the same directory in your project's out path, so that the
ADF framework can find it at runtime.
If you look inside the file,
you'll notice that each named configuration is saved in an
<AppModuleConfig> XML section in the file like this:
<BC4JConfig>
<AppModuleConfigBag>
<AppModuleConfig name="TestModuleLocal">
<AppModuleJndiName>test.model.TestModule</AppModuleJndiName>
<DeployPlatform>LOCAL</DeployPlatform>
<JDBCName>scott</JDBCName>
<ApplicationName>test.model.TestModule</ApplicationName>
<jbo.project>Model</jbo.project>
</AppModuleConfig>
<!-- Other AppModuleConfig sections repeat here -->
</AppModuleConfigBag>
<ConnectionDefinition name="scott">
<!-- etc. -->
</ConnectionDefinition>
</BC4JConfig>
Note that child elements of the
<AppModuleConfig> tag appear with tag names matching their
property values. It's also important to understand that if a property is
currently set to its runtime default value, then the
Configuration Manager does not write
the entry to the bc4j.xcfg file.
As an
alternative to specifying configuration properties in the
bc4j.xcfg file, you can also set Java VM system parameters
with the same property names. These system parameters will be used
only if a corresponding property does not
exist in the relevant bc4j.xcfg file for the
application module in question. In other words, configuration parameters that
appear in the application module configuration take precedence over parameters
of the same name supplied as Java system parameters.
You typically
set Java system parameters using the -D command line flag to
the Java VM like this:
java -Dproperty=value -jar yourserver.jar
Alternatively, your J2EE container probably has a
section in its own configuration files where Java system parameters can be
specified for use at J2EE container startup time.
| TIP: |
Many
customers adopt the best practice technique of supplying site-specific
default values for ADF configuration parameters as Java
system parameters and then make sure that their bc4j.xcfg
files do not include references to these parameters unless
an application-module-specific exception to these global default values is
required.
Using OC4J you can specify these parameters either as -D
Java system parameters on the command line that starts OC4J, or provide them —
one per line — in the oc4j.properties file and add the
-properties oc4j.properties command line flag to OC4J at
startup.
|
| CAVEAT: |
The values of Idle Instance
Timeout, Pool Polling Interval settings for
both the Application Pool and the database
Connection Pool are displayed and edited in this dialog as
a number of seconds, but are saved to the configuration
file in milliseconds. If you provide a value for any of these four parameters
as a Java System parameter — or if you hand-edit the
bc4j.xcfg file — make sure to provide these time interval
values in milliseconds!
|
AM State Snapshots and the
Internal Connection
In order to manage application module pending
work, the application module pool asks AM instances to "snapshot" their state
to XML at different times. What is saved to the snapshot is not a copy of all
data that's been queried by the view objects in the application module, but
rather a kind of "redo log" of entity cache information about what pending
entity object instances have been created, deleted, and modified, along with
some view rowset iterator bookkeeping information for view objects with active
rowsets.
If the value of the jbo.dofailover
configuration parameter is true, then this XML snapshotting
will happen each time the AM instance is released to the pool. You control this
in the Configuration Manager by the checkbox labeled
Failover Transaction State Upon Managed Release on the
Pooling and Scalability tab. The default is to have this
checkbox checked, meaning the parameter has a value of true.
If the value is false, then an XML snapshot of pending work
will only be taken on demand when an AM instance that was referenced by session
"A" had to be handed out to another session "B" before session "A", that used
it last and released it in managed state mode, came back to use it again. Those
XML state snapshots are used by the pool to reinstate the pending work that
your session had done up to the last time the AM instance was released to the
pool in the case that your session cannot end up exploiting the session
affinity optimization.
The setting of the jbo.passivationstore parameter
controls whether the XML snapshots are written to files on disk (when the value
is file) or to a BLOB column in a row in the PS_TXN table in
the database (when the value is database). The default setting for this
property is the string-value "null", which causes a database-based passivation
scheme to be used against Oracle or DB2, and a file-based passivation scheme to
be used otherwise.
While the file-based option is a little faster, unless your multiple
application server instances share a file system, then the the database-backed
passivation scheme is the most robust for application server-farm and failover
scenarios.
If you use database passivation, then the framework will
use a JDBC connection from a database connection pool for "internal connection"
instances. The internal connection credentials are controlled by the value of
the jbo.server.internal_connection configuration parameter.
Its value can be a fully-qualified JDBC connection URL (e.g.
jdbc:oracle:thin:statemgmtuser/password@penguin:1521:ORCL)
or a JNDI name for a JDBC DataSource (e.g.
java:comp/env/jdbc/AnotherConnectionDS). It is typically a
different database account than your application data. Nothing prevents you
from setting the internal connection to be using a database on a different
machine as well, if desired.
How
Many Pools are Created, and When?
There are two kinds of pools in
use when running a typical ADF web application, Application Module pools and
database connection pools. It's important to understand how many of each kind
of pool your application will create, so let's explore both kinds in
turn.
Application Module
Pools
Application Module components can be used at runtime in two ways:
- As a application module the client accesses
directly, or
- As a reusable component
aggregated (or "nested") inside of another application module
instance.
When a client accesses it
directly, an application module is called a root application
module. Clients access nested application modules
indirectly as a part of their containing application
module instance. It's possible, but not common, to use the same application
module at runtime in both ways. The important point is that ADF only creates an
application module pool for a root application module.
Nested application modules are "along for the ride", so to speak, with the
eventual root application module instance that contains them.
The
basic rule is:
One application module pool is created
for each root application module used by an ADF web
application in each Java VM where a root application
module of that type is used by the ADF controller layer.
Database Connection Pools
ADF web applications always use a database connection pool, but which one
they use for your application modules depends on whether your they define their
connection using a:
- JDBC URL (e.g.
jdbc:oracle:thin:@penguin:1521:ORCL),
or a
- JNDI Name for a Datasource (e.g.
java:comp/env/jdbc/YourConnectionDS)
If you supply a JDBC URL connection while configuring your application
module — which happens when you select a JDeveloper named connection which
encapsulates the JDBC URL and username information — then the ADF database
connection pool will be used for managing the connection pool.
If
instead you supply the JNDI name of a JDBC Datasource then the ADF database
connection pool will not be used and the configuration
parameters described below relating to the ADF database connection pool are not
relevant.
| NOTE: |
To configure the database connection pool for JDBC
Datasources looked-up by JNDI from your J2EE Web and/or EJB container, consult
the documentation for your J2EE container to understand the pooling
configuration options and how to set them.
|
Using ADF database connection pooling, we have the following basic
rule:
One database connection pool is created for each
unique <JDBCURL,Username> pair, in each Java VM
where a <JDBCURL,Username> connection is requested by a root application
used by the ADF controller layer.
Applying These Rules of Thumb to a Scenario
To better
understand these rules of thumb, let's apply them to a simple scenario. We'll
make the following assumptions:
- Your web
application makes use of two application modules
HRModule
and PayablesModule.
- You
have a
CommonLOVModule containing a set of commonly used
view objects to support list-of-values in your application, and that both
HRModule and PayablesModule aggregate a
nested instance of CommonLOVModule to access the common LOV
view object's it contains.
- You have
configured both
HRModule and
PayablesModule to use the same JDeveloper connection
definition named appuser
- In both
HRModule and PayablesModule
you have configured jbo.passivationstore=database (the
default) and configured the ADF "internal connection"
(jbo.server.internal_connection) used for state management
persistence to have the value of a fully-qualified JDBC URL that points to a
different username than the appuser
connection does.
Let's look at how many
pools of which kinds are created for this application in both a single JVM and
multiple JVM runtime scenario.
Single
OracleAS Instance, Single OC4J Container, Single JVM
If we deploy
this application to a single Oracle Application Server instance, configured
with a single OC4J container having a single Java VM, there understandably only
a single Java VM available to service the web requests coming from our
application users.
Assuming that all the users are making use of web pages that access both
the HRModule and the PayablesModule, this
will give us:
- One AM pool for the
HRModule root application module
- One AM pool for the
PayablesModule root application
module
- One DB connection pool for the
appuser connection
- One DB
connection pool for the JDBC URL supplied for the internal connection for state
management.
This gives us a total of 2 AM
pools and 2 database pools in this single Java VM.
| NOTE: |
There is
no separate AM pool for the nested instances of the reusable
CommonLOVModule. It goes along for the ride with instances
of HRModule and PayablesModule in their
respective AM pools.
|
Multiple OracleAS Instances, Single OC4J Container, Multiple
JVMs
Let's consider next a deployment environment involving
multiple Java VM's. Assume that we have installed Oracle Application Server 10g
(version 9.0.4) onto two different physical machines, with a hardware
load-balancer in front of it. On each of these two machines, imagine that the
OracleAS instance is configured to have one OC4J container with two JVMs. As
users of our application access the application, their requests end up getting
"fanned out" across these two OracleAS instances, and within each OracleAS
instance, across the two JVMs that its OC4J container has available.
Again assuming that all the users are making use of web pages that access
both the HRModule and the PayablesModule,
this will give us:
-
(1 HRModule Root AM) x (2
OracleAS Instances) x (2 OC4J JVMs each) =
Four AM pools for
HRModule, one in each of 4 JVMs.
-
(1 PayablesModule Root AM) x (2 OracleAS Instances) x
(2 OC4J JVMs each) =
Four AM pools for
PayablesModule, one in each of 4 JVMs.
-
(1 appuser DB connection pool) x (2 OracleAS
Instances) x (2 OC4J JVMs each) =
Four DB connection pools for
appuser, one in each of 4 JVMs.
-
(1 internal connection JDBC URL DB connection pool) x (2 OracleAS
Instances) x (2 OC4J JVMs each) =
Four DB connection pools for the
internal connection JDBC URL, one in each of 4
JVMs.
This gives us a total of 8 AM pools
and 8 DB connection pools spread across 4 JVMs.
As we begin to
explore the configuration parameters for the AM pools in the next section, keep
in mind that they apply to a given AM pool for a given application module in a
single JVM. As the load balancing spreads user request across the multiple JVMs
where ADF is running, each individual AM pool in each JVM will have to support
one Nth of the user load — where
N is number of JVMs available to
service those user requests. The appropriate values of the AM and DB connection
pools need to be set with the number of Java VM's in
mind.
Application Module Pool Parameters
The application module
pool configuration parameters fall into two logical categories relating to pool
sizing and pool cleanup behavior.
Pool Sizing Parameters
Table 1
lists the application module configuration parameters that affect the sizing of
the application module pool.
Table 1: Application Module Pool Sizing Configuration
Parameters
| Pool Parameter |
Configuration Parameter Name |
Description |
| Initial Pool Size |
jbo.ampool.initpoolsize |
The number of AM instances to created when the pool
is initialized.
The default is 0 (zero)
instances.
|
| Maximum Pool
Size
|
jbo.ampool.maxpoolsize |
The maximum number of AM instances that the pool
can allocate.
The pool will never create more AM instances than
this limit imposes. The default is 5000 instances.
|
| Referenced Pool Size |
jbo.recyclethreshold |
The maximum number of AM instances in the pool that
attempt to preserve session affinity for the next request made by the session
which used them last before releasing them to the pool in managed-state mode.
The referenced pool size should always be less than or equal to
the maximum pool size. The default is to allow 10 available
instances to try and remain "loyal" to the affinity they have with the most
recent session that released them in managed state mode.
|
Pool Cleanup Parameters
A
single "application module pool monitor" per Java VM runs in a background
thread and wakes up every so often to do resource reclamation.
Table 2 lists the parameters that affect how resources
are reclaimed when the pool monitor does one of its resource cleanup
passes.
| TIP: |
Since there is only a single application monitor pool monitor per
Java VM, the value that will effectively be used for the AM pool monitor
polling interval will be the value found in the AM configuration read by the
first AM pool that gets created. To make sure this value
is set in a predictable way, it is best practice for all application modules to
use the same Pool Polling Interval value.
|
Table 2: Application Module Resource Management
Configuration Parameters
| Pool Parameter |
Configuration Parameter Name |
Description |
| Pool Polling Interval |
jbo.ampool.monitorsleepinterval |
The length of time in milliseconds between pool
resource cleanup.
While the number of AM instances in the pool
will never exceed the maximum pool size, available instances which are
candidates for getting removed from the pool do not get "cleaned up" until the
next time the AM pool monitor wakes up to do its job. The default is to have
the AM pool monitor wake up every 600000 milliseconds (which
is 600 seconds, or ten minutes).
| Note: |
Value in the configuration UI is in shown/edited in seconds, but saved in
milliseconds. |
|
| Maximum
Available Size
|
jbo.ampool.maxavailablesize |
The ideal maximum number of AM instances in the
pool when not under abnormal load.
When the pool monitor wakes up
to do resource cleanup, it will try to remove available AM instances to bring
the total number of available instances down to this ideal maximum. Instances
that have been not been used for a period longer than the idle instance timeout
will always get cleaned up at this time, then additional available instances
will be removed if necessary to bring the number of available instances down to
this size. The default maximum available size is 25
instances.
|
| Minimum Available
Size
|
jbo.ampool.minavailablesize |
The minimum number of available AM instances that
the pool monitor should leave in the pool during a resource cleanup operation.
Set to zero (0) if you want the pool to shrink to contain no
instances when all instances have been idle for longer than the idle
timeout.
The default is 5 instances.
|
| Idle Instance Timeout |
jbo.ampool.maxinactiveage |
The number of milliseconds after which to consider
an inactive AM instance in the pool as a candidate for removal during the next
resource cleanup.
The default is 600000 milliseconds of idle time
(which is 600 seconds, or ten minutes).
| Note: |
Value in the configuration UI is in shown/edited in seconds, but saved in
milliseconds. |
|
| Maximum Instance Time to Live |
jbo.ampool.timetolive |
The number of milliseconds after which to consider
an AM instance in the pool as a candidate for removal during the next
resource cleanup regardless of whether it would bring the number of instances in the pool below minavailablesize.
The default is 3600000 milliseconds of total time to live (which is 3600 seconds, or one hour)
| Note: |
This property only appears in the Properties panel, not on the Pooling and Scalability Tab |
|
Database Connection Pool Parameters
If you are using a JDBC URL for your connection information so that the
ADF database connection pool is used, then configuration parameters listed in
Table 3 can be used to tune the behavior of the
database connection pool. A single "database connection pool monitor" per Java
VM runs in a background thread and wakes up every so often to do resource
reclamation. The parameters in Table 2 include the ones
that affect how resources are reclaimed when the pool monitor does one of its
resource cleanup passes.
| TIP: |
Since the tuning parameters for
all ADF database connection pools — regardless of
<JDBCURL,Username> value — will be set based on the parameters found in
the configuration for the first AM pool that is created.
To insure the most predictable behavior, it is best practice to leave the
values of the parameters in the Connnection Pooling
section of the Pooling and Scalability tab at their
default values — so that no entry for them is written into
the bc4j.xcfg file — and to instead set the desired values
for the database connection pooling tuning parameters as Java System Parameters
in your J2EE container.
In fact, to a Bug# 3678499 in JDeveloper
10g (version 9.0.5.x) database connection pool tuning parameters that appear in
your application module configuration files (bc4j.xcfg) are
inadvertently ignored and default settings are used, including the default
setting of jbo.poolminavailablesize controlling the minimum
number of instances to always remain in the pool. So in the 9.0.5.x release,
the only way to set non-default database pooling
parameters is to set them using Java System parameters.
|
Table 3: Database Connection Pool Parameters
| Pool Parameter |
Configuration Parameter Name |
Description |
| Initial Pool Size |
jbo.initpoolsize |
The number of JDBC connection instances to created when
the pool is initialized
The default is an initial size of
0 instances.
|
| Maximum Pool Size |
jbo.maxpoolsize |
The maximum number of JDBC connection instances that the pool can
allocate.
The pool will never create more JDBC connections than
this imposes. The default is 5000 instances.
| Note: |
Value in the configuration UI is in shown/edited in seconds, but saved in
milliseconds. |
|
| Pool
Polling Interval
|
jbo.poolmonitorsleepinterval |
The length of time in milliseconds between pool
resource cleanup.
While the number of JDBC connection instances in
the pool will never exceed the maximum pool size, available instances which are
candidates for getting removed from the pool do not get "cleaned up" until the
next time the JDBC connection pool monitor wakes up to do its job. The default
is 600000 milliseconds of idle time (which is 600 seconds,
or ten minutes).
| Note: |
Value in the configuration UI is in shown/edited in seconds, but saved in
milliseconds. |
|
| Maximum Available Size |
jbo.poolmaxavailablesize |
The ideal maximum number of JDBC connection
instances in the pool when not under abnormal load.
When the pool
monitor wakes up to do resource cleanup, it will try to remove available JDBC
connection instances to bring the total number of available instances down to
this ideal maximum. Instances that have been not been used for a period longer
than the idle instance timeout will always get cleaned up at this time, then
additional available instances will be removed if necessary to bring the number
of available instances down to this size. The default is an ideal maximum of
25 instances (when not under load).
|
| Minimum Available Size |
jbo.poolminavailablesize |
The minimum number of available JDBC connection
instances that the pool monitor should leave in the pool during a resource
cleanup operation. Set to zero (0) if you want the pool to
shrink to contain no instances when all instances have been idle for longer
than the idle timeout.
The default is to not let the minimum
available size drop below 5 instances.
|
| Idle Instance Timeout |
jbo.poolmaxinactiveage |
The number of seconds after which to consider an
inactive JDBC connection instance in the pool as a candidate for removal during
the next resource cleanup.
The default is
600000 milliseconds of idle time (which is 600 seconds, or
ten minutes).
| Note: |
Value in the configuration UI is in shown/edited in seconds, but saved in
milliseconds. |
|
| Maximum Instance Time to Live |
jbo.pooltimetolive |
The number of milliseconds after which to consider
an connection instance in the pool as a candidate for removal during the next
resource cleanup regardless of whether it would bring the number of instances in the pool below minavailablesize.
The default is 3600000 milliseconds of total time to live (which is 3600 seconds, or one hour)
| Note: |
This property only appears in the Properties panel, not on the Pooling and Scalability Tab |
|
Notice that since the BC4J database connection pool does not implement
the heuristic of session affinity, there is no
configuration parameter for the database connection pool which controls the
referenced pool size.
You should take care not
to configure the jbo.ampool.monitorsleepinterval (for the AM
pools) or the jbo.poolmonitorsleepinterval (for the DB
pools) to be too short of a time period because the chance exists — with a
large number of AM pools to cleanup — that your next pool monitor "wakeup"
might occur while your previous cleanup-cycle is still going on. The default of
10 minutes (600000 milliseconds) is reasonable. Setting it
to something like 10 seconds (10000 milliseconds) might
cause trouble. Forewarned is forearmed.
Understanding How Database and
Application Module Pools Cooperate
How ADF application module pools use the database connection pool depends
on the setting of the jbo.doconnectionpooling AM
configuration parameter. In the Configuration Manager
panel that you see in Figure 1, you set this parameter using
the checkbox labelled Disconnect Application Module Upon
Release.
| NOTE: |
The notion of disconnecting the application module
upon release to the pool better captures what the actual feature is doing than
the related configuration parameter name
(jbo.doconnectionpooling) does. As we'll see the setting of
jbo.doconnectionpooling=false does not mean that there is no
database connection pooling happening. What it means is that the AM is not
disconnected from its JDBC connection upon checkin back to the AM
pool.
|
If jbo.doconnectionpooling=false,
which is the default, then when an AM instance is created in any pool it
acquires a JDBC connection from the appropriate connection pool (based on the
JDBC URL in the ADF case, or from the underlying JDBC datasource
implementation's pool in the case of a JNDI datasource name). That AM instance
holds onto the JDBC connection object that it acquired from the pool until the
AM instance is removed from the AM pool. During its lifetime, that AM instance
may service many different users, and ADF worries about issuing rollbacks on
the database connection so that different users don't end up getting pending
database state confused. This provides the best performance in general because,
by holding onto the JDBC connection, it allows each AM instance to keep its
JDBC PreparedStatements's open and usable across subsequent accesses by
clients.
If jbo.doconnectionpooling=true, then
each time a user session finishes using an AM (typically at the end of each
HTTP request), the AM instance disassociates itself with the JDBC connection it
was using on that request and it returns it to the JDBC connection pool. The
next time that AM instance is used by a user session, it will reacquire a JDBC
connection from the JDBC connection pool and use it for the span of time that
that AM is checked out of the AM pool (again, typically the span of one HTTP
request). Since the AM instance "unplugs" itself from the JDBC connection
object used to create the PreparedStatements it might have used during the
servicing of the current HTTP request, those PreparedStatements are no longer
usable on the next HTTP request because they are only valid in the context of
the Connection object in which they were created. So, using the connection
pooling mode turned "on" like this, the tradeoff is a slightly more JDBC
setup/overhead each time in return for using a smaller number of overall
database connections.
The key difference is seen when many AM pools are all using the same
underlying database user for their application connection.
- If 50 different AM pools each have even just a
single AM instance in them, with
jbo.doconnectionpooling=false there will be 50 JDBC
application connections in use. If the AM pooling parameters are set such that
the AM pools are allowed to shrink to 0 instances after an
appropriate instance idle timeout by setting
jbo.ampool.minavailablesize=0, then when the AM is removed
from its pool, it will put back the connection its holding onto.
- In contrast, if 50 different AM pools each
have a single AM instance and
jbo.doconnectionpooling=true,
then the amount of JDBC connections in use will depend on how many of those
AM's are simultaneously being used by different clients.
If an AM instance is in the pool and is not currently being used by a user
session, then with jbo.doconnectionpooling=true it will have
released its JDBC connection back to the connection pool and while the AM
instance is sitting there waiting for either another user to need it again, or
to eventually be cleaned up by the AM pool monitor, it will not be "hanging on"
to a JDBC connection.
For highest performance, we recommend not disconnecting the application
module instance from its database connection on each check in to the AM pool.
Accordingly, the default setting of the
jbo.doconnectionpooling configuration parameter is
false. The pooling of application module instances is
already an effective way to optimize resource usage, and there are runtime
efficiencies that the ADF framework can gain if we do not have to disconnect AM
instances from their associated JDBC connection after each release to the pool.
Effectively, by pooling the application modules which are related one-to-one
with a JDBC connection, you are already achieving a pooling of database
connections that is optimal for most web applications.
In contrast
to our default recommendation, one situation in which it might be opportune to
use database connection pooling is when you have a large number of application
module pools all needing to use database connections from the same underlying
application user at the database level. In this case, the many application
module pools can perhaps economize on the total overall database sessions by
sharing a single, underlying database connection pool of JDBC connections,
albeit at a loss of efficiency of each one. This choice would be favored only
if total overall database sessions is of maximum priority.
| CAVEAT: |
Disconnecting the AM from it's JDBC connection at each AM checkin is
fundamentally incompatible with the use of the ADF Business Components feature
to call postChanges() — without committing — on the current
transaction. Having this feature work correctly relies on allowing the AM to
retain its database connection so that interim posted database changes — which
have yet to be committed — are maintained by the database. The use of
postChanges() is often a sign that you are not aware that
the ADF pending state management mechanism will automatically keep track of
pending new, modified, and deleted rows for you across web page requests
without needing to post them to the database until the final transaction
commit.
|
Conclusion
I hope these tips have cleared up some of the
concepts and options around the application module pooling feature. I'll use
this article as a place to add additional information in the future that might
become frequently asked questions about the Application Module Pool.
|