Since the Phoenix documentation lacks a detailied dynamic view of its
internal processes (does it? I haven't found one), I used a debugger to step
through the initialization phase of the jakarta James server.

Can anybody verify my comments?

I hope this is beneficial to the people who are (like me) at the start of
the steep Avalon learning curve...


-------------------

1. Phoenix main (phoenix.launcher.Main) is started. It transfers directly to
another main class.
Default: Command Line interface (CLIMain. That is currently a constant in
launcher/Main.java). This reads command line options and the kernel.xml
file, which contains the "embeddor" class to be used. The embeddor has the
function to bootstrap the kernel and load a number of system components.

2. CLIMain calls this Embeddor.
(phoenix.components.embeddor.DefaultEmbeddor). Which one, is specified in
phoenix/conf/kernel.xml. This file also contains a number of system
components that are loaded first, one of which is the kernel itself.
The Embeddor then looks for applications (in apps/) and deploys them in the
Kernel via a Deployer component (deployer.DefaultDeployer - from kernel.xml)

Via command line, one can specify the location of an application to be
deployed ("application-location"). In extension to that, all .sar files in
the apps/ directory are deployed. This consists of expanding .sar files and
parsing the conf/*.xml files. The .sar structure is also validated. It is
made sure that, for example, assembly.xml doesn't contain circular
dependencies between the components. Each .sar ends up in a SarEntry
structure. This contains the application class to be used (usually null), a
map of classloaders (there are two defined named "*system*" (the SUN class
loader) and "default"
(org.apache.avalon.phoenix.components.classloader.PolicyClassLoader),
Loggers, some meta data, and a work directory.

The deployed application is then added to the Kernel , which starts it (in
DefaultKernel.addApplication).
[by the way: It seems that the .sar files are installed _whenever_ they are
found. That is, if you leave them in the apps/ directory, they will be
deployed again after a restart.]

3. An Application is usually an object of type DefaultApplication (as
specified in DefaultKernel.startup(). It seems that at the moment one cannot
change this, since the SarEntry with the empty application field is also
created within DefaultKernel - in addApplication()).
An Application can implement the Startable interface (which
DefaultApplication does), in which case each of the Application's blocks is
started (by DefaultApplication). That is, during startup, there is a
hierarchy Kernel -> Application -> Blocks (-> Components) which equals the
IOC pattern.

The startup process for blocks is done (in DefaultApplication) as follows:
 a) a list of all blocks is created from the config data and a hash map of
"BlockEntry" objects (hashed by the block name) is built
(DefaultApplication.start())
 b) The app is put into the "run phase". The init order is resolved by a
dependendy walker. That is, for each of the blocks initialized, the blocks
it depends on must have been initialized already - if the dependency graph
allows that (which is verified during deployment - what if one changes
assembly.xml after the deployment?). Then, for each block, a startup
procedure is followed:
    1. Creation stage: The object (the block's main class) is created
    2. Logging stage: If the block implements the "Loggable" interface, the
logger is passed to the block
    3. Contextualize stage: If the block implements "Contextualizable", the
block's context is passed to it
    4. Composition stage: If the block implements "Servicable", a
ServiceManager is passed. If it implements "Composable" a ComponentManager
is passed (from the docs I recall that one of them is deprecated; I think
Composable is more current)
    5. Configuring stage: If the block implements "Configurable", the
block's configuration (the part of the config.xml file that is enclosed by a
tag named with the Block's role name) is passed to it
    6. Parameterization stage: If the block implements "Paremeterizable",
the block's parameters (a simplified name-value map of configuration
parameters in config.xml file ) is passed to it
    7. Initialize stage: All of the above is only for the block to remember
the data structures. If it implements "initializable", this method is now
called and allows the block to initialize itself
    8. start stage: If it implements a "Startable" interface, it is now
started
c) the block's exported interfaces are registered (see 4. below)

At this time, the whole application is up and running. In the case of JAMES
(in the default configuration), I recognized a bunch of threads running at
that time:

  1. A large thread pool with 49 worker threads (which seems to be built by
the Cornerstone thread manager), started by different components. 35 seemed
to be "empty" or idle, 4 were called by
"james.util.connection.ServerConnection", and 10 were called by the
JamesSpoolManager.
  2. An "Excalibor ActiveMonitor" thread
  3. A "Remote delivery thread" of the James AvalonSpoolRepository
  4. An NNTPSpool thread

4. The application and the interfaces exported by the blocks are registered
with JMX (see http://jakarta.apache.org/avalon/phoenix/mx/overview.html).

- Deployer returns

- Embeddor loops forever: It goes to sleep for 1 sec, then checks if
"m_shutdown" is set or if there are no deployed applications.
m_shutdown can be set, from what I see here,  only by pressing ctrl-c (using
the CLIMain launcher). How else?









--------------------------------------
http://www.cmarschner.net


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to