A Seedling application (that is, an application built using the Seedling platform) is made up of one or more modules. Each module contributes new components to the tree, and customizes the configuration of existing components. This chapter describes how a Seedling application is organized and launched.
Modules can be broadly classified into two main roles.
Supporting modules provide specialized frameworks or
services, but are not useful in isolation. For example, the
runtime module provides the core facilities of the
Seedling platform, the
jelly module provides support for
XML-based node configuration and scripting, and the
bonsai module provides a generic GUI framework.
Primary modules provide an application's custom
functionality, typically by pulling together supporting modules and
configuring them into a useful system. In general, an application is
launched by indicating just its primary module; any supporting modules are
automatically loaded by the launcher.
|There is no concrete difference between primary and supporting modules; this is just terminology we use to talk about two common ways in which modules can be used.|
A Seedling module has two aspects: a configuration layer that
specifies the module's runtime components, and (optionally) a set of Jar
files providing classes and resources. Since no module can stand alone
(except the core
runtime module), each one can declare
its predecessors: required modules that provide necessary frameworks
and/or services. The Seedling runtime launcher will automatically load all
necessary modules, determine the appropriate class path, and construct the
proper sequence of configuration layers.
A module is deployed in the form of a single directory tree; each module deployed within an application must therefore have a unique name. A module's directory has the following structure:
contains a tree of Java
.class files to be
added to the runtime classpath.
contains the module's config tree when “Directory Config
Format” is used.
contains the module's config tree when “ZipFile Config
Format” is used.
(optional) contains additional libraries to be added to the
(optional) defines various properties of the module.
module.properties file is a standard Java
properties file that is used to configure the module as a whole. There is
currently only one property supported:
If defined, this property's value must be a comma-separated list of module names. These are the predecessors of this module: each one must be available within the current deployment, and all are loaded into the Seedling before the current module. Note that nodes configured in this module will therefore override any configuration provided by predecessor modules.
To start the application, the Seedling launcher analyzes each module and creates a class path with all of the necessary resources. A module may contribute several items to the class path according to these rules:
If the module defines any predecessor modules, they are processed first, so that their resources precede this module in the class path. This rule avoids “class hiding” for security purposes: a module cannot replace classes or resources provided by a predecessor.
If the module has a
classes directory, it
is appended to the class path.
If the module has a
lib directory, any
zip files within it
are appended to the class path in an undefined order.
The module's configuration tree can be packaged in several ways. The following list describes the different formats; the first format found will be used.
In ZipFile Config Format, the
config tree is stored in a
config.zip file in the
module's directory. This is a standard ZIP file, with resources
arranged in subdirectories according to the branch/node
In Directory Config Format, the
config tree is found in the module's
directory as normal files. You can easily convert this format to the
ZipFile format by simply zipping up the contents
of this directory (but not the
The Seedling build system provides an Ant target
buildModule (defined in
moduleTargets.xml) that builds the appropriate
structures in the module's main Jar file.
The basic deployment approach is to construct a single directory that contains both the Seedling platform modules and all application modules. The typical file layout is as follows:
is also known as the
launcher.jar is the
Seedling bootstrap jar.
logs/ is the default
location for any log files created by the application.
all of the modules deployed as part of the application.
contains a single deployed module. The contents of this
directory are described in the Module Structure
Since an application is usually launched by naming one or more primary modules, it is acceptable for the deployed system to contain additional modules that may not be loaded (because they are not required by the primary modules). This feature can be used to deploy several applications within one directory tree by providing multiple startup scripts that launch Seedling with different primary modules.
modules directory is known as a
repository, and Seedling can load modules from more
than one of them. The best use for this feature is to avoid modifying the
standard Seedling home directory, keeping application code completely
separate from the platform, in observance of the Open/Closed Principle.
The various launching approaches described in the next section each
have a means for utilizing multiple repositories.
Seedling provides a spectrum of options for launching the container,
depending on how much control the application is willing to give Seedling
with regards to
main() and class loading.
At one end of the launching spectrum is “Seedling on the
outside”, where Seedling takes resposibility for
main() and for all module and class loading.
This is easy to achieve: just run the
SEEDLING_HOME and the names of the required modules.
A typical application can thus be started simply by naming the primary module(s):
java -jar launcher.jar
The launcher inspects the contents of the named modules and
recursively loads all of the required modules, each of which must
reside in one of the known repository directories. The launcher constructs
ClassLoader to gain access to the libraries
provided by each
module (in the
script is a generic example of this approach and is very useful during
For more information on launching options, see the documentation
To put Seedling “in the middle”, the application
main() and handles class loading for (at least) the
Seedling runtime module, letting Seedling perform dynamic loading of other
modules into the container.
There are several viable ways to achieve this:
Add all of the bootstrap jars to the JVM command line.
The required jars are
Deploy the application as a jar that has the bootstrap declared in the
launcher.jar is an example of this
Construct a dynamic
ClassLoader that provides the
bootstrap jars, then calls a trampoline method via reflection.
The trampoline isolates the outer launch code from having a static
dependency on Seedling classes.
The go-to class for putting Seedling in the middle is
allows the application to provide
additional module repositories, and the required modules.
At the other end of the launching spectrum is “Seedling on the inside”, where the application embeds Seedling as a library and handles all class loading itself. This option is not recommended, since it requires the application to determine the transitive closure of required modules and build the appropriate class path.
There is currently minimal platform support for this approach.
Again, the important API is the