Tutorial: Exposing SOAP Services as REST Resources
This tutorial will show you how to make a SOAP Web Service accessible as a REST resource.
To run the example do the following:
1. Download Membrane Service Proxy version 4.0.7 or above.
2. Execute service-proxy.bat in the MEMBRANE_HOME/examples/soap2Rest directory.
The script service-proxy.bat will start the router and load the proxies.xml file.
<spring:beans xmlns="http://membrane-soa.org/proxies/1/" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://membrane-soa.org/proxies/1/ http://membrane-soa.org/schemas/proxies-1.xsd"> <router> <serviceProxy name="BLZ" port="2000"> <rest2Soap> <mapping regex="/bank/.*" soapAction="" soapURI="/axis2/services/BLZService" requestXSLT="get2soap.xsl" responseXSLT="strip-env.xsl" /> </rest2Soap> <target host="thomas-bayer.com" /> </serviceProxy> </router> </spring:beans>
3. Now open the following URL:
http://localhost:2000/bank/37050198
You will receive a response like the following:
<ns1:getBankResponse xmlns:ns1=http://thomas-bayer.com/blz/ xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <ns1:details> <ns1:bezeichnung>Sparkasse KölnBonn</ns1:bezeichnung> <ns1:bic>COLSDE33XXX</ns1:bic> <ns1:ort>Köln</ns1:ort> <ns1:plz>50667</ns1:plz> </ns1:details> </ns1:getBankResponse>
How it Works
Take a look at the proxies.xml file. Notice the rest2Soap element. It contains all the information needed to expose a SOAP service as REST resource.
<rest2Soap> <mapping regex="/bank/.*" soapAction="" soapURI="/axis2/services/BLZService" requestXSLT="get2soap.xsl" responseXSLT="strip-env.xsl" /> </rest2Soap>
The interceptor can be configured with nested mapping elements.
<mapping regex="/bank/.*" soapAction="" soapURI="/axis2/services/BLZService" requestXSLT="get2soap.xsl" responseXSLT="strip-env.xsl" />
Each mapping element has a regex attribute that will by matched against the URI of incoming requests. The data given by the first mapping element whose regex matches the URI will be used for the following steps. If no match is found, nothing will be done.
In this tutorial the regular expression bank/.* will match /bank/37050198 so that the interceptor uses the mapping element's other attributes and continues with the next step.
If we open the following URL in a browser,
http://localhost:2000/bank/37050198
the browser will send a HTTP request to Membrane similar to the following one:
GET /bank/37050198 HTTP/1.1 Host: www.thomas-bayer.com:80 User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive X-Forwarded-For: 0:0:0:0:0:0:0:1
Now the rest2Soap interceptor will transform the HTTP request into a temporary XML document. Usually this temporary XML document is used internally in memory only. Depending on your logging configuration, the temporary XML document might be dumped into the log file.
<http:request method="GET" http-version="1.1" xmlns:http="http://membrane-soa.org/schemas/http/v1/"> <uri value="/bank/37050198"> <path> <component>bank</component> <component>37050198</component> </path> </uri> <headers> <header name="Host">localhost:2000</header> <header name="User-Agent">Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1</header> <header name="Accept">text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</header> <header name="Accept-Language">de-de,de;q=0.8,en-us;q=0.5,en;q=0.3</header> <header name="Accept-Encoding">gzip, deflate</header> <header name="Accept-Charset">ISO-8859-1,utf-8;q=0.7,*;q=0.7</header> <header name="Keep-Alive">115</header> <header name="Connection">keep-alive</header> <header name="X-Forwarded-For">0:0:0:0:0:0:0:1</header> </headers> <body type="plain"><![CDATA[]]> </body> </http:request>
As you can see, there are elements for the HTTP headers too. This allows an XSLT stylesheet to reference HTTP headers when constructing the SOAP envelope in the next step. The stylesheet that is used to transform the XML document into a SOAP message is referenced by the mapping attribute "requestXSLT". In our example the stylesheet looks like the following:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"> <xsl:template match="/"> <s11:Envelope > <s11:Body> <blz:getBank xmlns:blz="http://thomas-bayer.com/blz/"> <blz:blz><xsl:value-of select="//path/component[2]"/></blz:blz> </blz:getBank> </s11:Body> </s11:Envelope> </xsl:template> </xsl:stylesheet>
After the transformation the SOAP message will look like the following:
<s11:Envelope xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://thomas-bayer.com/blz/"> <s11:Body> <ns1:getBank> <ns1:blz>37050198</ns1:blz> </ns1:getBank> </s11:Body> </s11:Envelope>
POST /axis2/services/BLZService HTTP/1.1 Host: www.thomas-bayer.com:80 User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive X-Forwarded-For: 0:0:0:0:0:0:0:1 Content-Length: 237 SOAPAction: Content-Type: text/xml;charset=UTF-8 <s11:Envelope xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://thomas-bayer.com/blz/"> <s11:Body> <ns1:getBank> <ns1:blz>37050198</ns1:blz> </ns1:getBank> </s11:Body> </s11:Envelope>
To view these transformation steps live in the log file, add two log interceptors to the serviceProxy in proxies.xml and re-issue the GET request described above.
<spring:beans xmlns="http://membrane-soa.org/proxies/1/" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://membrane-soa.org/proxies/1/ http://membrane-soa.org/schemas/proxies-1.xsd"> <router> <serviceProxy name="BLZ" port="2000"> <log /> <rest2Soap> <mapping regex="/bank/.*" soapAction="" soapURI="/axis2/services/BLZService" requestXSLT="get2soap.xsl" responseXSLT="strip-env.xsl" /> </rest2Soap> <log /> </serviceProxy> </router> </spring:beans>
After the transformation, Membrane sends this final HTTP request to the target service at www.thomas-bayer.com. The BLZService responses then with the following HTTP message:
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/xml;charset=UTF-8 Transfer-Encoding: chunked Date: Thu, 12 May 2011 15:05:17 GMT 195 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <ns1:getBankResponse xmlns:ns1="http://thomas-bayer.com/blz/"> <ns1:details> <ns1:bezeichnung>Sparkasse KölnBonn</ns1:bezeichnung> <ns1:bic>COLSDE33XXX</ns1:bic> <ns1:ort>Köln</ns1:ort> <ns1:plz>50667</ns1:plz> </ns1:details> </ns1:getBankResponse> </soapenv:Body> </soapenv:Envelope> 0
The interceptor then applies another XSLT stylesheet to the body of the response to strip the SOAP Envelope and Body from the XML document. The stylesheet performing this task is specified in the responseXSLT attribute. You will find a copy of the stylesheet below:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"> <xsl:template match="/"> <xsl:apply-templates select="//s11:Body/*"/> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates /> </xsl:copy> </xsl:template> </xsl:stylesheet>
Finally, the transformed response body will show up in your browser:
<ns1:getBankResponse xmlns:ns1=http://thomas-bayer.com/blz/ xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <ns1:details> <ns1:bezeichnung>Sparkasse KölnBonn</ns1:bezeichnung> <ns1:bic>COLSDE33XXX</ns1:bic> <ns1:ort>Köln</ns1:ort> <ns1:plz>50667</ns1:plz> </ns1:details> </ns1:getBankResponse>