Powered By Blogger

Sep 28, 2014

Removing additional namespace prefixes in the SOAP Fault using xslt


As some of you all know there is a limitation with AXIOM where is generates additional namespace prefixes inside the SOAP Fault. In order to get rid of the issue you can include a namespace prefix to the fault message generates from the Fault Mediator before sending back. You can easily do this by using an XSLT mediator. Please refer the proxy configuration and the xslt as a sample. 


TestProxy


<proxy xmlns="http://ws.apache.org/ns/synapse" name="TestProxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true"> 

    <target> 
        <inSequence> 
            <makefault version="soap11" response="true"> 
                <code xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/" value="soap11Env:VersionMismatch"/> 
                <reason value="Test the SOAP Message"/> 
                <role/> 
                <detail expression="/*[local-name()='Envelope']/*[local-name()='Body']/*"/> 
            </makefault> 
            <xslt key="prefixSet" source="//detail/child::node()"/> 
            <send/> 
        </inSequence> 
    </target> 
    <description/> 

</proxy> 



prefixSet.xslt 


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://some.data" version="1.0"> 

        <xsl:output omit-xml-declaration="yes" indent="yes"></xsl:output> 
        <xsl:strip-space elements="*"></xsl:strip-space> 
        <xsl:template match="node()|@*"> 
            <xsl:copy> 
                <xsl:apply-templates select="node()|@*"></xsl:apply-templates> 
            </xsl:copy> 
        </xsl:template> 
        <xsl:template match="*"> 
            <xsl:element name="ns0:{name()}" namespace="http://some.data"> 
                <xsl:copy-of select="namespace::*"></xsl:copy-of> 
                <xsl:apply-templates select="node()|@*"></xsl:apply-templates> 
            </xsl:element> 
        </xsl:template> 
    </xsl:stylesheet> 

This transformation applies for the fault message and includes in the OMElement created, and provides a response with a predefined namespace prefix as follows.



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

   <soapenv:Body>
      <soapenv:Fault>
         <faultcode xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/">soap11Env:VersionMismatch</faultcode>
         <faultstring>Test the SOAP Message</faultstring>
         <detail>
            <ns0:someData xmlns:ns0="http://some.data">
               <ns0:blaData/>
            </ns0:someData>
         </detail>
      </soapenv:Fault>
   </soapenv:Body>

</soapenv:Envelope>



Save the thread dump when server starts as a background service

When you do a normal server start up and if you kill the process using the command 
kill -3 <%PID%> then you can view the thread dump in the console. But if you start the server as a background service then it is impossible to view the thread dump in the console. In order to view it follow the below steps.

1. Start the server as a background process by using the below command 

sh ./wso2server.sh start 

2. Run the below command

jstack %PID% > threaddump.txt

Please note the PID is the process ID and you can get this by running the command ps -ax|grep wso2 )



Also if you start the server with nohup command  (nohup wso2server.sh)  then you can see the thread dump in the nohup.out



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>









Share database across computers on the same network


In order to allow remote access to your mysql server, first you need to change the "bind-address". By default it only allows connections from localhost therefore to allow connections from all networks just comment the line "bind-address = 127.0.0.1" in /etc/mysql/my.cnf

Let's assume that you want to grant permission to a database called 'testDB', you can easily grant permission using below command


grant all privileges on testDB.* to '<uname>'@'%' IDENTIFIED BY '<password>';


Then the other machine on the network can access this database by using the command

mysql -u<uname> -p<password> -h<IP>