This example invokes the one-way 'placeOrder' operation on the
SimpleStockQuoteService using the custom client which uses the Axis2
ServiceClient.fireAndForget() API. To test this, use 'ant
-Dmode=placeorder...' and you will notice the one way message flowing
through Synapse into the sample Axis2 server instance, which reports the
acceptance of the order as follows:
If you send your client request through TCPmon, you will notice that the
SimpleStockQuoteService replies to Synapse with a HTTP 202 reply, and that
Synapse in-turn replies to the client with a HTTP 202 acknowledgement
<!-- demonstrate JMS pure text, binary and POX message support -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="text_proxy">
<header name="Action" value="urn:placeOrder"/>
<script language="js"><![CDATA[
var args = mc.getPayloadXML().toString().split(" ");
mc.setPayloadXML(
<m:placeOrder xmlns:m="http://services.samples/xsd">
<m:order>
<m:price>{args[0]}</m:price>
<m:quantity>{args[1]}</m:quantity>
<m:symbol>{args[2]}</m:symbol>
</m:order>
</m:placeOrder>);
]]></script>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
</sequence>
<sequence name="mtom_proxy">
<header name="Action" value="urn:oneWayUploadUsingMTOM"/>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/MTOMSwASampleService" optimize="mtom"/>
</endpoint>
</send>
</sequence>
<sequence name="pox_proxy">
<header name="Action" value="urn:placeOrder"/>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService" format="soap"/>
</endpoint>
</send>
</sequence>
<sequence name="out">
<send/>
</sequence>
<proxy name="JMSFileUploadProxy" transports="jms">
<target inSequence="mtom_proxy" outSequence="out"/>
<parameter name="transport.jms.Wrapper">{http://services.samples/xsd}element</parameter>
</proxy>
<proxy name="JMSTextProxy" transports="jms">
<target inSequence="text_proxy" outSequence="out"/>
<parameter name="transport.jms.Wrapper">{http://services.samples/xsd}text</parameter>
</proxy>
<proxy name="JMSPoxProxy" transports="jms">
<target inSequence="pox_proxy" outSequence="out"/>
</proxy>
</definitions>
Objective: Pure POX/Text and Binary JMS Proxy services -
including MTOM
Pre-Requisites:
Configure JMS for
Synapse (Refer notes)
Start the Synapse configuration numbered
113: i.e. synapse -sample 113
Start the Axis2 server and deploy
the SimpleStockQuoteService and the MTOMSwASampleService if not already
done
This configuration creates three JMS proxy services named
JMSFileUploadProxy, JMSTextProxy and JMSPoxProxy exposed over JMS queues
with the same names as the services. The first part of this example
demonstrates the pure text message support with JMS, where a user sends a
space separated text JMS message of the form "<price> <qty>
<symbol>". Synapse converts this message into a SOAP message and
sends this to the SimpleStockQuoteServices' placeOrder operation. Synapse
uses the script mediator to transform the text message into a XML payload
using the Javascript support available to tokenize the string. The proxy
service property named "transport.jms.Wrapper" defines a custom wrapper
element QName, to be used when wrapping text/binary content into a SOAP
envelope.
Execute JMS client as follows. This will post a pure text JMS message with
the content defined (e.g. "12.33 1000 ACP") to the specified JMS
destination - dynamicQueues/JMSTextProxy
ant jmsclient -Djms_type=text -Djms_payload="12.33 1000 ACP" -Djms_dest=dynamicQueues/JMSTextProxy
Following the debug logs, you could notice that Synapse received the JMS
text message and transformed it into a SOAP payload as follows. Notice
that the wrapper element "{http://services.samples/xsd}text" has been used
to hold the text message content.
[JMSWorker-1] DEBUG ProxyServiceMessageReceiver - Body :
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body><axis2ns1:text xmlns:axis2ns1="http://services.samples/xsd">12.33 1000 ACP</axis2ns1:text></soapenv:Body>
</soapenv:Envelope>
Now, you could see how the script mediator created a stock quote request
by tokenizing the text as follows, and sent the message to the placeOrder
operation of the SimpleStockQuoteService.
[JMSWorker-1] DEBUG AddressEndpoint - Sending message to endpoint :: name = AnonymousEndpoints resolved address = http://localhost:9000/soap/SimpleStockQuoteService
[JMSWorker-1] DEBUG AddressEndpoint - SOAPAction: urn:placeOrder
[JMSWorker-1] DEBUG AddressEndpoint - WSA-Action: urn:placeOrder
[JMSWorker-1] DEBUG AddressEndpoint - Body :
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body>
<m:placeOrder xmlns:m="http://services.samples/xsd"><m:order><m:price>12.33</m:price><m:quantity>1000</m:quantity><m:symbol>ACP</m:symbol></m:order>
</m:placeOrder></soapenv:Body></soapenv:Envelope>
The sample Axis2 server would now accept the one way message and issue the
following message:
Wed Apr 25 19:50:56 LKT 2007 samples.services.SimpleStockQuoteService :: Accepted order for : 1000 stocks of ACP at $ 12.33
The next section of this example demonstrates how a pure binary JMS
message could be received and processed through Synapse. The configuration
creates a proxy service named 'JMSFileUploadProxy' that accepts binary
messages and wraps them into a custom element
'{http://services.samples/xsd}element'. The received message is then
forwarded to the MTOMSwASampleService using the SOAP action
'urn:oneWayUploadUsingMTOM' and optimizing binary conent using MTOM. To
execute this sample, use the JMS client to publish a pure binary JMS
message containing the file
'./../../repository/conf/sample/resources/mtom/asf-logo.gif' to the JMS
destination 'dynamicQueues/JMSFileUploadProxy' as follows:
ant jmsclient -Djms_type=binary -Djms_dest=dynamicQueues/JMSFileUploadProxy -Djms_payload=./../../repository/conf/sample/resources/mtom/asf-logo.gif
Examining the Synapse debug logs reveals that the binary content was
received over JMS and wrapped with the specified element into a SOAP
infoset as follows:
[JMSWorker-1] DEBUG ProxyServiceMessageReceiver - Proxy Service JMSFileUploadProxy received a new message...
...
[JMSWorker-1] DEBUG ProxyServiceMessageReceiver - Body :
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body><axis2ns1:element xmlns:axis2ns1="http://services.samples/xsd">R0lGODlhgw...AAOw==</axis2ns1:element></soapenv:Body>
</soapenv:Envelope>
Thereafter the message was sent as a MTOM optimized message as specified
by the 'format=mtom' attribute of the endpoint, to the
MTOMSwASampleService using the SOAP action 'urn:oneWayUploadUsingMTOM'.
Once received by the sample service, it is saved into a temporary file and
could be verified for correctness.
Wrote to file : /tmp/mtom-60319.gif
The final section of this example shows how a POX JMS message received by
Synapse is sent to the SimpleStockQuoteService as a SOAP message. Use the
JMS client as follows to create a POX (Plain Old XML) message with a stock
quote request payload (without a SOAP envelope), and send it to the JMS
destination 'dynamicQueues/JMSPoxProxy' as follows:
ant jmsclient -Djms_type=pox -Djms_dest=dynamicQueues/JMSPoxProxy -Djms_payload=MSFT
You can see that Synapse received the POX message and displays it as
follows in the debug logs, and then converts it into a SOAP payload and
sends to the SimpleStockQuoteService after setting the SOAP action as
'urn:placeOrder'.
[JMSWorker-1] DEBUG ProxyServiceMessageReceiver - Proxy Service JMSPoxProxy received a new message...
...
[JMSWorker-1] DEBUG ProxyServiceMessageReceiver - Body :
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><m:placeOrder xmlns:m="http://services.samples/xsd">
<m:order>
<m:price>172.39703010684752</m:price>
<m:quantity>19211</m:quantity>
<m:symbol>MSFT</m:symbol>
</m:order>
</m:placeOrder></soapenv:Body></soapenv:Envelope>
[JMSWorker-1] DEBUG ProxyServiceMessageReceiver - Using the sequence named pox_proxy for message mediation
...
[JMSWorker-1] DEBUG HeaderMediator - Setting header : Action to : urn:placeOrder
...
[JMSWorker-1] DEBUG AddressEndpoint - Sending message to endpoint :: name = AnonymousEndpoints resolved address = http://localhost:9000/soap/SimpleStockQuoteService
[JMSWorker-1] DEBUG AddressEndpoint - SOAPAction: urn:placeOrder
[JMSWorker-1] DEBUG AddressEndpoint - Body :
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><m:placeOrder xmlns:m="http://services.samples/xsd">
<m:order>
<m:price>172.39703010684752</m:price>
<m:quantity>19211</m:quantity>
<m:symbol>MSFT</m:symbol>
</m:order>
</m:placeOrder></soapenv:Body></soapenv:Envelope>
[JMSWorker-1] DEBUG Axis2FlexibleMEPClient - sending [add = false] [sec = false] [rm = false] [ mtom = false] [ swa = false] [ force soap=true; pox=false] [ to null]
The sample Axis2 server displays a successful message on the receipt of
the message as:
Wed Apr 25 20:24:50 LKT 2007 samples.services.SimpleStockQuoteService :: Accepted order for : 19211 stocks of MSFT at $ 172.39703010684752
<!-- one-way message bridging between JMS to HTTP and sending a 202 Accepted -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<proxy name="JMStoHTTPStockQuoteProxy" transports="jms">
<target>
<endpoint>
<address uri="http://localhost:9001/soap/SimpleStockQuoteService"/>
</endpoint>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
</proxy>
<proxy name="OneWayProxy" transports="http">
<target>
<inSequence>
<log level="full"/>
<property name="RESPONSE" value="true"/>
<header name="To" value="http://www.w3.org/2005/08/addressing/anonymous"/>
<property name="SC_ACCEPTED" value="true" scope="axis2"/>
<send/>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
</proxy>
</definitions>
Objective: Demonstrate one way message bridging from JMS to
http and replying with a http 202 Accepted response
Pre-Requisites:
Start the Axis2 server
and deploy the SimpleStockQuoteService if not already done
Start the Synapse configuration numbered 114: i.e. synapse -sample 114
This example invokes the one-way 'placeOrder' operation on the
SimpleStockQuoteService using the Axis2 ServiceClient.fireAndForget() API
at the client. To test this, use 'ant -Dmode=placeorder...' and you will
notice the one way JMS message flowing through Synapse into the sample
Axis2 server instance over http, and Axis2 acknowledging it with a http
202 Accepted response.
ant stockquote -Dmode=placeorder -Dtrpurl="jms:/JMStoHTTPStockQuoteProxy?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616"
SimpleStockQuoteService :: Accepted order for : 7482 stocks of IBM at $ 169.27205579038733
The second example shows how Synapse could be made to respond with a http
202 Accepted response to a request received. The proxy service simply logs
the message received and acknowledges it. On the Synapse console you could
see the logged message, and if TCPMon was used at the client, you would
see the 202 Accepted response sent back to the client from Synapse
ant stockquote -Dmode=placeorder -Dtrpurl=http://localhost:8080/soap/OneWayProxy
HTTP/1.1 202 Accepted
Content-Type: text/xml; charset=UTF-8
Host: 127.0.0.1
SOAPAction: "urn:placeOrder"
Date: Sun, 06 May 2007 17:20:19 GMT
Server: Synapse-HttpComponents-NIO
Transfer-Encoding: chunked
0
Synapse supports Mediators implemented in a variety of scripting languages
such as JavaScript, Python or Ruby. Implementing a Mediator with a script
language can have advantages over using the built in Synapse Mediator
types or implementing a custom Java class Mediator. Script Mediators have
all the flexibility of a class Mediator with access to the Synapse
MessageContext and SynapseEnvironment APIs, and the ease of use and
dynamic nature of scripting languages allows rapid development and
prototyping of custom mediators. An additional benefit of some scripting
languages is that they have very simple and elegant XML manipulation
capabilities, for example JavaScript E4X or Ruby REXML, so this makes them
well suited for use in the Synapse mediation environment.
The Synapse Script Mediator is a Synapse extension, and thus all
pre-requisites are not bundled by default with the Synapse distribution.
Before you use some script mediators you may need to manually add the
required jar files to the Synapse lib directory, and optionally perform
other installation tasks as may be required by the individual scripting
language. This is detailed in the Samples Setup guide.
<!-- Introduction to the script mediator -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<localEntry key="stockquoteScript" src="file:repository/conf/sample/resources/script/stockquoteTransformRequest.js"/>
<in>
<!-- transform the custom quote request into a standard quote request expected by the service -->
<script language="js" key="stockquoteScript" function="transformRequest"/>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
</in>
<out>
<!-- transform the standard response back into the custom format the client expects -->
<script language="js" key="stockquoteScript" function="transformResponse"/>
<send/>
</out>
</definitions>
<x><![CDATA[
function transformRequest(mc) {
var symbol = mc.getPayloadXML()..*::Code.toString();
mc.setPayloadXML(
<m:getQuote xmlns:m="http://services.samples/xsd">
<m:request>
<m:symbol>{symbol}</m:symbol>
</m:request>
</m:getQuote>);
}
function transformResponse(mc) {
var symbol = mc.getPayloadXML()..*::symbol.toString();
var price = mc.getPayloadXML()..*::last.toString();
mc.setPayloadXML(
<m:CheckPriceResponse xmlns:m="http://www.apache-synapse.org/test">
<m:Code>{symbol}</m:Code>
<m:Price>{price}</m:Price>
</m:CheckPriceResponse>);
}
]]></x>
Objective: Introduction to script mediators
Pre-Requisites:
Start the Synapse configuration numbered 500: i.e. synapse -sample 500
Start the Axis2 server and deploy the SimpleStockQuoteService if not
already done
This sample is similar to sample 8 but instead of using XSLT the
transformation is done with JavaScript and E4X. Note that the script
source loaded from a resource must be specified within a CDATA tag within
an XML element. The script used in this example has two functions,
'transformRequest' and 'transformResponse', and the Synapse configuration
uses the function attribute to specify which function should be invoked.
Use the stock quote client as follows to issue a custom quote client:
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/ -Dmode=customquote
Synapse uses the script mediator and the specified Javascript function to
convert the custom request to a standard quote request. Subsequently the
response received is transformed back and sent back to the client.
<!-- introduction to inline script mediation -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<in>
<!-- transform the custom quote request into a standard quote requst expected by the service -->
<script language="js"><![CDATA[
var symbol = mc.getPayloadXML()..*::Code.toString();
mc.setPayloadXML(
<m:getQuote xmlns:m="http://services.samples/xsd">
<m:request>
<m:symbol>{symbol}</m:symbol>
</m:request>
</m:getQuote>);
]]></script>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
</in>
<out>
<!-- transform the standard response back into the custom format the client expects -->
<script language="js"><![CDATA[
var symbol = mc.getPayloadXML()..*::symbol.toString();
var price = mc.getPayloadXML()..*::last.toString();
mc.setPayloadXML(
<m:CheckPriceResponse xmlns:m="http://www.apache-synapse.org/test">
<m:Code>{symbol}</m:Code>
<m:Price>{price}</m:Price>
</m:CheckPriceResponse>);
]]></script>
<send/>
</out>
</definitions>
Objective: Introduction to in-line script mediation
Pre-Requisites:
Start the Synapse configuration numbered 501: i.e. synapse -sample 501
Start the Axis2 server and deploy the SimpleStockQuoteService if not
already done
This example is functionally equivalent to sample # 500 and sample # 8,
and demonstrates in-line script mediation in Synapse. Use the stock quote
client to send a custom quote as in example # 500 to test this example.
<!-- accessing the Synapse APIs from scripting languages -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<in>
<!-- change the MessageContext into a response and set a response payload -->
<script language="js"><![CDATA[
mc.setTo(mc.getReplyTo());
mc.setProperty("RESPONSE", "true");
mc.setPayloadXML(
<ns:getQuoteResponse xmlns:ns="http://services.samples/xsd">
<ns:return>
<ns:last>99.9</ns:last>
</ns:return>
</ns:getQuoteResponse>);
]]></script>
</in>
<send/>
</definitions>
Objective: Accessing the Synapse APIs from scripting languages
Pre-Requisites:
Start the Synapse configuration numbered 502: i.e. bin/synapse -sample 502
This example shows how an inline Javascript mediator script could access
the Synapse message context API to set its 'To' EPR and to set a custom
property to mark it as a response. Execute the stock quote client, and you
will receive the response "99.9" as the last sale price as per the above
script.
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/
...
stockquote:
[java] Standard :: Stock price = $99.9
<!-- Introduction to the script mediator with Ruby scripts-->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<localEntry key="stockquoteScript" src="file:repository/conf/sample/resources/script/stockquoteTransform.rb"/>
<in>
<!-- transform the custom quote request into a standard quote request expected by the service -->
<script language="rb" key="stockquoteScript" function="transformRequest"/>
<!-- send message to real endpoint referenced by name "stockquote" and stop -->
<send>
<endpoint name="stockquote">
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
</in>
<out>
<!-- transform the standard response back into the custom format the client expects -->
<script language="rb" key="stockquoteScript" function="transformResponse"/>
<send/>
</out>
</definitions>
<x><![CDATA[
require 'rexml/document'
include REXML
def transformRequest(mc)
newRequest= Document.new '<m:getQuote xmlns:m="http://services.samples/xsd">'<<
'<m:request><m:symbol></m:symbol></m:request></m:getQuote>'
newRequest.root.elements[1].elements[1].text = mc.getPayloadXML().root.elements[1].get_text
mc.setPayloadXML(newRequest)
end
def transformResponse(mc)
newResponse = Document.new '<m:CheckPriceResponse xmlns:m="http://www.apache-synapse.org/test"><m:Code>' <<
'</m:Code><m:Price></m:Price></m:CheckPriceResponse>'
newResponse.root.elements[1].text = mc.getPayloadXML().root.elements[1].elements[1].get_text
newResponse.root.elements[2].text = mc.getPayloadXML().root.elements[1].elements[2].get_text
mc.setPayloadXML(newResponse)
end
]]></x>
Objective: Script mediators using Ruby
Pre-Requisites:
This sample uses Ruby so first setup support for this in Synapse as
described at Configuring JRuby.
Start the Synapse configuration numbered 503: i.e. bin/synapse -sample 503
Start the Axis2 server and deploy the SimpleStockQuoteService if not
already done
This sample is functionally equivalent to sample # 500 (#501 and #8) but
instead uses a Ruby script using the JRuby interpreter. The script has two
functions, 'transformRequest' and 'transformResponse', and the Synapse
configuration specifies which function is to be invoked when used. Execute
the stock quote client to send a custom stock quote as per example #500
and check the received stock quote response.
<!-- Demonstrate the use of class mediator -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="fault">
<makefault>
<code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
<reason value="Mediation failed."/>
</makefault>
<send/>
</sequence>
<sequence name="main" onError="fault">
<in>
<send>
<endpoint name="stockquote">
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
</in>
<out>
<class name="samples.mediators.DiscountQuoteMediator">
<property name="discountFactor" value="10"/>
<property name="bonusFor" value="5"/>
</class>
<send/>
</out>
</sequence>
</definitions>
Objective: Demonstrate the use of Class mediator to extend the
mediation functionality
Pre-Requisites:
Make sure the synapse-samples-1.0.jar is in your class path (by default
this jar is placed in the lib directory when installing Synapse).
Start Synapse with the sample configuration 600 (i.e. synapse -sample 600)
Start the sample Axis2 server and deploy the SimpleStockQuoteService.
In this configuration, Synapse hands over the request message to the
specified endpoint, which sends it to the Axis2 server running on port
9000.
But the response message is passed through the class mediator before
sending it back to the client. Two parameters named "discountFactor"
and "bonusFor" are passed to the instance mediator implementation class
(i.e. samples.mediators.DiscountQuoteMediator) before each
invocation. Code of the mediator implementation class is shown below.
package samples.mediators;
import org.apache.synapse.MessageContext;
import org.apache.synapse.Mediator;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.xml.namespace.QName;
public class DiscountQuoteMediator implements Mediator {
private static final Log log = LogFactory.getLog(DiscountQuoteMediator.class);
private String discountFactor="10";
private String bonusFor="10";
private int bonusCount=0;
public DiscountQuoteMediator(){}
public boolean mediate(MessageContext mc) {
String price= mc.getEnvelope().getBody().getFirstElement().getFirstElement().
getFirstChildWithName(new QName("http://services.samples/xsd","last")).getText();
//converting String properties into integers
int discount=Integer.parseInt(discountFactor);
int bonusNo=Integer.parseInt(bonusFor);
double currentPrice=Double.parseDouble(price);
//discounting factor is deducted from current price form every response
Double lastPrice = new Double(currentPrice - currentPrice * discount / 100);
//Special discount of 5% offers for the first responses as set in the bonusFor property
if (bonusCount <= bonusNo) {
lastPrice = new Double(lastPrice.doubleValue() - lastPrice.doubleValue() * 0.05);
bonusCount++;
}
String discountedPrice = lastPrice.toString();
mc.getEnvelope().getBody().getFirstElement().getFirstElement().getFirstChildWithName
(new QName("http://services.samples/xsd","last")).setText(discountedPrice);
System.out.println("Quote value discounted.");
System.out.println("Original price: " + price);
System.out.println("Discounted price: " + discountedPrice);
return true;
}
public String getType() {
return null;
}
public void setTraceState(int traceState) {
traceState = 0;
}
public int getTraceState() {
return 0;
}
public void setDiscountFactor(String discount) {
discountFactor=discount;
}
public String getDiscountFactor() {
return discountFactor;
}
public void setBonusFor(String bonus){
bonusFor=bonus;
}
public String getBonusFor(){
return bonusFor;
}
}
All classes specified for the Class mediatoe should implement the Mediator
interface, which contains the mediate(...) method. mediate(...) method of
the above class is invoked for each response message mediated through the
main sequence, with the message context of the current message as the
parameter. All the details of the message including the SOAP headers, SOAP
body and properties of the context hierachy can be accessed from the
message context. In this sample, the body of the message is retrieved and
discount percentage is substracted from the quote price. If the
quote request number is lesser than the number specified in the "bonusFor"
property in the configuration, a special discount is given.
Now run the client using the following command.
ant stockquote -Dsymbol=IBM -Dmode=quote -Daddurl=http://localhost:8080
You will see the below output in the client console with the discounted
quote value.
[java] Standard :: Stock price = $138.77458254967408
Now check the console running Synapse. You will see the original value and
the discounted value for the requested quote as follows.
Quote value discounted.
Original price: 162.30945327447262
Discounted price: 138.77458254967408
<definitions xmlns="http://ws.apache.org/ns/synapse"
xmlns:throttle="http://ws.apache.org/ns/synapse/throttle">
<sequence name="main">
<in>
<throttle:throttle>
<policy>
<!-- define throttle policy -->
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:throttle="http://www.wso2.org/products/wso2commons/throttle">
<throttle:ThrottleAssertion>
<wsp:All>
<throttle:ID throttle:type="IP">Other</throttle:ID>
<wsp:ExactlyOne>
<wsp:All>
<throttle:MaximumCount>4</throttle:MaximumCount>
<throttle:UnitTime>800000</throttle:UnitTime>
<throttle:ProhibitTimePeriod wsp:Optional="true">10000</throttle:ProhibitTimePeriod>
</wsp:All>
<throttle:IsAllow>true</throttle:IsAllow>
</wsp:ExactlyOne>
</wsp:All>
<wsp:All>
<throttle:ID throttle:type="IP">192.168.8.200-192.168.8.222</throttle:ID>
<wsp:ExactlyOne>
<wsp:All>
<throttle:MaximumCount>8</throttle:MaximumCount>
<throttle:UnitTime>800000</throttle:UnitTime>
<throttle:ProhibitTimePeriod wsp:Optional="true">10</throttle:ProhibitTimePeriod>
</wsp:All>
<throttle:IsAllow>true</throttle:IsAllow>
</wsp:ExactlyOne>
</wsp:All>
<wsp:All>
<throttle:ID throttle:type="IP">192.168.8.201</throttle:ID>
<wsp:ExactlyOne>
<wsp:All>
<throttle:MaximumCount>200</throttle:MaximumCount>
<throttle:UnitTime>600000</throttle:UnitTime>
<throttle:ProhibitTimePeriod wsp:Optional="true"></throttle:ProhibitTimePeriod>
</wsp:All>
<throttle:IsAllow>true</throttle:IsAllow>
</wsp:ExactlyOne>
</wsp:All>
<wsp:All>
<throttle:ID throttle:type="IP">192.168.8.198</throttle:ID>
<wsp:ExactlyOne>
<wsp:All>
<throttle:MaximumCount>50</throttle:MaximumCount>
<throttle:UnitTime>500000</throttle:UnitTime>
<throttle:ProhibitTimePeriod wsp:Optional="true"></throttle:ProhibitTimePeriod>
</wsp:All>
<throttle:IsAllow>true</throttle:IsAllow>
</wsp:ExactlyOne>
</wsp:All>
</throttle:ThrottleAssertion>
</wsp:Policy>
</policy>
<onAccept>
<log level="custom">
<property name="text" value="**Access Accept**"/>
</log>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
</onAccept>
<onReject>
<log level="custom">
<property name="text" value="**Access Denied**"/>
</log>
<makefault>
<code value="tns:Receiver"
xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
<reason value="**Access Denied**"/>
</makefault>
<property name="RESPONSE" value="true"/>
<header name="To" expression="get-property('ReplyTo')"/>
<send/>
<drop/>
</onReject>
</throttle:throttle>
</in>
<out>
<send/>
</out>
</sequence>
</definitions>
Objective: Demonstrate the use of throttle mediator for
restricting request counts
Pre-Requisites:
Deploy the SimpleStockQuoteService in sample Axis2 server and start it on
port 9000.
Start Synapse with the sample configuration 600 (i.e. synapse -sample
600).
Above configuration specifies a throttle mediator inside the in mediator.
Therefore, all request messages directed to the main sequence will be
subjected to throttling. Throttle mediator has policy, onAccept and
onReject tags at top level. Policy tag specifies the throttling policy to
be applied for messages. It contains some IP address ranges and maximum
number of messages to be allowed for those ranges within the time range
given in "UnitTime" tag. "ProhibitTimePeriod" tag specifies the time
period to prohibit further requests after the received request count
exceeds the specified time. Now run the client 5 times repetitively using
the below command to see how throttling works.
ant stockquote -Dsymbol=IBM -Dmode=quote -Daddurl=http://localhost:8080
For the first four requests you will get the quote prices for IBM as
follows:
[java] Standard :: Stock price = $177.20143371883802
You will receive the following response for the fifth request:
[java] org.apache.axis2.AxisFault: **Access Denied**
Maximum number of requests within 800000 milliseconds is specified as 4
for any server (including localhost) other than the explicitly specified
ones. Therefore, our fifth request is denied by the throttle mediator. You
can verify this by looking at the Synapse console.
[HttpServerWorker-1] INFO LogMediator - text = **Access Accept**
[HttpServerWorker-2] INFO LogMediator - text = **Access Accept**
[HttpServerWorker-3] INFO LogMediator - text = **Access Accept**
[HttpServerWorker-4] INFO LogMediator - text = **Access Accept**
[HttpServerWorker-5] INFO LogMediator - text = **Access Denied**