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]>