Using XML Validation Framework with Web Services
来源:百度文库 编辑:神马文学网 时间:2024/10/01 08:42:08
A good Web service has to have a well defined and enforceable contract. Typically, the contract is expressed using XML Schema language. Unfortunately, up until recently, enforcing the contact was very problematic because of the huge performance overhead associated with running schema validation. XML parsers used to load and parse the schema for every validation request, which was clearly expensive.
This has changed with the release JAXP 1.3 which comes with theschema validation framework which allows to first load and compile a schema and then reuse the compiled version for all subsequent validation requests. This may finally make it feasible to use the schema validation for Web services in production environment.
I decided to prototype the use of the validation framework for my Web services implemented in XFire (you may also want to explore aschema validation component implemented inServiceMix ESB).
All it took is a fairly simple handler:
public class XFireSchemaValidationHandler extends AbstractHandler {private Schema schema = null;public XFireSchemaValidationHandler() throws SAXException{super();setPhase(Phase.PARSE);before(ReadHeadersHandler.class.getName());// Load the schema - note that handler is only// instantiated once, so we can keep the schema in// an instance variableSchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);// I‘m hardcoding the path for now, but we should be able// to extract it from the WSDLStreamSource ss = new StreamSource(new File("/ws/xfire/etc/person.xsd"));schema = factory.newSchema(ss);}public void invoke(MessageContext ctx) throws Exception {InMessage message = ctx.getInMessage();XMLStreamReader streamReader = message.getXMLStreamReader();// create JDom from the stream - alternatively we can rely on// DOM and XFire DOM handlerStaxBuilder builder = new StaxBuilder();Document doc = builder.build(streamReader);// get to the body firstElement body =(Element)doc.getRootElement().getChildren().get(0);// we assume that we use "unwrapped" mode and// our payload is the direct child of the body elementElement payload = (Element) body.getChildren().get(0);// dump the message for testing purposesXMLOutputter outputter =new XMLOutputter(Format.getPrettyFormat());outputter.output(payload, System.out);// create validation handler from the pre-complied schemaValidatorHandler vh = schema.newValidatorHandler();// the handler only works with SAX events, so we create// SAX from JDomSAXOutputter so = new SAXOutputter(vh);// Validator will run as a SAX handler and throw an exception// if the validation fails.so.output(payload);System.out.println("\nValidation passed");// rewind the stream reader for subsequent processingmessage.setXMLStreamReader( new JDOMStreamReader( doc) );}}
Unfortunately, the validation framework does not currently support StAX, so an XML document has to be parsed using SAX or DOM (or JDom with subsequent SAX conversion which is what I chose to do since it was quicker to develop that way). I‘m sure this conversion (and the validation process itself) adds some performance overhead, but I‘m hoping that it won‘t be too bad, especially for simple schemas (and from my experience 90% of all Web services have very simple messages). JAX-RPC-compliant Web services engines should see even less of performance penalty since everything is loaded into DOM from the get-go. Perhaps I‘ll try to run some performance tests and see what happens.
This has changed with the release JAXP 1.3 which comes with theschema validation framework which allows to first load and compile a schema and then reuse the compiled version for all subsequent validation requests. This may finally make it feasible to use the schema validation for Web services in production environment.
I decided to prototype the use of the validation framework for my Web services implemented in XFire (you may also want to explore aschema validation component implemented inServiceMix ESB).
All it took is a fairly simple handler:
public class XFireSchemaValidationHandler extends AbstractHandler {private Schema schema = null;public XFireSchemaValidationHandler() throws SAXException{super();setPhase(Phase.PARSE);before(ReadHeadersHandler.class.getName());// Load the schema - note that handler is only// instantiated once, so we can keep the schema in// an instance variableSchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);// I‘m hardcoding the path for now, but we should be able// to extract it from the WSDLStreamSource ss = new StreamSource(new File("/ws/xfire/etc/person.xsd"));schema = factory.newSchema(ss);}public void invoke(MessageContext ctx) throws Exception {InMessage message = ctx.getInMessage();XMLStreamReader streamReader = message.getXMLStreamReader();// create JDom from the stream - alternatively we can rely on// DOM and XFire DOM handlerStaxBuilder builder = new StaxBuilder();Document doc = builder.build(streamReader);// get to the body firstElement body =(Element)doc.getRootElement().getChildren().get(0);// we assume that we use "unwrapped" mode and// our payload is the direct child of the body elementElement payload = (Element) body.getChildren().get(0);// dump the message for testing purposesXMLOutputter outputter =new XMLOutputter(Format.getPrettyFormat());outputter.output(payload, System.out);// create validation handler from the pre-complied schemaValidatorHandler vh = schema.newValidatorHandler();// the handler only works with SAX events, so we create// SAX from JDomSAXOutputter so = new SAXOutputter(vh);// Validator will run as a SAX handler and throw an exception// if the validation fails.so.output(payload);System.out.println("\nValidation passed");// rewind the stream reader for subsequent processingmessage.setXMLStreamReader( new JDOMStreamReader( doc) );}}
Unfortunately, the validation framework does not currently support StAX, so an XML document has to be parsed using SAX or DOM (or JDom with subsequent SAX conversion which is what I chose to do since it was quicker to develop that way). I‘m sure this conversion (and the validation process itself) adds some performance overhead, but I‘m hoping that it won‘t be too bad, especially for simple schemas (and from my experience 90% of all Web services have very simple messages). JAX-RPC-compliant Web services engines should see even less of performance penalty since everything is loaded into DOM from the get-go. Perhaps I‘ll try to run some performance tests and see what happens.
Using XML Validation Framework with Web Services
XML.com: Second Generation Web Services
XML.com: Telnet and REST Web Services?
Selective Validation Using ASP.NET Validation Controls
ASP.NET: Selectively Enable Form Validation When Using ASP.NET Web Controls -- MSDN Magazine, April
Web Services学习路线图之XML学习篇-SOA-Java
Web Services学习路线图之XML学习篇-SOA-Java
Using Lucene with OJB
Web services programming tips and tricks: SOAP attachments with JAX-RPC
web.xml
web.xml
Web.xml
Web Services的魅力
Using resource files with Delphi
Java Web Framework综述
Working with XML
SOA and Web services 新手入门
SOA and Web services 新手入门
Web Services overview - Design Issues
XML: Building with Oracle XML Database
Launching the Web 2.0 Framework
Using JAXB 2.1 with JavaSE 6
XML Web Service 基础
XML Web Service