WSO2 ESB - Proxy Service Samples

Running the Proxy Services samples with WSO2 Enterprise Service Bus (ESB)

Sample 150: Introduction to proxy services

<definitions xmlns="http://ws.apache.org/ns/synapse">
    <proxy name="StockQuoteProxy">
        <target>
            <endpoint>
                <address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
            </endpoint>
            <outSequence>
                <send/>
            </outSequence>
        </target>
        <publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>
    </proxy>
</definitions>

Objective: Introduction to ESB proxy services

Prerequisites:
Start the Synapse configuration numbered 150: i.e. wso2esb-samples -sn 150
Start the Axis2 server and deploy the SimpleStockQuoteService if not already done

Once ESB starts, you could go to http://localhost:8280/services/StockQuoteProxy?wsdl and view the WSDL generated for the proxy service defined in the configuration. This WSDL is based on the source WSDL supplied in the proxy service definition, and is updated to reflect the proxy service EPR.

Execute the stock quote client by requesting for a stock quote on the proxy service as follows:

ant stockquote -Daddurl=http://localhost:8280/services/StockQuoteProxy

An 'inSequence' or 'endpoint' or both of these would decide how the message would be handled after the proxy service receives the message. In the above example, the request received is forwarded to the sample service hosted on Axis2. The 'outSequence' defines how the response is handled before it is sent back to the client. By default, a proxy service is exposed over all transports configured for ESB, unless these are specifically mentioned through the 'transports' attribute.

Sample 151: Custom sequences and endpoints with proxy services

<definitions xmlns="http://ws.apache.org/ns/synapse">

    <sequence name="proxy_1">
        <send>
            <endpoint><address uri="http://localhost:9000/services/SimpleStockQuoteService"/></endpoint>
        </send>
    </sequence>
    <sequence name="out">
        <send/>
    </sequence>
    <endpoint name="proxy_2_endpoint">
        <address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
    </endpoint>
    <localEntry key="proxy_wsdl" src="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>

    <proxy name="StockQuoteProxy1">
        <publishWSDL key="proxy_wsdl"/>
        <target inSequence="proxy_1" outSequence="out"/>
    </proxy>

    <proxy name="StockQuoteProxy2">
        <publishWSDL key="proxy_wsdl"/>
        <target endpoint="proxy_2_endpoint" outSequence="out"/>
    </proxy>
</definitions>

Objective: Using custom sequences and endpoints for message mediation with proxy services

Prerequisites:
Start the Synapse configuration numbered 151: i.e. wso2esb-samples -sn 151
Start the Axis2 server and deploy the SimpleStockQuoteService if not already done

This configuration creates two proxy services.. The first proxy service 'StockQuoteProxy1' uses the sequence named 'proxy_1' to process incoming messages and the sequence named "out" to process outgoing responses. The second proxy service 'StockQuoteProxy2' is set to directly forward messages that are received to the endpoint named 'proxy_2_endpoint' without any mediation.

You could send a stock quote request to each of these proxy services and receive the reply generated by the actual service hosted on the Axis2 instance.

ant stockquote -Daddurl=http://localhost:8280/services/StockQuoteProxy1
ant stockquote -Daddurl=http://localhost:8280/services/StockQuoteProxy2

Sample 152: Switching transports and message format from SOAP to REST/POX

<definitions xmlns="http://ws.apache.org/ns/synapse">
    <proxy name="StockQuoteProxy" transports="https">
        <target>
            <endpoint>
                <address uri="http://localhost:9000/services/SimpleStockQuoteService" format="pox"/>
            </endpoint>
            <outSequence>
                <send/>
            </outSequence>
        </target>
        <publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>
    </proxy>
</definitions>

Objective: Switching transports and message format from SOAP to REST/POX

Prerequisites:
Start the Synapse configuration numbered 152: i.e. wso2esb-samples -sn 152

Start the Axis2 server and deploy the SimpleStockQuoteService if not already done

This configuration demonstrates how a proxy service could be exposed on a subset of available transports, and how it could switch from one transport to another. This example exposes the created proxy service only on https, and thus if the user tries to access it over http, would result in a fault.

ant stockquote -Dtrpurl=http://localhost:8280/services/StockQuoteProxy
...
     [java] org.apache.axis2.AxisFault: The service cannot be found for the endpoint reference (EPR) /services/StockQuoteProxy

Accessing this over https (ant stockquote -Dtrpurl=https://localhost:8243/services/StockQuoteProxy) causes the proxy service to access the SimpleStockQuoteService on the sample Axis2 server using REST/POX. This could be seen if the message exchange was captured using TCPMon as follows. The REST/POX response is now transformed back into a SOAP message and returned to the client.

POST http://localhost:9000/services/SimpleStockQuoteService HTTP/1.1
Host: 127.0.0.1
SOAPAction: urn:getQuote
Content-Type: application/xml; charset=UTF-8;action="urn:getQuote";
Transfer-Encoding: chunked
Connection: Keep-Alive
User-Agent: Synapse-HttpComponents-NIO

75
<m0:getQuote xmlns:m0="http://services.samples/xsd">
   <m0:request>
      <m0:symbol>IBM</m0:symbol>
   </m0:request>
</m0:getQuote>
HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8;action="http://services.samples/SimpleStockQuoteServicePortType/getQuoteResponse";
Date: Tue, 24 Apr 2007 14:42:11 GMT
Server: Synapse-HttpComponents-NIO
Transfer-Encoding: chunked
Connection: Keep-Alive

2b3
<ns:getQuoteResponse xmlns:ns="http://services.samples/xsd">
   <ns:return>
      <ns:change>3.7730036841862384</ns:change>
      <ns:earnings>-9.950236235550818</ns:earnings>
      <ns:high>-80.23868444613285</ns:high>
      <ns:last>80.50750970812187</ns:last>
      <ns:lastTradeTimestamp>Tue Apr 24 20:42:11 LKT 2007</ns:lastTradeTimestamp>
      <ns:low>-79.67368355714606</ns:low>
      <ns:marketCap>4.502043663670823E7</ns:marketCap>
      <ns:name>IBM Company</ns:name>
      <ns:open>-80.02229531286982</ns:open>
      <ns:peRatio>25.089295161182022</ns:peRatio>
      <ns:percentageChange>4.28842665653824</ns:percentageChange>
      <ns:prevClose>87.98107059692451</ns:prevClose>
      <ns:symbol>IBM</ns:symbol>
      <ns:volume>19941</ns:volume>
   </ns:return></ns:getQuoteResponse>

Sample 153: Routing the messages arrived to a proxy service without processing the security headers

<definitions xmlns="http://ws.apache.org/ns/synapse">
    <proxy name="StockQuoteProxy">
        <target>
            <inSequence>
		<property name="preserveProcessedHeaders" value="true"/>
                <send>
                    <endpoint>
                        <address uri="http://localhost:9000/services/SecureStockQuoteService"/>
                    </endpoint>
                </send>
            </inSequence>
            <outSequence>
                <send/>
            </outSequence>
        </target>
        <publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>
    </proxy>
</definitions>

Objective: Routing the messages arrived to a proxy service without processing the MustUnderstand headers (Security header)

Prerequisites:
You may also need to download and install the unlimited strength policy files for your JDK before using Apache Rampart (e.g. see http://java.sun.com/javase/downloads/index_jdk5.jsp)

Start the Synapse configuration numbered 153: i.e. wso2esb-samples -sn 153
Start the Axis2 server and deploy the SecureStockQuoteService if not already done

The proxy service will receive secure messages with security headers which are MustUnderstand. But hence element 'engageSec' is not present in the proxy configuration ESB will not engage that Apache Rampart on this proxy service. It is expected that an MustUnderstand failure exception on the AxisEngine would occur before the message arrives ESB. But ESB handles this message and gets it in by setting all the headers which are MustUnderstand and not processed to processed state. This will enable ESB to route the messages without reading the Security headers (just routing the messages from client to service, both of which are secure). To execute the client, send a stock quote request to the proxy service, and sign and encrypt the request by specifying the client side security policy as follows:

ant stockquote -Dtrpurl=http://localhost:8280/services/StockQuoteProxy -Dpolicy=./../../repository/samples/resources/policy/client_policy_3.xml

By following through the debug logs or TCPMon output, you could see that the request received by the proxy service was signed and encrypted. Also, looking up the WSDL of the proxy service by requesting the URL http://localhost:8280/services/StockQuoteProxy?wsdl reveals the security policy attachments are not there and security is not engaged. When sending the message to the backend service, you could verify that the security headers were there as in the original message to ESB from client, and that the response received does use WS-Security, and forwarded back to the client without any modification. You should note that this wont be a security hole because the message inside ESB is signed and encrypted and can only be forwarded to a secure service to be useful.

Sample 154: Load Balancing with Proxy Services

   <!-- A proxy service with a loadbalace endpoint -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
    <proxy name="LBProxy" transports="https http" startOnLoad="true">
        <target faultSequence="errorHandler">
            <inSequence>
                <send>
                    <endpoint>
                        <session type="simpleClientSession"/>
                        <loadbalance algorithm="org.apache.synapse.endpoints.algorithms.RoundRobin">
                            <endpoint>
                                <address uri="http://localhost:9001/services/LBService1">
                                    <enableAddressing/>
                                    <suspendDurationOnFailure>20</suspendDurationOnFailure>
                                </address>
                            </endpoint>
                            <endpoint>
                                <address uri="http://localhost:9002/services/LBService1">
                                    <enableAddressing/>
                                    <suspendDurationOnFailure>20</suspendDurationOnFailure>
                                </address>
                            </endpoint>
                            <endpoint>
                                <address uri="http://localhost:9003/services/LBService1">
                                    <enableAddressing/>
                                    <suspendDurationOnFailure>20</suspendDurationOnFailure>
                                </address>
                            </endpoint>
                        </loadbalance>
                    </endpoint>
                </send>
                <drop/>
            </inSequence>
            <outSequence>
                <send/>
            </outSequence>
        </target>
        <publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_2.wsdl"/>
    </proxy>
    <sequence name="errorHandler">

        <makefault>
            <code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
            <reason value="COULDN'T SEND THE MESSAGE TO THE SERVER."/>
        </makefault>

        <header name="To" action="remove"/>
        <property name="RESPONSE" value="true"/>

        <send/>
    </sequence>
</definitions> 

Objective: Load Balancing with Proxy Service

Prerequisites:

Sample setup is same as LoadBalance endpoints (#53 to #54).

Start the Synapse configuration numbered 154: i.e. wso2esb-samples -sn 154
Start the Axis2 server and deploy the LoadbalanceFailoverService if not already done

Runs the client with

 ant loadbalancefailover -Dmode=session -Dtrpurl=http://localhost:8280/services/LBProxy

Functionality is similar to the sample #54.

Sample 155: Dual channel invocation on both client side and serverside of synapse with Proxy Services

<definitions xmlns="http://ws.apache.org/ns/synapse">
    <proxy name="StockQuoteProxy">
        <target>
            <endpoint>
                <address uri="http://localhost:9000/services/SimpleStockQuoteService">
                    <enableAddressing separateListener="true"/>
                </address>
            </endpoint>
            <outSequence>
                <send/>
            </outSequence>
        </target>
        <publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>
    </proxy>
</definitions>

Objective: Demonstrate the dual channel invocation with Synapse proxy services

Prerequisites:
Start the Synapse configuration numbered 155: i.e. wso2esb-samples -sn 155
Start the Axis2 server and deploy the SimpleStockQuoteService if not already done

This sample will show the action of the dual channel invocation within client and Synapse as well as within synapse and the actual server. Note that if you want to enable dual channel invocation you need to set the separateListener attribute to true of the enableAddressing element of the endpoint.

Execute the stock quote client by requesting for a stock quote on a dual channel from the proxy service as follows:

ant stockquote -Daddurl=http://localhost:8280/services/StockQuoteProxy -Dmode=dualquote

In the above example, the request received is forwarded to the sample service hosted on Axis2 and the endpoint specifies to enable addressing and do the invocation over a dual channel. If you observe this message flow by using a TCPmon, you could see that on the channel you send the request to synapse the response has been written as an HTTP 202 Accepted, where as the real response from synapse will come over a different channel which cannot be obsesrved unless you use tcpdump to dump all the TCP level messages.

At the same time you can observe the behaviour of the invocation between synapse and the actual Axis2 service, where you can see a 202 Accepted message being delivered to synapse as the response to the request. The actual response will be delivered to synapse over a different channel.

Sample 156: Service Integration with specifying the receiving sequence

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

<!-- Service Integration with specifying the receiving sequence -->
<definitions xmlns="http://ws.apache.org/ns/synapse">

    <localEntry key="sec_policy" src="file:repository/conf/sample/resources/policy/policy_3.xml"/>

    <proxy name="StockQuoteProxy">
        <target>
            <inSequence>
                <enrich>
                    <source type="body"/>
                    <target type="property" property="REQUEST"/>
                </enrich>

                <send receive="SimpleServiceSeq">
                    <endpoint name="secure">
                        <address uri="http://localhost:9000/services/SecureStockQuoteService">
                            <enableSec policy="sec_policy"/>
                        </address>
                    </endpoint>
                </send>
            </inSequence>
            <outSequence>
                <drop/>
            </outSequence>
        </target>
    </proxy>


    <sequence name="SimpleServiceSeq">
        <property name="SECURE_SER_AMT" expression="//ns:getQuoteResponse/ns:return/ax21:last"
                xmlns:ns="http://services.samples" xmlns:ax21="http://services.samples/xsd"/>
        <log level="custom">
            <property name="SecureStockQuoteService-Amount" expression="get-property('SECURE_SER_AMT')"/>
        </log>
        <enrich>
            <source type="body"/>
            <target type="property" property="SecureService_Res"/>
        </enrich>
        <enrich>
            <source type="property" property="REQUEST"/>
            <target type="body"/>
        </enrich>
        <send receive="ClientOutSeq">
            <endpoint name="SimpleStockQuoteService">
                <address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
            </endpoint>
        </send>
    </sequence>

    <sequence name="ClientOutSeq">
        <property name="SIMPLE_SER_AMT" expression="//ns:getQuoteResponse/ns:return/ax21:last"
                       xmlns:ns="http://services.samples" xmlns:ax21="http://services.samples/xsd"/>
        <log level="custom">
            <property name="SimpleStockQuoteService-Amount" expression="get-property('SIMPLE_SER_AMT')"/>
        </log>
        <enrich>
            <source type="body"/>
            <target type="property" property="SimpleService_Res"/>
        </enrich>

        <filter xpath="fn:number(get-property('SIMPLE_SER_AMT')) > fn:number(get-property('SECURE_SER_AMT'))">
            <then>
                <log>
                    <property name="StockQuote" value="SecureStockQuoteService"/>
                </log>
                <enrich>
                    <source type="property" property="SecureService_Res"/>
                    <target type="body"/>
                </enrich>
            </then>
            <else>
                <log>
                    <property name="StockQuote" value="SimpleStockQuoteService"/>
                </log>
            </else>
        </filter>

        <send/>
    </sequence>

</definitions>

Objective: Using synapse to integrate services.

Prerequisites:
We will be using two services in this sample; i.e. SimpleStockQuoteService and SecureStockQuoteService. Therefore the prerequisites of sample 100 is also applied here.

Start the Synapse configuration numbered 156: i.e. wso2esb-samples -sn 156
Start the Axis2 server and deploy the SimpleStockQuoteService if not already done.

This sample contains a proxy service which provides the seamless integration of SimpleStockQuoteService and SecureStockQuoteService. Once a client send a request to this proxy service, it sends the same request to both these services and resolve the service with cheapest stock quote price.

Execute the stock quote client by requesting for a cheapest stock quote from the proxy service as follows:

ant stockquote -Daddurl=http://localhost:8280/services/StockQuoteProxy

Above sample uses the concept of specifying the receiving sequence in the send mediator. In this case once the message is sent from the in sequence then the response won't come to out sequence as the receiving sequence is specified in the send mediator.

Sample 157: Conditional Router for Routing Messages based on HTTP URL, HTTP Headers and Query Parameters

<definitions xmlns="http://ws.apache.org/ns/synapse">
    <proxy name="StockQuoteProxy" transports="https http" startOnLoad="true" trace="disable">
        <target>
            <inSequence>
                <conditionalRouter continueAfter="false">
                    <conditionalRoute breakRoute="false">
                        <condition>
                            <match xmlns="" type="header" source="foo" regex="bar.*"/>
                        </condition>
                        <target sequence="cnd1_seq"/>
                    </conditionalRoute>

                    <conditionalRoute breakRoute="false">
                        <condition>
                            <and xmlns="">
                                <match type="header" source="my_custom_header1" regex="foo.*"/>
                                <match type="url" regex="/services/StockQuoteProxy.*"/>
                            </and>
                        </condition>
                        <target sequence="cnd2_seq"/>
                    </conditionalRoute>

                    <conditionalRoute breakRoute="false">
                        <condition>
                            <and xmlns="">
                                <match type="header" source="my_custom_header2" regex="bar.*"/>
                                <equal type="param" source="qparam1" value="qpv_foo"/>
                                <or>
                                    <match type="url" regex="/services/StockQuoteProxy.*"/>
                                    <match type="header" source="my_custom_header3" regex="foo.*"/>
                                </or>
                                <not>
                                    <equal type="param" source="qparam2" value="qpv_bar"/>
                                </not>
                            </and>
                        </condition>
                        <target sequence="cnd3_seq"/>
                    </conditionalRoute>
                </conditionalRouter>
            </inSequence>
            <outSequence>
                <send/>
            </outSequence>
        </target>
    </proxy>

    <sequence name="cnd1_seq">
        <log level="custom">
            <property name="MSG_FLOW" value="Condition (I) Satisfied"/>
        </log>
        <sequence key="send_seq"/>
    </sequence>
    <sequence name="cnd2_seq">
        <log level="custom">
            <property name="MSG_FLOW" value="Condition (II) Satisfied"/>
        </log>
        <sequence key="send_seq"/>
    </sequence>
    <sequence name="cnd3_seq">
        <log level="custom">
            <property name="MSG_FLOW" value="Condition (III) Satisfied"/>
        </log>
        <sequence key="send_seq"/>
    </sequence>

    <sequence name="send_seq">
        <log level="custom">
            <property name="DEBUG" value="Condition Satisfied"/>
        </log>
        <send>
            <endpoint name="simple">
                <address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
            </endpoint>
        </send>
    </sequence>
</definitions>

    

Objective: Routing Messages based on the HTTP Transport properties.

Prerequisites:
Start the Synapse configuration numbered 157: i.e. wso2esb-samples -sn 157
Start the Axis2 server and deploy the SimpleStockQuoteService if not already done. For this particular case we will be using 'curl' to send requests with custom HTTP Headers to the proxy service. You may use a similar tool with facilitate those requirements.

The request file : stockQuoteReq.xml, should contain the following request.

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ser="http://services.samples" xmlns:xsd="http://services.samples/xsd">
   <soap:Header/>
   <soap:Body>
      <ser:getQuote>
         <ser:request>
            <xsd:symbol>IBM</xsd:symbol>
         </ser:request>
      </ser:getQuote>
   </soap:Body>
</soap:Envelope>

Condition I : Matching HTTP Header

curl -d @stockQuoteReq.xml -H "Content-Type: application/soap+xml;charset=UTF-8" -H "foo:bar" "http://localhost:8280/services/StockQuoteProxy"
    

Condition II : Matching HTTP Header AND Url

curl -d @stockQuoteReq.xml -H "Content-Type: application/soap+xml;charset=UTF-8" -H "my_custom_header1:foo1" "http://localhost:8280/services/StockQuoteProxy"

Condition III :
Complex conditions with AND, OR and NOT

curl -d @stockQuoteReq.xml -H "Content-Type: application/soap+xml;charset=UTF-8" -H "my_custom_header2:bar" -H "my_custom_header3:foo" "http://localhost:8280/services/StockQuoteProxy?qparam1=qpv_foo&qparam2=qpv_foo2"