Darran Lofthouse [
http://community.jboss.org/people/dlofthouse] modified the document:
"AS7 XML Parser Validation [Proposed Idea]"
To view the document, visit:
http://community.jboss.org/docs/DOC-17243
--------------------------------------------------------------
Within JBoss AS7 all of the configuration that can be written for standalone and domain
server is described by making use of XML schemas, the XML is then parsed using parsers
making StAX calls.
This approach has started to lead to possible issues in a couple of areas: -
* Error checking / reporting is duplicated across all of the parsers.
* No automated validation realistically possible that the parser implementation matches
the schema definition.
This article is to propose a possible wrapper around the existing XMLElementReader that at
server runtime takes over the error reporting during parsing, this in turn will open up
possibilites within the testsuite to validate that the calls the parser makes to the new
wrapper match the definition of the schema.
The change to the wrapper would potentially be intrusive as code making calls to the
XMLElementReader API and performing validation would need to change to make calls to the
new wrapper and remove the validation - having said that the wrapper is after all a
wrapper, this means that integration could be gradual e.g. it could be introduced on a
subsystem by subsystem basis as a subsystem moves to a new namespace version.
h2. Runtime
The proposal is that a wrapper around the XMLElementReader that implements the following
interface will be provided: -
public interface ValidatingXmlReader {
/**
* Identify if the next element is the element specified by 'name'
*
* @param name - the name to compare with the name of the next element.
* @param optional - is the next element optional.
* @throws UnexpectedAttributeException - if there are still attributes that have not
been read.
* @throws UnexpectedElementException - if optional is false and the next
* element does not match the name supplied.
* @throws UnexpectedContent - if the wrapping element had content that has not been
read.
* @throws MissingElementException - if optional is false and the end element is
encountered.
*
* @return true if the name of the next element matches the name supplied, otherwise
false.
*/
boolean nextElement(String name, boolean optional);
/**
* Return the content of the element.
*
* @param optional is content optional on the current element.
* @throws UnexpectedAttributeException - if there are still attributes that have not
been read.
*
* @return the content of the element or null if it is optional and not specified.
*/
String readElementContent(boolean optional);
/**
* Return the value of the specified attribute.
*
* @param name - the name of the attribute to read.
* @param optional - is this an optional attribute?
* @throws MissingAttributeException - if the element is not optional and it is not
specified.
* @return the value of the attribute or null if it is optional and not specified.
*/
String readAttribute(String name, boolean optional);
/**
* Verifies that an end element has been reached.
*
* @throws UnexpectedAttributeException - if there are still attributes that have not
been read.
* @throws UnexpectedElementException - if optional is false and the next
* element does not match the name supplied.
* @throws UnexpectedContent - if the element had content that has not been read.
*/
void endElement();
}
The following (modified) complex type definition is for the host element in the host.xml
configuration file: -
<xs:element name='host'>
<xs:complexType>
<xs:sequence>
<xs:element name='system-properties'
type='properties-with-boottime' minOccurs='0'/>
<xs:element name='paths' type='specified-pathsType'
minOccurs='0' maxOccurs='1' />
<xs:element name='management' type='managementType'
minOccurs='0' maxOccurs='1'/>
<xs:element name='domain-controller'
type='domain-controllerType'/>
<xs:element name='interfaces'
type='specified-interfacesType' minOccurs='0'
maxOccurs='unbounded'/>
</xs:sequence>
<xs:attribute name='name' type='xs:string'
use='optional'/>
</xs:complexType>
</xs:element>
Using the new wrapper to read an XML document containing this type would be as: -
private void readHostElement(final ValidatingXmlReader reader, final ModelNode
address, final List list) {
String name = reader.readAttribute("name", true);
if (reader.nextElement("system-properties", true)) {
readSystemProperties(reader, address, list);
}
if (reader.nextElement("paths", true)) {
readPaths(reader, address, list);
}
if (reader.nextElement("management", true)) {
readManagement(reader, address, list);
}
if (reader.nextElement("domain-controller", false)) {
readDomainController(reader, address, list);
}
while (reader.nextElement("interfaces", true)) {
readInterfaces(reader, address, list);
}
reader.endElement();
}
So the call structure still follows the same structure we are already using, the main
difference is that apart from the call to end element to signify that we have reached the
end there is now no element / attribute checking or error handling - the wrapper handles
all of that now by keeping up with the calls from the parser.
Here are a few possible errors that could have been reported here: -
* If an additional attribute was provided an exception would have been thrown from the
call to nextElement for "system-properties"
* If an additional "paths" element was supplied an exception would have been
called from the call to nextElement for "domain-controller"
* If the "domain-controller" element was missing the call to nextElement for
"domain-controller" would thrown an exception.
* If an additional "domain-controler" element was provided the call to
endElement would throw an exception.
h2. Testsuite
+*Note:* The testsuite enhancement introduces schema validation, this is an overhead
however it only applies during specific tests - everything else will just be using the
wrapper with no notion of the underlying schema.+
As the change requires the parsers to specify the elements and attributes expected and
identify if the requested items are optional when running within the testsuite it would
also be potentially possible to verify those calls against the schema definition, this
would allow the following scenarios to be detected within the testsuite: -
* Missed calls for seldom used optional elements / attributes.
* Calls for elements / attributes not specified in the schema.
* Missed calls for subsequent instances of elements where more than one can be supplied.
* Calls for additional instances of elements beyond the limits specified in the schema.
For testing within the testsuite the first pre-requisit to resolve will be obtaining a
representation of the schema at least to the point of fully modelling the structure of the
schema.
For test cases the idea would be to perform the validated testing in issolation within the
testsuite, the test would be to load configuration (or configuration extracts for
subsystems) that uses all of the possible XML structure - the resulting operations will
not be executed against a server so the test is just that the entire schema is supported
and results in ModelNode operations.
Similar to code coverage tools the validating wrapper can monitor how much of the schema
is actually visited during testing, a report could be generated of areas not visited and
even a pre-determined threshold set for how much of schema to cover automatically failing
the test if the threshold is not met - this could provide a smoke test that automatically
fails if a new XML element is added but not visited during testing.
h4. Limitations
There are a couple of limitations in testing: -
* Where there is an XML choice in a schema multiple XML representations will be needed to
ensure all choices are tested.
* Where an element is unbounded the wrapper can validate that there was at lease one
optional call for the element after the last instance encountered, however it can not
validate how long the parser would keep looping for true unbounded.
--------------------------------------------------------------
Comment by going to Community
[
http://community.jboss.org/docs/DOC-17243]
Create a new document in JBoss AS7 Development at Community
[
http://community.jboss.org/choose-container!input.jspa?contentType=102&am...]