JBoss.org Community Documentation

23.1. Introduction

So far we have established the structure of a deployment using StructureDeployer classes and created a corresponding DeploymentContext using a StructureBuilder . Nested deployments have been dealt with by creating additional DeploymentContexts and adding these as children of the parent DeploymentContext .

The next step in the deployment framework is to process the deployment. The objective being to extract any metadata from the deployment descriptors and create a classloader. Components must also be identified during this process and a ComponentDeploymentContext created for each one so that they can be deployed into the runtime.

The Deployers interface defines the operations that need to take place:


public interface Deployers
{
   ...
   
   void process(List<DeploymentContext> deploy, List<DeploymentContext> undeploy);

   void checkComplete(Collection<DeploymentContext> errors, Collection<Deployment> missingDeployer) throws DeploymentException;

   void checkComplete(DeploymentContext... contexts) throws DeploymentException;

   void checkStructureComplete(DeploymentContext... contexts) throws DeploymentException;
}

In the default implementation DeployersImpl the process() method creates new DeploymentControllerContexts for each DeploymentContext in the deploy list and installs them into the microcontainer controller:


public class DeployersImpl implements Deployers, ControllerContextActions
{
    ...

   public void process(List<DeploymentContext> deploy, List<DeploymentContext> undeploy)
   {
        ...

      // There is something to deploy
      if (deploy != null && deploy.isEmpty() == false)
      {
         // Create the controller contexts
         for (DeploymentContext context : deploy)
         {
            DeploymentControllerContext deploymentControllerContext = new DeploymentControllerContext(context, this);
            try
            {
               controller.install(deploymentControllerContext);
               context.setState(DeploymentState.DEPLOYING);
               ...
               context.getTransientAttachments().addAttachment(ControllerContext.class, deploymentControllerContext);
               ...
            }
            catch (Throwable t)
            {
               // Set the error on the parent
               context.setState(DeploymentState.ERROR);
               context.setProblem(t);
               // Set the children to not deployed
               setState(context, DeploymentState.UNDEPLOYED, DeploymentState.DEPLOYING);
            }
         }

         // Go through the states in order
         List<ControllerState> states = controller.getStates();
         for (ControllerState state : states)
         {
            for (DeploymentContext context : deploy)
            {
               if (DeploymentState.ERROR.equals(context.getState()) == false)
               {
                  DeploymentControllerContext deploymentControllerContext = context.getTransientAttachments().getAttachment(ControllerContext.class.getName(), DeploymentControllerContext.class);
                  try
                  {
                     controller.change(deploymentControllerContext, state);
                  }
                  catch (Throwable t)
                  {
                     context.setState(DeploymentState.ERROR);
                     context.setProblem(t);
                  }
               }
            }
         }
       }
    }

    ...
}

Notice that a reference to the DeploymentControllerContext is stored as an attachment to the DeploymentContext so that it can be retrieved later and passed to the controller.install() method.

Undeployment happens in a similar way. First of all the DeploymentControllerContexts associated with the DeploymentContexts in the undeploy list are extracted into a separate list. The microcontainer controller is then used again to push them through the deployment states in reverse order. Finally the DeploymentControllerContexts are removed from the DeploymentContext attachments where they were initially stored and uninstalled from the controller:


public class DeployersImpl implements Deployers, ControllerContextActions
{
    ...

   public void process(List<DeploymentContext> deploy, List<DeploymentContext> undeploy)
   {
      // There is something to undeploy
      if (undeploy != null && undeploy.isEmpty() == false)
      {
         // Build a list in reverse order
         List<DeploymentControllerContext> toUndeploy = new ArrayList<DeploymentControllerContext>();
         for (int i = undeploy.size()-1; i >= 0; --i)
         {
            DeploymentContext context = undeploy.get(i);
            if (DeploymentState.ERROR.equals(context.getState()) == false)
               context.setState(DeploymentState.UNDEPLOYING);
            ...
            DeploymentControllerContext deploymentControllerContext = context.getTransientAttachments().getAttachment(ControllerContext.class.getName(), DeploymentControllerContext.class);
            if (deploymentControllerContext == null)
            {
               log.debug("DeploymentContext has no DeploymentControllerContext during undeploy request, ignoring: " + context);
            }
            else
            {
               toUndeploy.add(deploymentControllerContext);
            }
         }

         // Go through the states in reverse order
         List<ControllerState> states = controller.getStates();
         for (int i = states.size()-1; i >= 0; --i)
         {
            ControllerState state = states.get(i);
            for (DeploymentControllerContext deploymentControllerContext : toUndeploy)
            {
               DeploymentContext context = deploymentControllerContext.getDeploymentContext();
               if (ControllerState.ERROR.equals(context.getState()) == false)
               {
                  try
                  {
                     controller.change(deploymentControllerContext, state);
                  }
                  catch (Throwable t)
                  {
                     ...
                     context.setState(DeploymentState.ERROR);
                     context.setProblem(t);
                  }
               }
            }
         }

         // Uninstall the contexts
         for (DeploymentControllerContext deploymentControllerContext : toUndeploy)
         {
            DeploymentContext context = deploymentControllerContext.getDeploymentContext();
            context.getTransientAttachments().removeAttachment(ControllerContext.class);
            try
            {
               controller.uninstall(deploymentControllerContext.getName());
               setState(context, DeploymentState.UNDEPLOYED, null);
               ...
               cleanup(context);
              ...
            }
            catch (Throwable t)
            {
               ...
               context.setState(DeploymentState.ERROR);
               context.setProblem(t);
            }
         }
      }

      ...
   }

   ...
}

Note

Undeployments are actually processed before deployments to ensure that we don't end up in a situation where a deployment that depends on a subsequently undeployed deployment has to be undeployed again straight away.

You should hopefully see from this breakdown that each deployment is processed by creating a DeploymentControllerContext that is then installed into the microcontainer controller and pushed through a series of deployment stages. What these stages are and how they are created is the subject of the next section.