JBoss.org Community Documentation

22.4. Deployment components

Deployments usually contain one or more runtime components in addition to configuration information and resource files. By runtime components we mean any classes that require a container in which to run. Containers take care of controlling a component's lifecycle in addition to providing common behaviours so that component developers do not have to do this themselves. By leveraging the work of the container, components allow you to concentrate on developing the business logic of your application without having to continually write code for common tasks. This typically reduces the time needed to develop systems with advanced behaviour.

The simplest example of a component is a POJO. In this case the container controls when the POJO is created based on when a client performs a lookup. It can also take care of wiring different POJOs together based on information in a deployment descriptor so that the developer doesn't have to hard-code any relationships. This makes configuration of the runtime environment easier to change.

Another example is an MBean. Here the container (an MBeanServer) takes care of routing all method calls through a bus so that clients never reference the MBean directly. This allows MBeans to be replaced at runtime without impacting any clients. It also allows the management interface of an MBean, the attributes and operations exposed to clients, to change at runtime without needing to redeploy it.

A further example is an OSGi service bundle. Here the container ensures that the classes required by the bundle are available in the runtime before the service is started. It also takes care of making classes within the bundle available to others when deployed and removing them again when undeployed. This makes the runtime environment easier to construct and maintain with fewer classloading issues.

In order to provide support for deploying different types of runtime components, JBoss Microcontainer requires that each one is represented by its own ComponentDeploymentContext :


public class ComponentDeploymentContext implements DeploymentContext
{
    ...
}

This is similer to a normal DeploymentContext implementation but with some important differences:

  • Components always have a relative order of 0

  • Components do not have a metadata path

  • Components always use the classloader of the containing deployment

  • Components cannot change their parent once constructed

  • Components can contain other components

  • Components are never considered top-level deployments

In addition ComponentDeploymentContexts delegate to their parent DeploymentContext for information such as:

  • simple name

  • relative path

  • deployment types

  • deployment state

  • class loader

  • Resource class loader

  • Deployment Resource Loader

  • Dependency Info

  • get/setProblem

The reason we use the DeploymentContext interface is so that we can process components together with normal deployments. This ensures that when a deployment is deployed any components that it contains are deployed with it. Similarly undeploying a deployment causes its components to be undeployed at the same time.

Important

An additional motivation is that we can easily create separate ControllerContexts for each component which we can then process using the state machine. This allows us to perform a well-defined set of deployment actions to deploy/undeploy each component in and out of the runtime.

Having separate ControllerContexts for each component also allows you to manage the components individually, possibly via an Admin console. Furthermore each component can have its own dependencies allowing fine-grained control of how the runtime is constructed and destructed.

ComponentDeploymentContexts are added to a DeploymentUnit using the addComponent() method whenever a component is discovered during the deployment process:


public class AbstractDeploymentUnit extends AbstractMutableAttachments implements DeploymentUnit
{
    ...

   public DeploymentUnit addComponent(String name)
   {
      DeploymentContext component = createComponentDeploymentContext(name, deploymentContext);
      DeploymentUnit unit = createComponentDeploymentUnit(component);
      component.setDeploymentUnit(unit);
      deploymentContext.addComponent(component);
      return unit;
   }

   ...

   protected DeploymentContext createComponentDeploymentContext(String name, DeploymentContext parent)
   {
      return new ComponentDeploymentContext(name, parent);
   }

    ...
}

As components are usually accessed with the DeploymentUnit interface they can also have attachments just like any other deployment:


public interface DeploymentUnit extends MutableAttachments
{
    ...
}

public interface MutableAttachments extends Attachments
{
    ...

   Object addAttachment(String name, Object attachment);

    ...
}

An attachment may well be metadata associated with the component. In this way the metadata can be processed using deployment actions as the component's ControllerContext passes through the state machine.