Powered By Blogger

Sep 20, 2014

Validate XML messages using more than one schemas

Validate Mediator of WSO2 ESB can be used to validate requests since it is vital in order to maximize resource utilization. Validate mediator facilitates validating the request against multiple XSDs as well. 

This blog post describes a scenario where you have an one XSD which has a reference to another XSD.  

1. Create XSD files

Basically we have the main XSD (TestSchema.xsd) which has a reference to another XSD ( referenceSchema.xsd).  The two schemas are as follows.

TestSchema.xsd


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

xmlns:ns0="http://www.wso2.org/refer"
xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ns2="http://www.wso2.org/test"
attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="http://www.wso2.org/test">
 <xs:import namespace="http://www.wso2.org/refer"
               schemaLocation="referenceSchema.xsd" />
<xs:element name="test" type="ns0:refer">
</xs:element>
</xs:schema>


If you observer the schema definition, you can see there is a reference to the schema xmlns:ns0="http://www.wso2.org/refer" which is defined in the other schema file and type 'refer' is also defined in the second schema as follows.

referenceSchema.xsd


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ns0="http://www.wso2.org/refer"
attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="http://www.wso2.org/refer">
<xs:element name="refer" type="ns0:refer"></xs:element>
<xs:complexType name="refer">
<xs:sequence>
<xs:element minOccurs="1" name="name" >
 <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:minLength value="1" />
        </xs:restriction>
    </xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>


After you create the XSD, just upload them to the registry of WSO2 ESB at the location \_system\conf\


2. Create the Proxy Service

First let me consider about the validate mediator configuration which uses to validate the request



 <validate>

            <schema key="conf:/TestSchema.xsd"/>
            <resource location="referenceSchema.xsd" key="conf:/referenceSchema.xsd"/>
            <on-fail>
               <makefault version="soap11">
                  <code xmlns:tns="http://www.w3.org/2003/05/soap-envelope" value="tns:Receiver"/>
                  <reason value="Request is Invalid........"/>
                  <role/>
               </makefault>
               <log level="full"/>
               <property name="RESPONSE" value="true"/>
               <header name="To" action="remove"/>
               <send/>
               <drop/>
            </on-fail>
         </validate>


Basically we are validating the request against the schema TestSchema.xsd which states as key="conf:/TestSchema.xsd" which has a reference to the referenceSchema.xsd. 

In Validate mediator there is an attribute called <resource> to indicate on where to find other schemas. The key entry specifies the current location of the schema. ( key="conf:/referenceSchema.xsd") . In order to map schemas correctly, the 'location' entry in the Validate mediator should match with the 'schemaLocation' in the xsd. 

location="referenceSchema.xsd"
schemaLocation="referenceSchema.xsd"

The proxy configuration is as follows.



<?xml version="1.0" encoding="UTF-8"?>

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="TestProxy"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
       <validate>
            <schema key="conf:/TestSchema.xsd"/>
            <resource location="referenceSchema.xsd" key="conf:/referenceSchema.xsd"/>
            <on-fail>
               <makefault version="soap11">
                  <code xmlns:tns="http://www.w3.org/2003/05/soap-envelope" value="tns:Receiver"/>
                  <reason value="Request is Invalid........"/>
                  <role/>
               </makefault>
               <log level="full"/>
               <property name="RESPONSE" value="true"/>
               <header name="To" action="remove"/>
               <send/>
               <drop/>
            </on-fail>
         </validate>
         <respond/>
      </inSequence>
      <outSequence>
         <send/>
      </outSequence>
   </target>
   <description/>
</proxy>
                               

3. Testing the scenario

First you can send the below request


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <p:test xmlns:p="http://www.wso2.org/test" xmlns:q="http://www.wso2.org/refer">
         <q:name>sohani</q:name>
      </p:test>
   </soapenv:Body>
</soapenv:Envelope>


Then you will have a response as below.



<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">

   <soapenv:Header/>
   <soapenv:Body>
      <p:test xmlns:p="http://www.wso2.org/test" xmlns:q="http://www.wso2.org/refer">
         <q:name>sohani</q:name>
      </p:test>
   </soapenv:Body>
</soapenv:Envelope>


If you send an invalid request then you will receive the response as below.



<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <p:test xmlns:p="http://www.wso2.org/test" xmlns:q="http://www.wso2.org/refer">
         <q:name></q:name>
      </p:test>
   </soapenv:Body>
</soapenv:Envelope>




<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode xmlns:tns="http://www.w3.org/2003/05/soap-envelope">tns:Receiver</faultcode>
         <faultstring>Request is Invalid........</faultstring>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>









No comments:

Post a Comment