Misleading error when StructuraDeployer throws an exception
adrian.brock Nov 13, 2007 1:56 PMI 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.