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
- The
MainDeployer
passes the deployment to the set ofStructuralDeployer
s for recognition, and receives back a Deployment context. - Next, the
MainDeployer
passes the resulting Deployment context to theDeployers
for handling by the appropriateDeployer
.
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 properStructureMetaData
. - 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"/>