7 Replies Latest reply on Jan 28, 2008 9:00 AM by alesj

    Checking DeploymentContext for failures

    alesj

      Regarding http://jira.jboss.com/jira/browse/JBMICROCONT-187.

      What's the best way to get failing ControllerContexts that belong to DeploymentContext param?

      This is what I came up currently:

       protected final void checkComplete(
       DeploymentContext context,
       Map<String, Throwable> contextsInError,
       Map<String, Set<MissingDependency>> contextsMissingDependencies,
       Set<ControllerContext> notInstalled,
       List<ControllerState> states)
       {
       Attachments attachments = context.getDeploymentUnit();
       if (attachments != null && checkers != null)
       {
       for (AttachmentChecker checker : checkers)
       {
       ControllerContext cc = checker.getControllerContext(controller, attachments);
       if (cc != null)
       {
       if (cc.getState().equals(cc.getRequiredState()) == false && notInstalled.contains(cc))
       {
       checkControllerContext(cc, contextsInError, contextsMissingDependencies, states);
       }
       }
       }
       }
       List<DeploymentContext> children = context.getChildren();
       if (children != null && children.isEmpty() == false)
       {
       for(DeploymentContext child : children)
       checkComplete(child, contextsInError, contextsMissingDependencies, notInstalled, states);
       }
       }
      


      where AttachmentChecker looks like this, e.g. Bean checker:
      public abstract class AbstractAttachmentChecker<T> implements AttachmentChecker
      {
       private Class<T> type;
      
       protected AbstractAttachmentChecker(Class<T> type)
       {
       if (type == null)
       throw new IllegalArgumentException("Null type.");
       this.type = type;
       }
      
       public ControllerContext getControllerContext(Controller controller, Attachments attachments)
       {
       T attachment = attachments.getAttachment(type);
       if (attachment != null)
       return getControllerContext(controller, attachment);
      
       return null;
       }
      
       protected abstract ControllerContext getControllerContext(Controller controller, T attachment);
      }
      
      public class BeanAttachmentChecker extends AbstractAttachmentChecker<BeanMetaData>
      {
       public BeanAttachmentChecker()
       {
       super(BeanMetaData.class);
       }
      
       protected ControllerContext getControllerContext(Controller controller, BeanMetaData attachment)
       {
       return controller.getContext(attachment.getName(), null);
       }
      }
      


      Another checker implementations would include ServiceAC (mbeans) and ControllerContextAC (OSGi deployments).
      Any others?

        • 1. Re: Checking DeploymentContext for failures

          I answered this on the dev-list since the forums were down,
          copied to here:

          You don't need to do anything so complicated.

          You just need the relevant deployers to record the context names in some
          well defined place, e.g. the Deployment{Unit|Context}

          It's probably important enough to use a special method rather than
          an attachment.

          e.g.

          public class BeanMetaDataDeployer extends
          AbstractSimpleRealDeployer<BeanMetaData>
          {
           /** The kernel controller */
           private final KernelController controller;
          
           /**
           * Create a new BeanDeployer.
           *
           * @param kernel the kernel
           * @throws IllegalArgumentException for a null kernel
           */
           public BeanMetaDataDeployer(Kernel kernel)
           {
           super(BeanMetaData.class);
           if (kernel == null)
           throw new IllegalArgumentException("Null kernel");
           controller = kernel.getController();
           setComponentsOnly(true);
           }
          
           @Override
           public void deploy(DeploymentUnit unit, BeanMetaData deployment)
          throws DeploymentException
           {
           KernelControllerContext context = new
          AbstractKernelControllerContext(null, deployment, null);
           try
           {
           controller.install(context);
          + unit.addControllerContextName(deployment.getName());
           }
           catch (Throwable t)
           {
           throw DeploymentException.rethrowAsDeploymentException("Error
          deploying: " + deployment.getName(), t);
           }
           }
          
           @Override
           public void undeploy(DeploymentUnit unit, BeanMetaData deployment)
           {
          + unit.removeControllerContextName(deployment.getName());
           controller.uninstall(deployment.getName());
           }
          }
          


          In practice, the component deployment unit name should be the context
          name.
          This is at least true for the POJO and Service deployers.

          So you could just add it as some kind of easy declaration in the
          constructor:

           public BeanMetaDataDeployer(Kernel kernel)
           {
           super(BeanMetaData.class);
           if (kernel == null)
           throw new IllegalArgumentException("Null kernel");
           controller = kernel.getController();
           setComponentsOnly(true);
           // obviously some shorter property name ;-)
           setComponentDeploymentNameIsControllerContextName(true);
           }
          


          and handle it in the abstract classes:

           deploy(...); // will throw an error if not registered in the
          controller
           if (unit.isComponent() &&
          isComponentDeploymentNameControllerContextName())
           addComponentContextName(unit.getSimpleName());
          



          • 2. Re: Checking DeploymentContext for failures
            alesj

            How does this take care of DeploymentControllerContext?
            Since it's not a part of Deployers.

            Or just treating this ControllerContext lookup differently?

            Via AttachmentCreator this was transparent. :-)

            public class ControllerContextAttachmentChecker extends AbstractAttachmentChecker<ControllerContext>
            {
             public ControllerContextAttachmentChecker()
             {
             super(ControllerContext.class);
             }
            
             protected ControllerContext getControllerContext(Controller controller, ControllerContext attachment)
             {
             return attachment;
             }
            }
            


            • 3. Re: Checking DeploymentContext for failures

              We're having this discussion in two places, let's keep it here. ;-)

              You already know the context name of the deployment controller
              context and how to retrieve it (assuming it has got as
              far as creating it :-)

              It's an implementation detail of the class you are changing.

              The ones you don't know about are those created by
              the deployers, i.e. the [Kernel|Service]ControllerContext

              You just need those deployers that create them to record
              them somewhere for you to check.

              Looking at the attachments can even be misleading, because
              the attachment may exist (created by the parsing
              deployer) but it never got as far as actually
              registering them in the controller.

              Or maybe the deployer tried to register it, but found it
              was a duplicate (already registered).
              So you'd actually be looking at the wrong context!

              Besides it's over engineered for the purpose.
              You just want a set of names that were definitely
              registered in the controller for that deployment.

              Once you have those, you also need to recurse through the
              DependencyInfo looking to find the possible root cause
              for failed contexts.

              • 4. Re: Checking DeploymentContext for failures
                alesj

                 

                "adrian@jboss.org" wrote:
                Looking at the attachments can even be misleading, because
                the attachment may exist (created by the parsing
                deployer) but it never got as far as actually
                registering them in the controller.

                Or maybe the deployer tried to register it, but found it
                was a duplicate (already registered).
                So you'd actually be looking at the wrong context!

                Yup.
                You're right. :-)
                Will refactor/impl to your suggestion.

                "adrian@jboss.org" wrote:

                Once you have those, you also need to recurse through the
                DependencyInfo looking to find the possible root cause
                for failed contexts.

                Already done. ;-)

                • 5. Re: Checking DeploymentContext for failures
                  alesj

                  I believe I'm missing the check of components being in failure in DeployersImpl.checkComplete:

                   protected final void checkComplete(
                   DeploymentContext context,
                   Map<String, Throwable> contextsInError,
                   Map<String, Set<MissingDependency>> contextsMissingDependencies,
                   Set<ControllerContext> notInstalled,
                   List<ControllerState> states)
                   {
                   DeploymentControllerContext dcc = context.getTransientAttachments().getAttachment(ControllerContext.class.getName(), DeploymentControllerContext.class);
                   checkControllerContext(dcc, contextsInError, contextsMissingDependencies, notInstalled, states);
                  
                   Set<Object> names = context.getControllerContextNames();
                   if (names != null && names.isEmpty() == false)
                   {
                   for(Object name : names)
                   {
                   ControllerContext cc = controller.getContext(name, null);
                   checkControllerContext(cc, contextsInError, contextsMissingDependencies, notInstalled, states);
                   }
                   }
                  
                   List<DeploymentContext> children = context.getChildren();
                   if (children != null && children.isEmpty() == false)
                   {
                   for(DeploymentContext child : children)
                   checkComplete(child, contextsInError, contextsMissingDependencies, notInstalled, states);
                   }
                  
                   // CURRENTLY MISSING
                   List<DeploymentContext> components = context.getComponents();
                   if (components != null && components.isEmpty() == false)
                   {
                   for(DeploymentContext component : components)
                   checkComplete(component, contextsInError, contextsMissingDependencies, notInstalled, states);
                   }
                   }
                  


                  btw: What's the difference between a component and a child context?

                  • 6. Re: Checking DeploymentContext for failures
                    starksm64

                    A child context is a structural child, an ejb jar in an ear, a beans.xml. A component is a runtime unit such as an mc bean unit based on BeanMetaData from a beans.xml context with a KernelDeployment.

                    • 7. Re: Checking DeploymentContext for failures
                      alesj

                      I've added that piece of missing code.
                      That's really the part that picks up BeanMetaData and ServiceMetaData runtime components, and checks if they are complete.

                      In order to fix JBAS-4292, this would require new MC release.