Running the WSO2 Enterprise Service Bus (ESB), v1.0 Samples
While the Samples Setup Guide
document above gives you a generic description on how to set up and and run
the WSO2 ESB samples, this document takes each sample, one by one and
discusses the objective of the sample, its prerequisites, and its expected
behavior when the sample is built.
Note: The ESB configurations listed below, with each
sample, is the raw source XML serialization of the sample configuration. This
may be viewed graphically through the WSO2 ESB administration console after
logging into the console.
<definitions xmlns="http://ws.apache.org/ns/synapse">
<!-- log all attributes of messages passing through -->
<log level="full"/>
<!-- Send the messageto implicit destination -->
<send/>
</definitions>
Objective: Introduction to the ESB. Shows how a message could be
made to pass through the ESB and logged before it is
delivered to its ultimate receiver.
The Stock quote client can operate in the following modes for this
example.
- Smart Client mode
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/
- Using the ESB as a HTTP Proxy
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dprxurl=http://localhost:8080/
- Gateway mode / Dumb Client
See sample # 1
Pre-Requisites:
Start the WSO2 ESB configuration numbered 0: e.g.
wso2-esb -sample 0
Start the Apache Axis2 server and deploy the SimpleStockQuoteService if not
already deployed
Execute the Smart Client
By following the execution of the ESB through the DEBUG level log output
to the system output stream (i.e., the console), you will notice that the
client request arrived at the ESB with a WS-Addressing 'To' EPR of
http://localhost:9000/soap/SimpleStockQuoteService. The ESB engine now logs
the message at the "full" log level (i.e., all message headers and the body)
and sends the message to its implicit 'To' address - which is
http://localhost:9000/soap/SimpleStockQuoteService. Then on the Axis2 server
console, you will see a message confirming that the message got routed to the
sample server and the sample service that was invoked generated a stock quote
for the requested symbol.
Sat Nov 18 21:01:23 IST 2006 SimpleStockQuoteService :: Generating quote for : IBM
The response message generated by the service is received by the ESB
again, and flows through the same mediation rules, which logs the response
message and then sends it back - this time to the client. On the client
console, you should see an output similar to the following, based on the
message received by the client.
Standard :: Stock price = $95.26454380258552
Execute the Proxy Client
You will see the same behaviour as per the previous example when you run
this scenario. However, this time the difference is at the client. It sends
the message to the WS-Addressing 'To' address
http://localhost:9000/soap/SimpleStockQuoteService, but the transport
specifies the ESB as the HTTP proxy.
<!-- simple content based routing of messages -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<!-- filtering of messages with XPath and regex matches -->
<filter source="get-property('To')" regex=".*/StockQuote.*">
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
<drop/>
</filter>
<send/>
</definitions>
Objective: Introduction to simple content based routing. Shows how
a message can be made to pass through the ESB using the Dumb Client mode,
where the ESB acts as a gateway to accept all messages and then performs
mediation and routing based on message properties or content.
Pre-requisites:
Start the ESB configuration numbered 1: i.e., wso2-esb -sample 1
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
deployed
Execute the Dumb Client
ant stockquote -Dtrpurl=http://localhost:8080/soap/StockQuote
This time you will notice that the ESB received a message for which it was
set as the ultimate receiver of the message. Based on the 'To' EPR of
http://localhost:8080/soap/StockQuote, the ESB performs a match to the path
'/StockQuote' and as the request matched the XPath expression of the filter
mediator, the filter mediators' child mediators execute. Thereby sending the
message to a different endpoint as specified by the endpoint definition. The
'drop' mediator terminates further processing of the current message in a
configuration. During response processing, the filter condition fails, and
thus the implicit 'Send' mediator forwards the reply back to the client.
<!-- switch-case mediator and setting and reading of local properties on a message -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<switch source="//m0:getQuote/m0:request/m0:symbol" xmlns:m0="http://services.samples/xsd">
<case regex="IBM">
<!-- the property mediator sets a local property on the *current* message -->
<property name="symbol" value="Great stock - IBM"/>
</case>
<case regex="MSFT">
<property name="symbol" value="Are you sure? - MSFT"/>
</case>
<default>
<!-- it is possible to assign the result of an XPath expression as well -->
<property name="symbol"
expression="fn:concat('Normal Stock - ', //m0:getQuote/m0:request/m0:symbol)"
xmlns:m0="http://services.samples/xsd"/>
</default>
</switch>
<log level="custom">
<!-- the get-property() XPath extension function allows the lookup of local message properties
as well as properties from the Axis2 or Transport contexts (i.e. transport headers) -->
<property name="symbol" expression="get-property('symbol')"/>
<!-- the get-property() function supports the implicit message headers To/From/Action/FaultTo/ReplyTo -->
<property name="epr" expression="get-property('To')"/>
</log>
<!-- Send the messages where they are destined to (i.e. the 'To' EPR of the message) -->
<send/>
</definitions>
Objective: Introduce switch-case mediator and writing and reading
of local properties set on a message instance
Pre-Requisites:
Start the ESB configuration numbered 2: i.e. wso2-esb -sample 2
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done.
Execute the 'ant stockquote ..' request again in the smart client mode,
specifying 'IBM', 'MSFT' and 'SUN' as the stock symbols. When the symbol IBM
is requested, you will see by following through the mediation logs, that the
case statements' first case for 'IBM' was executed and a local property named
'symbol' was set to 'Great stock - IBM'. Subsequently, this local property
value is looked up by the log mediator and logged using the 'get-property()'
XPath extension function.
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService
-Dtrpurl=http://localhost:8080/ -Dsymbol=IBM
INFO LogMediator - symbol = Great stock - IBM, epr = http://localhost:9000/axis2/services/SimpleStockQuoteService
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService
-Dtrpurl=http://localhost:8080/ -Dsymbol=MSFT
INFO LogMediator - symbol = Are you sure? - MSFT, epr = http://localhost:9000/axis2/services/SimpleStockQuoteService
<!-- illustration of local registry entry definitions, and reusable endpoints and sequences -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<!-- define a string resource entry to the local registry -->
<localEntry key="version">0.1</localEntry>
<!-- define a reuseable endpoint definition -->
<endpoint name="simple">
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
<!-- define a reusable sequence -->
<sequence name="stockquote">
<!-- log the message using the custom log level. illustrates custom properties for log -->
<log level="custom">
<property name="Text" value="Sending quote request"/>
<property name="version" expression="get-property('version')"/>
<property name="direction" expression="get-property('direction')"/>
</log>
<!-- send message to real endpoint referenced by key "simple" endpoint definition -->
<send>
<endpoint key="simple"/>
</send>
</sequence>
<sequence name="main">
<in>
<property name="direction" value="incoming"/>
<sequence key="stockquote"/>
</in>
<out>
<send/>
</out>
</sequence>
</definitions>
Objective: Illustrates local registry entry definitions, reusable
endpoints, and sequences
Pre-requisites:
Start the ESB configuration numbered 3: i.e., wso2-esb -sample 3
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
This example uses a sequence named "main" that specifies the main
mediation rules to be executed. This is equivalent to directly specifying the
mediators of the main sequence within the <definitions> tags. This is
the recommended and also a neater approach for non trivial configurations.
Execute the 'ant stockquote ..' request again, and you will see by following
through the mediation logs, that the sequence named "main" has been executed.
Then for the incoming message flow the <in> mediator executes, and it
calls into the sequence named "stockquote"
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/
DEBUG SequenceMediator - Sequence mediator <main> :: mediate()
DEBUG InMediator - In mediator mediate()
DEBUG SequenceMediator - Sequence mediator <stockquote> :: mediate()
As the "stockquote" sequence executes, the log mediator dumps a simple
text/string property, an XPath evaluation result - that picks up the key
named "version", and a second XPath evaluation result that picks up a local
message property set previously by the <property> mediator. The
get-property() XPath extension function is able to read message properties
local to the current message, local or remote registry entries, Axis2 message
context properties, as well as transport headers. The local entry definition
for "version" defines a simple text/string registry entry for that is visible
to all messages that pass through the ESB.
[HttpServerWorker-1] INFO LogMediator - Text = Sending quote request, version = 0.1, direction = incoming
[HttpServerWorker-1] DEBUG SendMediator - Send mediator :: mediate()
[HttpServerWorker-1] DEBUG AddressEndpoint - Sending To: http://localhost:9000/soap/SimpleStockQuoteService
<!-- introduction to error handling -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<!-- the default fault handling sequence used by Synapse - named 'fault' -->
<sequence name="fault">
<log level="custom">
<property name="text" value="An unexpected error occured"/>
<property name="message" expression="get-property('ERROR_MESSAGE')"/>
</log>
<drop/>
</sequence>
<sequence name="sunErrorHandler">
<log level="custom">
<property name="text" value="An unexpected error occured for stock SUN"/>
<property name="message" expression="get-property('ERROR_MESSAGE')"/>
</log>
<drop/>
</sequence>
<!-- default message handling sequence used by Synapse - named 'main' -->
<sequence name="main">
<in>
<switch source="//m0:getQuote/m0:request/m0:symbol" xmlns:m0="http://services.samples/xsd">
<case regex="IBM">
<send>
<endpoint><address uri="http://localhost:9000/soap/SimpleStockQuoteService"/></endpoint>
</send>
</case>
<case regex="MSFT">
<send>
<endpoint key="bogus"/>
</send>
</case>
<case regex="SUN">
<sequence key="sunSequence"/>
</case>
</switch>
<drop/>
</in>
<out>
<send/>
</out>
</sequence>
<sequence name="sunSequence" onError="sunErrorHandler">
<send>
<endpoint key="sunPort"/>
</send>
</sequence>
</definitions>
Objective: Introduction to error handling with the 'fault'
sequence
Pre-requisites:
Start the ESB configuration numbered 4: i.e., wso2-esb -sample 4
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
When the IBM stock quote is requested, the configuration routes it to the
endpoint defined as 'simple' endpoint, which routes the message to the
SimpleStockQuoteService on the local Axis2 instance. Hence a valid response
message is shown at the client.
If you lookup a stock quote for 'MSFT', the ESB is instructed to route the
message to the endpoint defined as the 'bogus' endpoint, which does not
exist. The ESB executes the specified error handler sequence closest to the
point where the error was encountered. In this case, the currently executing
sequence is 'main' and it does not specify an 'onError' attribute. Whenever
the ESB cannot find an error handler, it looks up for a sequence named
'fault'. Thus the 'fault' sequence can be seen executing, and writing the
generic error message into the logs.
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/ -Dsymbol=MSFT
[HttpServerWorker-1] DEBUG SendMediator - Send mediator :: mediate()
[HttpServerWorker-1] ERROR IndirectEndpoint - Reference to non-existent endpoint for key : bogus
[HttpServerWorker-1] DEBUG MediatorFaultHandler - MediatorFaultHandler :: handleFault
[HttpServerWorker-1] DEBUG SequenceMediator - Sequence mediator <fault> :: mediate()
[HttpServerWorker-1] DEBUG LogMediator - Log mediator :: mediate()
[HttpServerWorker-1] INFO LogMediator - text = An unexpected error occured, message = Reference to non-existent endpoint for key : bogus
When the 'SUN' quote is requested, a custom sequence 'sunSequence' is
invoked, and it specifies 'sunErrorHandler' as its error handler. Hence when
the send fails, now you can see the proper error handler invocation and the
custom error message as follows:
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/ -Dsymbol=SUN
[HttpServerWorker-1] DEBUG SequenceMediator - Sequence mediator <sunSequence> :: mediate()
[HttpServerWorker-1] DEBUG SequenceMediator - Setting the onError handler for the sequence
[HttpServerWorker-1] DEBUG AbstractListMediator - Implicit Sequence <SequenceMediator> :: mediate()
[HttpServerWorker-1] DEBUG SendMediator - Send mediator :: mediate()
[HttpServerWorker-1] ERROR IndirectEndpoint - Reference to non-existent endpoint for key : sunPort
[HttpServerWorker-1] DEBUG MediatorFaultHandler - MediatorFaultHandler :: handleFault
[HttpServerWorker-1] DEBUG SequenceMediator - Sequence mediator <sunErrorHandler> :: mediate()
[HttpServerWorker-1] DEBUG AbstractListMediator - Implicit Sequence <SequenceMediator> :: mediate()
[HttpServerWorker-1] DEBUG LogMediator - Log mediator :: mediate()
[HttpServerWorker-1] INFO LogMediator - text = An unexpected error occured for stock SUN, message = Reference to non-existent endpoint for key : sunPort
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="myFaultHandler">
<makefault>
<code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
<reason expression="get-property('ERROR_MESSAGE')"/>
</makefault>
<property name="RESPONSE" value="true"/>
<header name="To" expression="get-property('ReplyTo')"/>
<send/>
</sequence>
<sequence name="main" onError="myFaultHandler">
<in>
<switch source="//m0:getQuote/m0:request/m0:symbol"
xmlns:m0="http://services.samples/xsd">
<case regex="MSFT">
<send>
<endpoint><address uri="http://bogus:9000/soap/NonExistentStockQuoteService"/></endpoint>
</send>
</case>
<case regex="SUN">
<send>
<endpoint><address uri="http://localhost:9009/soap/NonExistentStockQuoteService"/></endpoint>
</send>
</case>
</switch>
<drop/>
</in>
<out>
<send/>
</out>
</sequence>
</definitions>
Objective: Makefault mediator and sending back error
responses
Pre-requisites:
Start the ESB configuration numbered 5: i.e., wso2-esb -sample 5
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
When the MSFT stock quote is requested, an unknown host exception would be
caused, and a connection refused exception would be caused for the SUN stock.
This information is captured and returned back to the original client as a
SOAP fault in this example.
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/ -Dsymbol=MSFT
Returns:
<soapenv:Fault xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><faultcode>soapenv:Client</faultcode>
<faultstring>java.net.UnknownHostException: bogus</faultstring><detail /></soapenv:Fault>
and
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/ -Dsymbol=SUN
Returns:
<soapenv:Fault xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><faultcode>soapenv:Client</faultcode>
<faultstring>java.net.ConnectException: Connection refused</faultstring><detail /></soapenv:Fault>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<in>
<header name="To" value="http://localhost:9000/soap/SimpleStockQuoteService"/>
</in>
<send/>
</definitions>
Objective: Introduction to header, in (out) mediators
Pre-requisites:
Start the ESB configuration numbered 6: i.e., wso2-esb -sample 6
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
In this example, we use the stockquote client in the dumb client mode,
setting the 'To' EPR of the message to the ESB. Then the 'in' mediator
processes the incoming messages, and manipulates the 'To' header to refer to
the stock quote service on the sample Axis2 server. Thus it is now possible
to request for a stock quote as follows:
ant stockquote -Dtrpurl=http://localhost:8080/soap/SimpleStockQuoteService
<!-- introduction of static inline XML properties and the validation mediator -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<localEntry key="validate_schema">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.apache-synapse.org/test" elementFormDefault="qualified"
attributeFormDefault="unqualified"
targetNamespace="http://services.samples/xsd">
<xs:element name="getQuote">
<xs:complexType>
<xs:sequence>
<xs:element name="request">
<xs:complexType>
<xs:sequence>
<xs:element name="stocksymbol" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</localEntry>
<in>
<validate>
<schema key="validate_schema"/>
<on-fail>
<!-- if the request does not validate againt schema throw a fault -->
<makefault>
<code value="tns:Receiver"
xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
<reason value="Invalid custom quote request"/>
</makefault>
<property name="RESPONSE" value="true"/>
<header name="To" expression="get-property('ReplyTo')"/>
</on-fail>
</validate>
</in>
<send/>
</definitions>
Objective: Introduction to local (static) registry entries and the
validate mediator
Pre-requisites:
Start the ESB configuration numbered 7: i.e., wso2-esb -sample 7
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
This example shows how a static XML fragment could be made available to
the ESB local registry. Resources defined in the local registry are static
(i.e., never changes over the lifetime of the configuration) and may be
specified as a source URL, inline-text, or inline-xml. In this example, the
schema is made available under the key 'validate_schema'.
The validate mediator by default operates on the first child element of
the SOAP body. You can specify an XPath expression using the 'source'
attribute to override this behaviour. The validate mediator now uses the
'validate_schema' resource to validate the incoming message, and if the
message gives an error, invokes the 'on-fail' sequence of mediators.
If you send a stockquote request using 'ant stockquote ..' you will now
get a fault back with a message 'Invalid custom quote request' as the schema
validation failed. This is because the schema used in the example expects a
slightly different message than what is created by the stock quote client.
(i.e., expects a 'stocksymbol' element instead of 'symbol' to specify the
stock symbol)
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/
<!-- introduction to static and dynamic registry resources and the XSLT mediator -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<!-- the SimpleURLRegistry allows access to a URL based registry (e.g. file:/// or http://) -->
<registry provider="org.wso2.esb.registry.ESBRegistry">
<!-- the root property of the simple URL registry helps resolve a resource URL as root + key -->
<parameter name="root">file:repository/conf/sample/resources/</parameter>
<!-- all resources loaded from the URL registry would be cached for this number of milli seconds -->
<parameter name="cachableDuration">15000</parameter>
</registry>
<!-- define the request processing XSLT resource as a static URL source -->
<localEntry key="xslt-key-req" src="file:repository/conf/sample/resources/transform/transform.xslt"/>
<in>
<!-- transform the custom quote request into a standard quote requst expected by the service -->
<xslt key="xslt-key-req"/>
</in>
<out>
<!-- transform the standard response back into the custom format the client expects -->
<!-- the key is looked up in the remote registry and loaded as a 'dynamic' registry resource -->
<xslt key="transform/transform_back.xslt"/>
</out>
<send/>
</definitions>
Objective: Introduction to static and dynamic registry resources
and the XSLT mediator
Pre-requisites:
Start the ESB configuration numbered 8: i.e., wso2-esb -sample 8
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
This example uses the XSLT mediator to perform transformations, and the
XSLT transformations are specified as registry resources. The first resource
'xslt-key-req' is specified as a 'local' registry entry. Local entries do not
place the resource on the registry, but simply makes it available to the
local configuration. If a local entry is defined with a key that already
exists in the remote registry, the local entry will have preference and hide
the existence of the remote resource.
In this example, you will notice the new 'registry' definition. The WSO2
ESB comes with a simple URL based registry implementation ESBRegistry. During
initialization of the registry, the SimpleURLRegistry expects to find a
property named 'root', which specifies a prefix for the registry keys used
later. When the SimpleURLRegistry is used, this root is prefixed to the entry
keys to form the complete URL for the resource being looked up. The registry
caches a resource once requested, and caches it internally for a specified
duration. Once this period expires, it will reload the meta information about
the resource and reload its cached copy if necessary, the next time the
resource is requested.
Hence, the second XSLT resource key 'transform/transform_back.xslt'
concatenated with the 'root' of the SimpleURLRegistry
'file:repository/conf/sample/resources/' forms the complete URL of the
resource as
'file:repository/conf/sample/resources/transform/transform_back.xslt' and
caches its value for a period of 15000 ms.
Execute the custom quote client as 'ant stockquote -Dmode=customquote ..'
and analyze the the ESB debug log output as shown below.
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/ -Dmode=customquote
[HttpServerWorker-1] DEBUG XSLTMediator - Performing XSLT transformation against property with key : xslt-key-req
[HttpServerWorker-1] DEBUG XSLTMediator - Transformation source :
<m0:CheckPriceRequest xmlns:m0="http://www.apache-synapse.org/test"><m0:Code>IBM</m0:Code></m0:CheckPriceRequest>
[HttpServerWorker-1] DEBUG XSLTMediator - Transformation result : <m:getQuote xmlns:m="http://services.samples/xsd">
The incoming message is now transformed into a standard stock quote
request as expected by the SimpleStockQuoteService deployed on the local
Axis2 instance by the XSLT mediator. The XSLT mediator uses Xalan-J to
perform the transformations. It is possible to configure the underlying
transformation engine using properties where necessary. The response from the
SimpleStockQuoteService is converted back into the custom format as expected
by the client during the out message processing.
During the response processing, you will notice the SimpleURLRegistry
fetching the resource as shown by the log message below.
[HttpClientWorker-1] INFO SimpleURLRegistry - ==> Repository fetch of resource with key : transform/transform_back.xslt
If you re-run the client immediately (i.e., within 15 seconds of the first
request) you will not see the resource being re-loaded by the registry as the
cached value would be still be valid.
However if you leave the system idle for 15 seconds or more and then retry
the same request, you will notice that the registry noted the cache expiry
and checked the meta information about the resource to check whether the
resource itself has changed and requires a fresh fetch from the source URL.
If the meta data / version number indicates that a reload of the cached
resource is not necessary (i.e., unless the resource itself actually changed)
the updated meta information is used and the cache lease is extended as
appropriate.
[HttpClientWorker-1] DEBUG AbstractRegistry - Cached object has expired for key : transform/transform_back.xslt
[HttpClientWorker-1] DEBUG SimpleURLRegistry - Perform RegistryEntry lookup for key : transform/transform_back.xslt
[HttpClientWorker-1] DEBUG AbstractRegistry - Expired version number is same as current version in registry
[HttpClientWorker-1] DEBUG AbstractRegistry - Renew cache lease for another 15s
Now edit the
repository/conf/sample/resources/transform/transform_back.xslt file and add a
blank line at the end. Now when you run the client again, and if the cache is
expired, the resource would be re-fetched by its URL from the registry. This
can be seen by the following debug log messages.
[HttpClientWorker-1] DEBUG AbstractRegistry - Cached object has expired for key : transform/transform_back.xslt
[HttpClientWorker-1] DEBUG SimpleURLRegistry - Perform RegistryEntry lookup for key : transform/transform_back.xslt
[HttpClientWorker-1] INFO SimpleURLRegistry - ==> Repository fetch of resource with key : transform/transform_back.xslt
Thus the ESBRegistry allows resource to be cached, and updates detected so
that changes could be reloaded without restarting the WSO2 ESB instance.
<!-- introduction dynamic sequences -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<registry provider="org.wso2.esb.registry.ESBRegistry">
<parameter name="root">file:repository/conf/sample/resources/</parameter>
<parameter name="cachableDuration">15000</parameter>
</registry>
<sequence key="sequence/dynamic_seq_1.xml"/>
</definitions>
Objective: Introduction to dynamic sequences with a
registry
Pre-Requisites:
Start the ESB configuration numbered 9: i.e., wso2-esb -sample 9
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
This example introduces the dynamic behaviour of the WSO2 ESB through the
use of a Registry. The WSO2 ESB supports dynamic definitions for sequences
and endpoints, and as seen before, for resources. In this example, we define
an ESB configuration which references a sequence definition specified as a
registry key. The registry key resolves to the actual content of the
sequence, which would be loaded dynamically by the ESB at runtime, and cached
appropriately as per its definition in the registry. Once the cache expires,
the ESB would re-check the meta information for the definition and re-load
the sequence definition if necessary and re-cache it again.
Once the ESB is started, execute the stock quote client as 'ant
stockquote..'. You will notice that the ESB fetches the definition of the
sequence from the registry and executes its rules as follows:
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/
[HttpServerWorker-1] INFO ESBRegistry - ==> Repository fetch of resource with key : sequence/dynamic_seq_1.xml
...
[HttpServerWorker-1] DEBUG SequenceMediator - Sequence mediator <dynamic_sequence> :: mediate()
...
[HttpServerWorker-1] INFO LogMediator - message = *** Test Message 1 ***
Now if you execute the client immediately (i.e., within 15 seconds of the
last execution) you will notice that the sequence was not reloaded. If you
edit the sequence definition in
repository/conf/sample/resources/sequence/dynamic_seq_1.xml and edit the log
message to read as "*** Test Message 2 ***" and execute the client again, you
will notice that the new message is not yet visible (i.e., if you execute
this within 15 seconds of loading the resource for the first time). However,
after 15 seconds have elapsed since the original caching of the sequence, you
will notice that the new sequence is loaded and executed by the ESB from the
following log messages:
[HttpServerWorker-1] INFO SimpleURLRegistry - ==> Repository fetch of resource with key : sequence/dynamic_seq_1.xml
...
[HttpServerWorker-1] DEBUG SequenceMediator - Sequence mediator <dynamic_sequence> :: mediate()
...
[HttpServerWorker-1] INFO LogMediator - message = *** Test Message 2 ***
The cache timeout could be tuned appropriately by configuring the registry
or the individual keys to suite the environment and the needs.
<!-- introduction dynamic endpoints -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<registry provider="org.wso2.esb.registry.ESBRegistry">
<parameter name="root">file:repository/conf/sample/resources/</parameter>
<parameter name="cachableDuration">15000</parameter>
</registry>
<in>
<send>
<endpoint key="endpoint/dynamic_endpt_1.xml"/>
</send>
</in>
<out>
<send/>
</out>
</definitions>
Objective: Introduction to dynamic endpoints with the
registry
Pre-Requisites:
Start the ESB configuration numbered 10: i.e., wso2-esb -sample 10
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
Start a second Axis2 server on HTTP port 9001 and HTTPS port 9003 as
follows:
./axis2server.sh -http 9001 -https 9003
This example introduces dynamic endpoints, where the definition of an
endpoint is stored in the Registry. To follow this example, execute the stock
quote client as 'ant stockquote..' and see that the message is routed to the
SimpleStockQuoteService on the default Axis2 instance on HTTP port 9000.
Repeat the above example immediately, and notice that the endpoint is cached
and re-used by the ESB - similar to example # 8.
ant stockquote -Dtrpurl=http://localhost:8080/
Now edit the repository/conf/sample/resources/endpoint/dynamic_endpt_1.xml
definition and update the address to
"http://localhost:9001/soap/SimpleStockQuoteService". After the cache
expires, the registry loads the new definition of the endpoint, and then the
messages can be seen being routed to the second sample Axis2 server on HTTP
port 9001.
<!-- a full registry based configuration -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<registry provider="org.wso2.esb.registry.ESBRegistry">
<parameter name="root">file:./repository/conf/sample/resources/</parameter>
<parameter name="cachableDuration">15000</parameter>
</registry>
</definitions>
Objective: A full registry based configuration
Pre-requisites:
Start the ESB configuration numbered 11: i.e., wso2-esb -sample 11
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
This example shows a full registry based ESB configuration. Thus it is
possible to start a remote configuration from multiple instances of the WSO2
ESB in a clustered environment easily and also allow the configuration to be
reloaded. The configuration held on a node hosting the ESB simply points to
the registry and looks up the actual configuration by requesting the key
''synapse.xml'.
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=http://localhost:8080/
[HttpServerWorker-1] INFO LogMediator - message = This is a dynamic ESB configuration
The actual synapse.xml loaded is:
<!-- a registry based Synapse configuration -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property name="message" value="This is a dynamic ESB configuration $$$"/>
</log>
<send/>
</definitions>
<!-- Connecting to endpoints with WS-Security for outgoing messages -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<localEntry key="sec_policy" src="file:repository/conf/sample/resources/policy/policy_3.xml"/>
<in>
<send>
<endpoint name="secure">
<address uri="http://localhost:9000/soap/SecureStockQuoteService">
<enableSec policy="sec_policy"/>
<enableAddressing/>
</address>
</endpoint>
</send>
</in>
<out>
<header name="wsse:Security" action="remove"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"/>
<send/>
</out>
</definitions>
Objective: Connecting to endpoints with WS-Security for outgoing
messages
Pre-requisites:
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 ESB configuration numbered 50: i.e., wso2-esb -sample 50
Start the Axis2 server and deploy the SecureStockQuoteService if not already
done
Use the stock quote client to send a request without WS-Security. The ESB
is configured to enable WS-Security as per the policy specified by
'policy_3.xml' for the outgoing messages to the SecureStockQuoteService
endpoint hosted on the Axis2 instance. The debug log messages on the ESB
shows the encrypted message flowing to the service and the encrypted response
being received by the ESB. The wsse:Security header is then removed from the
decrypted message and the response is delivered back to the client, as
expected. You may execute the client as follows:
ant stockquote -Dtrpurl=http://localhost:8080/
The message sent by the ESB to the secure service can be seen as follows
when TCPMon is used.
POST http://localhost:9001/soap/SecureStockQuoteService HTTP/1.1
Host: 127.0.0.1
SOAPAction: urn:getQuote
Content-Type: text/xml; charset=UTF-8
Transfer-Encoding: chunked
Connection: Keep-Alive
User-Agent: Synapse-HttpComponents-NIO
800
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:wsa="http://www.w3.org/2005/08/addressing" ..>
<soapenv:Header>
<wsse:Security ..>
<wsu:Timestamp ..>
...
</wsu:Timestamp>
<xenc:EncryptedKey..>
...
</xenc:EncryptedKey>
<wsse:BinarySecurityToken ...>
<ds:SignedInfo>
...
</ds:SignedInfo>
<ds:SignatureValue>
...
</ds:SignatureValue>
<ds:KeyInfo Id="KeyId-29551621">
...
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
<wsa:To>http://localhost:9001/soap/SecureStockQuoteService</wsa:To>
<wsa:MessageID>urn:uuid:1C4CE88B8A1A9C09D91177500753443</wsa:MessageID>
<wsa:Action>urn:getQuote</wsa:Action>
</soapenv:Header>
<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-3789605">
<xenc:EncryptedData Id="EncDataId-3789605" Type="http://www.w3.org/2001/04/xmlenc#Content">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<xenc:CipherData>
<xenc:CipherValue>Layg0xQcnH....6UKm5nKU6Qqr</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</soapenv:Body>
</soapenv:Envelope>0
<!-- MTOM and SwA and message properties to correlate requests and responses -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<in>
<filter source="get-property('Action')" regex="urn:uploadFileUsingMTOM">
<property name="example" value="mtom"/>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/MTOMSwASampleService" optimize="mtom"/>
</endpoint>
</send>
</filter>
<filter source="get-property('Action')" regex="urn:uploadFileUsingSwA">
<property name="example" value="swa"/>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/MTOMSwASampleService" optimize="swa"/>
</endpoint>
</send>
</filter>
</in>
<out>
<filter source="get-property('example')" regex="mtom">
<property name="enableMTOM" value="true" scope="axis2"/>
</filter>
<filter source="get-property('example')" regex="swa">
<property name="enableSwA" value="true" scope="axis2"/>
</filter>
<send/>
</out>
</definitions>
Objective: MTOM and SwA optimizations and request/response
correlation
Pre-requisites:
Start the ESB configuration numbered 51: i.e., wso2-esb -sample 51
Start the Axis2 server and deploy the MTOMSwASampleService if not already
done
Execute the 'ant optimizeclient' specifying MTOM optimization as
follows:
ant optimizeclient -Dopt_mode=mtom
The configuration now sets a local message context property, and forwards
the message to 'http://localhost:9000/soap/MTOMSwASampleService' optimizing
binary content as MTOM. By sending this message through TCPMon, you will be
able to see the actual message sent over the HTTP transport if required. Thus
during response processing, by checking the local message property, the ESB
can identify the past information about the current message context, and use
this knowledge to transform the response back to the client in the same
format as the original request.
When the client executes successfully, it will upload a file containing
the ASF logo and receive its response back again and save it into a temporary
file.
[java] Sending file : ./../../repository/conf/sample/resources/mtom/asf-logo.gif as MTOM
[java] Saved response to file : /tmp/mtom-36877.gif
Next try SwA as:
ant optimizeclient -Dopt_mode=swa
[java] Sending file : ./../../repository/conf/sample/resources/mtom/asf-logo.gif as SwA
[java] Saved response to file : /tmp/swa-47549.gif
By using TCPMon and sending the message through it, you can inspect that
the requests and responses sent are indeed MTOM optimized or sent as HTTP
attachments as follows:
POST http://localhost:9000/soap/MTOMSwASampleService HTTP/1.1
Host: 127.0.0.1
SOAPAction: urn:uploadFileUsingMTOM
Content-Type: multipart/related; boundary=MIMEBoundaryurn_uuid_B94996494E1DD5F9B51177413845353; type="application/xop+xml";
start="<0.urn:uuid:B94996494E1DD5F9B51177413845354@apache.org>"; start-info="text/xml"; charset=UTF-8
Transfer-Encoding: chunked
Connection: Keep-Alive
User-Agent: Synapse-HttpComponents-NIO
--MIMEBoundaryurn_uuid_B94996494E1DD5F9B51177413845353241
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID:
<0.urn:uuid:B94996494E1DD5F9B51177413845354@apache.org>221b1
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<m0:uploadFileUsingMTOM xmlns:m0="http://www.apache-synapse.org/test">
<m0:request>
<m0:image>
<xop:Include href="cid:1.urn:uuid:78F94BC50B68D76FB41177413845003@apache.org" xmlns:xop="http://www.w3.org/2004/08/xop/include" />
</m0:image>
</m0:request>
</m0:uploadFileUsingMTOM>
</soapenv:Body>
</soapenv:Envelope>
--MIMEBoundaryurn_uuid_B94996494E1DD5F9B51177413845353217
Content-Type: image/gif
Content-Transfer-Encoding: binary
Content-ID:
<1.urn:uuid:78F94BC50B68D76FB41177413845003@apache.org>22800GIF89a... << binary content >>
POST http://localhost:9000/soap/MTOMSwASampleService HTTP/1.1
Host: 127.0.0.1
SOAPAction: urn:uploadFileUsingSwA
Content-Type: multipart/related; boundary=MIMEBoundaryurn_uuid_B94996494E1DD5F9B51177414170491; type="text/xml";
start="<0.urn:uuid:B94996494E1DD5F9B51177414170492@apache.org>"; charset=UTF-8
Transfer-Encoding: chunked
Connection: Keep-Alive
User-Agent: Synapse-HttpComponents-NIO
--MIMEBoundaryurn_uuid_B94996494E1DD5F9B51177414170491225
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID:
<0.urn:uuid:B94996494E1DD5F9B51177414170492@apache.org>22159
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<m0:uploadFileUsingSwA xmlns:m0="http://www.apache-synapse.org/test">
<m0:request>
<m0:imageId>urn:uuid:15FD2DA2584A32BF7C1177414169826</m0:imageId>
</m0:request>
</m0:uploadFileUsingSwA>
</soapenv:Body>
</soapenv:Envelope>22--34MIMEBoundaryurn_uuid_B94996494E1DD5F9B511774141704912
17
Content-Type: image/gif
Content-Transfer-Encoding: binary
Content-ID:
<urn:uuid:15FD2DA2584A32BF7C1177414169826>22800GIF89a... << binary content >>
<!-- POX to SOAP conversion -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<!-- filtering of messages with XPath and regex matches -->
<filter source="get-property('To')" regex=".*/StockQuote.*">
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService" format="soap"/>
</endpoint>
</send>
<drop/>
</filter>
<send/>
</definitions>
Objective: POX to SOAP conversion
Pre-requisites:
Start the ESB configuration numbered 52: i.e., wso2-esb -sample 52
Start the Axis2 server and deploy the SimpleStockQuoteService if not
already done.
Execute the 'ant stockquote' specifying that the request should be a REST
request as follows:
ant stockquote -Dtrpurl=http://localhost:8080/soap/StockQuote -Drest=true
This example shows a HTTP REST request (as shown below) being transformed
into a SOAP request and forwarded to the stock quote service.
POST /soap/StockQuote HTTP/1.1
Content-Type: application/xml; charset=UTF-8;action="urn:getQuote";
SOAPAction: urn:getQuote
User-Agent: Axis2
Host: 127.0.0.1
Transfer-Encoding: chunked
75
<m0:getQuote xmlns:m0="http://services.samples/xsd">
<m0:request>
<m0:symbol>IBM</m0:symbol>
</m0:request>
</m0:getQuote>0
<!-- RMSequence example -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<in>
<RMSequence single="true" version="1.0"/>
<send>
<endpoint name="reliable">
<address uri="http://localhost:9000/soap/ReliableStockQuoteService">
<enableRM/>
<enableAddressing/>
</address>
</endpoint>
</send>
</in>
<out>
<header name="wsrm:SequenceAcknowledgement" action="remove"
xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<header name="wsrm:Sequence" action="remove"
xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<send/>
</out>
</definitions>
Objective: Demonstrate the message exchange between the ESB and the
server using WS-ReliableMessaging (WS-RM)
Pre-requisites:
Deploy the ReliableStockQuoteService in the sample Axis2 server by
switching to the samples/axis2Server/src/ReliableStockQuoteService directory
and running Ant.
Start the sample Axis2 server on port 9000.
Start the ESB with the sample configuration 53 (i.e., wso2-esb -sample
53).
In the above configuration, WS-RM is engaged to the endpoint using the
<enableRM/> tag. It is possible to engage WS-RM to both Address and
WSDL endpoints using this tag. In addition to the RM enabled endpoint, the
RMSequence mediator is specified before the 'send' mediator. This mediator is
used to specify the set of messages to be sent using a single RM sequence. In
this sample it is specified as single message per sequence. It also specifies
the version of the WS-RM to be used. Refer to the Synapse configuration
language documentation for more information about the RMSequence mediator. RM
related SOAP headers are removed from the message in the out mediator, as
WS-RM message exchange happens only between the ESB and the server. Now run
the sample client using the following command.
ant stockquote -Dsymbol=IBM -Dmode=quote -Daddurl=http://localhost:8080
You can observe the client output displaying the quote price for IBM as
follows:
[java] Standard :: Stock price = $189.2521262517493
There is no difference to be observed between the normal message exchange
and WS-RM enabled message exchange as far as client and server outputs are
considered. If you look at the wire level messages, you would observe
additional WS-RM messages and WS-RM elements. ESB, the initiator of the RM
sequence, first tries to create a sequence by sending a message with
CreateSequence element.
...
<soapenv:Body>
<wsrm:CreateSequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:AcksTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsrm:AcksTo>
<wsrm:Offer>
<wsrm:Identifier>urn:uuid:546F6F33FB7D8BBE351179807372769</wsrm:Identifier>
</wsrm:Offer>
</wsrm:CreateSequence>
</soapenv:Body>
...
Sample Axis2 server responds to CreateSequence request with the following
message:
...
<soapenv:Body>
<wsrm:CreateSequenceResponse xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:Identifier>urn:uuid:879853A6871A66641C1179807373270</wsrm:Identifier>
<wsrm:Accept>
<wsrm:AcksTo>
<wsa:Address>http://localhost:9000/soap/ReliableStockQuoteService</wsa:Address>
</wsrm:AcksTo>
</wsrm:Accept>
</wsrm:CreateSequenceResponse>
</soapenv:Body>
...
Once the sequence is established, ESB sends the request to the server with
the pre-negotiated sequence ID.
<soapenv:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsa:To>http://localhost:9000/soap/ReliableStockQuoteService</wsa:To>
<wsa:MessageID>urn:uuid:DB9A5257B637DDA38B1179807372560712002-1515891720</wsa:MessageID>
<wsa:Action>urn:getQuote</wsa:Action>
<wsrm:Sequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"
soapenv:mustUnderstand="1">
<wsrm:Identifier>urn:uuid:879853A6871A66641C1179807373270</wsrm:Identifier>
<wsrm:MessageNumber>1</wsrm:MessageNumber>
<wsrm:LastMessage/>
</wsrm:Sequence>
</soapenv:Header>
<soapenv:Body>
<m0:getQuote xmlns:m0="http://services.samples/xsd">
<m0:request>
<m0:symbol>IBM</m0:symbol>
</m0:request>
</m0:getQuote>
</soapenv:Body>
</soapenv:Envelope>
ESB keeps on sending the above message till the server responds with a
valid response message with 200 OK HTTP header. If the server is not ready
with a response, it will respond with 202 Accepted HTTP header for all
requests. Once the server is ready with a response it will send the response
message with a sequence ID as follows.
<soapenv:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsa:MessageID>urn:uuid:879853A6871A66641C1179807373804</wsa:MessageID>
<wsa:Action>http://services.samples/ReliableStockQuoteServicePortType/getQuoteResponse
</wsa:Action>
<wsa:RelatesTo>urn:uuid:DB9A5257B637DDA38B1179807372560712002-1515891720</wsa:RelatesTo>
<wsrm:Sequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"
soapenv:mustUnderstand="1">
<wsrm:Identifier>urn:uuid:546F6F33FB7D8BBE351179807372769</wsrm:Identifier>
<wsrm:MessageNumber>1</wsrm:MessageNumber>
<wsrm:LastMessage/>
</wsrm:Sequence>
<wsrm:SequenceAcknowledgement xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"
soapenv:mustUnderstand="1">
<wsrm:Identifier>urn:uuid:879853A6871A66641C1179807373270</wsrm:Identifier>
<wsrm:AcknowledgementRange Lower="1" Upper="1"/>
</wsrm:SequenceAcknowledgement>
</soapenv:Header>
<soapenv:Body>
<ns:getQuoteResponse xmlns:ns="http://services.samples/xsd">
...
Now both the ESB and the server are done with the actual message exchange.
Then the ESB sends a request to terminate the sequence as follows:
<soapenv:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsa:To>http://localhost:9000/soap/ReliableStockQuoteService</wsa:To>
<wsa:MessageID>urn:uuid:546F6F33FB7D8BBE351179807379591</wsa:MessageID>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</wsa:Action>
<wsrm:SequenceAcknowledgement xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"
soapenv:mustUnderstand="1">
<wsrm:Identifier>urn:uuid:546F6F33FB7D8BBE351179807372769</wsrm:Identifier>
<wsrm:AcknowledgementRange Lower="1" Upper="1"/>
</wsrm:SequenceAcknowledgement>
</soapenv:Header>
<soapenv:Body>
<wsrm:TerminateSequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:Identifier>urn:uuid:879853A6871A66641C1179807373270</wsrm:Identifier>
</wsrm:TerminateSequence>
</soapenv:Body>
</soapenv:Envelope>
Server responds to the sequence termination message, accepting to
terminate the sequence as follows.
<soapenv:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsa:ReplyTo>
<wsa:Address>http://localhost:9000/soap/ReliableStockQuoteService</wsa:Address>
</wsa:ReplyTo>
<wsa:MessageID>urn:uuid:879853A6871A66641C1179807380190</wsa:MessageID>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<wsrm:TerminateSequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:Identifier>urn:uuid:546F6F33FB7D8BBE351179807372769</wsrm:Identifier>
</wsrm:TerminateSequence>
</soapenv:Body>
</soapenv:Envelope>
Note that although each of above messages are separate SOAP messages, in
most cases they will be exchanged in a single socket connection as HTTP
Keep-Alive header is used.
<!-- demontrates simple session less load balancing between 3 endpoints -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="main" onError="errorHandler">
<in>
<send>
<endpoint>
<loadbalance>
<endpoint>
<address uri="http://localhost:9001/soap/LBService1">
<enableAddressing/>
<suspendDurationOnFailure>60</suspendDurationOnFailure>
</address>
</endpoint>
<endpoint>
<address uri="http://localhost:9002/soap/LBService1">
<enableAddressing/>
<suspendDurationOnFailure>60</suspendDurationOnFailure>
</address>
</endpoint>
<endpoint>
<address uri="http://localhost:9003/soap/LBService1">
<enableAddressing/>
<suspendDurationOnFailure>60</suspendDurationOnFailure>
</address>
</endpoint>
</loadbalance>
</endpoint>
</send>
</in>
<out>
<!-- Send the messages where they have been sent (i.e. implicit To EPR) -->
<send/>
</out>
</sequence>
<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: Demonstrate simple load balancing among a set of
endpoints
Pre-requisites:
Start the ESB configuration numbered 54: i.e., wso2-esb -sample 54
Deploy the LoadbalanceFailoverService by switching to
samples/axis2Server/src/LoadbalanceFailoverServer directory and running
Ant.
Start three instances of sample Axis2 server on HTTP ports 9001, 9002 and
9003 and give some unique names to each server.
Example commands to run sample Axis2 servers in Linux is listed below:
axis2Server.sh -http 9001 -https 9005 -name MyServer1
axis2Server.sh -http 9002 -https 9006 -name MyServer2
axis2Server.sh -http 9003 -https 9007 -name MyServer3
Now we are done with setting up the environment for the load balance
sample. Start the load balance and failover client using the following
command:
ant loadbalancefailover -Di=100
This client sends 100 requests to the LoadbalanceFailoverService through
the ESB. The WSO2 ESB will distribute the load among the three endpoints
mentioned in the configuration in round robin manner.
LoadbalanceFailoverService appends the name of the server to the response, so
that the client can determine which server has processed the message. If you
examine the console output of the client, you can see that requests are
processed by three servers as follows:
[java] Request: 1 ==> Response from server: MyServer1
[java] Request: 2 ==> Response from server: MyServer2
[java] Request: 3 ==> Response from server: MyServer3
[java] Request: 4 ==> Response from server: MyServer1
[java] Request: 5 ==> Response from server: MyServer2
[java] Request: 6 ==> Response from server: MyServer3
[java] Request: 7 ==> Response from server: MyServer1
...
Now run the client without the -Di=100 parameter to send infinite
requests. While running the client, shutdown the server named MyServer1. You
can observe that requests are only distributed among MyServer2 and MyServer3
after shutting down MyServer1. Console output before and after shutting down
MyServer1 is listed below (MyServer1 was shutdown after request 63):
...
[java] Request: 61 ==> Response from server: MyServer1
[java] Request: 62 ==> Response from server: MyServer2
[java] Request: 63 ==> Response from server: MyServer3
[java] Request: 64 ==> Response from server: MyServer2
[java] Request: 65 ==> Response from server: MyServer3
[java] Request: 66 ==> Response from server: MyServer2
[java] Request: 67 ==> Response from server: MyServer3
...
Now restart MyServer1. You will observe that requests will be sent again
to all three servers roughly after 60 seconds. This is because we have
specified <suspendDurationOnFailure> as 60 seconds in the
configuration. Therefore, load balance endpoint will suspend any failed child
endpoint only for 60 seconds after detecting the failure.
<!-- Demontrates failover sending among 3 endpoints. -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="main" onError="errorHandler">
<in>
<send>
<endpoint>
<failover>
<endpoint>
<address uri="http://localhost:9001/soap/LBService1">
<enableAddressing/>
<suspendDurationOnFailure>60</suspendDurationOnFailure>
</address>
</endpoint>
<endpoint>
<address uri="http://localhost:9002/soap/LBService1">
<enableAddressing/>
<suspendDurationOnFailure>60</suspendDurationOnFailure>
</address>
</endpoint>
<endpoint>
<address uri="http://localhost:9003/soap/LBService1">
<enableAddressing/>
<suspendDurationOnFailure>60</suspendDurationOnFailure>
</address>
</endpoint>
</failover>
</endpoint>
</send>
</in>
<out>
<!-- Send the messages where they have been sent (i.e. implicit To EPR) -->
<send/>
</out>
</sequence>
<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: Demonstrate the failover sending
Pre-requisites:
Start the ESB configuration numbered 55: i.e., wso2-esb -sample 55
Deploy the LoadbalanceFailoverService and start three instances of sample
Axis2 server as mentioned in sample 54.
The above configuration sends messages with the failover behavior.
Initially the server at port 9001 is treated as primary and other two are
treated as back ups. Messages are always directed only to the primary server.
If the primary server has failed, the next listed server is selected as the
primary. Thus, messages are sent successfully as long as there is at least
one active server. To test this, run the loadbalancefailover client to send
infinite requests as follows:
ant loadbalancefailover
You will see that all requests are processed by MyServer1. Now shutdown
MyServer1 and inspect the console output of the client. You will observe that
all subsequent requests are processed by MyServer2.
The console output with MyServer1 shuts down after request 127 is listed
below:
...
[java] Request: 125 ==> Response from server: MyServer1
[java] Request: 126 ==> Response from server: MyServer1
[java] Request: 127 ==> Response from server: MyServer1
[java] Request: 128 ==> Response from server: MyServer2
[java] Request: 129 ==> Response from server: MyServer2
[java] Request: 130 ==> Response from server: MyServer2
...
You can keep on shutting down servers like this. The client will continue
to get a response till you shutdown all the listed servers. Once all the
servers are shutdown, the error sequence is activated and a fault message is
sent to the client as follows:
[java] COULDN'T SEND THE MESSAGE TO THE SERVER.
Once a server is detected as failed, it will be added to the active
servers list again after 60 seconds (specified in
<suspendDurationOnFailure> in the configuration). Therefore, if you
have restarted any of the stopped servers and shut down all other servers,
messages will be directed to the newly started server.
<!-- Demontrates session affinity load balancing between 3 endpoints. We are using client
initiated session for this sample. -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="main" onError="errorHandler">
<in>
<send>
<endpoint>
<!-- specify the session as the simple client session provided by Synapse for
testing purpose -->
<session type="simpleClientSession"/>
<loadbalance>
<endpoint>
<address uri="http://localhost:9001/soap/LBService1">
<enableAddressing/>
</address>
</endpoint>
<endpoint>
<address uri="http://localhost:9002/soap/LBService1">
<enableAddressing/>
</address>
</endpoint>
<endpoint>
<address uri="http://localhost:9003/soap/LBService1">
<enableAddressing/>
</address>
</endpoint>
</loadbalance>
</endpoint>
</send>
</in>
<out>
<!-- Send the messages where they have been sent (i.e. implicit To EPR) -->
<send/>
</out>
</sequence>
<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: Demonstrate load balancing with session affinity using
client initiated sessions
Pre-requisites:
Start the ESB with a sample configuration 56 (i.e., wso2-esb -sample
56).
Deploy the LoadbalanceFailoverService and start three instances of the
sample Axis2 server as in sample 54.
The above configuration is the same as the load balancing configuration in
sample 54, except that the session type is specified as
"simpleClientSession". This is a client initiated session, which means that
the client generates the session identifier and sends it with each request.
In this sample session type, the client adds a SOAP header named ClientID
containing the identifier of the client. ESB binds this ID with a server on
the first request and sends all successive requests containing that ID to the
same server. Now switch to the samples/axis2Client directory and run the
client using the following command to check this in action.
ant loadbalancefailover -Dmode=session
In the session mode, the client continuously sends requests with three
different client (session) IDs. One ID is selected among these three IDs for
each request randomly. Then the client prints the session ID with the
responded server for each request. Client output for the first 10 requests
are shown below.
[java] Request: 1 Session number: 1 Response from server: MyServer3
[java] Request: 2 Session number: 2 Response from server: MyServer2
[java] Request: 3 Session number: 0 Response from server: MyServer1
[java] Request: 4 Session number: 2 Response from server: MyServer2
[java] Request: 5 Session number: 1 Response from server: MyServer3
[java] Request: 6 Session number: 2 Response from server: MyServer2
[java] Request: 7 Session number: 2 Response from server: MyServer2
[java] Request: 8 Session number: 1 Response from server: MyServer3
[java] Request: 9 Session number: 0 Response from server: MyServer1
[java] Request: 10 Session number: 0 Response from server: MyServer1
...
You can see that session number 0 is always directed to the server named
MyServer1. That means session number 1 is bound to MyServer3. Similarly
session 1 and 2 are bound to MyServer3 and MyServer2 respectively.
<!-- Demonstrates the session affinity load balancing between fail over endpoints. If endpoint servers
maintain session specific data, such data have to replicated among the failover endpoints. -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="main" onError="errorHandler">
<in>
<send>
<endpoint>
<!-- specify the session as the simple client session provided by Synapse for
testing purpose -->
<session type="simpleClientSession"/>
<loadbalance>
<endpoint>
<failover>
<endpoint>
<address uri="http://localhost:9001/soap/LBService1">
<enableAddressing/>
</address>
</endpoint>
<endpoint>
<address uri="http://localhost:9002/soap/LBService1">
<enableAddressing/>
</address>
</endpoint>
</failover>
</endpoint>
<endpoint>
<failover>
<endpoint>
<address uri="http://localhost:9003/soap/LBService1">
<enableAddressing/>
</address>
</endpoint>
<endpoint>
<address uri="http://localhost:9004/soap/LBService1">
<enableAddressing/>
</address>
</endpoint>
</failover>
</endpoint>
</loadbalance>
</endpoint>
</send>
</in>
<out>
<!-- Send the messages where they have been sent (i.e. implicit To EPR) -->
<send/>
</out>
</sequence>
<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: Demonstrate the session affinity based load balancing
with failover capability
Pre-requisites:
Start the ESB with sample configuration 57 (i.e., wso2-esb -sample 57).
Deploy the LoadbalanceFailoverService and start four sample Axis2 servers
on HTTP ports 9001, 9002, 9003, and 9004 respectively (make sure to specify
non conflicting HTTPS ports).
This configuration also uses "simpleClientSession" to bind sessions as in
the previous sample. Failover endpoints are specified as the child endpoints
of the load balance endpoint. Therefore, sessions are bound to the failover
endpoints. Session information has to be replicated among the servers listed
under each failover endpoint using some clustering mechanism. Therefore, if
one endpoint is bound to a session that has failed, successive requests for
that session will be directed to the next endpoint in that failover group.
Run the client using the following command to observe this behavior.
ant loadbalancefailover -Dmode=session
You can see a client output similar to the one shown below.
...
[java] Request: 222 Session number: 0 Response from server: MyServer1
[java] Request: 223 Session number: 0 Response from server: MyServer1
[java] Request: 224 Session number: 1 Response from server: MyServer1
[java] Request: 225 Session number: 2 Response from server: MyServer3
[java] Request: 226 Session number: 0 Response from server: MyServer1
[java] Request: 227 Session number: 1 Response from server: MyServer1
[java] Request: 228 Session number: 2 Response from server: MyServer3
[java] Request: 229 Session number: 1 Response from server: MyServer1
[java] Request: 230 Session number: 1 Response from server: MyServer1
[java] Request: 231 Session number: 2 Response from server: MyServer3
...
Note that in this sample, session 0 is always directed to MyServer1 and
session 1 is directed to MyServer3. No requests are directed to MyServer2 and
MyServer4 as they are kept as backups by failover endpoints. Now shutdown the
server named MyServer1 while running the sample. You will observe that all
successive requests for session 0 is now directed to MyServer2, which is the
backup server for MyServer1's group. This is shown below, where MyServer1 was
shutdown after the request 534.
...
[java] Request: 529 Session number: 2 Response from server: MyServer3
[java] Request: 530 Session number: 1 Response from server: MyServer1
[java] Request: 531 Session number: 0 Response from server: MyServer1
[java] Request: 532 Session number: 1 Response from server: MyServer1
[java] Request: 533 Session number: 1 Response from server: MyServer1
[java] Request: 534 Session number: 1 Response from server: MyServer1
[java] Request: 535 Session number: 0 Response from server: MyServer2
[java] Request: 536 Session number: 0 Response from server: MyServer2
[java] Request: 537 Session number: 0 Response from server: MyServer2
[java] Request: 538 Session number: 2 Response from server: MyServer3
[java] Request: 539 Session number: 0 Response from server: MyServer2
...
<!-- demonstrates wsdl endpoint -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="main">
<in>
<send>
<!-- get epr from the given wsdl -->
<endpoint>
<wsdl uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl" service="SimpleStockQuoteService" port="SimpleStockQuoteServiceSOAP11port_http"/>
</endpoint>
</send>
</in>
<out>
<send/>
</out>
</sequence>
</definitions>
Objective: Demonstrate the use of WSDL endpoints
Pre-requisites:
Start the ESB configuration numbered 60 (i.e., wso2-esb -sample 60).
Deploy the SimpleStockQuoteService and start the sample Axis2 server.
This sample uses a WSDL endpoint inside the send mediator. WSDL endpoints
can extract an endpoint's address from the given WSDL. As WSDL documents can
have many services and many ports inside each service, the service and port
of the required endpoint has to be specified. As with address endpoints, QoS
parameters for the endpoint can be specified inline in the configuration. An
excerpt taken from the sample_proxy_1.wsdl containing the specified service
and port is listed below.
<wsdl:service name="SimpleStockQuoteService">
<wsdl:port name="SimpleStockQuoteServiceSOAP11port_http"
binding="axis2:SimpleStockQuoteServiceSOAP11Binding">
<soap:address location="http://localhost:9000/soap/SimpleStockQuoteService"/>
</wsdl:port>
<wsdl:port name="SimpleStockQuoteServiceSOAP12port_http"
binding="axis2:SimpleStockQuoteServiceSOAP12Binding">
<soap12:address location="http://localhost:9000/soap/SimpleStockQuoteService"/>
</wsdl:port>
</wsdl:service>
The specified service and port refers to the endpoint address
"http://localhost:9000/soap/SimpleStockQuoteService" according to the above
WSDL. Now run the client using the below command.
ant stockquote -Dsymbol=IBM -Dmode=quote -Daddurl=http://localhost:8080
The client will print the quote price for IBM received from the server
running on port 9000. Observe the Axis2 console and the ESB console to verify
this behavior.
<!-- introduction to Synapse proxy services -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<proxy name="StockQuoteProxy">
<target>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
</proxy>
</definitions>
Objective: Introduction to proxy services
Pre-requisites:
Start the ESB configuration numbered 100: i.e., wso2-esb -sample 100
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
Once the ESB starts, you could go to
http://localhost:8080/soap/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:8080/soap/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 the WSO2 ESB, unless they are specifically
mentioned through the 'transports' attribute.
<!-- using custom sequences for incoming and outgoing message mediation with proxy services -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="proxy_1">
<send>
<endpoint><address uri="http://localhost:9000/soap/SimpleStockQuoteService"/></endpoint>
</send>
</sequence>
<sequence name="out">
<send/>
</sequence>
<endpoint name="proxy_2_endpoint">
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
<localEntry key="proxy_wsdl" src="file:repository/conf/sample/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
Pre-requisites:
Start the ESB configuration numbered 101: i.e., wso2-esb -sample 101
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 can 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:8080/soap/StockQuoteProxy1
ant stockquote -Daddurl=http://localhost:8080/soap/StockQuoteProxy2
<!-- switching from https to REST/POX -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<proxy name="StockQuoteProxy" transports="https">
<target>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService" format="pox"/>
</endpoint>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
</proxy>
</definitions>
Objective: Switching transports from SOAP to REST/POX
Pre-requisites:
Start the ESB configuration numbered 102: i.e., wso2-esb -sample 102
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:8080/soap/StockQuoteProxy
...
[java] org.apache.axis2.AxisFault: The service cannot be found for the endpoint reference (EPR) /soap/StockQuoteProxy
Accessing this over HTTPS (ant stockquote
-Dtrpurl=https://localhost:8443/soap/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/soap/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>
<!-- attaching service level WS-Security policies to proxy services -->
<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>
<header name="wsse:Security" action="remove"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"/>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
<policy key="sec_policy"/>
<enableSec/>
</proxy>
</definitions>
Objective: Using WS-Security signing and encryption with proxy
services through WS-Policy
Pre-requisites:
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 ESB configuration numbered 103: i.e., wso2-esb -sample 103
Start the Axis2 server and deploy the SimpleStockQuoteService if not already
done
The proxy service expects to receive a signed and encrypted message as
specified by the security policy. Please see Apache Rampart and Axis2
documentation on the format of the policy file. The element 'engageSec'
specifies that Apache Rampart should be engaged on this proxy service. Hence
if Rampart rejects any request messages that do not conform to the specified
policy, those messages will never reach the 'inSequence' to be processed.
Since the proxy service is forwarding the received request to the simple
stock quote service that does not use WS-Security, we are instructing the ESB
to remove the wsse:Security header from the outgoing message. 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:8080/soap/StockQuoteProxy -Dpolicy=./../../repository/conf/sample/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
URLhttp://localhost:8080/soap/StockQuoteProxy?wsdl reveals the security
policy attachment to the supplied base WSDL. When sending the message to the
back-end service, you could verify that the security headers were removed,
and that the response received does not use WS-Security, but that the
response being forwarded back to the client is signed and encrypted as
expected by the client.
<!-- attaching service level WS-RM policies to proxy services -->
<definitions xmlns="http://ws.apache.org/ns/synapse">
<proxy name="StockQuoteProxy">
<target>
<inSequence>
<header name="wsrm:SequenceAcknowledgement" action="remove"
xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<header name="wsrm:Sequence" action="remove"
xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<send>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
<enableRM/>
</proxy>
</definitions>
Objective: Demonstrate the reliable message exchange between the
client and the ESB using WS-ReliableMessaging (WS-RM)
Pre-requisites:
Deploy the SimpleStockQuoteService in the sample Axis2 server and start it
on port 9000.
Start the ESB with the sample configuration number 104 (i.e., wso2-esb
-sample 104).
In the above configuration, a proxy service is created with WS-RM enabled
using the <enableRM/> tag. Therefore, this proxy service is capable of
communicating with a WS-RM client. It also removes the WS-RM headers in the
In Sequence before the message is sent to the back end server. This is
required as the reliable messaging is applicable only between the client and
the ESB. Now start the client with WS-RM as follows:
ant stockquote -Dsymbol=IBM -Dmode=quote -Daddurl=http://localhost:8080/soap/StockQuoteProxy -Dwsrm=true
In this case, the client sends WS-RM enabled request to the ESB, where the
ESB sends normal requests to the server. This can be observed by examining
the wire level messages between the client and the ESB. These messages would
be similar to the wire level messages shown in sample 53. Each message would
perform a similar function to the messages discussed in sample 53.
<definitions xmlns="http://ws.apache.org/ns/synapse">
<proxy name="StockQuoteProxy" transports="jms">
<target>
<endpoint>
<address uri="http://localhost:9000/soap/SimpleStockQuoteService"/>
</endpoint>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
</proxy>
</definitions>
Objective: Introduction to switching transports with proxy
services
Pre-requisites:
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps
above)
Download, install, and start a JMS server, and configure the ESB to listen on
JMS (refer notes below)
Start the ESB configuration numbered 110: i.e. wso2-esb -sample 110
For this example, we would use ActiveMQ as the JMS provider. Once ActiveMQ is
installed and started, you should get a message as follows:
INFO BrokerService - ActiveMQ JMS Message Broker (localhost) started
You will now need to configure the Axis2 instance used by the ESB (not the
sample Axis2 server) to enable JMS support using the above provider. Refer to
the Axis2 documentation on setting up JMS for more details
(http://ws.apache.org/axis2/1_1/jms-transport.html). For a default ActiveMQ
v4.0 installation, you would need to uncomment the Axis2 transport listener
configuration found at conf/axis2.xml as
<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener"> ...
Once you start the ESB configuration and request for the WSDL of the proxy
service (http://localhost:8080/soap/StockQuoteProxy?wsdl) you will notice
that its exposed only on the JMS transport. This is because the configuration
specified this requirement in the proxy service definition.
Now lets send a stock quote request on JMS, using the dumb stock quote
client as follows:
ant jmsclient -Djms_type=pox -Djms_dest=dynamicQueues/StockQuoteProxy -Djms_payload=MSFT
On the ESB debug log you will notice that the JMS listener received the
request message as:
[JMSWorker-1] DEBUG ProxyServiceMessageReceiver -Proxy Service StockQuoteProxy received a new message...
Now if you examine the console running the sample Axis2 server, you will
see a message indicating that the server has accepted an order as follows:
Accepted order for : 16517 stocks of MSFT at $ 169.14622538721846
In this sample, the client sends the request message to the proxy service
exposed in JMS in the ESB. The ESB forwards this message to the HTTP EPR of
the simple stock quote service hosted on the sample Axis2 server, and returns
the reply back to the client through a JMS temporary queue.
Note: It is possible to instruct a JMS proxy service to listen to an
already existing destination without creating a new one. To do this, use the
property elements on the proxy service definition to specify the destination,
connection factory, etc.
e.g.,
<property name="transport.jms.Destination" value="dynamicTopics/something.TestTopic"/>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<proxy name="StockQuoteProxy" transports="http">
<target>
<endpoint>
<address uri="jms:/SimpleStockQuoteService?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616"/>
</endpoint>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
</proxy>
</definitions>
Objective: Demonstrate switching from HTTP to JMS
Pre-requisites:
Download, install and start a JMS server.
Configure sample Axis2 server for JMS (refer notes above)
Start the Axis2 server and deploy the SimpleStockQuoteService (see below)
Start the ESB configuration numbered 111: i.e., wso2-esb -sample 111
To switch from HTTP to JMS, edit the
samples/axis2Server/repository/conf/axis2.xml for the sample Axis2 server and
enable JMS (refer notes above), and restart the server. Now you can see that
the simple stock quote service is available in both JMS and HTTP in the
sample Axis2 server. To see this, point your browser to the WSDL of the
service at http://localhost:9000/soap/SimpleStockQuoteService?wsdl. JMS URL
for the service is mentioned as below:
jms:/SimpleStockQuoteService?transport.jms.ConnectionFactoryJNDIName=
QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&
java.naming.provider.url=tcp://localhost:61616
You may also notice that the simple stock quote proxy service exposed in
the ESB is now available only in HTTP as we have specified the transport for
that service as HTTP. To observe this, access the WSDL of the stock quote
proxy service at http://localhost:8080/soap/StockQuoteProxy?wsdl.
This ESB configuration creates a proxy service over HTTP and forwards
received messages to the above EPR using JMS. It sends back the response to
the client over HTTP once the simple stock quote service responds with the
stock quote reply over JMS, to the ESB server. To test this, send a place
order request to the ESB using HTTP as follows:
ant stockquote -Daddurl=http://localhost:8080/soap/StockQuoteProxy -Dmode=placeorder -Dsymbol=MSFT
The sample Axis2 server console will print a message indicating that it
has accepted the order as follows:
Accepted order for : 18406 stocks of MSFT at $ 83.58806051152119
Objective: Demonstrate one way messaging /
fireAndForget()
Pre-requisites:
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps
above)
Start the ESB configuration numbered 1: i.e., wso2-esb -sample 1
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
the ESB into the sample Axis2 server instance, which reports the acceptance
of the order as follows:
ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dmode=placeorder
SimpleStockQuoteService :: Accepted order for : 7482 stocks of IBM at $ 169.27205579038733
If you send your client request through TCPmon, you will notice that the
SimpleStockQuoteService replies to the ESB with a HTTP 202 reply, and that
the ESB 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 the ESB (Refer notes)
Start the ESB configuration numbered 113: i.e. wso2-esb -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>". The
WSO2 ESB converts this message into a SOAP message and sends this to the
SimpleStockQuoteServices' placeOrder operation. The ESB uses the script
mediator to transform the text message into an 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 the 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 will notice that the ESB received the JMS
text message and transformed it into a SOAP payload as follows. Note 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 the ESB. 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 content 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 ESB 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 an 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 can 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
the ESB 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 the ESB 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 ESB configuration numbered 114: i.e., wso2-esb -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 the ESB 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 the ESB can 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 ESB 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 the ESB.
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
The WSO2 ESB 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 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 allow 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, which makes them well suited for use in the ESB mediation
environment.
The Script Mediator is a Synapse extension, and thus all pre-requisites
for all supported BSF scripting languages may not be bundled by default with
the ESB distribution. Before you use some script mediators you may need to
manually add additional required .jar files to the ESB 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/stockquoteTransform.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 ESB configuration numbered 500: i.e., wso2-esb -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 ESB 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
The ESB 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 ESB configuration numbered 501: i.e. wso2-esb -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 the ESB. 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 ESB configuration numbered 502: i.e., bin/wso2-esb -sample
502
This example shows how an inline Javascript mediator script accesses 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 set up support for this in the ESB as
described in Configuring JRuby.
Start the ESB configuration numbered 503: i.e., bin/wso2-esb -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 ESB
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 a 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 file is placed in the lib directory when installing the ESB).
Start the ESB with the sample configuration 600 (i.e., wso2-esb -sample
600)
Start the sample Axis2 server and deploy the SimpleStockQuoteService.
In this configuration, ESB 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. The 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 mediator should implement the mediator
interface, which contains the mediate(...) method. The 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 hierarchy can be accessed from the message
context. In this sample, the body of the message is retrieved and the
discount percentage is subtracted from the quoted 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 the ESB. 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 the Throttle mediator for
restricting request counts
Pre-requisites:
Deploy the SimpleStockQuoteService in sample Axis2 server and start it on
port 9000.
Start the ESB with the sample configuration 600 (i.e., wso2-esb -sample
600).
The above configuration specifies a throttle mediator inside the 'in'
mediator. Therefore, all request messages directed to the main sequence will
be subjected to throttling. The throttle mediator has policies, onAccept and
onReject tags at top level. The policy tag specifies the throttling policy to
be applied for messages. It contains some IP address ranges and the maximum
number of messages to be allowed for those ranges within the time range given
in "UnitTime" tag. The "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 command
below, 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**
The 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 ESB 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**