cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Berin Loritsch <blorit...@apache.org>
Subject [RT] Blocks and Really Making them Work
Date Wed, 27 Aug 2003 12:39:28 GMT
If blocks are deployment components (like WAR files and EAR files), we have
ways of simply making the blocks happen.  Sure we will have hundreds of small
JAR files to juggle around, but it will enable us to upgrade our site one piece
at a time.

There are currently two issues at hand: classloader structure and required meta
data.  Whether you formally specify them or not doesn't really matter, they are
needs.  To that end, it would make sense to learn from how others solved these
problems.

For instance, there are two ways of solving the classloader issue--which can
be used together.  The first is the use of the MANIFEST.MF file to declare
both the id info for the declared JAR and the dependency info for the JAR.
Maven takes care of this automatically--but there is a standard already.  The
other is the Advanced Classloading portion of the JMX spec.  Using a combination
of the info and a modified JMX style classloading architecture we can get all
the components we need.

The simple explanation of the JMX style advanced classloading is that we have
a ClassLoader repository sitting on top of a parent classloader.  So the
repository will be where we load the blocks, and the parent will be the Servlet
classloader (or the system classloader if we are using CLI).  The repository
works by having an object (let's call it Block) that *is* a classloader
represent each and every JAR.  It's a one-to-one mapping: one JAR to one object.
The semantics work as you would normally expect with one additional twist:
after the Block classloader tries to load from the parent classloader and can't,
it iterates through the other Block classloaders in the repository.

According to the JMX specs, the order that the blocks are added is the order
that they are searched--and to avoid deadlocks once we encounter our block
again the search is over.  We can use the information from the MANIFEST.MF file
to coerce the order for any particular Block so that we can ensure all
classloaders are checked and it cannot ever see itself in the list (i.e. a tad
more advanced than the JMX specs).  If it still can't find the requested class,
it will try itself (without any worries about blocking).

So what about those Blocks who would really like to have a set of JARs
encapsulated inside the parent JAR?  I would propose that the Block classloader
mechanism be made smart enough to either use a MANIFEST.MF entry, or a special
block.xml file to list the locations of all the internal JAR files.  Those
JAR files are only accessible from the Block classloader (i.e. they are
considered private).

As to unloading and reloading the Blocks (upgrading, downgrading, etc.) the
Repository must be smart enough to unload that Block and all other Blocks that
use it.  For some central blocks, the impact will be huge.  For other less
central blocks, the impact will be minor.

Each block should have a block.xml or similar file that establishes the
configuration for any new components that need to be loaded to support the
Block, as well as a laundry list of components that the Block needs in order
to run.  That laundry list will let the container see if the requested component
is available already so that the number of new components created will be kept
to a minimum.  Beyond that, if there is a sitemap.xml it is mounted in the
appropriate location.

For something like Cocoon, where assembling a hierarchical system is very
natural, there can be more than one repository--where the parent classloader
is the parent repository.  That will help certain things like auto-mounting
of blocks relative to a particular URL.  Cocoon just has to be smart enough
to do some "smart-mounting".

Smart-mounting involves mounting a block by name, so that a parent sitemap.xml
will specify where in the URL hierarchy that the mount goes--but the actual
implementation is in a compiled block.

I would start with something like this, and see how far it can take you--and
if there are new features required, add them.

-- 

"They that give up essential liberty to obtain a little temporary safety
  deserve neither liberty nor safety."
                 - Benjamin Franklin


Mime
View raw message