Martin Cooper wrote:

> What do you have in mind with regard to Digester-based 
> configuration? I'd be willing to take a crack at doing 
> this if you could give me some pointers on what you'd like 
> to see. Bear in mind that I'm not exactly a JOCL expert. ;-)

Recall that an "instance" of DBCP glues together three different tiers:

* A client-interface tier (like PoolingDataSource or PoolingDriver)

* A pool implementation (like GenericObjectPool or anything else that
implements org.apache.commons.pool.ObjectPool)

* A (Poolable)Connection factory (like DataSourceConnectionFactory or
DriverConnectionFactory or DriverManagerConnectionFactory)

One simple (but run-time inflexible) way of doing this is just to glue the
pieces together with a little bit of Java code, as Craig has done with
BasicDataSource (see the createDataSource method), or as shown in the
Manual*Example.java files in the dbcp/doc directory.  

(In retrospect, perhaps we should stress this way of using DBCP a bit
more--providing basic, "pre-assembled" connection pools that are suitable
for most people's needs--which avoids the configuration learning curve.)

In the general case, we'd like (or at least I'd like) to allow run-time or
at least init-time selection and configuration of each tier, so that I can
put together an arbitrary DBCP "instance" without changing the source code.
Hence some configuration mechanism is necessary.  In Java code, it's really
not that hard, a few lines will suffice:

// create a pool
ObjectPool connPool = new GenericObjectPool(...);

// create a connection factory
ConnectionFactory factory = new DriverManagerConnectionFactory(...);

// wrap the factory in a PoolableConnectionFactory
// which will allow the connections created by factory to be pooled
PoolableConnectionFactory poolableConnectionFactory = new
PoolableConnectionFactory(...);

// create a PoolingDataSource from that pool
PoolingDataSource dataSource = new PoolingDataSource(...);

(This example is pulled from setupDataSource in
http://cvs.apache.org/viewcvs/~checkout~/jakarta-commons/dbcp/doc/ManualPool
ingDataSourceExample.java?content-type=text/plain if you'd like to see more
detail.)

The trouble is, if we want generality, we can't know the implementation of
ObjectPool or ConnectionFactory before-hand, and most implementations of
those will have quite a number of configuration options we'll want to
expose.  (And the complexity increases if I want to allow
PreparedStatementPooling, since then I'll need/want to configure the pools
of statements as well.)

JOCL was an effort to solve this problem, although it's clearly more
oriented toward the easiest implementation as opposed to the most-user
friendly configuration.  If it's easy to do the configuration by
instantiating Java objects, then give me a way to instantiate Java objects
via my configuration file.

It works like this: Every element in a JOCL document represents the
instantiation of a Java object (or primitive).  Hence there's an <object>
tag, one for each primitive (<int>,<boolean>, etc.) and for convenience, a
<string> tag.  Object tags have an attribute indicating the class to be
instantiated, and may contain other tags which indicate the signature of the
constructor to be invoked as well as the values to pass into it.  For
example:

<object class="java.util.Date"><long value="1015542020159"/></object>

is equivalent to:

new java.util.Date(1015542020159L);

and 

<object class="mypackage.Foo">
 <object class="java.util.Date">
   <long value="1015542020159"/>
 </object>
</object>

is equivalent to:

new mypackage.Foo(new java.util.Date(1015542020159L));

So, whatever you can create via a chain of constructors and primitives, you
can create with JOCL.

I find this works rather well in practice as long as the file is maintained
by someone slightly Java-literate. (See
http://cvs.apache.org/viewcvs/~checkout~/jakarta-commons/dbcp/doc/poolingDri
verExample.jocl.sample?content-type=text/plain for a DBCP example.)  The
main problem is that the JOCL file doesn't provide much context on it's
own--you either need to add XML comments or look up the constructor
signatures and their meanings in the JavaDocs.

In my original comment:

> The JOCL configuration should probably either be 
> converted to Digester or something like it, or JOCL 
> moved to a stand-alone component.

The point I was trying to make is that JOCL is an odd component to have
tucked away inside of DBCP, so let's either promote it or remove it.
Digester and JOCL have a lot of overlap on the surface--both provide a way
of mapping XML to Java methods and both are largely used for supporting
XML-based configuration files.  The primary difference I see between the two
is that Digester seems oriented toward writing small amounts of specialized
Java code for parsing known-at-compile-time DTDs/schemas, while JOCL tries
to provide single syntax for java-object-construction, supporting (however
crudely) the configuration of whatever new types should come along.  (So,
for example, if I create a great new ObjectPool implementation, I can
convert all my DBCP pools to using it by simply adding the new impl to my
classpath, and changing that section of the JOCL files. I don't need to
rewrite or add to my configuration file parser.)

One option would be to re-implement JOCL as an application of Digester.  We
even talked about that briefly back when commons was being created.  But I
think maybe that solves the wrong problem.  The JOCL impl seems to work
fine, and it's a small amount of code.  The problem, as I see it, is that
JOCL leads to an especially user-unfriendly configuration syntax.  Making it
more readable, perhaps in a Digester-like setter/getter way, would be
helpful, I'm just not sure on what that syntax/impl would be in the general
case.  The ideal solution, as I see it, would be able to support the
instantiation/configuration of arbitrary objects without additional code,
but would remain relatively readable in the process.  Something like:

<GenericObjectPool>
  <maxActive>100</maxActive>
  <maxIdle>10</maxIdle>
  <whenExhausted>BLOCK</whenExhausted>
  ...
</GenericObjectPool>

looks about right, but that glosses over a lot of detail.

 - Rod

Reply via email to