3 Replies Latest reply on Nov 14, 2007 10:04 AM by adrian.brock

    Misleading error when StructuraDeployer throws an exception

      I came across a problem where the structural deployers protocol
      leads to a misleading error message when a structural deployer throws an error.

      Really under the current protocol, it's a bug in the EARStructure Deployer.

      You get something like:

      19:18:05,290 WARN [EARStructure] Error during determineStructure: dd-web.ear
      java.lang.RuntimeException: Error determining structure: dd-web.ear
       at org.jboss.deployment.EARStructure.determineStructure(EARStructure.java:252)
       at org.jboss.deployers.vfs.plugins.structure.StructureDeployerWrapper.determineStructure(StructureDeployerWrapper.java:66)
       at org.jboss.deployers.vfs.plugins.structure.VFSStructuralDeployersImpl.doDetermineStructure(VFSStructuralDeployersImpl.java:192)
       at org.jboss.deployers.vfs.plugins.structure.VFSStructuralDeployersImpl.determineStructure(VFSStructuralDeployersImpl.java:216)
       at org.jboss.deployers.structure.spi.helpers.AbstractStructuralDeployers.determineStructure(AbstractStructuralDeployers.java:80)
       at org.jboss.deployers.plugins.main.MainDeployerImpl.determineStructure(MainDeployerImpl.java:528)
       at org.jboss.deployers.plugins.main.MainDeployerImpl.addDeployment(MainDeployerImpl.java:257)
      Caused by: org.jboss.xb.binding.JBossXBException: Failed to parse source: description not found as a child of web
       at org.jboss.xb.binding.parser.sax.SaxJBossXBParser.parse(SaxJBossXBParser.java:193)
       at org.jboss.xb.binding.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:153)
       at org.jboss.deployment.EARStructure.determineStructure(EARStructure.java:151)
       ... 58 more
      Caused by: org.jboss.xb.binding.JBossXBRuntimeException: description not found as a child of web
       at org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler.startElement(SundayContentHandler.java:396)
       at org.jboss.xb.binding.parser.sax.SaxJBossXBParser$DelegatingContentHandler.startElement(SaxJBossXBParser.java:407)
       at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
       at org.apache.xerces.xinclude.XIncludeHandler.startElement(Unknown Source)
       at org.apache.xerces.impl.dtd.XMLDTDValidator.startElement(Unknown Source)
       at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
       at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
       at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
       at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
       at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
       at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
       at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
       at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
       at org.jboss.xb.binding.parser.sax.SaxJBossXBParser.parse(SaxJBossXBParser.java:189)
       ... 60 more
      19:18:05,292 WARN [JARStructure] Error determining structure: dd-web.ear
      java.lang.IllegalStateException: Context already exists with path '' contexts=[ContextInfoImpl{path= metaData=META-INF classPath=null}]
       at org.jboss.deployers.plugins.structure.StructureMetaDataImpl.addContext(StructureMetaDataImpl.java:59)
       at org.jboss.deployers.vfs.spi.structure.helpers.AbstractStructureDeployer.createContext(AbstractStructureDeployer.java:271)
       at org.jboss.deployers.vfs.plugins.structure.jar.JARStructure.determineStructure(JARStructure.java:122)
       at org.jboss.deployers.vfs.plugins.structure.StructureDeployerWrapper.determineStructure(StructureDeployerWrapper.java:66)
       at org.jboss.deployers.vfs.plugins.structure.VFSStructuralDeployersImpl.doDetermineStructure(VFSStructuralDeployersImpl.java:192)
       at org.jboss.deployers.vfs.plugins.structure.VFSStructuralDeployersImpl.determineStructure(VFSStructuralDeployersImpl.java:216)
       at org.jboss.deployers.structure.spi.helpers.AbstractStructuralDeployers.determineStructure(AbstractStructuralDeployers.java:80)
       at org.jboss.deployers.plugins.main.MainDeployerImpl.determineStructure(MainDeployerImpl.java:528)
       at org.jboss.deployers.plugins.main.MainDeployerImpl.addDeployment(MainDeployerImpl.java:257)
      


      The second error is obviously bogus.

      What has happened is that the EARStructure Deployer has recognised
      the deployment, but then thrown a RuntimeException because it can't parse the xml.

      It's obviously thrown the RuntimeException because it can't throw a
      DeploymentException since that's not part of the api.

      But the EARStructure hasn't tidied up the context it added
      when it recognised the deployment.

      This leads the StructureDeployerWrapper to say the EARStructure
      didn't recognise the deployment
      
       public boolean determineStructure(VirtualFile root, VirtualFile parent, VirtualFile file, StructureMetaData metaData, VFSStructuralDeployers deployers)
       {
       if (file == null)
       throw new IllegalArgumentException("Null file");
      
       try
       {
       boolean result = deployer.determineStructure(root, parent, file, metaData, deployers);
       if (log.isTraceEnabled())
       {
       if (result == false)
       log.trace("Not recognised: " + file.getName());
       else
       log.trace("Recognised: " + file.getName());
       }
       return result;
       }
       catch (Throwable t)
       {
      
      // ===========> HERE!
      
       log.warn("Error during determineStructure: " + file.getName(), t);
       return false;
       }
       }
      


      and so it goes onto the JARStructure.

      This recognises it as a jar but it fails to create the top level context
      because it is still there from the EARStructure. This is the bogus error message.

      There are two possible fixes.

      1) Fix the EARStructure to tidyup after itself. Like the JARStructure
      deployer
       catch (Exception e)
       {
       log.warn("Error determining structure: " + file.getName(), e);
      
      // =====> HERE!
      
       // Remove the invalid context
       if( context != null )
       metaData.removeContext(context);
       return false;
       }
      


      or

      2) We allow structure deployers to say it recognised the deployment
      but can't process it because of some error.
      i.e. we allow determineStructure() to throw a DeploymentException
      (or unchecked exception) and terminate the determineStructure()
      althogether when an error occurs, leaving the deployment in an ERROR state.


      My thoughts:

      Solution (1) was the original design because a broken deployer can't completely
      break the server, e.g.

      public class DenialOfService implements StructureDeployer
      {
       public DenialOfService()
       {
       // I'm first!
       setRelativeOrder(Integer.MIN_VALUE);
       }
      
       public boolean determineStructure(...)
       {
       throw new RuntimeException("Nobody can deploy anything!");
       }
      }
      


      but deploying an ear as a jar because the application.xml is malformed
      doesn't sound correct either.