10.2. Separation of Structure Recognition From Deployment life-cycle logic

In order to do any real work on top of a deployment, you must first understand its structure, including its classpaths and metadata locations.
Metadata locations include the configuration files such as my-jboss-beans.xml, web.xml, ejb-jar.xml. Classpaths are classloader roots, such as WEB-INF/classes or myapp.ear/lib.
Bearing the structure in mind, you can proceed to actual deployment handling.

A typical deployment life cycle

  1. The MainDeployer passes the deployment to the set of StructuralDeployers for recognition, and receives back a Deployment context.
  2. Next, the MainDeployer passes the resulting Deployment context to the Deployers for handling by the appropriate Deployer.
In this way, the MainDeployer is a broker with the responsibility of deciding which Deployers to use.
In the case of virtual or programmatic deployment, an existing predetermined StructureMetaData information reads the structure information and handles it in one of the ways explained in Handling StructuredMetaData Information.

Handling StructuredMetaData Information

VFS-based deployments
the structure recognition is forwarded to a set of StructureDeployers.
JEE-specification-defined structures
we have matching StructureDeployer implementations:
  • EarStructure
  • WarStructure
  • JarStructure
DeclarativeStructures
looks for META-INF/jboss-structure.xml file inside your deployment, and parses it to construct a proper StructureMetaData.
FileStructures
only recognizes known configuration files, such as files like -jboss-beans.xml or -service.xml.

Example 10.1. An example of jboss-structure.xml

<structure>
  <context comparator="org.jboss.test.deployment.test.SomeDeploymentComparatorTop">
    <path name=""/>
    <metaDataPath>
      <path name="META-INF"/>
    </metaDataPath>
    <classpath>
      <path name="lib" suffixes=".jar"/>
    </classpath>
  </context>
</structure>
In the case of EarStructure, first recognize a top level deployment, then recursively process sub-deployments.
You can implement a custom StructureDeployer with the help of the generic GroupingStructure class provided by the generic StructureDeployer interface.
After you have a recognized deployment structure, you can pass it to real deployers. The Deployers object knows how to deal with the real deployers, using a chain of deployers per DeploymentStage.

Example 10.2. Deployment Stages

public interface DeploymentStages {
   /** The not installed stage - nothing is done here */
   DeploymentStage NOT_INSTALLED = new DeploymentStage("Not Installed");

   /** The pre parse stage - where pre parsing stuff can be prepared; altDD, ignore, ... */
   DeploymentStage PRE_PARSE = new DeploymentStage("PreParse", NOT_INSTALLED);

   /** The parse stage - where metadata is read */
   DeploymentStage PARSE = new DeploymentStage("Parse", PRE_PARSE);

   /** The post parse stage - where metadata can be fixed up */
   DeploymentStage POST_PARSE = new DeploymentStage("PostParse", PARSE);

   /** The pre describe stage - where default dependencies metadata can be created */
   DeploymentStage PRE_DESCRIBE = new DeploymentStage("PreDescribe", POST_PARSE);

   /** The describe stage - where dependencies are established */
   DeploymentStage DESCRIBE = new DeploymentStage("Describe", PRE_DESCRIBE);

   /** The classloader stage - where classloaders are created */
   DeploymentStage CLASSLOADER = new DeploymentStage("ClassLoader", DESCRIBE);

   /** The post classloader stage - e.g. aop */
   DeploymentStage POST_CLASSLOADER = new DeploymentStage("PostClassLoader", CLASSLOADER);

   /** The pre real stage - where before real deployments are done */
   DeploymentStage PRE_REAL = new DeploymentStage("PreReal", POST_CLASSLOADER);

   /** The real stage - where real deployment processing is done */
   DeploymentStage REAL = new DeploymentStage("Real", PRE_REAL);

   /** The installed stage - could be used to provide valve in future? */
   DeploymentStage INSTALLED = new DeploymentStage("Installed", REAL);
}
Preexisting deployment stages are mapped to the Microcontainer's built-in controller states. They provide a deployment/life cycle focused view of generic controller states.
Inside Deployers, the deployment is converted into the Microcontainer's component DeploymentControllerContext. The Microcontainer's state machine handles dependencies.
Deployments are handled sequentially by deployment stage. For each deployer, the entire deployed hierarchy order is handled, using the deployer's parent-first property. This property is set to true by default.
You can also specify which hierarchy levels your deployer handles. You can choose all, top level, components only, or no components.
The way the Microcontainer handles component models and dependency handling applies here as well. If there are unresolved dependencies, the deployment will wait in the current state, potentially reporting an error if the current state is not the required state.
Adding a new deployer is accomplished by extending one of the many existing helper deployers.
Some deployers actually need VFS backed deployment, while others can use a general deployment. In most cases the parsing deployers are the ones that need VFS backing.

Warning

Also be aware that deployers run recursively through every deployment, sub-deployment, and component. Your code needs to determine, as early in the process as possible, whether the deployer should handle the current deployment or not.

Example 10.3. Simple Deployer which Outputs Information About Its Deployment

public class StdioDeployer extends AbstractDeployer {
   public void deploy(DeploymentUnit unit) throws DeploymentException
   {
      System.out.println("Deploying unit: " + unit);
   }

   @Override
   public void undeploy(DeploymentUnit unit)
   {
      System.out.println("Undeploying unit: " + unit);
   }
}
Add this description into one of the -jboss-beans.xml files in deployers/ directory in JBoss Application Server, and MainDeployerImpl bean will pick up this deployer via the Microcontainer's IoC callback handling.

Example 10.4. Simple Deployment Descriptor

<bean name="StdioDeployer" class="org.jboss.acme.StdioDeployer"/>